From 6129e9c5b98ad0220a48ef9c93e1e9a3f09d38e1 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Fri, 18 Oct 2024 14:26:41 -0600 Subject: [PATCH] Starting rework for GPU driven UI rendering --- client/include/render.h | 4 +- client/include/ui.h | 131 ++-- .../{ui_colored_rect.frag => ui_rect.frag} | 0 .../{ui_colored_rect.vert => ui_rect.vert} | 11 +- client/shader_src/ui_text.comp | 21 +- client/shader_src/ui_text.frag | 6 +- client/shader_src/ui_text.vert | 26 +- client/src/main.c | 148 +---- client/src/render.c | 88 +-- client/src/ui.c | 581 ++++++------------ 10 files changed, 347 insertions(+), 669 deletions(-) rename client/shader_src/{ui_colored_rect.frag => ui_rect.frag} (100%) rename client/shader_src/{ui_colored_rect.vert => ui_rect.vert} (71%) diff --git a/client/include/render.h b/client/include/render.h index f887dde..11ada1d 100644 --- a/client/include/render.h +++ b/client/include/render.h @@ -92,8 +92,8 @@ VkResult init_vulkan( VkResult draw_frame( RenderContext* context, - UIContext* ui_context, - UILayer* ui_layers, + UIContextStorage* ui_context, + UILayerStorage* ui_layers, uint32_t ui_layer_count); VkResult create_transfer_buffer( diff --git a/client/include/ui.h b/client/include/ui.h index 8cdb617..278b63e 100644 --- a/client/include/ui.h +++ b/client/include/ui.h @@ -19,20 +19,16 @@ typedef struct GraphicsPipelineStruct { VkPipeline pipeline; } GraphicsPipeline; -typedef struct ColoredRectStruct { +typedef struct UIRectStruct { vec3 pos; - uint32_t padding0; + float pad0; vec2 size; vec4 color; -} ColoredRect; - -typedef struct UIUniformStruct { - mat4 screen; -} UIUniform; +} UIRect; typedef struct StringStruct { vec3 pos; - uint32_t padding0; + float pad0; vec4 color; float size; uint32_t offset; @@ -46,27 +42,26 @@ typedef struct DrawCommandStruct { uint32_t first_instance; } DrawCommand; -typedef struct StringPointersStruct { - VkDeviceAddress strings; - VkDeviceAddress codes; - VkDeviceAddress characters; - VkDeviceAddress draw; -} StringPointers; +typedef struct DispatchCommandStruct { + uint32_t x; + uint32_t y; + uint32_t z; +} DispatchCommand; typedef struct CharacterStruct { vec3 pos; - uint32_t padding0; + float pad0; vec4 color; float size; uint32_t code; } Character; -typedef struct FontUniformStruct { +typedef struct FontStruct { uint32_t num_symbols; uint32_t width; uint32_t height; VkDeviceAddress symbol_list; -} FontUniform; +} Font; typedef struct SymbolInfoStruct { int32_t top; @@ -76,17 +71,15 @@ typedef struct SymbolInfoStruct { uint32_t advance; } SymbolInfo; -typedef struct FontStruct { +typedef struct FontStorageStruct { VmaAllocation symbol_memory; - VmaAllocation uniform_memory; VmaAllocation image_memory; - VkBuffer symbols; - VkBuffer uniform; - VkImage image; - VkImageView view; - VkSampler sampler; - VkDescriptorSet set; -} Font; + VkBuffer symbols; + VkImage image; + VkImageView view; + VkSampler sampler; + uint32_t index; +} FontStorage; typedef struct TextPointersMemoryStruct { VmaAllocation pointers_memory; @@ -102,46 +95,72 @@ typedef struct TextPointersMemoryStruct { VkBuffer characters_buffer; } TextPointersMemory; +typedef struct UIlayerStorageStruct { + VkBuffer strings; + VkBuffer chars; + VkBuffer codes; + VkBuffer rects; + VkBuffer layer; + + VmaAllocation strings_memory; + VmaAllocation rects_memory; + VmaAllocation chars_memory; + VmaAllocation codes_memory; + VmaAllocation layer_memory; + + VkDeviceAddress address; +} UILayerStorage; + typedef struct UILayerStruct { - VkDeviceAddress colored_rects; - uint32_t colored_rect_count; + VkDeviceAddress rects; + uint32_t rect_count; - VkBuffer string_draw; - VkBuffer chars; - VkDeviceAddress string_pointers; - uint32_t string_count; - uint32_t chars_count; - Font font; + VkDeviceAddress strings; + uint32_t font_index; + + DrawCommand draw_chars; + DrawCommand draw_rects; + DispatchCommand dispatch_strings; } UILayer; typedef struct UIContextStruct { - VkBuffer ui_descriptor_buffer; - VmaAllocation ui_descriptor_memory; - VkDescriptorSetLayout ui_descriptor_layout; - VkDescriptorPool ui_descriptor_pool; - VkDescriptorSet ui_descriptor_set; - - VkDescriptorPool font_pool; - VkDescriptorSetLayout font_layout; - - GraphicsPipeline ui_pipeline_rect; - GraphicsPipeline ui_pipeline_text; - ComputePipeline ui_compute_text; + mat4 screen; + VkDeviceAddress font_infos; } UIContext; -VkResult init_pipelines( +typedef struct UIContextStorageStruct { + VkDeviceAddress address; + + VkBuffer context; + + VmaAllocation context_memory; + + VkBuffer font_infos; + VmaAllocation font_infos_memory; + VkDescriptorSet font_samplers; + VkDescriptorSet font_textures; + VkDescriptorSetLayout font_samplers_layout; + VkDescriptorSetLayout font_textures_layout; + VkDescriptorPool fonts_pool; + + GraphicsPipeline rect_pipeline; + GraphicsPipeline char_pipeline; + ComputePipeline string_pipeline; +} UIContextStorage; + +VkResult create_ui_context( VkDevice device, VmaAllocator allocator, - VkExtent2D swapchain_extent, - vec2 window_scale, VkRenderPass render_pass, - UIContext* context); + UIContextStorage* memory); VkResult load_font( VkDevice device, VmaAllocator allocator, - VkDescriptorSetLayout layout, - VkDescriptorPool pool, + VkBuffer font_infos, + VkDescriptorSet font_samplers, + VkDescriptorSet font_textures, + uint32_t last_index, VkCommandPool transfer_pool, Queue transfer_queue, FT_Library library, @@ -149,16 +168,16 @@ VkResult load_font( uint32_t size, VkBool32 antialias, uint32_t** charmap, - Font* descriptor); + FontStorage* memory); -VkResult create_text_pointers( +VkResult create_layer( uint32_t max_strings, uint32_t max_characters, + uint32_t max_rects, VkDevice device, VmaAllocator allocator, VkCommandPool transfer_pool, Queue transfer_queue, - TextPointersMemory* memory, + UILayerStorage* memory, VkDeviceAddress* address); - #endif diff --git a/client/shader_src/ui_colored_rect.frag b/client/shader_src/ui_rect.frag similarity index 100% rename from client/shader_src/ui_colored_rect.frag rename to client/shader_src/ui_rect.frag diff --git a/client/shader_src/ui_colored_rect.vert b/client/shader_src/ui_rect.vert similarity index 71% rename from client/shader_src/ui_colored_rect.vert rename to client/shader_src/ui_rect.vert index 83db32e..4afbb78 100644 --- a/client/shader_src/ui_colored_rect.vert +++ b/client/shader_src/ui_rect.vert @@ -1,10 +1,6 @@ #version 450 #extension GL_EXT_buffer_reference : require -layout(set = 0, binding = 0) uniform UIUniform { - mat4 screen; -} ubo; - struct Rect { vec3 pos; vec2 size; @@ -15,7 +11,12 @@ layout(std430, buffer_reference) readonly buffer RectList { Rect r[]; }; +layout(std430, buffer_reference) readonly buffer ScreenInfo { + mat4 bounds; +}; + layout(std430, push_constant) uniform PushConstant { + ScreenInfo screen; RectList rects; } pc; @@ -32,7 +33,7 @@ const vec2 square[6] = { void main() { Rect rect = pc.rects.r[gl_InstanceIndex]; - gl_Position = ubo.screen * vec4(vec3(square[gl_VertexIndex] * rect.size, 0.0) + rect.pos.xyz, 1.0); + gl_Position = pc.screen.bounds * vec4(vec3(square[gl_VertexIndex] * rect.size, 0.0) + rect.pos.xyz, 1.0); fragColor = rect.color; } diff --git a/client/shader_src/ui_text.comp b/client/shader_src/ui_text.comp index 18d3816..5c527a8 100644 --- a/client/shader_src/ui_text.comp +++ b/client/shader_src/ui_text.comp @@ -1,7 +1,7 @@ #version 450 #extension GL_EXT_buffer_reference : require -struct Symbol { +layout(buffer_reference, std430) buffer Symbol { int top; uint left; uint width; @@ -9,14 +9,14 @@ struct Symbol { uint advance; }; -struct Character { +layout(buffer_reference, std430) buffer Character { vec3 pos; vec4 color; float size; uint code; }; -struct String { +layout(buffer_reference, std430) buffer String { vec3 pos; vec4 color; float size; @@ -40,12 +40,12 @@ layout(buffer_reference, std430) readonly buffer Strings{ String strings[]; }; -layout(set = 0, binding = 0) uniform Font { +layout(buffer_reference, std430) readonly buffer Font { uint num_symbols; uint width; uint height; SymbolList symbol_list; -} font; +}; layout(buffer_reference, std430) buffer DrawCommand { uint vertex_count; @@ -61,7 +61,17 @@ layout(buffer_reference, std430) readonly buffer Pointers { DrawCommand draw; }; +layout(buffer_reference, std430) readonly buffer FontList { + Font fonts[]; +}; + +layout(buffer_reference, std430) readonly buffer UIContext { + mat4 screen; + FontList fonts; +}; + layout(std430, push_constant) uniform Push { + UIContext ui; Pointers pointers; } push; @@ -70,6 +80,7 @@ layout(local_size_x = 1) in; void main() { uint gID = gl_GlobalInvocationID.x; String string = push.pointers.strings.strings[gID]; + Font font = push.ui.fonts.fonts[0]; uint buffer_pos = atomicAdd(push.pointers.draw.instance_count, string.len); float x = 0; diff --git a/client/shader_src/ui_text.frag b/client/shader_src/ui_text.frag index ec0421e..813decd 100644 --- a/client/shader_src/ui_text.frag +++ b/client/shader_src/ui_text.frag @@ -1,6 +1,8 @@ #version 450 +#extension GL_EXT_nonuniform_qualifier : enable -layout(set = 1, binding = 1) uniform sampler2DArray font; +layout(set = 0, binding = 0) uniform sampler font_samplers[]; +layout(set = 1, binding = 0) uniform texture2DArray font_textures[]; layout(location = 0) in vec4 fragColor; layout(location = 1) in vec2 fragUV; @@ -9,6 +11,6 @@ layout(location = 2) flat in uint code; layout(location = 0) out vec4 outColor; void main() { - outColor = fragColor * texture(font, vec3(fragUV, code)); + outColor = fragColor * texture(sampler2DArray(font_textures[0], font_samplers[0]), vec3(fragUV, code)); } diff --git a/client/shader_src/ui_text.vert b/client/shader_src/ui_text.vert index 533550f..4bebc20 100644 --- a/client/shader_src/ui_text.vert +++ b/client/shader_src/ui_text.vert @@ -1,7 +1,7 @@ #version 450 #extension GL_EXT_buffer_reference : require -struct Symbol { +layout(buffer_reference, std430) buffer Symbol { int top; uint left; uint width; @@ -9,7 +9,7 @@ struct Symbol { uint advance; }; -struct Character { +layout(buffer_reference, std430) buffer Character { vec3 pos; vec4 color; float size; @@ -24,23 +24,30 @@ layout(buffer_reference, std430) readonly buffer CharacterList{ Character characters[]; }; -layout(set = 0, binding = 0) uniform UIUniform { - mat4 screen; -} ubo; - -layout(set = 1, binding = 0) uniform Font { +layout(buffer_reference, std430) readonly buffer Font { uint num_symbols; uint width; uint height; SymbolList symbol_list; -} font; +}; layout(buffer_reference, std430) readonly buffer Pointers { uint padding[4]; CharacterList characters; + +}; + +layout(buffer_reference, std430) readonly buffer FontList { + Font fonts[]; +}; + +layout(buffer_reference, std430) readonly buffer UIContext { + mat4 screen; + FontList fonts; }; layout(std430, push_constant) uniform Push { + UIContext ui; Pointers pointers; } push; @@ -59,6 +66,7 @@ const vec2 square[6] = { void main() { Character character = push.pointers.characters.characters[gl_InstanceIndex]; + Font font = push.ui.fonts.fonts[0]; Symbol symbol = font.symbol_list.symbols[character.code]; float fragU = square[gl_VertexIndex].x * symbol.width/font.width; @@ -68,7 +76,7 @@ void main() { fragUV = vec2(fragU, fragV); fragColor = character.color; - gl_Position = ubo.screen * vec4(vec3(x, y, 0.0) + character.pos, 1.0); + gl_Position = push.ui.screen * vec4(vec3(x, y, 0.0) + character.pos, 1.0); code = character.code; } diff --git a/client/src/main.c b/client/src/main.c index 6a0051b..a7df5d6 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -10,168 +10,42 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render_context) { VkResult result; - UIContext ui_context; - VkBuffer colored_rect_buffer; - VmaAllocation colored_rect_memory; - - result = init_pipelines(render_context->device, render_context->allocator, render_context->swapchain_extent, render_context->window_scale, render_context->render_pass, &ui_context); - if(result != VK_SUCCESS) { - return result; - } - + UIContextStorage ui; FT_Library library; - if(FT_Init_FreeType(&library) != FT_Err_Ok) { - return VK_ERROR_UNKNOWN; - } - - Font test_font; + FontStorage font; uint32_t* charmap; - result = load_font(render_context->device, render_context->allocator, ui_context.font_layout, ui_context.font_pool, render_context->transfer_pool, render_context->transfer_queue, library, "test.ttf", 16, VK_TRUE, &charmap, &test_font); - if(result != VK_SUCCESS) { - return result; - } - - VkBufferCreateInfo colored_rect_buffer_info = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, - .size = 3*sizeof(ColoredRect), - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }; - - VmaAllocationCreateInfo colored_rect_memory_info = { - .usage = VMA_MEMORY_USAGE_CPU_TO_GPU, - }; + VkBuffer temp_buffer; + VmaAllocation temp_memory; + void* mapped; + UILayerStorage layer = {}; - result = vmaCreateBuffer(render_context->allocator, &colored_rect_buffer_info, &colored_rect_memory_info, &colored_rect_buffer, &colored_rect_memory, NULL); + result = create_ui_context(render_context->device, render_context->allocator, render_context->render_pass, &ui); if(result != VK_SUCCESS) { return result; } - ColoredRect* colored_rects; - - result = vmaMapMemory(render_context->allocator, colored_rect_memory, (void**)&colored_rects); - if(result != VK_SUCCESS) { - return result; + if(FT_Init_FreeType(&library) != FT_Err_Ok) { + return VK_ERROR_UNKNOWN; } - colored_rects[0].pos[0] = 0.0; - colored_rects[0].pos[1] = 0.0; - colored_rects[0].pos[2] = 0.5; - colored_rects[0].size[0] = 100.0; - colored_rects[0].size[1] = 100.0; - colored_rects[0].color[0] = 1.0; - colored_rects[0].color[1] = 0.0; - colored_rects[0].color[2] = 0.0; - colored_rects[0].color[3] = 1.0; - - colored_rects[1].pos[0] = 0.0; - colored_rects[1].pos[1] = 100.0; - colored_rects[1].pos[2] = 0.5; - colored_rects[1].size[0] = 100.0; - colored_rects[1].size[1] = 100.0; - colored_rects[1].color[0] = 0.0; - colored_rects[1].color[1] = 0.0; - colored_rects[1].color[2] = 1.0; - colored_rects[1].color[3] = 1.0; - - colored_rects[2].pos[0] = 100.0; - colored_rects[2].pos[1] = 0.0; - colored_rects[2].pos[2] = 0.5; - colored_rects[2].size[0] = 100.0; - colored_rects[2].size[1] = 100.0; - colored_rects[2].color[0] = 0.0; - colored_rects[2].color[1] = 1.0; - colored_rects[2].color[2] = 0.0; - colored_rects[2].color[3] = 1.0; - - - vmaUnmapMemory(render_context->allocator, colored_rect_memory); - - TextPointersMemory text_pointers; - VkDeviceAddress text_pointers_address; - result = create_text_pointers(2, 100, render_context->device, render_context->allocator, render_context->transfer_pool, render_context->transfer_queue, &text_pointers, &text_pointers_address); + result = load_font(render_context->device, render_context->allocator, ui.font_infos, ui.font_samplers, ui.font_textures, 0, render_context->transfer_pool, render_context->transfer_queue, library, "test.ttf", 16, VK_TRUE, &charmap, &font); if(result != VK_SUCCESS) { return result; } - VkBuffer temp_buffer; - VmaAllocation temp_memory; - void* mapped; result = create_transfer_buffer(2*sizeof(String) + 100*sizeof(uint32_t), render_context->allocator, &temp_buffer, &temp_memory, (void**)&mapped); if(result != VK_SUCCESS) { return result; } - String* mapped_strings = (String*)mapped; - mapped_strings[0].pos[0] = 0; - mapped_strings[0].pos[1] = 200.0; - mapped_strings[0].pos[2] = 0.2; - mapped_strings[0].color[0] = 1.0; - mapped_strings[0].color[1] = 1.0; - mapped_strings[0].color[2] = 1.0; - mapped_strings[0].color[3] = 1.0; - mapped_strings[0].size = 50.0; - mapped_strings[0].length = 50; - mapped_strings[0].offset = 0; - - mapped_strings[1].pos[0] = 0; - mapped_strings[1].pos[1] = 225.0; - mapped_strings[1].pos[2] = 0.3; - mapped_strings[1].color[0] = 1.0; - mapped_strings[1].color[1] = 1.0; - mapped_strings[1].color[2] = 1.0; - mapped_strings[1].color[3] = 1.0; - mapped_strings[1].size = 50.0; - mapped_strings[1].length = 50; - mapped_strings[1].offset = 50; - - uint32* mapped_codes = (uint32_t*)(mapped + 2*sizeof(String)); - for(uint32_t i = 0; i < 100; i++) { - mapped_codes[i] = i; - } - - VkCommandBuffer command_buffer = command_begin_single(render_context->device, render_context->transfer_pool); - VkBufferCopy copy_string = { - .size = 2*sizeof(String), - .srcOffset = 0, - }; - vkCmdCopyBuffer(command_buffer, temp_buffer, text_pointers.strings_buffer, 1, ©_string); - VkBufferCopy copy_codes = { - .size = 100*sizeof(uint32_t), - .srcOffset = 2*sizeof(String), - }; - vkCmdCopyBuffer(command_buffer, temp_buffer, text_pointers.codes_buffer, 1, ©_codes); - result = command_end_single(render_context->device, command_buffer, render_context->transfer_pool, render_context->transfer_queue); - if(result != VK_SUCCESS) { - return result; - } - vkQueueWaitIdle(render_context->transfer_queue.handle); vmaUnmapMemory(render_context->allocator, temp_memory); vmaDestroyBuffer(render_context->allocator, temp_buffer, temp_memory); - - VkBufferDeviceAddressInfo colored_rect_address_info = { - .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, - .buffer = colored_rect_buffer, - }; - - UILayer test_layer = { - .colored_rects = vkGetBufferDeviceAddress(render_context->device, &colored_rect_address_info), - .colored_rect_count = 3, - - .font = test_font, - .chars = text_pointers.characters_buffer, - .string_count = 2, - .chars_count = 100, - .string_pointers = text_pointers_address, - .string_draw = text_pointers.draw_buffer, - }; - while(glfwWindowShouldClose(window) == 0) { glfwPollEvents(); - result = draw_frame(render_context, &ui_context, &test_layer, 1); + result = draw_frame(render_context, &ui, &layer, 1); if(result != VK_SUCCESS) { fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result)); return result; diff --git a/client/src/render.c b/client/src/render.c index 6373135..a00a2bc 100644 --- a/client/src/render.c +++ b/client/src/render.c @@ -344,6 +344,7 @@ VkResult create_logical_device(VkPhysicalDevice physical_device, VkSurfaceKHR su VkPhysicalDeviceVulkan12Features features_12 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, .bufferDeviceAddress = VK_TRUE, + .runtimeDescriptorArray = VK_TRUE, .descriptorIndexing = VK_TRUE, .descriptorBindingPartiallyBound = VK_TRUE, .descriptorBindingVariableDescriptorCount = VK_TRUE, @@ -976,7 +977,7 @@ VkResult init_vulkan(GLFWwindow* window, RenderContext* context) { return VK_SUCCESS; } -VkResult draw_frame(RenderContext* context, UIContext* ui_context, UILayer* ui_layers, uint32_t ui_layer_count) { +VkResult draw_frame(RenderContext* context, UIContextStorage* ui_context, UILayerStorage* ui_layers, uint32_t ui_layer_count) { VkResult result; result = vkWaitForFences(context->device, 1, &context->in_flight_fences[context->current_frame], VK_TRUE, UINT64_MAX); @@ -996,7 +997,6 @@ VkResult draw_frame(RenderContext* context, UIContext* ui_context, UILayer* ui_l return result; } - result = vkResetCommandBuffer(command_buffer, 0); if(result != VK_SUCCESS) { return result; @@ -1035,82 +1035,32 @@ VkResult draw_frame(RenderContext* context, UIContext* ui_context, UILayer* ui_l .pClearValues = clear_values, }; - // UI strings compute pass - vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, ui_context->ui_compute_text.pipeline); - for(uint32_t i = 0; i < ui_layer_count; i ++) { - if(ui_layers[i].string_count > 0) { - VkBufferMemoryBarrier draw_barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .size = sizeof(DrawCommand), - .buffer = ui_layers[i].string_draw, - .srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT, - .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - }; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 1, &draw_barrier, 0, NULL); - vkCmdFillBuffer(command_buffer, ui_layers[i].string_draw, offsetof(DrawCommand, instance_count), sizeof(uint32_t), 0); - VkBufferMemoryBarrier clear_barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .size = sizeof(uint32_t), - .offset = offsetof(DrawCommand, instance_count), - .buffer = ui_layers[i].string_draw, - .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, - }; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 1, &clear_barrier, 0, NULL); - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, ui_context->ui_compute_text.layout, 0, 1, &ui_layers[i].font.set, 0, NULL); - vkCmdPushConstants(command_buffer, ui_context->ui_pipeline_text.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0, 8, &ui_layers[i].string_pointers); - vkCmdDispatch(command_buffer, ui_layers[i].string_count, 1, 1); - - VkBufferMemoryBarrier character_compute_barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .size = ui_layers[i].chars_count, - .buffer = ui_layers[i].chars, - .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, - .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, - }; - VkBufferMemoryBarrier draw_compute_barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .size = sizeof(DrawCommand), - .buffer = ui_layers[i].string_draw, - .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, - .dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT, - }; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 1, &character_compute_barrier, 0, NULL); - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 1, &draw_compute_barrier, 0, NULL); - } + VkDeviceAddress push[2] = {ui_context->address, 0}; + + // Compute Pass + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, ui_context->string_pipeline.pipeline); + for(uint32_t i = 0; i < ui_layer_count; i++) { + push[1] = ui_layers[i].address; + vkCmdPushConstants(command_buffer, ui_context->string_pipeline.layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 16, push); + vkCmdDispatchIndirect(command_buffer, ui_layers[i].layer, offsetof(UILayer, dispatch_strings)); } + // Render Pass vkCmdBeginRenderPass(command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); // World subpass - vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE); // UI subpass - - // Draw UI colored rects //////////////////////////////// - vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->ui_pipeline_rect.pipeline); - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->ui_pipeline_rect.layout, 0, 1, &ui_context->ui_descriptor_set, 0, NULL); - - for(uint32_t i = 0; i < ui_layer_count; i++) { - if(ui_layers[i].colored_rect_count > 0) { - vkCmdPushConstants(command_buffer, ui_context->ui_pipeline_rect.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 8, &ui_layers[i].colored_rects); - vkCmdDraw(command_buffer, 6, ui_layers[i].colored_rect_count, 0, 0); - } - } - ///////////////////////////////////////////////////////// - // Draw UI text ///////////////////////////////////////// - vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->ui_pipeline_text.pipeline); - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->ui_pipeline_text.layout, 0, 1, &ui_context->ui_descriptor_set, 0, NULL); + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->rect_pipeline.layout, 0, 1, &ui_context->font_samplers, 0, NULL); + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->rect_pipeline.layout, 1, 1, &ui_context->font_textures, 0, NULL); for(uint32_t i = 0; i < ui_layer_count; i++) { - if(ui_layers[i].string_count > 0) { - // Bind Font Descriptor - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->ui_pipeline_text.layout, 1, 1, &ui_layers[i].font.set, 0, NULL); - // Push pointers - vkCmdPushConstants(command_buffer, ui_context->ui_pipeline_text.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0, 8, &ui_layers[i].string_pointers); - vkCmdDrawIndirect(command_buffer, ui_layers[i].string_draw, 0, 1, sizeof(DrawCommand)); - } + push[1] = ui_layers[i].address; + vkCmdPushConstants(command_buffer, ui_context->rect_pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 16, push); + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->rect_pipeline.pipeline); + vkCmdDrawIndirect(command_buffer, ui_layers[i].layer, offsetof(UILayer, draw_rects), 1, 0); + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->char_pipeline.pipeline); + vkCmdDrawIndirect(command_buffer, ui_layers[i].layer, offsetof(UILayer, draw_chars), 1, 0); } - ///////////////////////////////////////////////////////// vkCmdEndRenderPass(command_buffer); diff --git a/client/src/ui.c b/client/src/ui.c index 30b67bc..3db8c14 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -53,14 +53,33 @@ VkShaderModule load_shader_file(const char* path, VkDevice device) { VkResult create_ui_pipeline( VkDevice device, VkRenderPass render_pass, + VkDescriptorSetLayout font_samplers_layout, + VkDescriptorSetLayout font_textures_layout, VkPipelineShaderStageCreateInfo* shader_stages, uint32_t shader_stage_count, VkPipelineVertexInputStateCreateInfo input_info, - VkPipelineLayoutCreateInfo layout_info, VkPipelineInputAssemblyStateCreateInfo input_assembly_info, GraphicsPipeline* pipeline) { VkResult result; + VkPushConstantRange push_constants[] = { + { + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + .size = 16, + .offset = 0, + }, + }; + + VkDescriptorSetLayout set_layouts[] = {font_samplers_layout, font_textures_layout}; + + VkPipelineLayoutCreateInfo layout_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pushConstantRangeCount = sizeof(push_constants)/sizeof(VkPushConstantRange), + .pPushConstantRanges = push_constants, + .setLayoutCount = sizeof(set_layouts)/sizeof(VkDescriptorSetLayout), + .pSetLayouts = set_layouts, + }; + result = vkCreatePipelineLayout(device, &layout_info, 0, &pipeline->layout); if(result != VK_SUCCESS) { return result; @@ -176,12 +195,12 @@ VkResult create_ui_pipeline( return VK_SUCCESS; } -VkResult create_ui_colored_rect_pipeline(VkDevice device, VkRenderPass render_pass, VkDescriptorSetLayout ui_descriptor_layout, GraphicsPipeline* pipeline) { - VkShaderModule vert_shader = load_shader_file("shader_src/ui_colored_rect.vert.spv", device); +VkResult create_ui_rect_pipeline(VkDevice device, VkRenderPass render_pass, VkDescriptorSetLayout font_samplers_layout, VkDescriptorSetLayout font_textures_layout, GraphicsPipeline* pipeline) { + VkShaderModule vert_shader = load_shader_file("shader_src/ui_rect.vert.spv", device); if(vert_shader == VK_NULL_HANDLE) { return VK_ERROR_UNKNOWN; } - VkShaderModule frag_shader = load_shader_file("shader_src/ui_colored_rect.frag.spv", device); + VkShaderModule frag_shader = load_shader_file("shader_src/ui_rect.frag.spv", device); if(frag_shader == VK_NULL_HANDLE) { return VK_ERROR_UNKNOWN; } @@ -210,26 +229,13 @@ VkResult create_ui_colored_rect_pipeline(VkDevice device, VkRenderPass render_pa .vertexAttributeDescriptionCount = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription), }; - VkPushConstantRange push_constant = { - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - .size = 8, - }; - - VkPipelineLayoutCreateInfo layout_info = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = 1, - .pSetLayouts = &ui_descriptor_layout, - .pPushConstantRanges = &push_constant, - .pushConstantRangeCount = 1, - }; - VkPipelineInputAssemblyStateCreateInfo input_assembly_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, .primitiveRestartEnable = VK_FALSE, }; - VkResult result = create_ui_pipeline(device, render_pass, shader_stages, sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo), input_info, layout_info, input_assembly_info, pipeline); + VkResult result = create_ui_pipeline(device, render_pass, font_samplers_layout, font_textures_layout, shader_stages, sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo), input_info, input_assembly_info, pipeline); if(result != VK_SUCCESS) { return result; } @@ -237,7 +243,7 @@ VkResult create_ui_colored_rect_pipeline(VkDevice device, VkRenderPass render_pa return VK_SUCCESS; } -VkResult create_ui_text_pipeline(VkDevice device, VkRenderPass render_pass, VkDescriptorSetLayout ui_descriptor_layout, VkDescriptorSetLayout font_layout, GraphicsPipeline* pipeline, ComputePipeline* compute) { +VkResult create_ui_text_pipeline(VkDevice device, VkRenderPass render_pass, VkDescriptorSetLayout font_samplers_layout, VkDescriptorSetLayout font_textures_layout, GraphicsPipeline* pipeline, ComputePipeline* compute) { VkResult result; VkShaderModule compute_shader = load_shader_file("shader_src/ui_text.comp.spv", device); if(compute_shader == VK_NULL_HANDLE) { @@ -252,18 +258,14 @@ VkResult create_ui_text_pipeline(VkDevice device, VkRenderPass render_pass, VkDe }; VkPushConstantRange push_constant = { - .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_VERTEX_BIT, - .size = 8, + .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, + .size = 16, }; - VkDescriptorSetLayout compute_descriptors[] = {font_layout}; - VkPipelineLayoutCreateInfo compute_layout_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .pushConstantRangeCount = 1, .pPushConstantRanges = &push_constant, - .setLayoutCount = sizeof(compute_descriptors)/sizeof(VkDescriptorSetLayout), - .pSetLayouts = compute_descriptors, }; result = vkCreatePipelineLayout(device, &compute_layout_info, NULL, &compute->layout); @@ -320,23 +322,13 @@ VkResult create_ui_text_pipeline(VkDevice device, VkRenderPass render_pass, VkDe .vertexAttributeDescriptionCount = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription), }; - VkDescriptorSetLayout all_layouts[] = {ui_descriptor_layout, font_layout}; - - VkPipelineLayoutCreateInfo layout_info = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = sizeof(all_layouts)/sizeof(VkDescriptorSetLayout), - .pSetLayouts = all_layouts, - .pPushConstantRanges = &push_constant, - .pushConstantRangeCount = 1, - }; - VkPipelineInputAssemblyStateCreateInfo input_assembly_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, .primitiveRestartEnable = VK_FALSE, }; - result = create_ui_pipeline(device, render_pass, shader_stages, sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo), input_info, layout_info, input_assembly_info, pipeline); + result = create_ui_pipeline(device, render_pass, font_samplers_layout, font_textures_layout, shader_stages, sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo), input_info, input_assembly_info, pipeline); if(result != VK_SUCCESS) { return result; } @@ -344,219 +336,36 @@ VkResult create_ui_text_pipeline(VkDevice device, VkRenderPass render_pass, VkDe return VK_SUCCESS; } -VkResult create_font_descriptor_pools(VkDevice device, uint32_t max_sets, VkDescriptorPool* font_pool, VkDescriptorSetLayout* font_layout) { - VkResult result; - VkDescriptorPoolSize font_pool_sizes[] = { - { - .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1, - }, - { - .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1, - }, - }; - - VkDescriptorPoolCreateInfo font_pool_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .pPoolSizes = font_pool_sizes, - .poolSizeCount = sizeof(font_pool_sizes)/sizeof(VkDescriptorPoolSize), - .maxSets = max_sets, - }; - - result = vkCreateDescriptorPool(device, &font_pool_info, NULL, font_pool); - if(result != VK_SUCCESS) { - return result; - } - - VkDescriptorSetLayoutBinding font_descriptor_bindings[] = { - { - .binding = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT, - }, - { - .binding = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - }, - }; - - VkDescriptorSetLayoutCreateInfo font_descriptor_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .pBindings = font_descriptor_bindings, - .bindingCount = sizeof(font_descriptor_bindings)/sizeof(VkDescriptorSetLayoutBinding), - }; - - result = vkCreateDescriptorSetLayout(device, &font_descriptor_info, NULL, font_layout); - if(result != VK_SUCCESS) { - return result; - } - - return VK_SUCCESS; -} - -VkResult create_text_pointers( +VkResult create_layer( uint32_t max_strings, uint32_t max_characters, + uint32_t max_rects, VkDevice device, VmaAllocator allocator, VkCommandPool transfer_pool, Queue transfer_queue, - TextPointersMemory* memory, + UILayerStorage* memory, VkDeviceAddress* address) { VkResult result; - VmaAllocationCreateInfo memory_info = { - .usage = VMA_MEMORY_USAGE_GPU_ONLY, - }; - - VkBufferCreateInfo pointers_info = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = sizeof(StringPointers), - .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }; - - result = vmaCreateBuffer(allocator, &pointers_info, &memory_info, &memory->pointers_buffer, &memory->pointers_memory, NULL); - if(result != VK_SUCCESS) { - return result; - } - - VkBufferCreateInfo draw_info = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = sizeof(DrawCommand), - .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }; - - result = vmaCreateBuffer(allocator, &draw_info, &memory_info, &memory->draw_buffer, &memory->draw_memory, NULL); - if(result != VK_SUCCESS) { - return result; - } - - VkBufferCreateInfo strings_info = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = max_strings*sizeof(String), - .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }; - - result = vmaCreateBuffer(allocator, &strings_info, &memory_info, &memory->strings_buffer, &memory->strings_memory, NULL); - if(result != VK_SUCCESS) { - return result; - } - - VkBufferCreateInfo codes_info = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = max_characters*sizeof(DrawCommand), - .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }; - - result = vmaCreateBuffer(allocator, &codes_info, &memory_info, &memory->codes_buffer, &memory->codes_memory, NULL); - if(result != VK_SUCCESS) { - return result; - } - - VkBufferCreateInfo characters_info = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = max_characters*sizeof(DrawCommand), - .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }; - - result = vmaCreateBuffer(allocator, &characters_info, &memory_info, &memory->characters_buffer, &memory->characters_memory, NULL); - if(result != VK_SUCCESS) { - return result; - } - - VkBufferDeviceAddressInfo pointers_address = { - .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, - .buffer = memory->pointers_buffer, - }; - - VkBufferDeviceAddressInfo strings_address = { - .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, - .buffer = memory->strings_buffer, - }; - - VkBufferDeviceAddressInfo codes_address = { - .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, - .buffer = memory->codes_buffer, - }; - - VkBufferDeviceAddressInfo characters_address = { - .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, - .buffer = memory->characters_buffer, - }; - - VkBufferDeviceAddressInfo draw_address = { - .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, - .buffer = memory->draw_buffer, - }; - - VkBuffer temp_buffer; - VmaAllocation temp_memory; - VkBufferCreateInfo temp_buffer_info = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .size = sizeof(StringPointers) + - sizeof(DrawCommand), - }; - VmaAllocationCreateInfo temp_memory_info = { - .usage = VMA_MEMORY_USAGE_CPU_TO_GPU, - }; - result = vmaCreateBuffer(allocator, &temp_buffer_info, &temp_memory_info, &temp_buffer, &temp_memory, NULL); - if(result != VK_SUCCESS) { - return result; - } - - void* mapped; - result = vmaMapMemory(allocator, temp_memory, &mapped); - if(result != VK_SUCCESS) { - return result; - } - - DrawCommand draw = { - .vertex_count = 6, - }; - - memcpy(mapped + 0, &draw, sizeof(DrawCommand)); - StringPointers pointers = { - .strings = vkGetBufferDeviceAddress(device, &strings_address), - .codes = vkGetBufferDeviceAddress(device, &codes_address), - .characters = vkGetBufferDeviceAddress(device, &characters_address), - .draw = vkGetBufferDeviceAddress(device, &draw_address), - }; - memcpy(mapped + sizeof(DrawCommand), &pointers, sizeof(StringPointers)); - vmaUnmapMemory(allocator, temp_memory); - - VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); - VkBufferCopy copy_draw = { - .size = sizeof(DrawCommand), - .srcOffset = 0, - }; - vkCmdCopyBuffer(command_buffer, temp_buffer, memory->draw_buffer, 1, ©_draw); - VkBufferCopy copy_pointers = { - .size = sizeof(StringPointers), - .srcOffset = sizeof(DrawCommand), - }; - vkCmdCopyBuffer(command_buffer, temp_buffer, memory->pointers_buffer, 1, ©_pointers); - result = command_end_single(device, command_buffer, transfer_pool, transfer_queue); - if(result != VK_SUCCESS) { - return result; - } - vmaDestroyBuffer(allocator, temp_buffer, temp_memory); - *address = vkGetBufferDeviceAddress(device, &pointers_address); - return VK_SUCCESS; } -VkResult load_font(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayout layout, VkDescriptorPool pool,VkCommandPool transfer_pool, Queue transfer_queue, FT_Library library, const char* ttf_file, uint32_t size, VkBool32 antialias, uint32_t** charmap, Font* descriptor) { +VkResult load_font( + VkDevice device, + VmaAllocator allocator, + VkBuffer font_infos, + VkDescriptorSet font_samplers, + VkDescriptorSet font_textures, + uint32_t index, + VkCommandPool transfer_pool, + Queue transfer_queue, + FT_Library library, + const char* ttf_file, + uint32_t size, + VkBool32 antialias, + uint32_t** charmap, + FontStorage* memory) { FT_Face face; int error; @@ -572,7 +381,7 @@ VkResult load_font(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayou uint32_t* tmp_charmap = malloc(sizeof(uint32_t)*face->num_glyphs); SymbolInfo* symbols = malloc(sizeof(SymbolInfo)*face->num_glyphs); - FontUniform uniform; + Font info; uint32_t glyph_index; uint32_t max_height = 0; @@ -607,9 +416,9 @@ VkResult load_font(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayou c = FT_Get_Next_Char(face, c, &glyph_index); } - uniform.width = max_width; - uniform.height = max_height; - uniform.num_symbols = symbol_count; + info.width = max_width; + info.height = max_height; + info.num_symbols = symbol_count; uint32_t image_size = max_width*max_height*sizeof(uint32_t); uint32_t* images = malloc(image_size*symbol_count); memset(images, 0x00, image_size*symbol_count); @@ -636,53 +445,29 @@ VkResult load_font(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayou } VkResult result; - VkDescriptorSetAllocateInfo set_allocate_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .pSetLayouts = &layout, - .descriptorSetCount = 1, - .descriptorPool = pool, - }; - - result = vkAllocateDescriptorSets(device, &set_allocate_info, &descriptor->set); - if(result != VK_SUCCESS) { - return result; - } - VkBufferCreateInfo symbol_buffer_info = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .size = sizeof(SymbolInfo)*uniform.num_symbols, + .size = sizeof(SymbolInfo)*info.num_symbols, }; VmaAllocationCreateInfo symbol_memory_info = { .usage = VMA_MEMORY_USAGE_GPU_ONLY, }; - result = vmaCreateBuffer(allocator, &symbol_buffer_info, &symbol_memory_info, &descriptor->symbols, &descriptor->symbol_memory, NULL); + result = vmaCreateBuffer(allocator, &symbol_buffer_info, &symbol_memory_info, &memory->symbols, &memory->symbol_memory, NULL); if(result != VK_SUCCESS) { return result; } - VkBufferCreateInfo uniform_buffer_info = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - .size = sizeof(FontUniform), - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }; - - VmaAllocationCreateInfo uniform_memory_info = { - .usage = VMA_MEMORY_USAGE_GPU_ONLY, - }; - - 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 = uniform.width, - .extent.height = uniform.height, + .extent.width = info.width, + .extent.height = info.height, .mipLevels = 1, - .arrayLayers = uniform.num_symbols, + .arrayLayers = info.num_symbols, .format = VK_FORMAT_R8G8B8A8_SRGB, .tiling = VK_IMAGE_TILING_OPTIMAL, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, @@ -694,7 +479,7 @@ VkResult load_font(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayou .usage = VMA_MEMORY_USAGE_GPU_ONLY, }; - result = vmaCreateImage(allocator, &image_info, &image_memory_info, &descriptor->image, &descriptor->image_memory, NULL); + result = vmaCreateImage(allocator, &image_info, &image_memory_info, &memory->image, &memory->image_memory, NULL); if(result != VK_SUCCESS) { return result; } @@ -703,7 +488,7 @@ VkResult load_font(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayou .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .size = sizeof(FontUniform) + image_size*uniform.num_symbols + sizeof(SymbolInfo)*uniform.num_symbols, + .size = sizeof(Font) + image_size*info.num_symbols + sizeof(SymbolInfo)*info.num_symbols, }; VmaAllocationCreateInfo staging_memory_info = { @@ -722,66 +507,66 @@ VkResult load_font(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayou if(result != VK_SUCCESS) { return result; } - memcpy(mapped_staging + image_size*uniform.num_symbols + sizeof(FontUniform), symbols, sizeof(SymbolInfo)*uniform.num_symbols); + memcpy(mapped_staging + image_size*info.num_symbols + sizeof(Font), symbols, sizeof(SymbolInfo)*info.num_symbols); VkBufferDeviceAddressInfo address_info = { .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, - .buffer = descriptor->symbols, + .buffer = memory->symbols, }; - uniform.symbol_list = vkGetBufferDeviceAddress(device, &address_info); - memcpy(mapped_staging + image_size*uniform.num_symbols, &uniform, sizeof(FontUniform)); - memcpy(mapped_staging, images, image_size*uniform.num_symbols); + info.symbol_list = vkGetBufferDeviceAddress(device, &address_info); + memcpy(mapped_staging + image_size*info.num_symbols, &info, sizeof(Font)); + memcpy(mapped_staging, images, image_size*info.num_symbols); vmaUnmapMemory(allocator, staging_memory); free(images); free(symbols); VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); - VkBufferCopy uniform_copy_info = { - .size = sizeof(FontUniform), - .srcOffset = image_size*uniform.num_symbols, - .dstOffset = 0, + VkBufferCopy info_copy = { + .size = sizeof(Font), + .srcOffset = image_size*info.num_symbols, + .dstOffset = index*sizeof(Font), }; - vkCmdCopyBuffer(command_buffer, staging_buffer, descriptor->uniform, 1, &uniform_copy_info); + vkCmdCopyBuffer(command_buffer, staging_buffer, font_infos, 1, &info_copy); - VkBufferCopy symbol_copy_info = { - .size = sizeof(SymbolInfo)*uniform.num_symbols, - .srcOffset = image_size*uniform.num_symbols + sizeof(FontUniform), + VkBufferCopy symbol_copy = { + .size = sizeof(SymbolInfo)*info.num_symbols, + .srcOffset = image_size*info.num_symbols + sizeof(Font), .dstOffset = 0, }; - vkCmdCopyBuffer(command_buffer, staging_buffer, descriptor->symbols, 1, &symbol_copy_info); + vkCmdCopyBuffer(command_buffer, staging_buffer, memory->symbols, 1, &symbol_copy); VkImageMemoryBarrier first_barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .image = descriptor->image, + .image = memory->image, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .subresourceRange.levelCount = 1, - .subresourceRange.layerCount = uniform.num_symbols, + .subresourceRange.layerCount = info.num_symbols, .srcAccessMask = 0, .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, }; vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &first_barrier); VkBufferImageCopy image_copy = { - .imageSubresource.layerCount = uniform.num_symbols, + .imageSubresource.layerCount = info.num_symbols, .imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .imageExtent = image_info.extent, }; - vkCmdCopyBufferToImage(command_buffer, staging_buffer, descriptor->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); + vkCmdCopyBufferToImage(command_buffer, staging_buffer, memory->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); VkImageMemoryBarrier second_barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .image = descriptor->image, + .image = memory->image, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .subresourceRange.levelCount = 1, - .subresourceRange.layerCount = uniform.num_symbols, + .subresourceRange.layerCount = info.num_symbols, .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, }; @@ -795,18 +580,18 @@ VkResult load_font(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayou VkImageViewCreateInfo view_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .image = descriptor->image, + .image = memory->image, .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY, .format = VK_FORMAT_R8G8B8A8_SRGB, .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .layerCount = uniform.num_symbols, + .layerCount = info.num_symbols, .baseMipLevel = 0, .levelCount = 1, .baseArrayLayer = 0, }, }; - result = vkCreateImageView(device, &view_info, NULL, &descriptor->view); + result = vkCreateImageView(device, &view_info, NULL, &memory->view); if(result != VK_SUCCESS) { return result; } @@ -819,171 +604,199 @@ VkResult load_font(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayou .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT, .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT, }; - result = vkCreateSampler(device, &sampler_info, NULL, &descriptor->sampler); + result = vkCreateSampler(device, &sampler_info, NULL, &memory->sampler); if(result != VK_SUCCESS) { return result; } - VkDescriptorBufferInfo desc_uniform_info = { - .offset = 0, - .range = sizeof(FontUniform), - .buffer = descriptor->uniform, + VkDescriptorImageInfo desc_sampler_info = { + .sampler = memory->sampler, }; - VkDescriptorImageInfo desc_image_info = { - .sampler = descriptor->sampler, + VkDescriptorImageInfo desc_texture_info = { .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .imageView = descriptor->view, + .imageView = memory->view, }; VkWriteDescriptorSet descriptor_writes[] = { { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = descriptor->set, + .dstSet = font_textures, .dstBinding = 0, - .dstArrayElement = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .dstArrayElement = index, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, .descriptorCount = 1, - .pBufferInfo = &desc_uniform_info, + .pImageInfo = &desc_texture_info, }, { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = descriptor->set, - .dstBinding = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dstSet = font_samplers, + .dstBinding = 0, + .dstArrayElement = index, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, .descriptorCount = 1, - .pImageInfo = &desc_image_info, - } + .pImageInfo = &desc_sampler_info, + }, }; - vkUpdateDescriptorSets(device, 2, descriptor_writes, 0, NULL); + vkUpdateDescriptorSets(device, sizeof(descriptor_writes)/sizeof(VkWriteDescriptorSet), descriptor_writes, 0, NULL); return VK_SUCCESS; } -VkResult create_ui_descriptor_set(VkDevice device, VmaAllocator allocator, VkExtent2D swapchain_extent, vec2 window_scale, VkDescriptorSetLayout* ui_descriptor_layout, VkDescriptorPool* ui_descriptor_pool, VkDescriptorSet* ui_descriptor_set, VmaAllocation* ui_descriptor_memory, VkBuffer* ui_descriptor_buffer) { - VkDescriptorSetLayoutBinding ui_descriptor_bindings[] = { +VkResult create_ui_descriptor(VkDevice device, VmaAllocator allocator, uint32_t max_fonts, VkBuffer* font_infos, VmaAllocation* font_infos_memory, VkDescriptorSet* font_samplers, VkDescriptorSet* font_textures, VkDescriptorSetLayout* font_sampler_layout, VkDescriptorSetLayout* font_texture_layout, VkDescriptorPool* font_pool) { + VkBufferCreateInfo font_infos_buffer = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .size = sizeof(Font)*max_fonts, + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + }; + + VmaAllocationCreateInfo font_infos_memory_info = { + .usage = VMA_MEMORY_USAGE_GPU_ONLY, + }; + + VkResult result; + result = vmaCreateBuffer(allocator, &font_infos_buffer, &font_infos_memory_info, font_infos, font_infos_memory, NULL); + if(result != VK_SUCCESS) { + return result; + } + + VkDescriptorSetLayoutBinding font_sampler_bindings[] = { { .binding = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - } + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, + .descriptorCount = max_fonts, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + }, + }; + + VkDescriptorBindingFlags bindless_flags[] = { + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT, + }; + + VkDescriptorSetLayoutBindingFlagsCreateInfo font_sampler_bindings_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, + .bindingCount = sizeof(font_sampler_bindings)/sizeof(VkDescriptorSetLayoutBinding), + .pBindingFlags = bindless_flags, }; - VkDescriptorSetLayoutCreateInfo ui_descriptor_info = { + VkDescriptorSetLayoutCreateInfo font_sampler_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .pBindings = ui_descriptor_bindings, - .bindingCount = sizeof(ui_descriptor_bindings)/sizeof(VkDescriptorSetLayoutBinding), + .pBindings = font_sampler_bindings, + .bindingCount = sizeof(font_sampler_bindings)/sizeof(VkDescriptorSetLayoutBinding), + .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + .pNext = &font_sampler_bindings_info, }; - VkResult result; - result = vkCreateDescriptorSetLayout(device, &ui_descriptor_info, NULL, ui_descriptor_layout); + + result = vkCreateDescriptorSetLayout(device, &font_sampler_info, NULL, font_sampler_layout); if(result != VK_SUCCESS) { return result; } - VkDescriptorPoolSize pool_size = { - .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1, + VkDescriptorSetLayoutBinding font_texture_bindings[] = { + { + .binding = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + .descriptorCount = max_fonts, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + }, }; - VkDescriptorPoolCreateInfo ui_pool_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .pPoolSizes = &pool_size, - .poolSizeCount = 1, - .maxSets = 1, + VkDescriptorSetLayoutBindingFlagsCreateInfo font_texture_bindings_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, + .bindingCount = sizeof(font_texture_bindings)/sizeof(VkDescriptorSetLayoutBinding), + .pBindingFlags = bindless_flags, }; - result = vkCreateDescriptorPool(device, &ui_pool_info, NULL, ui_descriptor_pool); + VkDescriptorSetLayoutCreateInfo font_texture_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .pBindings = font_texture_bindings, + .bindingCount = sizeof(font_texture_bindings)/sizeof(VkDescriptorSetLayoutBinding), + .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + .pNext = &font_texture_bindings_info, + }; + + result = vkCreateDescriptorSetLayout(device, &font_texture_info, NULL, font_texture_layout); if(result != VK_SUCCESS) { return result; } - VkDescriptorSetAllocateInfo ui_descriptor_allocate_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .pSetLayouts = ui_descriptor_layout, - .descriptorSetCount = 1, - .descriptorPool = *ui_descriptor_pool, + VkDescriptorPoolSize font_pool_sizes[] = { + { + .type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + .descriptorCount = max_fonts, + }, + { + .type = VK_DESCRIPTOR_TYPE_SAMPLER, + .descriptorCount = max_fonts, + }, + }; + VkDescriptorPoolCreateInfo font_pool_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .pPoolSizes = font_pool_sizes, + .poolSizeCount = 2, + .maxSets = 2, + .flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, }; - result = vkAllocateDescriptorSets(device, &ui_descriptor_allocate_info, ui_descriptor_set); + result = vkCreateDescriptorPool(device, &font_pool_info, NULL, font_pool); if(result != VK_SUCCESS) { return result; } - VkBufferCreateInfo ui_uniform_buffer_info = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - .size = sizeof(UIUniform), - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + uint32_t max_font_binding = max_fonts - 1; + VkDescriptorSetVariableDescriptorCountAllocateInfo count_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, + .descriptorSetCount = 1, + .pDescriptorCounts = &max_font_binding, }; - VmaAllocationCreateInfo ui_uniform_memory_info = { - .usage = VMA_MEMORY_USAGE_CPU_TO_GPU, + VkDescriptorSetAllocateInfo allocate_font_samplers = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .pSetLayouts = font_sampler_layout, + .descriptorSetCount = 1, + .descriptorPool = *font_pool, + .pNext = &count_info, }; - result = vmaCreateBuffer(allocator, &ui_uniform_buffer_info, &ui_uniform_memory_info, ui_descriptor_buffer, ui_descriptor_memory, NULL); + VkDescriptorSetAllocateInfo allocate_font_textures = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .pSetLayouts = font_texture_layout, + .descriptorSetCount = 1, + .descriptorPool = *font_pool, + .pNext = &count_info, + }; + + result = vkAllocateDescriptorSets(device, &allocate_font_samplers, font_samplers); if(result != VK_SUCCESS) { return result; } - void* mapped; - result = vmaMapMemory(allocator, *ui_descriptor_memory, &mapped); + result = vkAllocateDescriptorSets(device, &allocate_font_textures, font_textures); if(result != VK_SUCCESS) { return result; } - UIUniform ui_uniform; - vec3 screen_offset = {-1.0, -1.0, 0.0}; - vec3 screen_scale = {1.0/(float)swapchain_extent.width*window_scale[0], 1.0/(float)swapchain_extent.height*window_scale[1], 1.0}; - glm_mat4_identity(ui_uniform.screen); - glm_translate(ui_uniform.screen, screen_offset); - glm_scale(ui_uniform.screen, screen_scale); - memcpy(mapped, &ui_uniform, sizeof(ui_uniform)); - vmaUnmapMemory(allocator, *ui_descriptor_memory); - - VkDescriptorBufferInfo ui_uniform_info = { - .offset = 0, - .range = sizeof(ui_uniform), - .buffer = *ui_descriptor_buffer, - }; - VkWriteDescriptorSet ui_uniform_write = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = *ui_descriptor_set, - .dstBinding = 0, - .dstArrayElement = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1, - .pBufferInfo = &ui_uniform_info, - }; - - vkUpdateDescriptorSets(device, 1, &ui_uniform_write, 0, NULL); return VK_SUCCESS; } -VkResult init_pipelines(VkDevice device, VmaAllocator allocator, VkExtent2D swapchain_extent, vec2 window_scale, VkRenderPass render_pass, UIContext* context) { +VkResult create_ui_context(VkDevice device, VmaAllocator allocator, VkRenderPass render_pass, UIContextStorage* memory) { VkResult result; - result = create_ui_descriptor_set(device, allocator, swapchain_extent, window_scale, &context->ui_descriptor_layout, &context->ui_descriptor_pool, &context->ui_descriptor_set, &context->ui_descriptor_memory, &context->ui_descriptor_buffer); + result = create_ui_descriptor(device, allocator, 10, &memory->font_infos, &memory->font_infos_memory, &memory->font_samplers, &memory->font_textures, &memory->font_samplers_layout, &memory->font_textures_layout, &memory->fonts_pool); if(result != VK_SUCCESS) { return result; } - result = create_ui_colored_rect_pipeline(device, render_pass, context->ui_descriptor_layout, &context->ui_pipeline_rect); + result = create_ui_rect_pipeline(device, render_pass, memory->font_samplers_layout, memory->font_textures_layout, &memory->rect_pipeline); if(result != VK_SUCCESS) { return result; } - result = create_font_descriptor_pools(device, 10, &context->font_pool, &context->font_layout); + result = create_ui_text_pipeline(device, render_pass, memory->font_samplers_layout, memory->font_textures_layout, &memory->char_pipeline, &memory->string_pipeline); if(result != VK_SUCCESS) { return result; } - result = create_ui_text_pipeline(device, render_pass, context->ui_descriptor_layout, context->font_layout, &context->ui_pipeline_text, &context->ui_compute_text); - if(result != VK_SUCCESS) { - return result; - } - - return VK_SUCCESS; }