diff --git a/code/core/impl/math.c b/code/core/impl/math.c index f19945c..430a5fc 100644 --- a/code/core/impl/math.c +++ b/code/core/impl/math.c @@ -1,3 +1,23 @@ +V2f V2F(F32 x, F32 y) { + V2f result = { x, y }; + return result; +} + +V3f V3F(F32 x, F32 y, F32 z) { + V3f result = { x, y, z }; + return result; +} + +V4f V4F(F32 x, F32 y, F32 z, F32 w) { + V4f result = { x, y, z, w }; + return result; +} + +R2f R2F(V2f min, V2f max) { + R2f result = { min, max }; + return result; +} + V3f V3f_Neg(V3f x) { V3f result = { -x.x, -x.y, -x.z }; return result; diff --git a/code/core/macros.h b/code/core/macros.h index cae2d9d..1ff0b56 100644 --- a/code/core/macros.h +++ b/code/core/macros.h @@ -4,6 +4,7 @@ #include #define Assert(exp) assert(exp) +#define StaticAssert(exp) static_assert(exp, #exp) #define ArraySize(x) (sizeof(x) / sizeof((x)[0])) #define Min(a, b) ((a) < (b) ? (a) : (b)) diff --git a/code/core/math.h b/code/core/math.h index 652f634..0b219d8 100644 --- a/code/core/math.h +++ b/code/core/math.h @@ -87,6 +87,18 @@ struct Mat4x4FInv { Mat4x4F inv; }; +typedef struct R2f R2f; +struct R2f { + V2f min; + V2f max; +}; + +function V2f V2F(F32 x, F32 y); +function V3f V3F(F32 x, F32 y, F32 z); +function V4f V4F(F32 x, F32 y, F32 z, F32 w); + +function R2f R2F(V2f min, V2f max); + function V3f V3f_Neg(V3f x); function V3f V3f_Scale(V3f x, F32 s); diff --git a/code/draw/core.c b/code/draw/core.c new file mode 100644 index 0000000..8d1c763 --- /dev/null +++ b/code/draw/core.c @@ -0,0 +1,132 @@ +void D_Begin(D_Context *draw, Vk_Frame *frame, U32 max_rects) { + Vk_Buffer *rbo = &frame->rbo; + + draw->rbo = rbo; + draw->n_rects = 0; + draw->max_rects = max_rects; + draw->rects = rbo->data; +} + +void D_End(D_Context *draw, Vk_Frame *frame) { + VkCommandBuffer cmd = frame->cmd; + Vk_Pipeline *basic = &draw->pipelines[0]; + + // We can probably stop doing this at some point + VkDescriptorSet set; + VkDescriptorSetAllocateInfo alloc_info = { 0 }; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = frame->descriptors; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &basic->layout.set; + + vk.AllocateDescriptorSets(vk.device, &alloc_info, &set); + + // 'update' the descriptor sets for binding + M_TempScope(0, 0) { + VkWriteDescriptorSet writes[2] = { 0 }; + + VkDescriptorBufferInfo rbo_info = { 0 }; + rbo_info.buffer = draw->rbo->handle; + rbo_info.offset = 0; + rbo_info.range = VK_WHOLE_SIZE; + + VkDescriptorImageInfo *image_info = M_ArenaPush(temp.arena, VkDescriptorImageInfo, .count = draw->n_images); + + for (U32 it = 0; it < draw->n_images; ++it) { + image_info[it].imageView = draw->images[it].image.view; + image_info[it].sampler = vk.sampler; + image_info[it].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } + + writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[0].dstSet = set; + writes[0].dstBinding = 0; + writes[0].descriptorCount = 1; + writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + writes[0].pBufferInfo = &rbo_info; + + writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[1].dstSet = set; + writes[1].dstBinding = 1; + writes[1].descriptorCount = draw->n_images; + writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writes[1].pImageInfo = image_info; + + vk.UpdateDescriptorSets(vk.device, ArraySize(writes), writes, 0, 0); + } + + vk.CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->handle); + vk.CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->layout.pipeline, 0, 1, &set, 0, 0); + vk.CmdPushConstants(cmd, basic->layout.pipeline, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(Mat4x4F), &draw->camera->proj.fwd); + + VkViewport viewport = { 0, 0, (F32) draw->window_width, (F32) draw->window_height, 0.0f, 1.0f }; + VkRect2D scissor = { 0, 0, draw->window_width, draw->window_height }; + + vk.CmdSetViewport(cmd, 0, 1, &viewport); + vk.CmdSetScissor(cmd, 0, 1, &scissor); + + vk.CmdDraw(cmd, 6, draw->n_rects, 0, 0); +} + +internal U32 V4f_UnormColour(V4f c) { + // @Todo: SRGB handling + U32 result = + ((U8) (255.0f * c.a)) << 24 | + ((U8) (255.0f * c.r)) << 16 | + ((U8) (255.0f * c.g)) << 8 | + ((U8) (255.0f * c.b)) << 0; + + return result; +} + +void _D_Rect(D_Context *draw, D_RectOpts *opts) { + if (draw->n_rects < draw->max_rects) { + D_Rect *rect = &draw->rects[draw->n_rects]; + + rect->texture = opts->texture; + + rect->x = opts->p.x; + rect->y = opts->p.y; + + rect->uv[0] = opts->uv.min.x; + rect->uv[1] = opts->uv.min.y; + rect->uv[2] = opts->uv.max.x; + rect->uv[3] = opts->uv.max.y; + + rect->angle = opts->angle; + + if (opts->flags & D_RECT_PER_VERTEX_COLOUR) { + rect->c[0] = V4f_UnormColour(opts->vtxc[0]); + rect->c[1] = V4f_UnormColour(opts->vtxc[1]); + rect->c[2] = V4f_UnormColour(opts->vtxc[2]); + rect->c[3] = V4f_UnormColour(opts->vtxc[3]); + } + else { + U32 unorm = V4f_UnormColour(opts->c); + + rect->c[0] = unorm; + rect->c[1] = unorm; + rect->c[2] = unorm; + rect->c[3] = unorm; + } + + if (opts->flags & D_RECT_IGNORE_ASPECT) { + rect->w = opts->w; + rect->h = opts->h; + } + else { + Vk_Image *image = &draw->images[opts->texture].image; + + if (image->width > image->height) { + rect->w = opts->scale * ((F32) image->width / (F32) image->height); + rect->h = opts->scale; + } + else { + rect->w = opts->scale; + rect->h = opts->scale * ((F32) image->height / (F32) image->width); + } + } + + draw->n_rects += 1; + } +} diff --git a/code/draw/core.h b/code/draw/core.h new file mode 100644 index 0000000..e565bf2 --- /dev/null +++ b/code/draw/core.h @@ -0,0 +1,85 @@ +#if !defined(LD_DRAW_CORE_H_) +#define LD_DRAW_CORE_H_ + +#define D_MAX_RECTS 1024 + +typedef struct D_Image D_Image; +struct D_Image { + Str8 name; + Vk_Image image; +}; + +typedef struct D_Rect D_Rect; +struct D_Rect { + U32 texture; + + U32 c[4]; // per-vertex colours + F32 uv[4]; + + F32 angle; + F32 x, y; + F32 w, h; + + U32 p0, p1; +}; + +StaticAssert(sizeof(D_Rect) == 64); + +struct G_Camera; + +typedef struct D_Context D_Context; +struct D_Context { + Vk_Buffer *rbo; + + U32 n_pipelines; + Vk_Pipeline *pipelines; + + U32 n_images; + D_Image *images; + + U32 max_rects; + U32 n_rects; + D_Rect *rects; + + U32 window_width; + U32 window_height; + + struct G_Camera *camera; +}; + +typedef U32 D_RectFlags; +enum D_RectFlags { + D_RECT_IGNORE_ASPECT = (1 << 0), // by default only width is used as a "dimension" + D_RECT_PER_VERTEX_COLOUR = (1 << 1), // split colours per vertex +}; + +typedef struct D_RectOpts D_RectOpts; +struct D_RectOpts { + D_RectFlags flags; + + U32 texture; + + R2f uv; + V2f p; + + F32 angle; + + union { + F32 w, h; + F32 scale, _h; + V2f dim; + }; + + union { + V4f c; + V4f vtxc[4]; + }; +}; + +function void D_Begin(D_Context *draw, Vk_Frame *frame, U32 max_rects); +function void D_End(D_Context *draw, Vk_Frame *frame); + +function void _D_Rect(D_Context *draw, D_RectOpts *opts); +#define D_Rect(draw, x, y, ...) _D_Rect(draw, &(D_RectOpts) { .p = V2F(x, y), .uv = R2F(V2F(0, 0), V2F(1, 1)), .scale = 1, .c = V4F(1, 1, 1, 1), ##__VA_ARGS__ }) + +#endif // LD_DRAW_CORE_H_ diff --git a/code/first.c b/code/first.c index 66801c0..574046a 100644 --- a/code/first.c +++ b/code/first.c @@ -11,6 +11,8 @@ #include "os/core.h" #include "vulkan/core.h" +#include "draw/core.h" + #include "game/core.h" #include "game/world.h" @@ -48,34 +50,26 @@ int main(int argc, char **argv) { G_Camera *camera = &game->camera; - camera->x = (V3f) { 1, 0, 0 }; - camera->y = (V3f) { 0, 1, 0 }; - camera->z = (V3f) { 0, 0, 1 }; - camera->p = (V3f) { 0, 0, 8 }; + camera->x = V3F(1, 0, 0); + camera->y = V3F(0, 1, 0); + camera->z = V3F(0, 0, 1); + camera->p = V3F(0, 0, 48); camera->fov = 60.0f; camera->nearp = 0.01f; camera->farp = 1000.0f; - Vk_Buffer *vbo = &game->vbo; - vbo->size = KB(4096); - vbo->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - vbo->host_visible = true; - - Vk_BufferCreate(vbo); - - G_Vertex *vertices = cast(G_Vertex *) vbo->data; - - vertices[0] = (G_Vertex) { -0.25f, -0.625f, 1.0f, 1.0f, 0.0f, 0.0f, 0xFFFFFFFF, 1}; - vertices[1] = (G_Vertex) { 0.25f, -0.625f, 1.0f, 1.0f, 1.0f, 0.0f, 0xFFFFFFFF, 1}; - vertices[2] = (G_Vertex) { -0.25f, 0.625f, 1.0f, 1.0f, 0.0f, 1.0f, 0xFFFFFFFF, 1}; - - vertices[3] = (G_Vertex) { 0.25f, -0.625f, 1.0f, 1.0f, 1.0f, 0.0f, 0xFFFFFFFF, 1}; - vertices[4] = (G_Vertex) { 0.25f, 0.625f, 1.0f, 1.0f, 1.0f, 1.0f, 0xFFFFFFFF, 1}; - vertices[5] = (G_Vertex) { -0.25f, 0.625f, 1.0f, 1.0f, 0.0f, 1.0f, 0xFFFFFFFF, 1}; + game->draw.camera = camera; } + Vk_Buffer rbo = { 0 }; + rbo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + rbo.size = KB(4); + rbo.host_visible = true; + + Vk_BufferCreate(&rbo); + bool running = true; Player player; player.pos.x = 0; @@ -122,6 +116,9 @@ int main(int argc, char **argv) { int w, h; SDL_GetWindowSizeInPixels(window, &w, &h); + game->draw.window_width = w; + game->draw.window_height = h; + G_CalulateCamera(&game->camera, (F32) w / (F32) h); Vk_Frame *frame = Vk_FrameBegin(window); @@ -150,62 +147,13 @@ int main(int argc, char **argv) { vk.CmdBeginRendering(cmd, &rendering_info); - Vk_Pipeline *basic = &game->pipelines[0]; + D_Begin(&game->draw, frame, D_MAX_RECTS); - VkDescriptorSet set; - VkDescriptorSetAllocateInfo alloc_info = { 0 }; - alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - alloc_info.descriptorPool = frame->descriptors; - alloc_info.descriptorSetCount = 1; - alloc_info.pSetLayouts = &basic->layout.set; + D_Rect(&game->draw, 0.0f, 0.0f, .texture = 1); + D_Rect(&game->draw, -8.0f, 0.0f, .texture = 2, .scale = 2.0f); + D_Rect(&game->draw, 6.0f, 0.0f, .texture = 3); - vk.AllocateDescriptorSets(vk.device, &alloc_info, &set); - - // 'update' the descriptor sets for binding - M_TempScope(0, 0) { - VkWriteDescriptorSet writes[2] = { 0 }; - - VkDescriptorBufferInfo vbo_info = { 0 }; - vbo_info.buffer = game->vbo.handle; - vbo_info.offset = 0; - vbo_info.range = 256; - - VkDescriptorImageInfo *image_info = M_ArenaPush(temp.arena, VkDescriptorImageInfo, .count = game->n_images); - - for (U32 it = 0; it < game->n_images; ++it) { - image_info[it].imageView = game->images[it].image.view; - image_info[it].sampler = vk.sampler; - image_info[it].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - - writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writes[0].dstSet = set; - writes[0].dstBinding = 0; - writes[0].descriptorCount = 1; - writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - writes[0].pBufferInfo = &vbo_info; - - writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writes[1].dstSet = set; - writes[1].dstBinding = 1; - writes[1].descriptorCount = game->n_images; - writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writes[1].pImageInfo = image_info; - - vk.UpdateDescriptorSets(vk.device, ArraySize(writes), writes, 0, 0); - } - - vk.CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->handle); - vk.CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->layout.pipeline, 0, 1, &set, 0, 0); - vk.CmdPushConstants(cmd, basic->layout.pipeline, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(Mat4x4F), &game->camera.proj.fwd); - - VkViewport viewport = { 0, 0, (F32) w, (F32) h, 0.0f, 1.0f }; - VkRect2D scissor = { 0, 0, w, h }; - - vk.CmdSetViewport(cmd, 0, 1, &viewport); - vk.CmdSetScissor(cmd, 0, 1, &scissor); - - vk.CmdDraw(cmd, 6, 1, 0, 0); + D_End(&game->draw, frame); vk.CmdEndRendering(cmd); @@ -221,4 +169,5 @@ int main(int argc, char **argv) { #include "core/core.c" #include "os/core.c" #include "vulkan/core.c" +#include "draw/core.c" #include "game/core.c" diff --git a/code/game/core.c b/code/game/core.c index d201fa5..a6b7569 100644 --- a/code/game/core.c +++ b/code/game/core.c @@ -1,5 +1,9 @@ +// @Todo: These should move to draw/core.c +// void G_ImagesLoad(G_State *game) { M_TempScope(0, 0) { + D_Context *draw = &game->draw; + Str8 exe_path = FS_SystemPath(temp.arena, FS_SYSTEM_PATH_EXE); Str8 path = Sf(temp.arena, "%.*s/assets", Sv(exe_path)); @@ -17,15 +21,99 @@ void G_ImagesLoad(G_State *game) { Vk_CommandBuffer *cmds = Vk_CommandBufferPush(); + // We reserve the first texture for the "white" texture + draw->n_images = 1; + for (FS_Entry *it = assets.first; it != 0; it = it->next) { if (Str8_EndsWith(it->basename, S("png"))) { - game->n_images += 1; + draw->n_images += 1; } } VkBufferImageCopy copy = { 0 }; - game->images = M_ArenaPush(game->arena, G_Image, .count = game->n_images); - game->n_images = 0; + draw->images = M_ArenaPush(game->arena, D_Image, .count = draw->n_images); + draw->n_images = 1; + + // Upload the white texture + { + D_Image *white = &draw->images[0]; + U32 white_data[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + + M_CopySize(base, white_data, sizeof(white_data)); + + copy.bufferOffset = offset; + copy.bufferRowLength = 0; + copy.bufferImageHeight = 0; + + copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy.imageSubresource.mipLevel = 0; + copy.imageSubresource.baseArrayLayer = 0; + copy.imageSubresource.layerCount = 1; + + copy.imageExtent.width = 2; + copy.imageExtent.height = 2; + copy.imageExtent.depth = 1; + + base += sizeof(white_data); + offset += sizeof(white_data); + + white->name = S("_WHITE"); + + white->image.width = 2; + white->image.height = 2; + white->image.format = VK_FORMAT_R8G8B8A8_SRGB; + white->image.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + + Vk_ImageCreate(&white->image); + + // We could combine all of these 'pre-transfer' and 'post-transfer' layers into one + // batch, it would simply mean doing three loops over the images and setting them all up + // and submitting them in one go. It doesn't really matter for now + // + + VkImageMemoryBarrier2 transfer = { 0 }; + VkImageMemoryBarrier2 shader_read = { 0 }; + + transfer.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; + transfer.srcStageMask = VK_PIPELINE_STAGE_2_NONE; + transfer.srcAccessMask = VK_ACCESS_2_NONE; + transfer.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT; + transfer.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; + transfer.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + transfer.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + transfer.image = white->image.handle; + + transfer.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + transfer.subresourceRange.layerCount = 1; + transfer.subresourceRange.levelCount = 1; + + shader_read.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; + shader_read.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT; + shader_read.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; + shader_read.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; + shader_read.dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT; + shader_read.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + shader_read.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + shader_read.image = white->image.handle; + + shader_read.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + shader_read.subresourceRange.layerCount = 1; + shader_read.subresourceRange.levelCount = 1; + + VkDependencyInfo dep = { 0 }; + dep.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; + + dep.imageMemoryBarrierCount = 1; + dep.pImageMemoryBarriers = &transfer; + + vk.CmdPipelineBarrier2(cmds->handle, &dep); + + vk.CmdCopyBufferToImage(cmds->handle, staging.handle, white->image.handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©); + + dep.pImageMemoryBarriers = &shader_read; + + vk.CmdPipelineBarrier2(cmds->handle, &dep); + } // Image upload is sbi_load -> copy to staging -> upload to gpu texture @@ -35,7 +123,7 @@ void G_ImagesLoad(G_State *game) { stbi_uc *data = stbi_load((const char *) it->path.data, &w, &h, &c, 4); if (data) { - G_Image *image = &game->images[game->n_images]; + D_Image *image = &draw->images[draw->n_images]; U64 image_sz = 4 * w * h; @@ -59,7 +147,7 @@ void G_ImagesLoad(G_State *game) { Assert(offset <= staging.size); - game->n_images += 1; + draw->n_images += 1; image->name = Str8_Copy(game->arena, Str8_RemoveAfterLast(it->basename, '.')); @@ -126,9 +214,11 @@ void G_ImagesLoad(G_State *game) { } void G_PipelinesLoad(G_State *game) { - game->pipelines = M_ArenaPush(game->arena, Vk_Pipeline, .count = 1); + D_Context *draw = &game->draw; - Vk_Pipeline *basic = &game->pipelines[0]; + draw->pipelines = M_ArenaPush(game->arena, Vk_Pipeline, .count = 1); + + Vk_Pipeline *basic = &draw->pipelines[0]; VkShaderModule vshader = 0, fshader = 0; M_TempScope(0, 0) { @@ -161,12 +251,12 @@ void G_PipelinesLoad(G_State *game) { bindings[1].binding = 1; bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - bindings[1].descriptorCount = game->n_images; + bindings[1].descriptorCount = game->draw.n_images; bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; VkDescriptorSetLayoutCreateInfo set_info = { 0 }; set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - set_info.bindingCount = 2; + set_info.bindingCount = ArraySize(bindings); set_info.pBindings = bindings; vk.CreateDescriptorSetLayout(vk.device, &set_info, 0, &basic->layout.set); diff --git a/code/game/core.h b/code/game/core.h index 4c8d66f..03df95f 100644 --- a/code/game/core.h +++ b/code/game/core.h @@ -1,20 +1,6 @@ #if !defined(LD_GAME_CORE_H_) #define LD_GAME_CORE_H_ -typedef struct G_Vertex G_Vertex; -struct G_Vertex { - F32 x, y, z, w; - F32 u, v; - U32 c; - U32 pad; -}; - -typedef struct G_Image G_Image; -struct G_Image { - Str8 name; - Vk_Image image; -}; - typedef struct G_Camera G_Camera; struct G_Camera { V3f x, y, z; @@ -30,19 +16,10 @@ typedef struct G_State G_State; struct G_State { M_Arena *arena; - U32 n_images; - G_Image *images; - - U32 n_pipelines; - Vk_Pipeline *pipelines; - - Vk_Buffer vbo; - + D_Context draw; G_Camera camera; }; - - function void G_ImagesLoad(G_State *game); function void G_PipelinesLoad(G_State *game); diff --git a/code/game/impl/npc.c b/code/game/impl/npc.c index 293e624..8249f26 100644 --- a/code/game/impl/npc.c +++ b/code/game/impl/npc.c @@ -16,7 +16,7 @@ void updateNPC(F32 delta, NPC *npc, World *world) { npc->path = Nav_Path(world->navMesh, npc->currentNavNode, npc->targetNavNode); printf("done\n"); npc->walkTimer = 0; - printf("%*.s started walking to %d\n", Sv(npc->name), npc->targetNavNode); + printf("%.*s started walking to %d\n", Sv(npc->name), npc->targetNavNode); } break; case NPC_ACTION_WALKING: diff --git a/code/vulkan/core.c b/code/vulkan/core.c index 9a7e23d..1c1b9af 100644 --- a/code/vulkan/core.c +++ b/code/vulkan/core.c @@ -372,6 +372,16 @@ bool Vk_Setup(SDL_Window *window) { vk.CreateDescriptorPool(vk.device, &descriptor_pool, 0, &frame->descriptors); + // rect buffer + // + + Vk_Buffer *rbo = &frame->rbo; + rbo->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + rbo->size = D_MAX_RECTS * sizeof(D_Rect); + rbo->host_visible = true; + + Vk_BufferCreate(rbo); + VkSemaphoreCreateInfo semaphore = { 0 }; semaphore.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; @@ -547,7 +557,7 @@ internal VkDeviceMemory Vk_Allocate(VkMemoryRequirements *mreq, VkMemoryProperty } } - if (type_index != -1) { + if (type_index != U32_MAX) { VkMemoryAllocateInfo alloc_info = { 0 }; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; alloc_info.allocationSize = mreq->size; @@ -556,6 +566,7 @@ internal VkDeviceMemory Vk_Allocate(VkMemoryRequirements *mreq, VkMemoryProperty vk.AllocateMemory(vk.device, &alloc_info, 0, &result); } + Assert(result != VK_NULL_HANDLE); return result; } @@ -566,6 +577,7 @@ void Vk_BufferCreate(Vk_Buffer *buffer) { create_info.size = buffer->size; vk.CreateBuffer(vk.device, &create_info, 0, &buffer->handle); + Assert(buffer->handle != VK_NULL_HANDLE); VkMemoryRequirements req; vk.GetBufferMemoryRequirements(vk.device, buffer->handle, &req); @@ -580,6 +592,7 @@ void Vk_BufferCreate(Vk_Buffer *buffer) { if (buffer->host_visible) { vk.MapMemory(vk.device, buffer->memory, 0, buffer->size, 0, &buffer->data); } + } void Vk_ImageCreate(Vk_Image *image) { diff --git a/code/vulkan/core.h b/code/vulkan/core.h index b6849bf..0dbb075 100644 --- a/code/vulkan/core.h +++ b/code/vulkan/core.h @@ -96,6 +96,8 @@ struct Vk_Frame { U32 next_scratch; Vk_CommandBuffer scratch[VK_NUM_SCRATCH]; + Vk_Buffer rbo; + U32 image; // swapchain image index }; diff --git a/code/vulkan/functions.h b/code/vulkan/functions.h index 458a9d6..89adfe7 100644 --- a/code/vulkan/functions.h +++ b/code/vulkan/functions.h @@ -62,6 +62,8 @@ VK_FUNC(CmdDraw); VK_FUNC(CmdSetViewport); VK_FUNC(CmdSetScissor); + VK_FUNC(CmdDrawIndexed); + VK_FUNC(CmdBindIndexBuffer); VK_FUNC(CmdPushConstants); VK_FUNC(CmdCopyBufferToImage); diff --git a/code/vulkan/shaders/basic.frag b/code/vulkan/shaders/basic.frag index 0a4c210..ef0b53b 100644 --- a/code/vulkan/shaders/basic.frag +++ b/code/vulkan/shaders/basic.frag @@ -4,12 +4,12 @@ layout(location = 0) in vec2 frag_uv; layout(location = 1) in vec4 frag_c; -layout(location = 2) in flat uint idx; +layout(location = 2) in flat uint texid; layout(location = 0) out vec4 framebuffer; -layout(binding = 1) uniform sampler2D u_image[]; +layout(binding = 1) uniform sampler2D u_images[]; void main() { - framebuffer = frag_c * texture(u_image[idx], frag_uv); + framebuffer = frag_c * texture(u_images[texid], frag_uv); } diff --git a/code/vulkan/shaders/basic.vert b/code/vulkan/shaders/basic.vert index 2229ba6..9277166 100644 --- a/code/vulkan/shaders/basic.vert +++ b/code/vulkan/shaders/basic.vert @@ -2,6 +2,28 @@ #extension GL_EXT_scalar_block_layout : enable +uint indices[6] = { 0, 1, 3, 0, 3, 2 }; + +vec2 verticies[4] = vec2[]( + vec2(-0.5, -0.5), + vec2( 0.5, -0.5), + vec2(-0.5, 0.5), + vec2( 0.5, 0.5) +); + +struct G_Rect { + uint id; + + uint c[4]; + float uv[4]; + + float angle; + float x, y; + float w, h; + + float _pad0, _pad1; +}; + struct Vertex { vec4 p; vec2 uv; @@ -15,22 +37,28 @@ uniform Global { }; layout(binding = 0, scalar) -readonly buffer Vertices { - Vertex vtx[]; +readonly buffer Rect { + G_Rect rects[]; }; layout(location = 0) out vec2 frag_uv; layout(location = 1) out vec4 frag_c; -layout(location = 2) out flat uint idx; +layout(location = 2) out flat uint texid; + +vec4 unorm_colour(uint c) { + vec4 result = vec4((c >> 0) & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, (c >> 24) & 0xFF) / 255.0f; + return result; +} void main() { - Vertex v = vtx[gl_VertexIndex]; + G_Rect rect = rects[gl_InstanceIndex]; + uint idx = indices[gl_VertexIndex]; - gl_Position = proj * v.p; + vec2 p = (verticies[idx] * vec2(rect.w, rect.h)) + vec2(rect.x, rect.y); - frag_uv = v.uv; - frag_c = vec4((v.c >> 24) & 0xFF, (v.c >> 16) & 0xFF, (v.c >> 8) & 0xFF, (v.c >> 0) & 0xFF) / 255.0f; - frag_c = frag_c.abgr; + gl_Position = proj * vec4(p, 1.0f, 1.0f); - idx = v.pad; + frag_uv = vec2(rect.uv[(idx & 1) << 1], rect.uv[1 + (uint(idx / 2) << 1)]); + frag_c = unorm_colour(rect.c[idx]); + texid = rect.id; }