diff --git a/client/include/ui.h b/client/include/ui.h index 2cc59d1..9a58d74 100644 --- a/client/include/ui.h +++ b/client/include/ui.h @@ -59,12 +59,6 @@ typedef struct FontStorageStruct { uint32_t index; } FontStorage; -typedef struct UIRectStruct { - vec2 pos; - vec2 size; - vec4 color; -} UIRect; - typedef struct UIStringStruct { vec2 pos; vec4 color; @@ -73,44 +67,44 @@ typedef struct UIStringStruct { uint32_t length; } UIString; -typedef struct UIGlyphStruct { - vec2 pos; - vec4 color; - float size; - uint32_t code; -} UIGlyph; - typedef struct UIlayerStorageStruct { VkBuffer strings; - VkBuffer glyphs; VkBuffer codes; - VkBuffer rects; + VkBuffer drawables; VkBuffer layer; VmaAllocation strings_memory; - VmaAllocation rects_memory; - VmaAllocation glyphs_memory; + VmaAllocation drawables_memory; VmaAllocation codes_memory; VmaAllocation layer_memory; VkDeviceAddress address; - uint32_t max_glyphs; - uint32_t max_string; - uint32_t max_rects; + uint32_t max_strings; + uint32_t max_codes; + uint32_t max_drawables; + uint32_t drawable_count; } UILayerStorage; +typedef struct UIDrawableStruct { + vec2 pos; + vec2 size; + vec4 color; + uint32_t type; + uint32_t code; +} UIDrawable; + typedef struct UILayerStruct { VkDeviceAddress strings; VkDeviceAddress codes; - VkDeviceAddress rects; - VkDeviceAddress glyphs; + VkDeviceAddress drawables; - DrawCommand draw_glyphs; - DrawCommand draw_rects; + DrawCommand draw; DispatchCommand dispatch_strings; + uint32_t font_index; + uint32_t drawable_count; } UILayer; typedef struct UIContextStruct { @@ -133,8 +127,7 @@ typedef struct UIContextStorageStruct { VkDescriptorSetLayout font_textures_layout; VkDescriptorPool fonts_pool; - GraphicsPipeline rect_pipeline; - GraphicsPipeline char_pipeline; + GraphicsPipeline pipeline; ComputePipeline string_pipeline; } UIContextStorage; @@ -164,8 +157,8 @@ VkResult load_font( VkResult create_layer( uint32_t max_strings, - uint32_t max_characters, - uint32_t max_rects, + uint32_t max_codes, + uint32_t max_drawables, uint32_t font_index, VkDevice device, VmaAllocator allocator, diff --git a/client/shader_src/ui_text.comp b/client/shader_src/string.comp similarity index 65% rename from client/shader_src/ui_text.comp rename to client/shader_src/string.comp index a92f4ec..af76c70 100644 --- a/client/shader_src/ui_text.comp +++ b/client/shader_src/string.comp @@ -13,25 +13,16 @@ layout(std430, buffer_reference) readonly buffer StringList { String s[]; }; -struct Glyph { - vec2 pos; - vec4 color; - float size; - uint code; -}; - -layout(std430, buffer_reference) readonly buffer GlyphList { - Glyph g[]; -}; - -struct Rect { +struct Drawable { vec2 pos; vec2 size; vec4 color; + uint type; + uint code; }; -layout(std430, buffer_reference) readonly buffer RectList { - Rect r[]; +layout(std430, buffer_reference) writeonly buffer DrawableList { + Drawable d[]; }; layout(std430, buffer_reference) readonly buffer CodeList { @@ -55,15 +46,13 @@ layout(std430, buffer_reference) buffer UILayer { StringList strings; CodeList codes; - RectList rects; - GlyphList glyphs; - - DrawCommand draw_glyphs; - DrawCommand draw_rects; + DrawableList drawables; - DispatchCommand dispatch_strings; + DrawCommand draw; + DispatchCommand dispatch; uint font_index; + uint drawable_count; }; struct Symbol { @@ -108,14 +97,16 @@ void main() { String string = pc.layer.strings.s[gID]; Font font = pc.context.fonts.f[pc.layer.font_index]; - uint buffer_pos = atomicAdd(pc.layer.draw_glyphs.instance_count, string.len); + uint buffer_pos = atomicAdd(pc.layer.draw.instance_count, string.len); float x = 0; for(uint i = 0; i < string.len; i++) { - Symbol symbol = font.symbols.s[pc.layer.codes.c[string.offset + i]]; - pc.layer.glyphs.g[buffer_pos + i].pos = string.pos + vec2(x, 0); + uint code = pc.layer.codes.c[string.offset + i]; + Symbol symbol = font.symbols.s[code]; + pc.layer.drawables.d[buffer_pos + i].pos = string.pos + vec2(x, 0); x += string.size*symbol.advance/font.width; - pc.layer.glyphs.g[buffer_pos + i].size = string.size; - pc.layer.glyphs.g[buffer_pos + i].color = string.color; - pc.layer.glyphs.g[buffer_pos + i].code = pc.layer.codes.c[string.offset + i]; + pc.layer.drawables.d[buffer_pos + i].size = vec2(string.size, string.size); + pc.layer.drawables.d[buffer_pos + i].color = string.color; + pc.layer.drawables.d[buffer_pos + i].code = pc.layer.codes.c[string.offset + i]; + pc.layer.drawables.d[buffer_pos + i].type = 1; } } diff --git a/client/shader_src/ui_text.frag b/client/shader_src/ui.frag similarity index 56% rename from client/shader_src/ui_text.frag rename to client/shader_src/ui.frag index 75176fc..0779f76 100644 --- a/client/shader_src/ui_text.frag +++ b/client/shader_src/ui.frag @@ -7,11 +7,16 @@ layout(set = 1, binding = 0) uniform texture2DArray font_textures[]; layout(location = 0) in vec4 fragColor; layout(location = 1) in vec2 fragUV; layout(location = 2) flat in uint code; -layout(location = 3) flat in uint font; +layout(location = 3) flat in uint index; +layout(location = 4) flat in uint type; layout(location = 0) out vec4 outColor; void main() { - outColor = fragColor * texture(sampler2DArray(font_textures[font], font_samplers[0]), vec3(fragUV, code)); + if(type == 0) { + outColor = fragColor; + } else if(type == 1) { + outColor = fragColor * texture(sampler2DArray(font_textures[index], font_samplers[index]), vec3(fragUV, code)); + } } diff --git a/client/shader_src/ui_text.vert b/client/shader_src/ui.vert similarity index 53% rename from client/shader_src/ui_text.vert rename to client/shader_src/ui.vert index 8bfa8dd..b01cd5e 100644 --- a/client/shader_src/ui_text.vert +++ b/client/shader_src/ui.vert @@ -13,25 +13,16 @@ layout(std430, buffer_reference) readonly buffer StringList { String s[]; }; -struct Glyph { - vec2 pos; - vec4 color; - float size; - uint code; -}; - -layout(std430, buffer_reference) readonly buffer GlyphList { - Glyph g[]; -}; - -struct Rect { +struct Drawable { vec2 pos; vec2 size; vec4 color; + uint type; + uint code; }; -layout(std430, buffer_reference) readonly buffer RectList { - Rect r[]; +layout(std430, buffer_reference) readonly buffer DrawableList { + Drawable d[]; }; layout(std430, buffer_reference) readonly buffer CodeList { @@ -55,15 +46,13 @@ layout(std430, buffer_reference) buffer UILayer { StringList strings; CodeList codes; - RectList rects; - GlyphList glyphs; + DrawableList drawables; - DrawCommand draw_glyphs; - DrawCommand draw_rects; - - DispatchCommand dispatch_strings; + DrawCommand draw; + DispatchCommand dispatch; uint font_index; + uint drawable_count; }; struct Symbol { @@ -78,7 +67,6 @@ layout(std430, buffer_reference) buffer SymbolList { Symbol s[]; }; - struct Font { SymbolList symbols; uint num_symbols; @@ -86,7 +74,6 @@ struct Font { uint height; }; - layout(std430, buffer_reference) buffer FontList { Font f[]; }; @@ -104,7 +91,8 @@ layout(std430, push_constant) uniform PushConstant { layout(location = 0) out vec4 fragColor; layout(location = 1) out vec2 fragUV; layout(location = 2) out uint code; -layout(location = 3) out uint font_index; +layout(location = 3) out uint index; +layout(location = 4) out uint type; const vec2 square[6] = { vec2(0.0, 0.0), @@ -116,19 +104,27 @@ const vec2 square[6] = { }; void main() { - Glyph glyph = pc.layer.glyphs.g[gl_InstanceIndex]; - Font font = pc.context.fonts.f[pc.layer.font_index]; - Symbol symbol = font.symbols.s[glyph.code]; - - float fragU = square[gl_VertexIndex].x * symbol.width/font.width; - float fragV = square[gl_VertexIndex].y * symbol.height/font.height; - float x = (square[gl_VertexIndex].x * symbol.width + symbol.left) * glyph.size / font.width; - float y = (square[gl_VertexIndex].y * symbol.height - symbol.top) * glyph.size / font.height; - - fragUV = vec2(fragU, fragV); - fragColor = glyph.color; - gl_Position = pc.context.screen * vec4(vec2(x, y) + glyph.pos, 0.0, 1.0); - code = glyph.code; - font_index = pc.layer.font_index; + Drawable drawable = pc.layer.drawables.d[gl_InstanceIndex]; + + if(drawable.type == 0) { + // Rect + gl_Position = pc.context.screen * vec4(square[gl_VertexIndex] * drawable.size + drawable.pos, 0.0, 1.0); + } else if(drawable.type == 1){ + // Glyph + Font font = pc.context.fonts.f[pc.layer.font_index]; + Symbol symbol = font.symbols.s[drawable.code]; + float fragU = square[gl_VertexIndex].x * symbol.width/font.width; + float fragV = square[gl_VertexIndex].y * symbol.height/font.height; + float x = (square[gl_VertexIndex].x * symbol.width + symbol.left) * drawable.size.x / font.width; + float y = (square[gl_VertexIndex].y * symbol.height - symbol.top) * drawable.size.x / font.height; + + fragUV = vec2(fragU, fragV); + gl_Position = pc.context.screen * vec4(vec2(x, y) + drawable.pos, 0.0, 1.0); + } + + fragColor = drawable.color; + code = drawable.code; + type = drawable.type; + index = pc.layer.font_index; } diff --git a/client/shader_src/ui_rect.frag b/client/shader_src/ui_rect.frag deleted file mode 100644 index 9d6b882..0000000 --- a/client/shader_src/ui_rect.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -layout(location = 0) in vec4 fragColor; - -layout(location = 0) out vec4 outColor; - -void main() { - outColor = fragColor; -} - diff --git a/client/shader_src/ui_rect.vert b/client/shader_src/ui_rect.vert deleted file mode 100644 index 760ba8e..0000000 --- a/client/shader_src/ui_rect.vert +++ /dev/null @@ -1,120 +0,0 @@ -#version 450 -#extension GL_EXT_buffer_reference : require - -struct String { - vec2 pos; - vec4 color; - float size; - uint offset; - uint length; -}; - -layout(std430, buffer_reference) readonly buffer StringList { - String s[]; -}; - -struct Glyph { - vec2 pos; - vec4 color; - float size; - uint code; -}; - -layout(std430, buffer_reference) readonly buffer GlyphList { - Glyph g[]; -}; - -struct Rect { - vec2 pos; - vec2 size; - vec4 color; -}; - -layout(std430, buffer_reference) readonly buffer RectList { - Rect r[]; -}; - -layout(std430, buffer_reference) readonly buffer CodeList { - uint c[]; -}; - -struct DrawCommand { - uint vertex_count; - uint instance_count; - uint fist_vertex; - uint first_instance; -}; - -struct DispatchCommand { - uint x; - uint y; - uint z; -}; - -layout(std430, buffer_reference) buffer UILayer { - StringList strings; - CodeList codes; - - RectList rects; - GlyphList glyphs; - - DrawCommand draw_glyphs; - DrawCommand draw_rects; - - DispatchCommand dispatch_strings; - - uint font_index; -}; - -struct Symbol { - int top; - uint left; - uint width; - uint height; - uint advance; -}; - -layout(std430, buffer_reference) buffer SymbolList { - Symbol s[]; -}; - - -struct Font { - uint num_symbols; - uint width; - uint height; - SymbolList symbols; -}; - - -layout(std430, buffer_reference) buffer FontList { - Font f[]; -}; - -layout(std430, buffer_reference) buffer UIContext { - FontList fonts; - mat4 screen; -}; - -layout(std430, push_constant) uniform PushConstant { - UIContext context; - UILayer layer; -} pc; - -layout(location = 0) out vec4 fragColor; - -const vec2 square[6] = { - vec2(0.0, 0.0), - vec2(1.0, 0.0), - vec2(0.0, 1.0), - vec2(1.0, 0.0), - vec2(1.0, 1.0), - vec2(0.0, 1.0), -}; - -void main() { - Rect rect = pc.layer.rects.r[gl_InstanceIndex]; - gl_Position = pc.context.screen * vec4(square[gl_VertexIndex] * rect.size + rect.pos, 0.0, 1.0); - fragColor = rect.color; -} - diff --git a/client/src/main.c b/client/src/main.c index f6b0cc6..318ffda 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -40,33 +40,36 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render) { VK_RESULT(load_font(render->device, render->allocator, &ui, 0, render->transfer_pool, render->transfer_queue, library, "test.ttf", 16, VK_TRUE, &font)); - VK_RESULT(create_layer(10, 100, 10, 0, render->device, render->allocator, render->transfer_pool, render->transfer_queue, &layers[0])); - VK_RESULT(create_layer(10, 100, 10, 0, render->device, render->allocator, render->transfer_pool, render->transfer_queue, &layers[1])); + VK_RESULT(create_layer(10, 100, 200, 0, render->device, render->allocator, render->transfer_pool, render->transfer_queue, &layers[0])); + VK_RESULT(create_layer(10, 100, 200, 0, render->device, render->allocator, render->transfer_pool, render->transfer_queue, &layers[1])); - VK_RESULT(create_transfer_buffer(render->allocator, sizeof(uint32_t) + 2*sizeof(UIRect) + sizeof(UIString) + 100*sizeof(uint32_t), &transfer, &transfer_memory, &mapped)); + VK_RESULT(create_transfer_buffer(render->allocator, 2*sizeof(uint32_t) + 2*sizeof(UIDrawable) + sizeof(UIString) + 100*sizeof(uint32_t), &transfer, &transfer_memory, &mapped)); uint32_t* mapped_count = (uint32_t*)(mapped); mapped_count[0] = 1; - UIRect* mapped_rect = (UIRect*)(mapped + sizeof(uint32_t)); - mapped_rect[0].pos[0] = 0.0; - mapped_rect[0].pos[1] = 0.0; - mapped_rect[0].size[0] = 200.0; - mapped_rect[0].size[1] = 200.0; - mapped_rect[0].color[0] = 1.0; - mapped_rect[0].color[1] = 0.0; - mapped_rect[0].color[2] = 0.0; - mapped_rect[0].color[3] = 1.0; - - mapped_rect[1].pos[0] = 200.0; - mapped_rect[1].pos[1] = 0.0; - mapped_rect[1].size[0] = 200.0; - mapped_rect[1].size[1] = 200.0; - mapped_rect[1].color[0] = 0.0; - mapped_rect[1].color[1] = 1.0; - mapped_rect[1].color[2] = 0.0; - mapped_rect[1].color[3] = 1.0; - - UIString* mapped_string = (UIString*)(mapped + sizeof(uint32_t) + 2*sizeof(UIRect)); + mapped_count[1] = 1; + UIDrawable* mapped_drawable = (UIDrawable*)(mapped + 2*sizeof(uint32_t)); + mapped_drawable[0].pos[0] = 0.0; + mapped_drawable[0].pos[1] = 0.0; + mapped_drawable[0].size[0] = 200.0; + mapped_drawable[0].size[1] = 200.0; + mapped_drawable[0].color[0] = 1.0; + mapped_drawable[0].color[1] = 0.0; + mapped_drawable[0].color[2] = 0.0; + mapped_drawable[0].color[3] = 1.0; + mapped_drawable[0].type = 0; + + mapped_drawable[1].pos[0] = 200.0; + mapped_drawable[1].pos[1] = 0.0; + mapped_drawable[1].size[0] = 200.0; + mapped_drawable[1].size[1] = 200.0; + mapped_drawable[1].color[0] = 0.0; + mapped_drawable[1].color[1] = 1.0; + mapped_drawable[1].color[2] = 0.0; + mapped_drawable[1].color[3] = 1.0; + mapped_drawable[1].type = 0; + + UIString* mapped_string = (UIString*)(mapped + 2*sizeof(uint32_t) + 2*sizeof(UIDrawable)); mapped_string->pos[0] = 0.0; mapped_string->pos[1] = 200.0; mapped_string->size = 100.0; @@ -76,21 +79,21 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render) { mapped_string->color[3] = 1.0; mapped_string->length = 100; mapped_string->offset = 0; - uint32_t* mapped_codes = (uint32_t*)(mapped + sizeof(uint32_t) + 2*sizeof(UIRect) + sizeof(UIString)); + uint32_t* mapped_codes = (uint32_t*)(mapped + 2*sizeof(uint32_t) + 2*sizeof(UIDrawable) + sizeof(UIString)); for(uint32_t i = 0; i < 100; i++) { mapped_codes[i] = i; } VkCommandBuffer command_buffer = command_begin_single(render->device, render->transfer_pool); - command_copy_buffer(command_buffer, transfer, layers[0].layer, 0, offsetof(UILayer, draw_rects) + offsetof(DrawCommand, instance_count), sizeof(uint32_t)); - command_copy_buffer(command_buffer, transfer, layers[1].layer, 0, offsetof(UILayer, draw_rects) + offsetof(DrawCommand, instance_count), sizeof(uint32_t)); - command_copy_buffer(command_buffer, transfer, layers[1].layer, 0, offsetof(UILayer, dispatch_strings) + offsetof(DispatchCommand, x), sizeof(uint32_t)); + command_copy_buffer(command_buffer, transfer, layers[0].layer, 0, offsetof(UILayer, drawable_count), sizeof(uint32_t)); + command_copy_buffer(command_buffer, transfer, layers[1].layer, 0, offsetof(UILayer, drawable_count), sizeof(uint32_t)); + command_copy_buffer(command_buffer, transfer, layers[1].layer, sizeof(uint32_t), offsetof(UILayer, dispatch_strings) + offsetof(DispatchCommand, x), sizeof(uint32_t)); - command_copy_buffer(command_buffer, transfer, layers[0].rects, sizeof(uint32_t), 0, sizeof(UIRect)); - command_copy_buffer(command_buffer, transfer, layers[1].rects, sizeof(uint32_t) + sizeof(UIRect), 0, sizeof(UIRect)); + command_copy_buffer(command_buffer, transfer, layers[0].drawables, 2*sizeof(uint32_t), 0, sizeof(UIDrawable)); + command_copy_buffer(command_buffer, transfer, layers[1].drawables, 2*sizeof(uint32_t) + sizeof(UIDrawable), 0, sizeof(UIDrawable)); - command_copy_buffer(command_buffer, transfer, layers[1].strings, sizeof(uint32_t) + 2*sizeof(UIRect), 0, sizeof(UIString)); - command_copy_buffer(command_buffer, transfer, layers[1].codes, sizeof(uint32_t) + 2*sizeof(UIRect) + sizeof(UIString), 0, 100*sizeof(uint32_t)); + command_copy_buffer(command_buffer, transfer, layers[1].strings, 2*sizeof(uint32_t) + 2*sizeof(UIDrawable), 0, sizeof(UIString)); + command_copy_buffer(command_buffer, transfer, layers[1].codes, 2*sizeof(uint32_t) + 2*sizeof(UIDrawable) + sizeof(UIString), 0, 100*sizeof(uint32_t)); VK_RESULT(command_end_single(render->device, command_buffer, render->transfer_pool, render->transfer_queue)); vkQueueWaitIdle(render->transfer_queue.handle); destroy_transfer_buffer(render->allocator, transfer, transfer_memory); diff --git a/client/src/render.c b/client/src/render.c index e14a759..35a761c 100644 --- a/client/src/render.c +++ b/client/src/render.c @@ -55,6 +55,7 @@ GLFWwindow* init_window() { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + GLFWwindow* window = glfwCreateWindow(800, 500, "roleplay", 0, 0); return window; @@ -977,7 +978,7 @@ VkResult init_vulkan(GLFWwindow* window, RenderContext* context) { return VK_SUCCESS; } -VkResult draw_frame(RenderContext* context, UIContextStorage* ui_context, UILayerStorage* ui_layers, uint32_t ui_layer_count) { +VkResult draw_frame(RenderContext* context, UIContextStorage* ui_context, UILayerStorage* layers, uint32_t layer_count) { VkResult result; result = vkWaitForFences(context->device, 1, &context->in_flight_fences[context->current_frame], VK_TRUE, UINT64_MAX); @@ -1023,7 +1024,7 @@ VkResult draw_frame(RenderContext* context, UIContextStorage* ui_context, UILaye }; vkCmdSetScissor(command_buffer, 0, 1, &scissor); - VkClearValue clear_values[2] = {{.color={{0.0f, 0.0f, 0.0f, 1.0f}}}, {.depthStencil={1.0f, 0.0f}}}; + VkClearValue clear_values[2] = {{.color={{0.0f, 0.0f, 0.0f, 0.0f}}}, {.depthStencil={1.0f, 0.0f}}}; VkRenderPassBeginInfo render_pass_begin = { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, @@ -1039,48 +1040,48 @@ VkResult draw_frame(RenderContext* context, UIContextStorage* ui_context, UILaye // 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; + for(uint32_t i = 0; i < layer_count; i++) { + push[1] = layers[i].address; VkBufferMemoryBarrier draw_command_barrier_1 = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .buffer = ui_layers[i].layer, - .offset = offsetof(UILayer, draw_glyphs), + .buffer = layers[i].layer, + .offset = offsetof(UILayer, draw), .size = sizeof(DrawCommand), .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_TRANSFER_BIT, 0, 0, NULL, 1, &draw_command_barrier_1, 0, NULL); - vkCmdFillBuffer(command_buffer, ui_layers[i].layer, offsetof(UILayer, draw_glyphs) + offsetof(DrawCommand, instance_count), sizeof(uint32_t), 0x00000000); + command_copy_buffer(command_buffer, layers[i].layer, layers[i].layer, offsetof(UILayer, drawable_count), offsetof(UILayer, draw) + offsetof(DrawCommand, instance_count), sizeof(uint32_t)); VkBufferMemoryBarrier draw_command_barrier_2 = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .buffer = ui_layers[i].layer, - .offset = offsetof(UILayer, draw_glyphs), + .buffer = layers[i].layer, + .offset = offsetof(UILayer, draw), .size = sizeof(DrawCommand), .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT, }; vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 1, &draw_command_barrier_2, 0, NULL); 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)); + vkCmdDispatchIndirect(command_buffer, layers[i].layer, offsetof(UILayer, dispatch_strings)); VkBufferMemoryBarrier draw_command_barrier_3 = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .buffer = ui_layers[i].layer, - .offset = offsetof(UILayer, draw_glyphs), + .buffer = layers[i].layer, + .offset = offsetof(UILayer, draw), .size = sizeof(DrawCommand), .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_DRAW_INDIRECT_BIT, 0, 0, NULL, 1, &draw_command_barrier_3, 0, NULL); - VkBufferMemoryBarrier glyphs_barrier = { + VkBufferMemoryBarrier drawables_barrier = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .buffer = ui_layers[i].glyphs, + .buffer = layers[i].drawables, .offset = 0, - .size = sizeof(UIGlyph)*ui_layers[i].max_glyphs, + .size = sizeof(UIDrawable)*layers[i].max_drawables, .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, }; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, NULL, 1, &glyphs_barrier, 0, NULL); + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, NULL, 1, &drawables_barrier, 0, NULL); } @@ -1089,17 +1090,15 @@ VkResult draw_frame(RenderContext* context, UIContextStorage* ui_context, UILaye // World subpass vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE); // UI subpass - for(uint32_t i = 0; i < ui_layer_count; i++) { - push[1] = ui_layers[i].address; - vkCmdPushConstants(command_buffer, ui_context->rect_pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_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); + for(uint32_t i = 0; i < layer_count; i++) { + push[1] = layers[i].address; + vkCmdPushConstants(command_buffer, ui_context->pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, push); + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.pipeline); if(i == 0) { - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->char_pipeline.layout, 0, 1, &ui_context->font_samplers, 0, NULL); - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->char_pipeline.layout, 1, 1, &ui_context->font_textures, 0, NULL); + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 0, 1, &ui_context->font_samplers, 0, NULL); + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 1, 1, &ui_context->font_textures, 0, NULL); } - vkCmdDrawIndirect(command_buffer, ui_layers[i].layer, offsetof(UILayer, draw_glyphs), 1, 0); + vkCmdDrawIndirect(command_buffer, layers[i].layer, offsetof(UILayer, draw), 1, 0); } vkCmdEndRenderPass(command_buffer); diff --git a/client/src/ui.c b/client/src/ui.c index 3136e41..99262d8 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -56,12 +56,88 @@ VkResult create_ui_pipeline( VkRenderPass render_pass, VkDescriptorSetLayout font_samplers_layout, VkDescriptorSetLayout font_textures_layout, - VkPipelineShaderStageCreateInfo* shader_stages, - uint32_t shader_stage_count, - VkPipelineVertexInputStateCreateInfo input_info, - VkPipelineInputAssemblyStateCreateInfo input_assembly_info, - GraphicsPipeline* pipeline) { + GraphicsPipeline* pipeline, + ComputePipeline* compute) { VkResult result; + VkShaderModule compute_shader = load_shader_file("shader_src/string.comp.spv", device); + if(compute_shader == VK_NULL_HANDLE) { + return VK_ERROR_UNKNOWN; + } + + VkPipelineShaderStageCreateInfo compute_shader_stage = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_COMPUTE_BIT, + .pName = "main", + .module = compute_shader, + }; + + VkPushConstantRange push_constant = { + .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, + .size = 16, + }; + + VkPipelineLayoutCreateInfo compute_layout_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pushConstantRangeCount = 1, + .pPushConstantRanges = &push_constant, + }; + + result = vkCreatePipelineLayout(device, &compute_layout_info, NULL, &compute->layout); + if(result != VK_SUCCESS) { + return result; + } + + VkComputePipelineCreateInfo compute_pipeline_info = { + .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + .layout = compute->layout, + .stage = compute_shader_stage, + }; + + result = vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &compute_pipeline_info, NULL, &compute->pipeline); + if(result != VK_SUCCESS) { + return result; + } + + VkShaderModule vert_shader = load_shader_file("shader_src/ui.vert.spv", device); + if(vert_shader == VK_NULL_HANDLE) { + return VK_ERROR_UNKNOWN; + } + VkShaderModule frag_shader = load_shader_file("shader_src/ui.frag.spv", device); + if(frag_shader == VK_NULL_HANDLE) { + return VK_ERROR_UNKNOWN; + } + + VkPipelineShaderStageCreateInfo shader_stages[] = { + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .module = vert_shader, + .pName = "main", + }, + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .module = frag_shader, + .pName = "main", + }, + }; + + VkVertexInputBindingDescription bindings[] = {}; + VkVertexInputAttributeDescription attributes[] = {}; + + VkPipelineVertexInputStateCreateInfo input_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .pVertexBindingDescriptions = bindings, + .vertexBindingDescriptionCount = sizeof(bindings)/sizeof(VkVertexInputBindingDescription), + .pVertexAttributeDescriptions = attributes, + .vertexAttributeDescriptionCount = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription), + }; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + .primitiveRestartEnable = VK_FALSE, + }; VkPushConstantRange push_constants[] = { { @@ -173,7 +249,7 @@ VkResult create_ui_pipeline( VkGraphicsPipelineCreateInfo draw_pipeline_info = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .stageCount = shader_stage_count, + .stageCount = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo), .pStages = shader_stages, .pVertexInputState = &input_info, .pInputAssemblyState = &input_assembly_info, @@ -193,154 +269,14 @@ VkResult create_ui_pipeline( if(result != VK_SUCCESS) { return result; } - return VK_SUCCESS; -} - -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_rect.frag.spv", device); - if(frag_shader == VK_NULL_HANDLE) { - return VK_ERROR_UNKNOWN; - } - VkPipelineShaderStageCreateInfo shader_stages[] = { - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = VK_SHADER_STAGE_VERTEX_BIT, - .module = vert_shader, - .pName = "main", - }, - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = VK_SHADER_STAGE_FRAGMENT_BIT, - .module = frag_shader, - .pName = "main", - }, - }; - - VkVertexInputBindingDescription bindings[] = {}; - VkVertexInputAttributeDescription attributes[] = {}; - VkPipelineVertexInputStateCreateInfo input_info = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .pVertexBindingDescriptions = bindings, - .vertexBindingDescriptionCount = sizeof(bindings)/sizeof(VkVertexInputBindingDescription), - .pVertexAttributeDescriptions = attributes, - .vertexAttributeDescriptionCount = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription), - }; - - 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, 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; - } - - return VK_SUCCESS; -} - -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) { - return VK_ERROR_UNKNOWN; - } - - VkPipelineShaderStageCreateInfo compute_shader_stage = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = VK_SHADER_STAGE_COMPUTE_BIT, - .pName = "main", - .module = compute_shader, - }; - - VkPushConstantRange push_constant = { - .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, - .size = 16, - }; - - VkPipelineLayoutCreateInfo compute_layout_info = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .pushConstantRangeCount = 1, - .pPushConstantRanges = &push_constant, - }; - - result = vkCreatePipelineLayout(device, &compute_layout_info, NULL, &compute->layout); - if(result != VK_SUCCESS) { - return result; - } - - VkComputePipelineCreateInfo compute_pipeline_info = { - .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - .layout = compute->layout, - .stage = compute_shader_stage, - }; - - result = vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &compute_pipeline_info, NULL, &compute->pipeline); - if(result != VK_SUCCESS) { - return result; - } - - VkShaderModule vert_shader = load_shader_file("shader_src/ui_text.vert.spv", device); - if(vert_shader == VK_NULL_HANDLE) { - return VK_ERROR_UNKNOWN; - } - VkShaderModule frag_shader = load_shader_file("shader_src/ui_text.frag.spv", device); - if(frag_shader == VK_NULL_HANDLE) { - return VK_ERROR_UNKNOWN; - } - - // TODO: add a compute stage before the shader stages that sets up the draw buffer and commands for the characters based off of strings + positions - // 1. Reserve a buffer for array of draw command params + Char on the GPU - // 2. Reserve a buffer for Text on the GPU - VkPipelineShaderStageCreateInfo shader_stages[] = { - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = VK_SHADER_STAGE_VERTEX_BIT, - .module = vert_shader, - .pName = "main", - }, - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = VK_SHADER_STAGE_FRAGMENT_BIT, - .module = frag_shader, - .pName = "main", - }, - }; - - VkVertexInputBindingDescription bindings[] = {}; - VkVertexInputAttributeDescription attributes[] = {}; - - VkPipelineVertexInputStateCreateInfo input_info = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .pVertexBindingDescriptions = bindings, - .vertexBindingDescriptionCount = sizeof(bindings)/sizeof(VkVertexInputBindingDescription), - .pVertexAttributeDescriptions = attributes, - .vertexAttributeDescriptionCount = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription), - }; - - 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, 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; - } return VK_SUCCESS; } VkResult create_layer( uint32_t max_strings, - uint32_t max_glyphs, - uint32_t max_rects, + uint32_t max_codes, + uint32_t max_drawables, uint32_t font_index, VkDevice device, VmaAllocator allocator, @@ -349,15 +285,14 @@ VkResult create_layer( UILayerStorage* memory) { VkResult result; - memory->max_string = max_strings; - memory->max_glyphs = max_glyphs; - memory->max_rects = max_rects; + memory->max_strings = max_strings; + memory->max_codes = max_codes; + memory->max_drawables = max_drawables; - VK_RESULT(create_storage_buffer(allocator, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, sizeof(UILayer), &memory->layer, &memory->layer_memory)); - VK_RESULT(create_storage_buffer(allocator, 0, sizeof(UIRect)*max_rects, &memory->rects, &memory->rects_memory)); + VK_RESULT(create_storage_buffer(allocator, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, sizeof(UILayer), &memory->layer, &memory->layer_memory)); VK_RESULT(create_storage_buffer(allocator, 0, sizeof(UIString)*max_strings, &memory->strings, &memory->strings_memory)) - VK_RESULT(create_storage_buffer(allocator, 0, sizeof(UIGlyph)*max_glyphs, &memory->glyphs, &memory->glyphs_memory)); - VK_RESULT(create_storage_buffer(allocator, 0, sizeof(uint32_t)*max_glyphs, &memory->codes, &memory->codes_memory)); + VK_RESULT(create_storage_buffer(allocator, 0, sizeof(UIDrawable)*max_drawables, &memory->drawables, &memory->drawables_memory)); + VK_RESULT(create_storage_buffer(allocator, 0, sizeof(uint32_t)*max_codes, &memory->codes, &memory->codes_memory)); VkBuffer transfer; VmaAllocation transfer_memory; @@ -367,31 +302,25 @@ VkResult create_layer( mapped->strings = buffer_address(device, memory->strings); mapped->codes = buffer_address(device, memory->codes); - mapped->glyphs = buffer_address(device, memory->glyphs); - mapped->rects = buffer_address(device, memory->rects); - - mapped->draw_glyphs.first_vertex = 0; - mapped->draw_glyphs.vertex_count = 6; - mapped->draw_glyphs.first_instance = 0; - mapped->draw_glyphs.instance_count = 0; + mapped->drawables = buffer_address(device, memory->drawables); - mapped->draw_rects.first_vertex = 0; - mapped->draw_rects.vertex_count = 6; - mapped->draw_rects.first_instance = 0; - mapped->draw_rects.instance_count = 0; + mapped->draw.first_vertex = 0; + mapped->draw.vertex_count = 6; + mapped->draw.first_instance = 0; + mapped->draw.instance_count = 0; mapped->dispatch_strings.x = 0; mapped->dispatch_strings.y = 1; mapped->dispatch_strings.z = 1; mapped->font_index = font_index; + mapped->drawable_count = 0; VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); command_copy_buffer(command_buffer, transfer, memory->layer, 0, 0, sizeof(UILayer)); - vkCmdFillBuffer(command_buffer, memory->rects, 0, sizeof(UIRect)*max_rects, 0x00000000); vkCmdFillBuffer(command_buffer, memory->strings, 0, sizeof(UIString)*max_strings, 0x00000000); - vkCmdFillBuffer(command_buffer, memory->glyphs, 0, sizeof(UIGlyph)*max_glyphs, 0x00000000); - vkCmdFillBuffer(command_buffer, memory->codes, 0, sizeof(uint32_t)*max_glyphs, 0x00000000); + vkCmdFillBuffer(command_buffer, memory->drawables, 0, sizeof(UIDrawable)*max_drawables, 0x00000000); + vkCmdFillBuffer(command_buffer, memory->codes, 0, sizeof(uint32_t)*max_codes, 0x00000000); VK_RESULT(command_end_single(device, command_buffer, transfer_pool, transfer_queue)); vkQueueWaitIdle(transfer_queue.handle); destroy_transfer_buffer(allocator, transfer, transfer_memory); @@ -805,9 +734,7 @@ VkResult create_ui_context( VK_RESULT(create_ui_descriptor(device, max_fonts, &memory->font_samplers, &memory->font_textures, &memory->font_samplers_layout, &memory->font_textures_layout, &memory->fonts_pool)); - VK_RESULT(create_ui_rect_pipeline(device, render_pass, memory->font_samplers_layout, memory->font_textures_layout, &memory->rect_pipeline)); - - VK_RESULT(create_ui_text_pipeline(device, render_pass, memory->font_samplers_layout, memory->font_textures_layout, &memory->char_pipeline, &memory->string_pipeline)); + VK_RESULT(create_ui_pipeline(device, render_pass, memory->font_samplers_layout, memory->font_textures_layout, &memory->pipeline, &memory->string_pipeline)); return VK_SUCCESS; }