Moved glsl structures to common file, added convenience functions for UI elements

main
noah metz 2024-10-20 21:59:28 -06:00
parent eca8f30175
commit 8c793d36c3
9 changed files with 358 additions and 264 deletions

@ -59,10 +59,10 @@ debug: roleplay $(EXTRA_DEBUG_REQUIREMENTS) $(SPV_FILES)
$(GDB) roleplay
%.vert.spv: %.vert
glslangValidator -V -o $@ $<
glslc -o $@ $<
%.frag.spv: %.frag
glslangValidator -V -o $@ $<
glslc -o $@ $<
%.comp.spv: %.comp
glslangValidator -V -o $@ $<
glslc -o $@ $<

@ -67,6 +67,32 @@ typedef struct UIStringStruct {
uint32_t length;
} UIString;
typedef struct UIDrawableStruct {
vec2 pos;
vec2 size;
vec4 color;
uint32_t type;
uint32_t code;
} UIDrawable;
typedef struct UILayerStruct {
VkDeviceAddress strings;
VkDeviceAddress codes;
VkDeviceAddress drawables;
DrawCommand draw;
DispatchCommand dispatch_strings;
uint32_t font_index;
uint32_t max_drawables;
uint32_t max_codes;
uint32_t max_strings;
uint32_t num_drawables;
VkDeviceAddress container;
} UILayer;
typedef struct UIlayerStorageStruct {
VkBuffer strings;
VkBuffer codes;
@ -80,36 +106,28 @@ typedef struct UIlayerStorageStruct {
VkDeviceAddress address;
uint32_t max_strings;
uint32_t max_codes;
uint32_t max_drawables;
uint32_t drawable_count;
UILayer data;
} UILayerStorage;
typedef struct UIDrawableStruct {
typedef struct UIContainerStruct {
vec2 pos;
vec2 size;
vec4 color;
uint32_t type;
uint32_t code;
} UIDrawable;
} UIContainer;
typedef struct UILayerStruct {
VkDeviceAddress strings;
VkDeviceAddress codes;
typedef struct UIContainerStorageStruct {
VkBuffer container;
VkDeviceAddress drawables;
VmaAllocation container_memory;
DrawCommand draw;
DispatchCommand dispatch_strings;
VkDeviceAddress address;
uint32_t font_index;
uint32_t drawable_count;
} UILayer;
UIContainer data;
} UIContainerStorage;
typedef struct UIContextStruct {
VkDeviceAddress font_infos;
mat4 screen;
vec2 screen;
vec2 scale;
} UIContext;
typedef struct UIContextStorageStruct {
@ -129,6 +147,8 @@ typedef struct UIContextStorageStruct {
GraphicsPipeline pipeline;
ComputePipeline string_pipeline;
UIContext data;
} UIContextStorage;
VkResult create_ui_context(
@ -155,6 +175,17 @@ VkResult load_font(
VkBool32 antialias,
FontStorage* memory);
VkResult create_container(
float x,
float y,
float width,
float height,
VkDevice device,
VmaAllocator allocator,
VkCommandPool transfer_pool,
Queue transfer_queue,
UIContainerStorage* memory);
VkResult create_layer(
uint32_t max_strings,
uint32_t max_codes,
@ -164,5 +195,37 @@ VkResult create_layer(
VmaAllocator allocator,
VkCommandPool transfer_pool,
Queue transfer_queue,
UIContainerStorage* container,
UILayerStorage* memory);
void set_ui_rect(
float x,
float y,
float width,
float height,
float r,
float g,
float b,
float a,
UIDrawable* drawable);
void set_ui_string(
float x,
float y,
float size,
float r,
float g,
float b,
float a,
uint32_t length,
uint32_t offset,
UIString* string);
VkResult set_ui_codes(
const char * text,
uint32_t* buffer,
uint32_t offset,
uint32_t* charmap,
uint32_t charmap_size);
#endif

@ -1,93 +1,11 @@
#version 450
#extension GL_EXT_buffer_reference : require
struct String {
vec2 pos;
vec4 color;
float size;
uint offset;
uint len;
};
layout(std430, buffer_reference) readonly buffer StringList {
String s[];
};
struct Drawable {
vec2 pos;
vec2 size;
vec4 color;
uint type;
uint code;
};
layout(std430, buffer_reference) writeonly buffer DrawableList {
Drawable d[];
};
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;
DrawableList drawables;
DrawCommand draw;
DispatchCommand dispatch;
uint font_index;
uint drawable_count;
};
struct Symbol {
int top;
uint left;
uint width;
uint height;
uint advance;
};
layout(std430, buffer_reference) buffer SymbolList {
Symbol s[];
};
struct Font {
SymbolList symbols;
uint num_symbols;
uint width;
uint height;
};
layout(std430, buffer_reference) buffer FontList {
Font f[];
};
layout(std430, buffer_reference) buffer UIContext {
FontList fonts;
mat4 screen;
};
#include "ui_common.glsl"
layout(std430, push_constant) uniform PushConstant {
UIContext context;
UILayer layer;
Context context;
Layer layer;
} pc;
layout(local_size_x = 1) in;

@ -1,5 +1,13 @@
#version 450
#extension GL_EXT_nonuniform_qualifier : enable
#extension GL_EXT_nonuniform_qualifier : require
#extension GL_EXT_buffer_reference : require
#include "ui_common.glsl"
layout(std430, push_constant) uniform PushConstant {
Context context;
Layer layer;
} pc;
layout(set = 0, binding = 0) uniform sampler font_samplers[];
layout(set = 1, binding = 0) uniform texture2DArray font_textures[];
@ -13,6 +21,13 @@ layout(location = 4) flat in uint type;
layout(location = 0) out vec4 outColor;
void main() {
vec2 pos = gl_FragCoord.xy - vec2(0.5, 0.5);
vec2 min = pc.layer.container.pos;
vec2 max = min + pc.layer.container.size;
if(pos.x < min.x || pos.y < min.y
|| pos.x > max.x || pos.y > max.y) {
discard;
}
if(type == 0) {
outColor = fragColor;
} else if(type == 1) {

@ -1,91 +1,11 @@
#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 Drawable {
vec2 pos;
vec2 size;
vec4 color;
uint type;
uint code;
};
layout(std430, buffer_reference) readonly buffer DrawableList {
Drawable d[];
};
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;
DrawableList drawables;
DrawCommand draw;
DispatchCommand dispatch;
uint font_index;
uint drawable_count;
};
struct Symbol {
int top;
uint left;
uint width;
uint height;
uint advance;
};
layout(std430, buffer_reference) buffer SymbolList {
Symbol s[];
};
struct Font {
SymbolList symbols;
uint num_symbols;
uint width;
uint height;
};
layout(std430, buffer_reference) buffer FontList {
Font f[];
};
layout(std430, buffer_reference) buffer UIContext {
FontList fonts;
mat4 screen;
};
#include "ui_common.glsl"
layout(std430, push_constant) uniform PushConstant {
UIContext context;
UILayer layer;
Context context;
Layer layer;
} pc;
layout(location = 0) out vec4 fragColor;
@ -104,24 +24,28 @@ const vec2 square[6] = {
};
void main() {
vec2 scale = pc.context.scale / pc.context.screen;
Drawable drawable = pc.layer.drawables.d[gl_InstanceIndex];
vec2 pos = square[gl_VertexIndex];
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);
float scalex = float(symbol.width)/float(font.width);
float scaley = float(symbol.height)/float(font.height);
float offx = float(symbol.left)/float(font.width);
float offy = float(symbol.top)/float(font.height);
fragUV = pos * vec2(scalex, scaley);
pos = pos * vec2(scalex, scaley) + vec2(offx, -offy);
}
gl_Position = vec4((pos * drawable.size + drawable.pos + pc.layer.container.pos) * scale, 0.0, 1.0) - vec4(1.0, 1.0, 0.0, 0.0);
fragColor = drawable.color;
code = drawable.code;
type = drawable.type;

@ -0,0 +1,95 @@
struct DrawCommand {
uint vertex_count;
uint instance_count;
uint fist_vertex;
uint first_instance;
};
layout(std430, buffer_reference) buffer DrawCommandList {
DrawCommand d[];
};
struct DispatchCommand {
uint x;
uint y;
uint z;
};
struct Symbol {
int top;
uint left;
uint width;
uint height;
uint advance;
};
layout(std430, buffer_reference) buffer SymbolList {
Symbol s[];
};
struct Font {
SymbolList symbols;
uint num_symbols;
uint width;
uint height;
};
layout(std430, buffer_reference) buffer FontList {
Font f[];
};
struct String {
vec2 pos;
vec4 color;
float size;
uint offset;
uint len;
};
layout(std430, buffer_reference) readonly buffer StringList {
String s[];
};
layout(std430, buffer_reference) readonly buffer CodeList {
uint c[];
};
struct Drawable {
vec2 pos;
vec2 size;
vec4 color;
uint type;
uint code;
};
layout(std430, buffer_reference) readonly buffer DrawableList {
Drawable d[];
};
layout(std430, buffer_reference) readonly buffer Container {
vec2 pos;
vec2 size;
};
layout(std430, buffer_reference) readonly buffer Layer {
StringList strings;
CodeList codes;
DrawableList drawables;
DrawCommand draw;
DispatchCommand dispatch;
uint font_index;
uint max_drawables;
uint max_codes;
uint max_strings;
uint num_drawables;
Container container;
};
layout(std430, buffer_reference) buffer Context {
FontList fonts;
vec2 screen;
vec2 scale;
};

@ -13,6 +13,7 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render) {
FT_Library library;
UIContextStorage ui;
UIContainerStorage container;
UILayerStorage layers[2];
FontStorage font;
@ -40,8 +41,10 @@ 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, 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_container(100, 100, 200, 200, render->device, render->allocator, render->transfer_pool, render->transfer_queue, &container));
VK_RESULT(create_layer(10, 100, 10, 0, render->device, render->allocator, render->transfer_pool, render->transfer_queue, &container, &layers[0]));
VK_RESULT(create_layer(10, 100, 10, 0, render->device, render->allocator, render->transfer_pool, render->transfer_queue, &container, &layers[1]));
VK_RESULT(create_transfer_buffer(render->allocator, 2*sizeof(uint32_t) + 2*sizeof(UIDrawable) + sizeof(UIString) + 100*sizeof(uint32_t), &transfer, &transfer_memory, &mapped));
@ -49,44 +52,17 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render) {
mapped_count[0] = 1;
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;
set_ui_rect( 0.0, 0.0, 100.0, 200.0, 1.0, 0.0, 0.0, 1.0, &mapped_drawable[0]);
set_ui_rect(100.0, 0.0, 100.0, 200.0, 0.0, 1.0, 0.0, 1.0, &mapped_drawable[1]);
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;
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;
set_ui_string(0.0, 100.0, 16.0, 1.0, 1.0, 1.0, 1.0, 5, 0, &mapped_string[0]);
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;
}
VK_RESULT(set_ui_codes("Hello", mapped_codes, 0, font.charmap, font.num_symbols));
VkCommandBuffer command_buffer = command_begin_single(render->device, render->transfer_pool);
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[0].layer, 0, offsetof(UILayer, num_drawables), sizeof(uint32_t));
command_copy_buffer(command_buffer, transfer, layers[1].layer, 0, offsetof(UILayer, num_drawables), 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].drawables, 2*sizeof(uint32_t), 0, sizeof(UIDrawable));

@ -1051,7 +1051,7 @@ VkResult draw_frame(RenderContext* context, UIContextStorage* ui_context, UILaye
.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);
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));
command_copy_buffer(command_buffer, layers[i].layer, layers[i].layer, offsetof(UILayer, num_drawables), offsetof(UILayer, draw) + offsetof(DrawCommand, instance_count), sizeof(uint32_t));
VkBufferMemoryBarrier draw_command_barrier_2 = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.buffer = layers[i].layer,
@ -1077,7 +1077,7 @@ VkResult draw_frame(RenderContext* context, UIContextStorage* ui_context, UILaye
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.buffer = layers[i].drawables,
.offset = 0,
.size = sizeof(UIDrawable)*layers[i].max_drawables,
.size = sizeof(UIDrawable)*layers[i].data.max_drawables,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
};

@ -273,6 +273,41 @@ VkResult create_ui_pipeline(
return VK_SUCCESS;
}
VkResult create_container(
float x,
float y,
float width,
float height,
VkDevice device,
VmaAllocator allocator,
VkCommandPool transfer_pool,
Queue transfer_queue,
UIContainerStorage* memory) {
VkResult result;
VK_RESULT(create_storage_buffer(allocator, 0, sizeof(UIContainer), &memory->container, &memory->container_memory));
VkBuffer transfer;
VmaAllocation transfer_memory;
void* mapped;
VK_RESULT(create_transfer_buffer(allocator, sizeof(UIContainer), &transfer, &transfer_memory, &mapped));
memory->data.pos[0] = x;
memory->data.pos[1] = y;
memory->data.size[0] = width;
memory->data.size[1] = height;
memcpy(mapped, &memory->data, sizeof(UIContainer));
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
command_copy_buffer(command_buffer, transfer, memory->container, 0, 0, sizeof(UIContainer));
VK_RESULT(command_end_single(device, command_buffer, transfer_pool, transfer_queue));
destroy_transfer_buffer(allocator, transfer, transfer_memory);
memory->address = buffer_address(device, memory->container);
return VK_SUCCESS;
}
VkResult create_layer(
uint32_t max_strings,
uint32_t max_codes,
@ -282,39 +317,40 @@ VkResult create_layer(
VmaAllocator allocator,
VkCommandPool transfer_pool,
Queue transfer_queue,
UIContainerStorage* container,
UILayerStorage* memory) {
VkResult result;
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 | 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(UIDrawable)*max_drawables, &memory->drawables, &memory->drawables_memory));
VK_RESULT(create_storage_buffer(allocator, 0, sizeof(UIDrawable)*(max_drawables + max_codes), &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;
UILayer* mapped;
VK_RESULT(create_transfer_buffer(allocator, sizeof(UILayer), &transfer, &transfer_memory, (void**)&mapped));
void* mapped;
VK_RESULT(create_transfer_buffer(allocator, sizeof(UILayer), &transfer, &transfer_memory, &mapped));
mapped->strings = buffer_address(device, memory->strings);
mapped->codes = buffer_address(device, memory->codes);
memory->data.strings = buffer_address(device, memory->strings);
memory->data.codes = buffer_address(device, memory->codes);
mapped->drawables = buffer_address(device, memory->drawables);
memory->data.drawables = buffer_address(device, memory->drawables);
mapped->draw.first_vertex = 0;
mapped->draw.vertex_count = 6;
mapped->draw.first_instance = 0;
mapped->draw.instance_count = 0;
memory->data.draw.first_vertex = 0;
memory->data.draw.vertex_count = 6;
memory->data.draw.first_instance = 0;
memory->data.draw.instance_count = 0;
mapped->dispatch_strings.x = 0;
mapped->dispatch_strings.y = 1;
mapped->dispatch_strings.z = 1;
memory->data.dispatch_strings.x = 0;
memory->data.dispatch_strings.y = 1;
memory->data.dispatch_strings.z = 1;
mapped->font_index = font_index;
mapped->drawable_count = 0;
memory->data.font_index = font_index;
memory->data.max_drawables = max_drawables;
memory->data.max_strings = max_strings;
memory->data.num_drawables = 0;
memory->data.container = container->address;
memcpy(mapped, &memory->data, sizeof(UILayer));
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
command_copy_buffer(command_buffer, transfer, memory->layer, 0, 0, sizeof(UILayer));
@ -717,14 +753,12 @@ VkResult create_ui_context(
VK_RESULT(create_transfer_buffer(allocator, sizeof(UIContext), &transfer, &transfer_memory, (void**)&mapped));
mapped->font_infos = buffer_address(device, memory->font_infos);
vec3 screen_offset = {-1.0, -1.0, 0.0};
vec3 screen_scale = {
1.0/(float)swapchain_extent.width*window_scale[0],
1.0/(float)swapchain_extent.height*window_scale[1], 1.0};
glm_mat4_identity(mapped->screen);
glm_translate(mapped->screen, screen_offset);
glm_scale(mapped->screen, screen_scale);
memory->data.font_infos = buffer_address(device, memory->font_infos);
memory->data.screen[0] = swapchain_extent.width;
memory->data.screen[1] = swapchain_extent.height;
memory->data.scale[0] = window_scale[0];
memory->data.scale[1] = window_scale[1];
memcpy(mapped, &memory->data, sizeof(UIContext));
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
command_copy_buffer(command_buffer, transfer, memory->context, 0, 0, sizeof(UIContext));
@ -738,3 +772,72 @@ VkResult create_ui_context(
return VK_SUCCESS;
}
void set_ui_rect(
float x,
float y,
float width,
float height,
float r,
float g,
float b,
float a,
UIDrawable* drawable) {
drawable->pos[0] = x;
drawable->pos[1] = y;
drawable->size[0] = width;
drawable->size[1] = height;
drawable->color[0] = r;
drawable->color[1] = g;
drawable->color[2] = b;
drawable->color[3] = a;
drawable->type = 0;
drawable->code = 0;
}
void set_ui_string(
float x,
float y,
float size,
float r,
float g,
float b,
float a,
uint32_t length,
uint32_t offset,
UIString* string) {
string->pos[0] = x;
string->pos[1] = y;
string->size = size;
string->color[0] = r;
string->color[1] = g;
string->color[2] = b;
string->color[3] = a;
string->length = length;
string->offset = offset;
}
VkResult set_ui_codes(
const char * text,
uint32_t* buffer,
uint32_t offset,
uint32_t* charmap,
uint32_t charmap_size) {
size_t i = 0;
while(text[i] != '\0') {
uint32_t mapped = 0xFFFFFFFF;
for(uint32_t j = 0; j < charmap_size; j++) {
if(charmap[j] == (uint32_t)text[i]) {
mapped = j;
break;
}
}
if(mapped == 0xFFFFFFFF) {
return VK_ERROR_UNKNOWN;
}
buffer[i] = mapped;
i += 1;
}
return VK_SUCCESS;
}