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

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

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

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

@ -9,7 +9,7 @@
#include "ft2build.h"
#include FT_FREETYPE_H
VkResult render_thread(GLFWwindow* window, RenderContext* render_context) {
VkResult render_thread(GLFWwindow* window, RenderContext* render) {
FT_Library library;
UIContextStorage ui;
@ -24,26 +24,26 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render_context) {
VkResult result;
VK_RESULT(create_ui_context(
render_context->device,
render_context->allocator,
render_context->render_pass,
render->device,
render->allocator,
render->render_pass,
10,
render_context->swapchain_extent,
render_context->window_scale,
render_context->transfer_pool,
render_context->transfer_queue,
render->swapchain_extent,
render->window_scale,
render->transfer_pool,
render->transfer_queue,
&ui));
if(FT_Init_FreeType(&library) != FT_Err_Ok) {
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, 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[0]));
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);
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[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[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[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);
destroy_transfer_buffer(render_context->allocator, transfer, transfer_memory);
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));
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) {
glfwPollEvents();
result = draw_frame(render_context, &ui, layers, 2);
result = draw_frame(render, &ui, layers, sizeof(layers)/sizeof(UILayerStorage));
if(result != VK_SUCCESS) {
fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result));
return result;
@ -101,12 +121,12 @@ int main() {
return 1;
}
RenderContext render_context = {};
if(init_vulkan(window, &render_context) != VK_SUCCESS) {
RenderContext render = {};
if(init_vulkan(window, &render) != VK_SUCCESS) {
return 2;
}
if(render_thread(window, &render_context) != VK_SUCCESS) {
if(render_thread(window, &render) != VK_SUCCESS) {
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);
for(uint32_t i = 0; i < ui_layer_count; i++) {
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);
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_glyphs,
uint32_t max_rects,
uint32_t font_index,
VkDevice device,
VmaAllocator allocator,
VkCommandPool transfer_pool,
@ -348,6 +349,10 @@ VkResult create_layer(
UILayerStorage* memory) {
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, 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))
@ -376,8 +381,10 @@ VkResult create_layer(
mapped->draw_rects.instance_count = 0;
mapped->dispatch_strings.x = 0;
mapped->dispatch_strings.y = 0;
mapped->dispatch_strings.z = 0;
mapped->dispatch_strings.y = 1;
mapped->dispatch_strings.z = 1;
mapped->font_index = font_index;
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
command_copy_buffer(command_buffer, transfer, memory->layer, 0, 0, sizeof(UILayer));
@ -397,9 +404,7 @@ VkResult create_layer(
VkResult load_font(
VkDevice device,
VmaAllocator allocator,
VkBuffer font_infos,
VkDescriptorSet font_samplers,
VkDescriptorSet font_textures,
UIContextStorage* context,
uint32_t index,
VkCommandPool transfer_pool,
Queue transfer_queue,
@ -488,19 +493,7 @@ VkResult load_font(
}
VkResult 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)*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;
}
VK_RESULT(create_storage_buffer(allocator, 0, sizeof(SymbolInfo)*info.num_symbols, &memory->symbols, &memory->symbol_memory));
VkImageCreateInfo image_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
@ -522,61 +515,25 @@ VkResult load_font(
.usage = VMA_MEMORY_USAGE_GPU_ONLY,
};
result = vmaCreateImage(allocator, &image_info, &image_memory_info, &memory->image, &memory->image_memory, NULL);
if(result != VK_SUCCESS) {
return result;
}
VK_RESULT(vmaCreateImage(allocator, &image_info, &image_memory_info, &memory->image, &memory->image_memory, NULL));
VkBufferCreateInfo staging_info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.size = sizeof(Font) + image_size*info.num_symbols + sizeof(SymbolInfo)*info.num_symbols,
};
VkBuffer transfer;
VmaAllocation transfer_memory;
void* mapped;
VK_RESULT(create_transfer_buffer(allocator, sizeof(Font) + image_size*info.num_symbols + sizeof(SymbolInfo)*info.num_symbols, &transfer, &transfer_memory, &mapped));
info.symbol_list = buffer_address(device, memory->symbols);
VmaAllocationCreateInfo staging_memory_info = {
.usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
};
memcpy(mapped, images, image_size*info.num_symbols);
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(symbols);
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
VkBufferCopy info_copy = {
.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);
command_copy_buffer(command_buffer, transfer, context->font_infos, image_size*info.num_symbols, index*sizeof(Font), sizeof(Font));
command_copy_buffer(command_buffer, transfer, memory->symbols, image_size*info.num_symbols + sizeof(Font), 0, sizeof(SymbolInfo)*info.num_symbols);
VkImageMemoryBarrier first_barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
@ -598,7 +555,7 @@ VkResult load_font(
.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.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 = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
@ -619,7 +576,8 @@ VkResult load_font(
if(result != VK_SUCCESS) {
return result;
}
vmaDestroyBuffer(allocator, staging_buffer, staging_memory);
vkQueueWaitIdle(transfer_queue.handle);
destroy_transfer_buffer(allocator, transfer, transfer_memory);
VkImageViewCreateInfo view_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
@ -664,7 +622,7 @@ VkResult load_font(
VkWriteDescriptorSet descriptor_writes[] = {
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = font_textures,
.dstSet = context->font_textures,
.dstBinding = 0,
.dstArrayElement = index,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
@ -673,7 +631,7 @@ VkResult load_font(
},
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = font_samplers,
.dstSet = context->font_samplers,
.dstBinding = 0,
.dstArrayElement = index,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
@ -686,23 +644,8 @@ VkResult load_font(
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) {
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 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) {
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,
@ -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(Font)*max_fonts, &memory->font_infos, &memory->font_infos_memory));
VkBuffer transfer;
VmaAllocation transfer_memory;
UIContext* mapped;
@ -861,7 +803,7 @@ VkResult create_ui_context(
destroy_transfer_buffer(allocator, transfer, transfer_memory);
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));