Got text rendering bindless

main
noah metz 2024-10-18 18:34:31 -06:00
parent dc7f8ed750
commit 7720d696bc
7 changed files with 283 additions and 200 deletions

@ -33,10 +33,10 @@ typedef struct DispatchCommandStruct {
} DispatchCommand; } DispatchCommand;
typedef struct FontStruct { typedef struct FontStruct {
VkDeviceAddress symbol_list;
uint32_t num_symbols; uint32_t num_symbols;
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
VkDeviceAddress symbol_list;
} Font; } Font;
typedef struct SymbolInfoStruct { typedef struct SymbolInfoStruct {
@ -94,6 +94,10 @@ typedef struct UIlayerStorageStruct {
VmaAllocation layer_memory; VmaAllocation layer_memory;
VkDeviceAddress address; VkDeviceAddress address;
uint32_t max_glyphs;
uint32_t max_string;
uint32_t max_rects;
} UILayerStorage; } UILayerStorage;
typedef struct UILayerStruct { typedef struct UILayerStruct {
@ -106,11 +110,12 @@ typedef struct UILayerStruct {
DrawCommand draw_glyphs; DrawCommand draw_glyphs;
DrawCommand draw_rects; DrawCommand draw_rects;
DispatchCommand dispatch_strings; DispatchCommand dispatch_strings;
uint32_t font_index;
} UILayer; } UILayer;
typedef struct UIContextStruct { typedef struct UIContextStruct {
mat4 screen;
VkDeviceAddress font_infos; VkDeviceAddress font_infos;
mat4 screen;
} UIContext; } UIContext;
typedef struct UIContextStorageStruct { typedef struct UIContextStorageStruct {
@ -147,9 +152,7 @@ VkResult create_ui_context(
VkResult load_font( VkResult load_font(
VkDevice device, VkDevice device,
VmaAllocator allocator, VmaAllocator allocator,
VkBuffer font_infos, UIContextStorage* context,
VkDescriptorSet font_samplers,
VkDescriptorSet font_textures,
uint32_t index, uint32_t index,
VkCommandPool transfer_pool, VkCommandPool transfer_pool,
Queue transfer_queue, Queue transfer_queue,
@ -163,6 +166,7 @@ VkResult create_layer(
uint32_t max_strings, uint32_t max_strings,
uint32_t max_characters, uint32_t max_characters,
uint32_t max_rects, uint32_t max_rects,
uint32_t font_index,
VkDevice device, VkDevice device,
VmaAllocator allocator, VmaAllocator allocator,
VkCommandPool transfer_pool, VkCommandPool transfer_pool,

@ -5,7 +5,8 @@ struct String {
vec2 pos; vec2 pos;
vec4 color; vec4 color;
float size; float size;
uint code; uint offset;
uint length;
}; };
layout(std430, buffer_reference) readonly buffer StringList { layout(std430, buffer_reference) readonly buffer StringList {
@ -61,6 +62,8 @@ layout(std430, buffer_reference) buffer UILayer {
DrawCommand draw_rects; DrawCommand draw_rects;
DispatchCommand dispatch_strings; DispatchCommand dispatch_strings;
uint font_index;
}; };
struct Symbol { struct Symbol {
@ -89,8 +92,8 @@ layout(std430, buffer_reference) buffer FontList {
}; };
layout(std430, buffer_reference) buffer UIContext { layout(std430, buffer_reference) buffer UIContext {
mat4 screen;
FontList fonts; FontList fonts;
mat4 screen;
}; };
layout(std430, push_constant) uniform PushConstant { layout(std430, push_constant) uniform PushConstant {

@ -1,95 +1,121 @@
#version 450 #version 450
#extension GL_EXT_buffer_reference : require #extension GL_EXT_buffer_reference : require
layout(buffer_reference, std430) buffer Symbol { struct String {
int top; vec2 pos;
uint left; vec4 color;
uint width; float size;
uint height; uint offset;
uint advance; uint len;
};
layout(std430, buffer_reference) readonly buffer StringList {
String s[];
}; };
layout(buffer_reference, std430) buffer Character { struct Glyph {
vec3 pos; vec2 pos;
vec4 color; vec4 color;
float size; float size;
uint code; uint code;
}; };
layout(buffer_reference, std430) buffer String { layout(std430, buffer_reference) readonly buffer GlyphList {
vec3 pos; Glyph g[];
};
struct Rect {
vec2 pos;
vec2 size;
vec4 color; vec4 color;
float size;
uint offset;
uint len;
}; };
layout(buffer_reference, std430) readonly buffer SymbolList{ layout(std430, buffer_reference) readonly buffer RectList {
Symbol symbols[]; Rect r[];
}; };
layout(buffer_reference, std430) writeonly buffer CharacterList{ layout(std430, buffer_reference) readonly buffer CodeList {
Character characters[]; uint c[];
}; };
layout(buffer_reference, std430) readonly buffer Characters{ struct DrawCommand {
uint codes[]; uint vertex_count;
uint instance_count;
uint fist_vertex;
uint first_instance;
}; };
layout(buffer_reference, std430) readonly buffer Strings{ struct DispatchCommand {
String strings[]; uint x;
uint y;
uint z;
}; };
layout(buffer_reference, std430) readonly buffer Font { layout(std430, buffer_reference) buffer UILayer {
uint num_symbols; 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 width;
uint height; uint height;
SymbolList symbol_list; uint advance;
}; };
layout(buffer_reference, std430) buffer DrawCommand { layout(std430, buffer_reference) buffer SymbolList {
uint vertex_count; Symbol s[];
uint instance_count;
uint first_vertx;
uint first_instance;
}; };
layout(buffer_reference, std430) readonly buffer Pointers {
Strings strings; struct Font {
Characters codes; SymbolList symbols;
CharacterList characters; uint num_symbols;
DrawCommand draw; uint width;
uint height;
}; };
layout(buffer_reference, std430) readonly buffer FontList {
Font fonts[]; layout(std430, buffer_reference) buffer FontList {
Font f[];
}; };
layout(buffer_reference, std430) readonly buffer UIContext { layout(std430, buffer_reference) buffer UIContext {
mat4 screen;
FontList fonts; FontList fonts;
mat4 screen;
}; };
layout(std430, push_constant) uniform Push { layout(std430, push_constant) uniform PushConstant {
UIContext ui; UIContext context;
Pointers pointers; UILayer layer;
} push; } pc;
layout(local_size_x = 1) in; layout(local_size_x = 1) in;
void main() { void main() {
uint gID = gl_GlobalInvocationID.x; uint gID = gl_GlobalInvocationID.x;
String string = push.pointers.strings.strings[gID]; String string = pc.layer.strings.s[gID];
Font font = push.ui.fonts.fonts[0]; Font font = pc.context.fonts.f[pc.layer.font_index];
uint buffer_pos = atomicAdd(push.pointers.draw.instance_count, string.len); uint buffer_pos = atomicAdd(pc.layer.draw_glyphs.instance_count, string.len);
float x = 0; float x = 0;
for(uint i = 0; i < string.len; i++) { for(uint i = 0; i < string.len; i++) {
Symbol symbol = font.symbol_list.symbols[push.pointers.codes.codes[string.offset + i]]; Symbol symbol = font.symbols.s[pc.layer.codes.c[string.offset + i]];
push.pointers.characters.characters[buffer_pos + i].pos = string.pos + vec3(x, 0, 0); pc.layer.glyphs.g[buffer_pos + i].pos = string.pos + vec2(x, 0);
x += string.size*symbol.advance/font.width; x += string.size*symbol.advance/font.width;
push.pointers.characters.characters[buffer_pos + i].size = string.size; pc.layer.glyphs.g[buffer_pos + i].size = string.size;
push.pointers.characters.characters[buffer_pos + i].color = string.color; pc.layer.glyphs.g[buffer_pos + i].color = string.color;
push.pointers.characters.characters[buffer_pos + i].code = push.pointers.codes.codes[string.offset + i]; pc.layer.glyphs.g[buffer_pos + i].code = pc.layer.codes.c[string.offset + i];
} }
} }

@ -1,55 +1,105 @@
#version 450 #version 450
#extension GL_EXT_buffer_reference : require #extension GL_EXT_buffer_reference : require
layout(buffer_reference, std430) buffer Symbol { struct String {
int top; vec2 pos;
uint left; vec4 color;
uint width; float size;
uint height; uint offset;
uint advance; uint length;
};
layout(std430, buffer_reference) readonly buffer StringList {
String s[];
}; };
layout(buffer_reference, std430) buffer Character { struct Glyph {
vec3 pos; vec2 pos;
vec4 color; vec4 color;
float size; float size;
uint code; uint code;
}; };
layout(buffer_reference, std430) readonly buffer SymbolList{ layout(std430, buffer_reference) readonly buffer GlyphList {
Symbol symbols[]; Glyph g[];
}; };
layout(buffer_reference, std430) readonly buffer CharacterList{ struct Rect {
Character characters[]; vec2 pos;
vec2 size;
vec4 color;
}; };
layout(buffer_reference, std430) readonly buffer Font { layout(std430, buffer_reference) readonly buffer RectList {
uint num_symbols; 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 width;
uint height; uint height;
SymbolList symbol_list; uint advance;
};
layout(std430, buffer_reference) buffer SymbolList {
Symbol s[];
}; };
layout(buffer_reference, std430) readonly buffer Pointers {
uint padding[4];
CharacterList characters;
struct Font {
SymbolList symbols;
uint num_symbols;
uint width;
uint height;
}; };
layout(buffer_reference, std430) readonly buffer FontList {
Font fonts[]; layout(std430, buffer_reference) buffer FontList {
Font f[];
}; };
layout(buffer_reference, std430) readonly buffer UIContext { layout(std430, buffer_reference) buffer UIContext {
mat4 screen;
FontList fonts; FontList fonts;
mat4 screen;
}; };
layout(std430, push_constant) uniform Push { layout(std430, push_constant) uniform PushConstant {
UIContext ui; UIContext context;
Pointers pointers; UILayer layer;
} push; } pc;
layout(location = 0) out vec4 fragColor; layout(location = 0) out vec4 fragColor;
layout(location = 1) out vec2 fragUV; layout(location = 1) out vec2 fragUV;
@ -66,19 +116,19 @@ const vec2 square[6] = {
}; };
void main() { void main() {
Character character = push.pointers.characters.characters[gl_InstanceIndex]; Glyph glyph = pc.layer.glyphs.g[gl_InstanceIndex];
Font font = push.ui.fonts.fonts[0]; Font font = pc.context.fonts.f[pc.layer.font_index];
Symbol symbol = font.symbol_list.symbols[character.code]; Symbol symbol = font.symbols.s[glyph.code];
float fragU = square[gl_VertexIndex].x * symbol.width/font.width; float fragU = square[gl_VertexIndex].x * symbol.width/font.width;
float fragV = square[gl_VertexIndex].y * symbol.height/font.height; float fragV = square[gl_VertexIndex].y * symbol.height/font.height;
float x = (square[gl_VertexIndex].x * symbol.width + symbol.left) * character.size / font.width; float x = (square[gl_VertexIndex].x * symbol.width + symbol.left) * glyph.size / font.width;
float y = (square[gl_VertexIndex].y * symbol.height - symbol.top) * character.size / font.height; float y = (square[gl_VertexIndex].y * symbol.height - symbol.top) * glyph.size / font.height;
fragUV = vec2(fragU, fragV); fragUV = vec2(fragU, fragV);
fragColor = character.color; fragColor = glyph.color;
gl_Position = push.ui.screen * vec4(vec3(x, y, 0.0) + character.pos, 1.0); gl_Position = pc.context.screen * vec4(vec2(x, y) + glyph.pos, 0.0, 1.0);
code = character.code; code = glyph.code;
font_index = 0; font_index = pc.layer.font_index;
} }

@ -9,7 +9,7 @@
#include "ft2build.h" #include "ft2build.h"
#include FT_FREETYPE_H #include FT_FREETYPE_H
VkResult render_thread(GLFWwindow* window, RenderContext* render_context) { VkResult render_thread(GLFWwindow* window, RenderContext* render) {
FT_Library library; FT_Library library;
UIContextStorage ui; UIContextStorage ui;
@ -24,26 +24,26 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render_context) {
VkResult result; VkResult result;
VK_RESULT(create_ui_context( VK_RESULT(create_ui_context(
render_context->device, render->device,
render_context->allocator, render->allocator,
render_context->render_pass, render->render_pass,
10, 10,
render_context->swapchain_extent, render->swapchain_extent,
render_context->window_scale, render->window_scale,
render_context->transfer_pool, render->transfer_pool,
render_context->transfer_queue, render->transfer_queue,
&ui)); &ui));
if(FT_Init_FreeType(&library) != FT_Err_Ok) { if(FT_Init_FreeType(&library) != FT_Err_Ok) {
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
VK_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, &font)); 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, render_context->device, render_context->allocator, render_context->transfer_pool, render_context->transfer_queue, &layers[0])); 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, render_context->device, render_context->allocator, render_context->transfer_pool, render_context->transfer_queue, &layers[1])); VK_RESULT(create_layer(10, 100, 10, 0, render->device, render->allocator, render->transfer_pool, render->transfer_queue, &layers[1]));
VK_RESULT(create_transfer_buffer(render_context->allocator, sizeof(uint32_t) + 2*sizeof(UIRect), &transfer, &transfer_memory, &mapped)); VK_RESULT(create_transfer_buffer(render->allocator, sizeof(uint32_t) + 2*sizeof(UIRect) + sizeof(UIString) + 100*sizeof(uint32_t), &transfer, &transfer_memory, &mapped));
uint32_t* mapped_count = (uint32_t*)(mapped); uint32_t* mapped_count = (uint32_t*)(mapped);
mapped_count[0] = 1; mapped_count[0] = 1;
@ -66,19 +66,39 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render_context) {
mapped_rect[1].color[2] = 0.0; mapped_rect[1].color[2] = 0.0;
mapped_rect[1].color[3] = 1.0; mapped_rect[1].color[3] = 1.0;
VkCommandBuffer command_buffer = command_begin_single(render_context->device, render_context->transfer_pool); UIString* mapped_string = (UIString*)(mapped + sizeof(uint32_t) + 2*sizeof(UIRect));
mapped_string->pos[0] = 0.0;
mapped_string->pos[1] = 200.0;
mapped_string->size = 100.0;
mapped_string->color[0] = 1.0;
mapped_string->color[1] = 1.0;
mapped_string->color[2] = 1.0;
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));
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[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, 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].rects, sizeof(uint32_t), 0, sizeof(UIRect)); 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[1].rects, sizeof(uint32_t) + sizeof(UIRect), 0, sizeof(UIRect));
VK_RESULT(command_end_single(render_context->device, command_buffer, render_context->transfer_pool, render_context->transfer_queue));
vkQueueWaitIdle(render_context->transfer_queue.handle); command_copy_buffer(command_buffer, transfer, layers[1].strings, sizeof(uint32_t) + 2*sizeof(UIRect), 0, sizeof(UIString));
destroy_transfer_buffer(render_context->allocator, transfer, transfer_memory); command_copy_buffer(command_buffer, transfer, layers[1].codes, sizeof(uint32_t) + 2*sizeof(UIRect) + 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);
while(glfwWindowShouldClose(window) == 0) { while(glfwWindowShouldClose(window) == 0) {
glfwPollEvents(); glfwPollEvents();
result = draw_frame(render_context, &ui, layers, 2); result = draw_frame(render, &ui, layers, sizeof(layers)/sizeof(UILayerStorage));
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result)); fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result));
return result; return result;
@ -101,12 +121,12 @@ int main() {
return 1; return 1;
} }
RenderContext render_context = {}; RenderContext render = {};
if(init_vulkan(window, &render_context) != VK_SUCCESS) { if(init_vulkan(window, &render) != VK_SUCCESS) {
return 2; return 2;
} }
if(render_thread(window, &render_context) != VK_SUCCESS) { if(render_thread(window, &render) != VK_SUCCESS) {
return 3; return 3;
} }

@ -1041,8 +1041,46 @@ VkResult draw_frame(RenderContext* context, UIContextStorage* ui_context, UILaye
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, ui_context->string_pipeline.pipeline); vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, ui_context->string_pipeline.pipeline);
for(uint32_t i = 0; i < ui_layer_count; i++) { for(uint32_t i = 0; i < ui_layer_count; i++) {
push[1] = ui_layers[i].address; push[1] = ui_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),
.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);
VkBufferMemoryBarrier draw_command_barrier_2 = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.buffer = ui_layers[i].layer,
.offset = offsetof(UILayer, draw_glyphs),
.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); 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, ui_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),
.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 = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.buffer = ui_layers[i].glyphs,
.offset = 0,
.size = sizeof(UIGlyph)*ui_layers[i].max_glyphs,
.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);
} }

@ -341,6 +341,7 @@ VkResult create_layer(
uint32_t max_strings, uint32_t max_strings,
uint32_t max_glyphs, uint32_t max_glyphs,
uint32_t max_rects, uint32_t max_rects,
uint32_t font_index,
VkDevice device, VkDevice device,
VmaAllocator allocator, VmaAllocator allocator,
VkCommandPool transfer_pool, VkCommandPool transfer_pool,
@ -348,6 +349,10 @@ VkResult create_layer(
UILayerStorage* memory) { UILayerStorage* memory) {
VkResult result; VkResult result;
memory->max_string = max_strings;
memory->max_glyphs = max_glyphs;
memory->max_rects = max_rects;
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, 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, 0, sizeof(UIRect)*max_rects, &memory->rects, &memory->rects_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(UIString)*max_strings, &memory->strings, &memory->strings_memory))
@ -376,8 +381,10 @@ VkResult create_layer(
mapped->draw_rects.instance_count = 0; mapped->draw_rects.instance_count = 0;
mapped->dispatch_strings.x = 0; mapped->dispatch_strings.x = 0;
mapped->dispatch_strings.y = 0; mapped->dispatch_strings.y = 1;
mapped->dispatch_strings.z = 0; mapped->dispatch_strings.z = 1;
mapped->font_index = font_index;
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
command_copy_buffer(command_buffer, transfer, memory->layer, 0, 0, sizeof(UILayer)); command_copy_buffer(command_buffer, transfer, memory->layer, 0, 0, sizeof(UILayer));
@ -397,9 +404,7 @@ VkResult create_layer(
VkResult load_font( VkResult load_font(
VkDevice device, VkDevice device,
VmaAllocator allocator, VmaAllocator allocator,
VkBuffer font_infos, UIContextStorage* context,
VkDescriptorSet font_samplers,
VkDescriptorSet font_textures,
uint32_t index, uint32_t index,
VkCommandPool transfer_pool, VkCommandPool transfer_pool,
Queue transfer_queue, Queue transfer_queue,
@ -488,19 +493,7 @@ VkResult load_font(
} }
VkResult result; VkResult result;
VkBufferCreateInfo symbol_buffer_info = { VK_RESULT(create_storage_buffer(allocator, 0, sizeof(SymbolInfo)*info.num_symbols, &memory->symbols, &memory->symbol_memory));
.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)*info.num_symbols,
};
VmaAllocationCreateInfo symbol_memory_info = {
.usage = VMA_MEMORY_USAGE_GPU_ONLY,
};
result = vmaCreateBuffer(allocator, &symbol_buffer_info, &symbol_memory_info, &memory->symbols, &memory->symbol_memory, NULL);
if(result != VK_SUCCESS) {
return result;
}
VkImageCreateInfo image_info = { VkImageCreateInfo image_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
@ -522,61 +515,25 @@ VkResult load_font(
.usage = VMA_MEMORY_USAGE_GPU_ONLY, .usage = VMA_MEMORY_USAGE_GPU_ONLY,
}; };
result = vmaCreateImage(allocator, &image_info, &image_memory_info, &memory->image, &memory->image_memory, NULL); VK_RESULT(vmaCreateImage(allocator, &image_info, &image_memory_info, &memory->image, &memory->image_memory, NULL));
if(result != VK_SUCCESS) {
return result;
}
VkBufferCreateInfo staging_info = { VkBuffer transfer;
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, VmaAllocation transfer_memory;
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, void* mapped;
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, VK_RESULT(create_transfer_buffer(allocator, sizeof(Font) + image_size*info.num_symbols + sizeof(SymbolInfo)*info.num_symbols, &transfer, &transfer_memory, &mapped));
.size = sizeof(Font) + image_size*info.num_symbols + sizeof(SymbolInfo)*info.num_symbols,
}; info.symbol_list = buffer_address(device, memory->symbols);
VmaAllocationCreateInfo staging_memory_info = { memcpy(mapped, images, image_size*info.num_symbols);
.usage = VMA_MEMORY_USAGE_CPU_TO_GPU, memcpy(mapped + image_size*info.num_symbols, &info, sizeof(Font));
}; memcpy(mapped + image_size*info.num_symbols + sizeof(Font), symbols, sizeof(SymbolInfo)*info.num_symbols);
VkBuffer staging_buffer;
VmaAllocation staging_memory;
result = vmaCreateBuffer(allocator, &staging_info, &staging_memory_info, &staging_buffer, &staging_memory, NULL);
if(result != VK_SUCCESS) {
return result;
}
void* mapped_staging;
result = vmaMapMemory(allocator, staging_memory, &mapped_staging);
if(result != VK_SUCCESS) {
return result;
}
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 = memory->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(images);
free(symbols); free(symbols);
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
command_copy_buffer(command_buffer, transfer, context->font_infos, image_size*info.num_symbols, index*sizeof(Font), sizeof(Font));
VkBufferCopy info_copy = { command_copy_buffer(command_buffer, transfer, memory->symbols, image_size*info.num_symbols + sizeof(Font), 0, sizeof(SymbolInfo)*info.num_symbols);
.size = sizeof(Font),
.srcOffset = image_size*info.num_symbols,
.dstOffset = index*sizeof(Font),
};
vkCmdCopyBuffer(command_buffer, staging_buffer, font_infos, 1, &info_copy);
VkBufferCopy symbol_copy = {
.size = sizeof(SymbolInfo)*info.num_symbols,
.srcOffset = image_size*info.num_symbols + sizeof(Font),
.dstOffset = 0,
};
vkCmdCopyBuffer(command_buffer, staging_buffer, memory->symbols, 1, &symbol_copy);
VkImageMemoryBarrier first_barrier = { VkImageMemoryBarrier first_barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
@ -598,7 +555,7 @@ VkResult load_font(
.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.imageExtent = image_info.extent, .imageExtent = image_info.extent,
}; };
vkCmdCopyBufferToImage(command_buffer, staging_buffer, memory->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); vkCmdCopyBufferToImage(command_buffer, transfer, memory->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy);
VkImageMemoryBarrier second_barrier = { VkImageMemoryBarrier second_barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
@ -619,7 +576,8 @@ VkResult load_font(
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
return result; return result;
} }
vmaDestroyBuffer(allocator, staging_buffer, staging_memory); vkQueueWaitIdle(transfer_queue.handle);
destroy_transfer_buffer(allocator, transfer, transfer_memory);
VkImageViewCreateInfo view_info = { VkImageViewCreateInfo view_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
@ -664,7 +622,7 @@ VkResult load_font(
VkWriteDescriptorSet descriptor_writes[] = { VkWriteDescriptorSet descriptor_writes[] = {
{ {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = font_textures, .dstSet = context->font_textures,
.dstBinding = 0, .dstBinding = 0,
.dstArrayElement = index, .dstArrayElement = index,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
@ -673,7 +631,7 @@ VkResult load_font(
}, },
{ {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = font_samplers, .dstSet = context->font_samplers,
.dstBinding = 0, .dstBinding = 0,
.dstArrayElement = index, .dstArrayElement = index,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
@ -686,23 +644,8 @@ VkResult load_font(
return VK_SUCCESS; return VK_SUCCESS;
} }
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) { VkResult create_ui_descriptor(VkDevice device, uint32_t max_fonts, 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; 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[] = { VkDescriptorSetLayoutBinding font_sampler_bindings[] = {
{ {
.binding = 0, .binding = 0,
@ -839,7 +782,6 @@ VkResult create_ui_context(
VK_RESULT(create_storage_buffer(allocator, 0, sizeof(UIContext), &memory->context, &memory->context_memory)); VK_RESULT(create_storage_buffer(allocator, 0, sizeof(UIContext), &memory->context, &memory->context_memory));
VK_RESULT(create_storage_buffer(allocator, 0, sizeof(Font)*max_fonts, &memory->font_infos, &memory->font_infos_memory)); VK_RESULT(create_storage_buffer(allocator, 0, sizeof(Font)*max_fonts, &memory->font_infos, &memory->font_infos_memory));
VkBuffer transfer; VkBuffer transfer;
VmaAllocation transfer_memory; VmaAllocation transfer_memory;
UIContext* mapped; UIContext* mapped;
@ -861,7 +803,7 @@ VkResult create_ui_context(
destroy_transfer_buffer(allocator, transfer, transfer_memory); destroy_transfer_buffer(allocator, transfer, transfer_memory);
memory->address = buffer_address(device, memory->context); memory->address = buffer_address(device, memory->context);
VK_RESULT(create_ui_descriptor(device, allocator, max_fonts, &memory->font_infos, &memory->font_infos_memory, &memory->font_samplers, &memory->font_textures, &memory->font_samplers_layout, &memory->font_textures_layout, &memory->fonts_pool)); 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_rect_pipeline(device, render_pass, memory->font_samplers_layout, memory->font_textures_layout, &memory->rect_pipeline));