Added rect draw api

Added some new maths types
Updated shaders to use new D_Rect structure
Added rect buffers to frames
Misc cleanup
This commit is contained in:
2025-10-05 14:27:05 +01:00
parent 3b8c50a361
commit 1757fc4b96
14 changed files with 432 additions and 121 deletions

View File

@@ -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, &copy);
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);