From 74e1a05790fc1faff6974274f59b29ebb223e2b3 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Mon, 14 Oct 2024 01:00:10 -0600 Subject: [PATCH] Got basic text pipeline working, want to minimize the amount of data transfered to GPU so that strings don't repeat so much data --- client/include/pipeline.h | 36 +++++++++-------- client/shader_src/ui_text.frag | 3 +- client/shader_src/ui_text.vert | 11 +++-- client/src/main.c | 74 ++++++++++++++++++++++++++++++++++ client/src/pipeline.c | 68 +++++++++++-------------------- client/src/render.c | 17 +++++++- 6 files changed, 140 insertions(+), 69 deletions(-) diff --git a/client/include/pipeline.h b/client/include/pipeline.h index 237f4f0..9bc48bc 100644 --- a/client/include/pipeline.h +++ b/client/include/pipeline.h @@ -30,10 +30,26 @@ typedef struct TextStruct { typedef struct FontUniformStruct { vec2 size; - uint32_t columns; + uint32_t cols; + uint32_t rows; uint32_t start; } FontUniform; +typedef struct FontDataStruct { + FontUniform info; + uint32_t* data; +} FontData; + +typedef struct FontDescriptorStruct { + VmaAllocation uniform_memory; + VmaAllocation image_memory; + VkBuffer uniform; + VkImage image; + VkImageView view; + VkSampler sampler; + VkDescriptorSet set; +} FontDescriptor; + typedef struct UILayerStruct { VkBuffer colored_rects; uint32_t colored_rect_count; @@ -44,15 +60,9 @@ typedef struct UILayerStruct { VkBuffer texts; uint32_t text_count; - VkDescriptorSet text_descriptor; + FontDescriptor font; } UILayer; -typedef struct FontDataStruct { - FontUniform info; - uint32_t rows; - vec4* data; -} FontData; - struct RectBuffer { VkBuffer vertex; VkBuffer index; @@ -71,14 +81,6 @@ typedef struct UIContextStruct { VkDescriptorPool font_pool; VkDescriptorSetLayout font_layout; - VmaAllocation test_font_uniform_memory; - VmaAllocation test_font_image_memory; - VkBuffer test_font_uniform; - VkImage test_font_image; - VkImageView test_font_view; - VkSampler test_font_sampler; - VkDescriptorSet test_font_set; - struct RectBuffer ui_rect; GraphicsPipeline ui_pipeline_rect; GraphicsPipeline ui_pipeline_text; @@ -86,4 +88,6 @@ typedef struct UIContextStruct { VkResult init_pipelines(VkDevice device, VmaAllocator allocator, VkExtent2D swapchain_extent, VkRenderPass render_pass, Queue transfer_queue, VkCommandPool transfer_pool, UIContext* context); +VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayout layout, VkDescriptorPool pool, FontData* font, VkCommandPool transfer_pool, Queue transfer_queue, FontDescriptor* descriptor); + #endif diff --git a/client/shader_src/ui_text.frag b/client/shader_src/ui_text.frag index 9955e64..7a0c0d6 100644 --- a/client/shader_src/ui_text.frag +++ b/client/shader_src/ui_text.frag @@ -8,7 +8,6 @@ layout(location = 1) in vec2 fragUV; layout(location = 0) out vec4 outColor; void main() { - outColor = vec4(fragUV, 0.0, 1.0); - //;fragColor * texture(font, fragUV); + outColor = fragColor * texture(font, fragUV); } diff --git a/client/shader_src/ui_text.vert b/client/shader_src/ui_text.vert index 1cabe9f..e7a8c87 100644 --- a/client/shader_src/ui_text.vert +++ b/client/shader_src/ui_text.vert @@ -5,8 +5,9 @@ layout(set = 0, binding = 0) uniform UIUniform { } ubo; layout(set = 1, binding = 0) uniform FontUniform { - vec2 font_size; - uint columns; + vec2 size; + uint cols; + uint rows; uint start; } font; @@ -20,8 +21,10 @@ layout(location = 0) out vec4 fragColor; layout(location = 1) out vec2 fragUV; void main() { - gl_Position = ubo.screen * vec4(vec3(inVertexPosition * inSize, 0.0) + inPosition, 1.0); - fragUV = inVertexPosition; + float row = floor(code/font.cols); + float col = code - row*font.cols; + fragUV = (vec2(col, row) + inVertexPosition) / vec2(font.cols, font.rows); fragColor = inColor; + gl_Position = ubo.screen * vec4(vec3(inVertexPosition * inSize, 0.0) + inPosition, 1.0); } diff --git a/client/src/main.c b/client/src/main.c index 1bf15c9..fdd4412 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -12,17 +12,42 @@ ColoredRect colored_rect(float width, float height, float r, float g, float b, f return rect; } +const uint32_t WHITE = 0xFFFFFFFF; +const uint32_t CLEAR = 0x00000000; +uint32_t test_font_data[] = { + WHITE, WHITE, CLEAR, WHITE, + CLEAR, CLEAR, WHITE, CLEAR, +}; + VkResult render_thread(GLFWwindow* window, RenderContext* render_context) { VkResult result; UIContext ui_context; VkBuffer colored_rect_buffer; + VkBuffer text_buffer; VmaAllocation colored_rect_memory; + VmaAllocation text_memory; result = init_pipelines(render_context->device, render_context->allocator, render_context->swapchain_extent, render_context->world_render_pass, render_context->transfer_queue, render_context->transfer_pool, &ui_context); if(result != VK_SUCCESS) { return result; } + FontData test_font = { + .info = { + .size = {2, 2}, + .start = 0, + .cols = 2, + .rows = 1, + }, + .data = test_font_data, + }; + + FontDescriptor test_font_descriptor; + result = create_text_descriptor(render_context->device, render_context->allocator, ui_context.font_layout, ui_context.font_pool, &test_font, render_context->transfer_pool, render_context->transfer_queue, &test_font_descriptor); + if(result != VK_SUCCESS) { + return result; + } + VkBufferCreateInfo colored_rect_buffer_info = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, @@ -52,9 +77,58 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render_context) { vmaUnmapMemory(render_context->allocator, colored_rect_memory); + VkBufferCreateInfo text_buffer_info = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + .size = 2*sizeof(Text), + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + + VmaAllocationCreateInfo text_memory_info = { + .usage = VMA_MEMORY_USAGE_CPU_TO_GPU, + }; + + result = vmaCreateBuffer(render_context->allocator, &text_buffer_info, &text_memory_info, &text_buffer, &text_memory, NULL); + if(result != VK_SUCCESS) { + return result; + } + + Text* text; + + result = vmaMapMemory(render_context->allocator, text_memory, (void**)&text); + if(result != VK_SUCCESS) { + return result; + } + + text[0].size[0] = 200.0f; + text[0].size[1] = 200.0f; + text[0].color[0] = 1.0f; + text[0].color[1] = 1.0f; + text[0].color[2] = 1.0f; + text[0].color[3] = 1.0f; + text[0].pos[0] = 200.0f; + text[0].pos[1] = 200.0f; + text[0].code = 0; + + text[1].size[0] = 200.0f; + text[1].size[1] = 200.0f; + text[1].color[0] = 1.0f; + text[1].color[1] = 1.0f; + text[1].color[2] = 1.0f; + text[1].color[3] = 1.0f; + text[1].pos[0] = 400.0f; + text[1].pos[1] = 200.0f; + text[1].code = 1; + + vmaUnmapMemory(render_context->allocator, text_memory); + UILayer test_layer = { .colored_rects = colored_rect_buffer, .colored_rect_count = 3, + + .font = test_font_descriptor, + .text_count = 2, + .texts = text_buffer, }; while(glfwWindowShouldClose(window) == 0) { diff --git a/client/src/pipeline.c b/client/src/pipeline.c index d0b1650..dc0f3a5 100644 --- a/client/src/pipeline.c +++ b/client/src/pipeline.c @@ -438,7 +438,7 @@ VkResult create_text_descriptor_pool(VkDevice device, uint32_t max_sets, VkDescr return VK_SUCCESS; } -VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayout layout, VkDescriptorPool pool, FontData* font, VkCommandPool transfer_pool, Queue transfer_queue, VmaAllocation* uniform_memory, VkBuffer* uniform, VmaAllocation* image_memory, VkImage* image, VkImageView* view, VkSampler* sampler, VkDescriptorSet* set) { +VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayout layout, VkDescriptorPool pool, FontData* font, VkCommandPool transfer_pool, Queue transfer_queue, FontDescriptor* descriptor) { VkResult result; VkDescriptorSetAllocateInfo set_allocate_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, @@ -447,7 +447,7 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr .descriptorPool = pool, }; - result = vkAllocateDescriptorSets(device, &set_allocate_info, set); + result = vkAllocateDescriptorSets(device, &set_allocate_info, &descriptor->set); if(result != VK_SUCCESS) { return result; } @@ -463,14 +463,14 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr .usage = VMA_MEMORY_USAGE_GPU_ONLY, }; - result = vmaCreateBuffer(allocator, &uniform_buffer_info, &uniform_memory_info, uniform, uniform_memory, NULL); + result = vmaCreateBuffer(allocator, &uniform_buffer_info, &uniform_memory_info, &descriptor->uniform, &descriptor->uniform_memory, NULL); VkImageCreateInfo image_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, .extent.depth = 1, - .extent.width = font->info.size[0]*font->info.columns, - .extent.height = font->info.size[1]*font->rows, + .extent.width = font->info.size[0]*font->info.cols, + .extent.height = font->info.size[1]*font->info.rows, .mipLevels = 1, .arrayLayers = 1, .format = VK_FORMAT_R8G8B8A8_SRGB, @@ -483,16 +483,17 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr .usage = VMA_MEMORY_USAGE_GPU_ONLY, }; - result = vmaCreateImage(allocator, &image_info, &image_memory_info, image, image_memory, NULL); + result = vmaCreateImage(allocator, &image_info, &image_memory_info, &descriptor->image, &descriptor->image_memory, NULL); if(result != VK_SUCCESS) { return result; } + uint32_t image_size = sizeof(uint32_t)*font->info.rows*font->info.size[0]*font->info.cols*font->info.size[1]; VkBufferCreateInfo staging_info = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .size = sizeof(FontUniform) + 4*image_info.extent.width*image_info.extent.height, + .size = sizeof(FontUniform) + image_size, }; VmaAllocationCreateInfo staging_memory_info = { @@ -511,22 +512,22 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr if(result != VK_SUCCESS) { return result; } - memcpy(mapped_staging, &font->info, sizeof(FontUniform)); - memcpy(mapped_staging + sizeof(FontUniform), font->data, 4*font->rows*font->info.columns); + memcpy(mapped_staging + image_size, &font->info, sizeof(FontUniform)); + memcpy(mapped_staging, font->data, image_size); vmaUnmapMemory(allocator, staging_memory); VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); VkBufferCopy copy_info = { .size = sizeof(FontUniform), - .srcOffset = 0, + .srcOffset = image_size, .dstOffset = 0, }; - vkCmdCopyBuffer(command_buffer, staging_buffer, *uniform, 1, ©_info); + vkCmdCopyBuffer(command_buffer, staging_buffer, descriptor->uniform, 1, ©_info); VkImageMemoryBarrier first_barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .image = *image, + .image = descriptor->image, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, @@ -543,13 +544,12 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr .imageSubresource.layerCount = 1, .imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .imageExtent = image_info.extent, - .bufferOffset = sizeof(FontUniform), }; - vkCmdCopyBufferToImage(command_buffer, staging_buffer, *image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); + vkCmdCopyBufferToImage(command_buffer, staging_buffer, descriptor->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); VkImageMemoryBarrier second_barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .image = *image, + .image = descriptor->image, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, @@ -570,7 +570,7 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr VkImageViewCreateInfo view_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .image = *image, + .image = descriptor->image, .viewType = VK_IMAGE_VIEW_TYPE_2D, .format = VK_FORMAT_R8G8B8A8_SRGB, .subresourceRange = { @@ -580,7 +580,7 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr .baseArrayLayer = 0, }, }; - result = vkCreateImageView(device, &view_info, NULL, view); + result = vkCreateImageView(device, &view_info, NULL, &descriptor->view); if(result != VK_SUCCESS) { return result; } @@ -593,7 +593,7 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT, .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT, }; - result = vkCreateSampler(device, &sampler_info, NULL, sampler); + result = vkCreateSampler(device, &sampler_info, NULL, &descriptor->sampler); if(result != VK_SUCCESS) { return result; } @@ -601,19 +601,19 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr VkDescriptorBufferInfo desc_uniform_info = { .offset = 0, .range = sizeof(FontUniform), - .buffer = *uniform, + .buffer = descriptor->uniform, }; VkDescriptorImageInfo desc_image_info = { - .sampler = *sampler, + .sampler = descriptor->sampler, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .imageView = *view, + .imageView = descriptor->view, }; VkWriteDescriptorSet descriptor_writes[] = { { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = *set, + .dstSet = descriptor->set, .dstBinding = 0, .dstArrayElement = 0, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, @@ -622,7 +622,7 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr }, { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = *set, + .dstSet = descriptor->set, .dstBinding = 1, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = 1, @@ -841,13 +841,6 @@ VkResult create_ui_rect_buffer(VkDevice device, Queue transfer_queue, VkCommandP return VK_SUCCESS; } -#define WHITE {1.0f, 1.0f, 1.0f, 1.0f} -#define CLEAR {0.0f, 0.0f, 0.0f, 0.0f} -vec4 test_font_data[] = { - WHITE, WHITE, CLEAR, WHITE, - CLEAR, CLEAR, WHITE, CLEAR, -}; - VkResult init_pipelines(VkDevice device, VmaAllocator allocator, VkExtent2D swapchain_extent, VkRenderPass render_pass, Queue transfer_queue, VkCommandPool transfer_pool, UIContext* context) { VkResult result; @@ -876,20 +869,5 @@ VkResult init_pipelines(VkDevice device, VmaAllocator allocator, VkExtent2D swap return result; } - FontData test_font = { - .info = { - .size = {4, 4}, - .start = 0, - .columns = 2, - }, - .rows = 1, - .data = test_font_data, - }; - - result = create_text_descriptor(device, allocator, context->font_layout, context->font_pool, &test_font, transfer_pool, transfer_queue, &context->test_font_uniform_memory, &context->test_font_uniform, &context->test_font_image_memory, &context->test_font_image, &context->test_font_view, &context->test_font_sampler, &context->test_font_set); - if(result != VK_SUCCESS) { - return result; - } - return VK_SUCCESS; } diff --git a/client/src/render.c b/client/src/render.c index 5306a6b..40a35d3 100644 --- a/client/src/render.c +++ b/client/src/render.c @@ -1016,8 +1016,21 @@ VkResult draw_frame(RenderContext* context, UIContext* ui_context, UILayer* ui_l vkCmdBindIndexBuffer(context->swapchain_command_buffers[context->current_frame], ui_context->ui_rect.index, 0, VK_INDEX_TYPE_UINT32); for(uint32_t i = 0; i < ui_layer_count; i++) { - vkCmdBindVertexBuffers(context->swapchain_command_buffers[context->current_frame], 1, 1, &ui_layers[i].colored_rects, &offset); - vkCmdDrawIndexed(context->swapchain_command_buffers[context->current_frame], 6, ui_layers[i].colored_rect_count, 0, 0, 0); + if(ui_layers[i].colored_rect_count > 0) { + vkCmdBindVertexBuffers(context->swapchain_command_buffers[context->current_frame], 1, 1, &ui_layers[i].colored_rects, &offset); + vkCmdDrawIndexed(context->swapchain_command_buffers[context->current_frame], 6, ui_layers[i].colored_rect_count, 0, 0, 0); + } + } + ///////////////////////////////////////////////////////// + // Draw UI text ///////////////////////////////////////// + vkCmdBindPipeline(context->swapchain_command_buffers[context->current_frame], VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->ui_pipeline_text.pipeline); + vkCmdBindDescriptorSets(context->swapchain_command_buffers[context->current_frame], VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->ui_pipeline_text.layout, 0, 1, &ui_context->ui_descriptor_set, 0, NULL); + for(uint32_t i = 0; i < ui_layer_count; i++) { + if(ui_layers[i].text_count > 0) { + vkCmdBindDescriptorSets(context->swapchain_command_buffers[context->current_frame], VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->ui_pipeline_text.layout, 1, 1, &ui_layers[i].font.set, 0, NULL); + vkCmdBindVertexBuffers(context->swapchain_command_buffers[context->current_frame], 1, 1, &ui_layers[i].texts, &offset); + vkCmdDrawIndexed(context->swapchain_command_buffers[context->current_frame], 6, ui_layers[i].text_count, 0, 0, 0); + } } /////////////////////////////////////////////////////////