This commit is contained in:
Luna 2025-02-24 20:11:51 +01:00
parent d8ba09a5a0
commit 1a6fa90571
12 changed files with 216 additions and 85 deletions

View file

@ -19,5 +19,5 @@ layout(location = 1) out vec2 fragUV;
void main() {
gl_Position = vec4(ubo.proj * ubo.view * ubo_inst.model[index] * vec3(inPosition, 1.0), 1.0);
fragColor = inColor;
fragUV = inPosition;
fragUV = inPosition + vec2(0.5, 0.5);
}

View file

@ -38,22 +38,25 @@ void uninit_mem(struct Mem *mem) {
}
static struct Alloc *get_next_alloc(struct Mem *mem) {
uint index = mem->count;
mem->count++;
while (*(uint32_t *)&mem->allocs[mem->count] != 0) {
while (mem->allocs[mem->count].start != NULL ||
mem->allocs[mem->count].size != 0 ||
mem->allocs[mem->count].next != NULL) {
mem->count++;
if (mem->count >= MAX_ALLOCS) {
crash("out of allocs!");
}
}
return &mem->allocs[index];
return &mem->allocs[mem->count];
}
void *mem_malloc(struct Mem *mem, size_t size) {
if (size <= 0) {
size = 1;
}
struct Alloc *prev = mem->alloc;
while (prev->next != NULL) {
struct Alloc *next = prev->next;
if (next->start - (prev->start + prev->size) > size) {
if (next->start - (prev->start + prev->size) > size && next != prev) {
struct Alloc *new = get_next_alloc(mem);
*new = (struct Alloc){
prev->start + prev->size,
@ -61,8 +64,9 @@ void *mem_malloc(struct Mem *mem, size_t size) {
next,
};
prev->next = new;
meow("MALLOC %p of size %zu, prev is at %p with size %u", new->start,
size, prev->start, prev->size);
meow("MALLOC %p:%ld, size %zu, prev is %p:%ld, size %u", new->start,
new - mem->allocs, size, prev->start, prev - mem->allocs,
prev->size);
/* print_backtrace(); */
return new->start;
} else {
@ -90,5 +94,7 @@ void mem_free(struct Mem *mem, void *p) {
if (index < mem->count) {
mem->count = index;
}
meow("FREE at %d : %p", index, current->start);
/* print_backtrace(); */
memset(&mem->allocs[index], 0, sizeof(struct Alloc));
}

View file

@ -1,15 +1,32 @@
#include "allocator.h"
#include <stdlib.h>
struct da_template {
void *items;
int count;
int capacity;
void *items;
struct Mem *mem;
};
// the array struct has to be freed manually, all internal data is freedd by
// dyn_array_destroy
void *dyn_array_create() {
struct da_template *da = malloc(sizeof(struct da_template));
da->items = malloc(0);
da->count = 0;
da->capacity = 0;
da->count = 0;
da->mem = NULL;
return da;
}
// the array struct has to be freed manually, all internal data is freedd by
// dyn_array_destroy
void *dyn_array_create_mem(struct Mem *mem) {
struct da_template *da = mem_malloc(mem, sizeof(struct da_template));
da->items = mem_malloc(mem, 0);
da->capacity = 0;
da->count = 0;
da->mem = mem;
return da;
}
void dyn_array_create_inplace(void *array) {
@ -17,4 +34,12 @@ void dyn_array_create_inplace(void *array) {
da->items = malloc(0);
da->count = 0;
da->capacity = 0;
da->mem = NULL;
}
void dyn_array_create_inplace_mem(void *array, struct Mem *mem) {
struct da_template *da = array;
da->items = mem_malloc(mem, 0);
da->count = 0;
da->capacity = 0;
da->mem = mem;
}

View file

@ -1,42 +1,70 @@
#ifndef INCLUDE_WAYLANDCLIENT_DYNARRAY_H_
#define INCLUDE_WAYLANDCLIENT_DYNARRAY_H_
#include "allocator.h"
#include <stdint.h>
#define dyn_array_append(array, item) \
do { \
if ((array)->count >= (array)->capacity) { \
(array)->capacity += 10; \
(array)->items = realloc((array)->items, \
(array)->capacity * sizeof(*(array)->items)); \
if ((array)->mem == NULL) { \
(array)->items = realloc((array)->items, \
(array)->capacity * sizeof(*(array)->items)); \
} else { \
void *temp = (array)->items; \
(array)->items = mem_malloc( \
(array)->mem, (array)->capacity * sizeof(*(array)->items)); \
memcpy((array)->items, temp, \
((array)->count) * sizeof(*(array)->items)); \
mem_free((array)->mem, temp); \
} \
} \
(array)->items[(array)->count++] = (item); \
} while (0)
#define dyn_array_remove(array, index) \
do { \
(array)->items[(index)] = (array)->items[(array)->count - 1]; \
(array)->items[(array)->count] = NULL; \
memset(&(array)->items[(array)->count], 0, sizeof((array)->items[0])); \
(array)->count--; \
} while (0)
#define dyn_array_destroy(array) free((array)->items)
#define dyn_array_destroy(array) \
if ((array)->mem == NULL) { \
free((array)->items); \
} else { \
mem_free((array)->mem, (array)->items); \
}
#define dyn_array_reset(array) \
do { \
(array)->capacity = 10; \
(array)->count = 0; \
(array)->items = \
realloc((array)->items, (array)->capacity * sizeof(*(array)->items)); \
if ((array)->mem == NULL) { \
(array)->items = realloc((array)->items, \
(array)->capacity * sizeof(*(array)->items)); \
} else { \
mem_free((array)->mem, (array)->items); \
(array)->items = mem_malloc((array)->mem, (array)->capacity * \
sizeof(*(array)->items)); \
} \
} while (0)
#define dyn_array_define($name, $type) \
struct $name { \
$type *items; \
int count; \
int capacity; \
$type *items; \
struct Mem *mem; \
}
dyn_array_define(da_uint32_t, uint32_t);
void *dyn_array_create();
void *dyn_array_create_mem(struct Mem *mem);
void dyn_array_create_inplace(void *array);
void dyn_array_create_inplace_mem(void *array, struct Mem *mem);
#endif // INCLUDE_WAYLANDCLIENT_DYNARRAY_H_

62
kitty.c
View file

@ -3,18 +3,31 @@
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_core.h>
#include "allocator.h"
#include "dynarray.h"
#include "io.h"
#include "kitty.h"
#include "vulkan.h"
#include "vulkan_helpers.c"
struct Kitty *kitty_make() {
struct Kitty *kitty = malloc(sizeof(struct Kitty));
struct Kitty *kitty_make(struct Mem *mem) {
struct Kitty *kitty;
if (mem == NULL) {
kitty = malloc(sizeof(struct Kitty));
} else {
kitty = mem_malloc(mem, sizeof(struct Kitty));
}
memset(kitty, 0, sizeof(struct Kitty));
dyn_array_create_inplace(&kitty->attatchments);
dyn_array_create_inplace(&kitty->vertex_buffer.format);
dyn_array_create_inplace(&kitty->instance_buffer.format);
kitty->mem = mem;
if (kitty->mem == NULL) {
dyn_array_create_inplace(&kitty->attatchments);
dyn_array_create_inplace(&kitty->vertex_buffer.format);
dyn_array_create_inplace(&kitty->instance_buffer.format);
} else {
dyn_array_create_inplace_mem(&kitty->attatchments, kitty->mem);
dyn_array_create_inplace_mem(&kitty->vertex_buffer.format, kitty->mem);
dyn_array_create_inplace_mem(&kitty->instance_buffer.format, kitty->mem);
}
meow("alloced a kitty at %p", kitty);
return kitty;
}
@ -144,8 +157,12 @@ void free_kitty(struct Vk *state, struct Kitty *kitty) {
dyn_array_destroy(&kitty->vertex_buffer.format);
dyn_array_destroy(&kitty->attatchments);
memset(kitty, 0, sizeof(struct Kitty));
free(kitty);
if (kitty->mem == NULL) {
memset(kitty, 0, sizeof(struct Kitty));
free(kitty);
} else {
mem_free(kitty->mem, kitty);
}
}
void kitty_set_next_push_constant(struct Kitty *kitty, void *data) {
@ -176,11 +193,25 @@ void kitty_set_next_ubo(struct Vk *state, struct Kitty *kitty, int index,
memcpy(dst_array, src_array, size_array);
break;
}
void *dst =
kitty->attatchments.items[index].ubo.memory[state->current_frame].mapped;
void *src = data;
int size = kitty->attatchments.items[index].ubo.size;
memcpy(dst, src, size);
}
void *kitty_get_next_ubo_pointer(struct Vk *state, struct Kitty *kitty,
int index) {
switch (kitty->attatchments.items[index].type) {
case CAT_ATTATCH_IMAGE:
meow("trying to update the contents of an image, not supported");
break;
case CAT_ATTATCH_UBO:;
return kitty->attatchments.items[index]
.ubo.memory[state->current_frame]
.mapped;
break;
case CAT_ATTATCH_UBO_ARRAY:;
return kitty->attatchments.items[index]
.ubo_array.memory[state->current_frame]
.mapped;
break;
}
}
void kitty_draw(struct Vk *state, uint32_t image_index, struct Kitty *kitty) {
@ -617,7 +648,6 @@ void kitty_create_descriptor_sets(struct Kitty *kitty, struct Vk *state) {
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
alloc_info.descriptorPool = kitty->descriptor_pool;
alloc_info.descriptorSetCount = MAX_FRAMES_IN_FLIGHT;
meow("allocing %d desc sets", MAX_FRAMES_IN_FLIGHT);
alloc_info.pSetLayouts = set_layouts;
CHECK_VK_RESULT(vkAllocateDescriptorSets(state->device, &alloc_info,
kitty->descriptor_sets));
@ -640,8 +670,6 @@ void kitty_create_descriptor_sets(struct Kitty *kitty, struct Vk *state) {
write_buffer.descriptorCount = 1;
write_buffer.pBufferInfo = &buffer_info;
vkUpdateDescriptorSets(state->device, 1, &write_buffer, 0, NULL);
meow("mapped ubo %d to set %d aka %p", index, i,
kitty->descriptor_sets[i]);
break;
case CAT_ATTATCH_UBO_ARRAY:;
for (int j = 0; j < kitty->attatchments.items[index].ubo_array.count;
@ -664,8 +692,6 @@ void kitty_create_descriptor_sets(struct Kitty *kitty, struct Vk *state) {
write_array_buffer.pBufferInfo = &array_buffer_info;
vkUpdateDescriptorSets(state->device, 1, &write_array_buffer, 0,
NULL);
meow("mapped ubo array %d, index %d to set %d aka %p", index, j, i,
kitty->descriptor_sets[i]);
}
break;
case CAT_ATTATCH_IMAGE:;
@ -683,8 +709,6 @@ void kitty_create_descriptor_sets(struct Kitty *kitty, struct Vk *state) {
write_image.descriptorCount = 1;
write_image.pImageInfo = &image_info;
vkUpdateDescriptorSets(state->device, 1, &write_image, 0, NULL);
meow("mapped image %d to set %d aka %p", index, i,
kitty->descriptor_sets[i]);
break;
}
}

View file

@ -59,9 +59,11 @@ struct Kitty {
VkDescriptorPool descriptor_pool;
VkDescriptorSetLayout descriptor_set_layout;
VkDescriptorSet descriptor_sets[MAX_FRAMES_IN_FLIGHT];
struct Mem *mem;
};
struct Kitty *kitty_make();
struct Kitty *kitty_make(struct Mem *mem);
void kitty_set_vertex_shader(struct Kitty *thingy, const char *path);
void kitty_set_fragment_shader(struct Kitty *thingy, const char *path);
@ -98,6 +100,8 @@ void kitty_finalise(struct Vk *state, struct Kitty *thingy);
void kitty_set_next_push_constant(struct Kitty *thingy, void *data);
void kitty_set_next_ubo(struct Vk *state, struct Kitty *thingy, int index,
void *data);
void *kitty_get_next_ubo_pointer(struct Vk *state, struct Kitty *kitty,
int index);
void kitty_draw(struct Vk *state, uint32_t image_index, struct Kitty *thingy);

View file

@ -1,5 +1,6 @@
#include "object.h"
#include "allocator.h"
#include "dynarray.h"
#include "log.h"
#include "register.h"
@ -7,6 +8,8 @@
#include <string.h>
#include <time.h>
#define DT_TARGET 0.016
struct Scene *make_scene(struct Vk *vk, struct Register *reg) {
struct Scene *scene = malloc(sizeof(struct Scene));
memset(scene, 0, sizeof(struct Scene));
@ -18,8 +21,9 @@ struct Scene *make_scene(struct Vk *vk, struct Register *reg) {
scene->reg = reg;
}
dyn_array_create_inplace(&scene->objects);
dyn_array_create_inplace(&scene->insert_queue);
dyn_array_create_inplace_mem(&scene->objects, scene->mem);
dyn_array_create_inplace_mem(&scene->insert_queue, scene->mem);
dyn_array_create_inplace_mem(&scene->named, scene->mem);
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
@ -40,6 +44,7 @@ void free_scene(struct Scene *scene) {
mem_free(scene->mem, scene->insert_queue.items[i]);
}
dyn_array_destroy(&scene->insert_queue);
dyn_array_destroy(&scene->named);
uninit_mem(scene->mem);
memset(scene, 0, sizeof(struct Scene));
@ -49,15 +54,14 @@ void free_scene(struct Scene *scene) {
void scene_tick(struct Scene *scene) {
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
long msecs = time.tv_sec * 1000000 + time.tv_nsec / 1000;
msecs *= 1.0f;
scene->delta_secs = (float)(msecs - scene->msecs) / 1000;
long msecs_start = time.tv_sec * 1000000 + time.tv_nsec / 1000;
scene->delta_secs = (float)(msecs_start - scene->msecs) / 1000000;
if (scene->insert_queue.count > 0) {
for (int i = 0; i < scene->insert_queue.count; i++) {
dyn_array_append(&scene->objects, scene->insert_queue.items[i]);
}
dyn_array_reset(&scene->insert_queue);
scene->insert_queue.count = 0;
}
for (int i = 0; i < scene->objects.count; i++) {
scene->objects.items[i]->type->tick(scene, scene->objects.items[i]->data);
@ -66,10 +70,19 @@ void scene_tick(struct Scene *scene) {
for (int i = 0; i < scene->insert_queue.count; i++) {
dyn_array_append(&scene->objects, scene->insert_queue.items[i]);
}
dyn_array_reset(&scene->insert_queue);
scene->insert_queue.count = 0;
}
scene->msecs = msecs;
clock_gettime(CLOCK_MONOTONIC, &time);
long msecs_end = time.tv_sec * 1000000 + time.tv_nsec / 1000;
struct timespec t = {
.tv_sec = 0,
.tv_nsec =
(((1.0 / 120.0) * 1000000) - (msecs_end - scene->msecs)) * 1000,
};
scene->msecs = msecs_start;
nanosleep(&t, NULL);
meow("dt was %f", scene->delta_secs);
}
void scene_queue_insert(struct Scene *scene, char *name, void *object_data) {
@ -87,3 +100,28 @@ void scene_queue_insert_from_data(struct Scene *scene, char *name, char *data,
object->data = type->make(scene, data, len);
dyn_array_append(&scene->insert_queue, object);
}
void scene_register_named(struct Scene *scene, const char *id,
struct Object *object) {
dyn_array_append(&scene->named, ((struct Named){id, object}));
}
void scene_unregister_named(struct Scene *scene, const char *id) {
for (int i = 0; i < scene->named.count; i++) {
if (strcmp(scene->named.items[i].id, id) == 0) {
dyn_array_remove(&scene->named, i);
return;
}
}
meow("object with name %s was not found", id);
}
struct Object *scene_get_named(struct Scene *scene, const char *id) {
for (int i = 0; i < scene->named.count; i++) {
if (strcmp(scene->named.items[i].id, id) == 0) {
return scene->named.items[i].object;
}
}
meow("object with name %s was not found", id);
return NULL;
}

View file

@ -5,12 +5,14 @@
// #include "vulkan_internal.h"
dyn_array_define(da_Object, struct Object *);
dyn_array_define(da_Named, struct Named);
struct Scene {
struct Vk *vk;
struct Mem *mem;
struct da_Object objects;
struct da_Object insert_queue;
struct da_Named named;
struct Register *reg;
float delta_secs;
@ -22,9 +24,19 @@ struct Object {
void *data;
};
struct Named {
const char *id;
struct Object *object;
};
struct Scene *make_scene(struct Vk *vk, struct Register *reg);
void free_scene(struct Scene *scene);
void scene_tick(struct Scene *scene);
void scene_queue_insert(struct Scene *scene, char *name, void *object_data);
void scene_register_named(struct Scene *scene, const char *id,
struct Object *object);
void scene_unregister_named(struct Scene *scene, const char *id);
struct Object *scene_get_named(struct Scene *scene, const char *id);
#endif // INCLUDE_WAYLANDCLIENT_OBJECT_H_

49
trig.c
View file

@ -10,23 +10,24 @@
struct Trig {
struct Kitty *kitty;
struct mat3x3 model[INSTANCE_COUNT];
struct Vec2 vel[INSTANCE_COUNT];
struct Vec2 pos[INSTANCE_COUNT];
float rot[INSTANCE_COUNT];
};
#define TRIG_VERTEX_COUNT 6
struct Vertex trig_vertices[TRIG_VERTEX_COUNT] = {
(struct Vertex){(struct Vec2){.x = 0.0f, .y = 0.0f},
(struct Vertex){(struct Vec2){.x = -0.5f, .y = -0.5f},
(struct Vec3){1.0f, 0.0f, 1.0f}},
(struct Vertex){(struct Vec2){.x = 1.0f, .y = 0.0f},
(struct Vertex){(struct Vec2){.x = 0.5f, .y = -0.5f},
(struct Vec3){1.0f, 0.0f, 0.0f}},
(struct Vertex){(struct Vec2){.x = 1.0f, .y = 1.0f},
(struct Vertex){(struct Vec2){.x = 0.5f, .y = 0.5f},
(struct Vec3){1.0f, 0.0f, 1.0f}},
(struct Vertex){(struct Vec2){.x = 0.0f, .y = 0.0f},
(struct Vertex){(struct Vec2){.x = -0.5f, .y = -0.5f},
(struct Vec3){1.0f, 0.0f, 1.0f}},
(struct Vertex){(struct Vec2){.x = 1.0f, .y = 1.0f},
(struct Vertex){(struct Vec2){.x = 0.5f, .y = 0.5f},
(struct Vec3){1.0f, 0.0f, 1.0f}},
(struct Vertex){(struct Vec2){.x = 0.0f, .y = 1.0f},
(struct Vertex){(struct Vec2){.x = -0.5f, .y = 0.5f},
(struct Vec3){0.0f, 0.0f, 1.0f}},
};
struct TrigUBO {
@ -34,10 +35,9 @@ struct TrigUBO {
struct mat3x3 proj;
};
struct Trig *trig_make_args(struct Scene *scene) {
/* struct Trig *trig = mem_malloc(scene->mem, sizeof(struct Trig)); */
struct Trig *trig = malloc(sizeof(struct Trig));
struct Trig *trig = mem_malloc(scene->mem, sizeof(struct Trig));
trig->kitty = kitty_make();
trig->kitty = kitty_make(scene->mem);
kitty_set_vertex_shader(trig->kitty, "./Shaders/vert.spv");
kitty_set_fragment_shader(trig->kitty, "./Shaders/frag.spv");
kitty_set_vertex_buffer(trig->kitty, trig_vertices, TRIG_VERTEX_COUNT,
@ -52,11 +52,11 @@ struct Trig *trig_make_args(struct Scene *scene) {
uint32_t instance_buffer[INSTANCE_COUNT] = {0};
for (int i = 0; i < INSTANCE_COUNT; i++) {
instance_buffer[i] = i;
trig->vel[i] = vec2_normalize((struct Vec2){randf() - 0.5, randf() - 0.5});
trig->model[i] =
multiply3x3(multiply3x3(translate3x3((struct Vec2){randf(), randf()}),
scale3x3((struct Vec2){0.1f, 0.1f})),
rotate3x3(randf() * 2 * PI));
trig->rot[i] = randf() * 2.0f * PI;
trig->pos[i] = (struct Vec2){randf(), randf()};
trig->vel[i] = vec2_mul(
vec2_normalize((struct Vec2){randf() - 0.5f, randf() - 0.5f}), 0.2f);
/* trig->vel[i] = (struct Vec2){1.0f, 0.0f}; */
}
kitty_add_instance_buffer(trig->kitty, instance_buffer, INSTANCE_COUNT,
sizeof(uint32_t));
@ -73,8 +73,7 @@ struct Trig *make_trig(struct Scene *scene, char *_data, int _len) {
void free_trig(struct Scene *scene, struct Trig *trig) {
free_kitty(scene->vk, trig->kitty);
/* mem_free(scene->mem, trig); */
free(trig);
mem_free(scene->mem, trig);
}
void trig_tick(struct Scene *scene, struct Trig *trig) {
@ -85,16 +84,20 @@ void trig_tick(struct Scene *scene, struct Trig *trig) {
(struct Vec2){1.f, (float)scene->vk->width / (float)scene->vk->heigh});
kitty_set_next_ubo(scene->vk, trig->kitty, 0, &ubo);
struct mat3x3 *model = kitty_get_next_ubo_pointer(scene->vk, trig->kitty, 1);
for (int i = 0; i < INSTANCE_COUNT; i++) {
trig->model[i] = multiply3x3(
trig->model[i],
translate3x3(vec2_mul(trig->vel[i], scene->msecs * 0.000000000002f)));
if (trig->model[i].m13 < 0 || trig->model[i].m13 > 2.5) {
trig->pos[i] =
vec2_add(trig->pos[i], vec2_mul(trig->vel[i], scene->delta_secs));
trig->rot[i] += scene->delta_secs;
if (trig->pos[i].x < 0 || trig->pos[i].x > 2.5) {
trig->vel[i].x = -trig->vel[i].x;
}
if (trig->model[i].m23 < -0.5 || trig->model[i].m23 > 2) {
if (trig->pos[i].y < -0.5 || trig->pos[i].y > 2) {
trig->vel[i].y = -trig->vel[i].y;
}
model[i] = IDENT3x3;
model[i] = multiply3x3(model[i], translate3x3(trig->pos[i]));
model[i] = multiply3x3(model[i], rotate3x3(trig->rot[i]));
model[i] = multiply3x3(model[i], scale3x3((struct Vec2){0.1f, 0.1f}));
}
kitty_set_next_ubo(scene->vk, trig->kitty, 1, &trig->model);
}

View file

@ -6,3 +6,7 @@ struct Vec2 vec2_normalize(struct Vec2 v) {
float abs = sqrt(v.x * v.x + v.y * v.y);
return (struct Vec2){v.x / abs, v.y / abs};
}
struct Vec2 vec2_rotate(struct Vec2 v, float alpha) {
return (struct Vec2){v.x * cosf(alpha) - v.y * sinf(alpha),
v.x * sinf(alpha) + v.y * cosf(alpha)};
}

View file

@ -16,7 +16,10 @@ struct Vec2 {
};
#define vec2_mul(v, n) \
(struct Vec2) { (v).x *(n), (v).y *(n) }
#define vec2_add(v1, v2) \
(struct Vec2) { (v1).x + (v2).x, (v1).y + (v2).y }
struct Vec2 vec2_normalize(struct Vec2 v);
struct Vec2 vec2_rotate(struct Vec2 v, float alpha);
struct IVec2 {
int x, y;

View file

@ -38,22 +38,6 @@ VkVertexInputBindingDescription get_vertex_binding_description() {
return description;
}
// return value owned by caller
VkVertexInputAttributeDescription *get_vertex_attribute_description() {
VkVertexInputAttributeDescription *description = malloc(
sizeof(VkVertexInputAttributeDescription) * VERTEX_ATTRIBUTE_COUNT);
description[0].binding = 0;
description[0].location = 0;
description[0].format = VK_FORMAT_R32G32_SFLOAT;
description[0].offset = offsetof(struct Vertex, pos);
description[1].binding = 0;
description[1].location = 1;
description[1].format = VK_FORMAT_R32G32B32_SFLOAT;
description[1].offset = offsetof(struct Vertex, col);
return description;
}
static const char *const extensions[] = {
"VK_EXT_debug_utils", "VK_KHR_surface", "VK_KHR_wayland_surface",
/* "VK_KHR_xcb_surface", */
@ -608,7 +592,7 @@ void transition_image_layout(struct Vk *state, VkImage image, VkFormat format,
source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dest_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} else {
meow("invalid transition OwO rudeeee");
meow("transition not supported TwT");
}
vkCmdPipelineBarrier(command_buffer, source_stage, dest_stage, 0, 0, NULL, 0,
NULL, 1, &barrier);