Got text and rects rendering from same pipeline

main
noah metz 2024-10-18 22:53:06 -06:00
parent 7720d696bc
commit eca8f30175
9 changed files with 235 additions and 451 deletions

@ -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,

@ -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;
}
}

@ -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));
}
}

@ -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;
}

@ -1,10 +0,0 @@
#version 450
layout(location = 0) in vec4 fragColor;
layout(location = 0) out vec4 outColor;
void main() {
outColor = fragColor;
}

@ -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;
}

@ -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);

@ -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);

@ -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;
}