From 62d3de16f779b8c580dfb2d670a7e0bd1786b017 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Sun, 12 Jul 2026 16:13:48 -0600 Subject: [PATCH] Changed strings to have their own code buffer instead of shared --- client/include/ui.h | 39 ++++++------- client/shader/string.comp | 2 +- client/shader/ui_common.glsl | 15 +++-- client/src/editor.c | 27 ++++----- client/src/gpu.c | 2 +- client/src/ui.c | 110 +++++++++++++++++++---------------- 6 files changed, 100 insertions(+), 95 deletions(-) diff --git a/client/include/ui.h b/client/include/ui.h index 76e6dac..08508f3 100644 --- a/client/include/ui.h +++ b/client/include/ui.h @@ -69,12 +69,13 @@ typedef struct TextureStruct { } Texture; typedef struct GPUStringStruct { - vec2 pos; - vec4 color; - float size; - uint32_t offset; - uint32_t length; - uint32_t font; + vec2 pos; + vec4 color; + float size; + uint32_t length; + uint32_t font; + uint32_t max_length; + VkDeviceAddress codes; } GPUString; typedef struct GPUDrawableStruct { @@ -91,47 +92,46 @@ typedef struct GPULayerStruct { DispatchCommand dispatch_strings; uint32_t max_drawables; - uint32_t max_codes; uint32_t max_strings; uint32_t num_drawables; VkDeviceAddress strings; - VkDeviceAddress codes; VkDeviceAddress drawables; VkDeviceAddress container; } GPULayer; +typedef struct StringResourcesStruct { + VkBuffer codes[MAX_FRAMES_IN_FLIGHT]; + VmaAllocation codes_memory[MAX_FRAMES_IN_FLIGHT]; + uint32_t* codes_buffer; +} StringResources; + typedef struct LayerStruct { VkBuffer strings[MAX_FRAMES_IN_FLIGHT]; - VkBuffer codes[MAX_FRAMES_IN_FLIGHT]; - VkBuffer drawables[MAX_FRAMES_IN_FLIGHT]; + VkBuffer drawables[MAX_FRAMES_IN_FLIGHT]; VkBuffer layer[MAX_FRAMES_IN_FLIGHT]; VmaAllocation strings_memory[MAX_FRAMES_IN_FLIGHT]; VmaAllocation drawables_memory[MAX_FRAMES_IN_FLIGHT]; - VmaAllocation codes_memory[MAX_FRAMES_IN_FLIGHT]; VmaAllocation layer_memory[MAX_FRAMES_IN_FLIGHT]; VkDeviceAddress address[MAX_FRAMES_IN_FLIGHT]; - GPUDrawable* drawables_buffer; - GPUString* strings_buffer; - uint32_t* codes_buffer; + GPUDrawable* drawables_buffer; + GPUString* strings_buffer; + StringResources* string_resources; GPULayer data; } Layer; typedef struct LayerInputStruct { uint32_t num_strings; - uint32_t num_codes; uint32_t num_drawables; - uint32_t max_codes; uint32_t max_strings; uint32_t max_drawables; - GPUString* strings; - uint32_t* codes; + GPUString* strings; GPUDrawable* drawables; } LayerInput; @@ -326,9 +326,8 @@ VkResult create_layer( Container* container); VkResult map_string( - const char * text, + const char* text, uint32_t* buffer, - uint32_t offset, uint32_t font, UIContext* context); diff --git a/client/shader/string.comp b/client/shader/string.comp index 66c2356..5c047ec 100644 --- a/client/shader/string.comp +++ b/client/shader/string.comp @@ -14,7 +14,7 @@ void main() { vec2 pen = vec2(0.0, 0.0); for(uint i = 0; i < string.len; i++) { - uint code = (pc.layer.codes.c[(string.offset + i)/4] >> ((string.offset + i) % 4)*8) & 0xFF; + uint code = (string.codes.c[i/4] >> (i % 4)*8) & 0xFF; Symbol symbol = font.symbols.s[code]; pc.layer.drawables.d[buffer_pos + i].pos = string.pos + pen; pen += string.size*symbol.advance; diff --git a/client/shader/ui_common.glsl b/client/shader/ui_common.glsl index bb97b10..b9d24fd 100644 --- a/client/shader/ui_common.glsl +++ b/client/shader/ui_common.glsl @@ -38,23 +38,24 @@ layout(std430, buffer_reference) buffer FontList { Font f[]; }; +layout(std430, buffer_reference) readonly buffer CodeList { + uint c[]; +}; + struct String { vec2 pos; vec4 color; float size; - uint offset; uint len; uint font; + uint max_len; + CodeList codes; }; layout(std430, buffer_reference) readonly buffer StringList { String s[]; }; -layout(std430, buffer_reference) readonly buffer CodeList { - uint c[]; -}; - struct Drawable { vec2 pos; vec2 size; @@ -86,14 +87,12 @@ layout(std430, buffer_reference) readonly buffer Container { layout(std430, buffer_reference) readonly buffer Layer { DrawCommand draw; DispatchCommand dispatch; - + uint max_drawables; - uint max_codes; uint max_strings; uint num_drawables; StringList strings; - CodeList codes; DrawableList drawables; Container container; }; diff --git a/client/src/editor.c b/client/src/editor.c index 00e7497..c4366ce 100644 --- a/client/src/editor.c +++ b/client/src/editor.c @@ -508,14 +508,17 @@ SAVED_COLOR_BUTTON_CALLBACK(11); // TODO: Make load from current state instead of having a default state VkResult color_ui(ClientContext* context) { + if(context_container(COLOR_PICK_CONTAINER_ID, &context->ui) != NULL) { + return VK_SUCCESS; + } + GPUString strings[] = { { .pos = {2, 150}, .color = {1, 1, 1, 1}, .size = 16, - .offset = 0, - .length = 9, .font = 0, + .max_length = 16, }, }; @@ -634,15 +637,11 @@ VkResult color_ui(ClientContext* context) { }, }; - uint32_t codes[9]; VkResult result; - VK_RESULT(map_string("#00000000", codes, 0, 0, &context->ui)); LayerInput layer = { .strings = strings, .num_strings = sizeof(strings)/sizeof(GPUString), - .codes = codes, - .num_codes = sizeof(codes)/sizeof(uint32_t), .drawables = drawables, .num_drawables = sizeof(drawables)/sizeof(GPUDrawable), }; @@ -723,7 +722,9 @@ VkResult color_ui(ClientContext* context) { .callback_count = sizeof(callbacks)/sizeof(UICallbacks), }; - return load_container(&container, &context->render, &context->ui); + VK_RESULT(load_container(&container, &context->render, &context->ui)); + Container* c = context_container(COLOR_PICK_CONTAINER_ID, &context->ui); + return update_ui_string(data->string, c, 0, 0, &context->ui, &context->render); } VkResult mode_string_ui(ClientContext* context) { @@ -733,17 +734,11 @@ VkResult mode_string_ui(ClientContext* context) { .pos = {0, 32}, .font = 0, .size = 32, - .length = strlen(ModeStrings[MODE_NONE]), .color = {1, 1, 1, 1}, + .max_length = 8, }; - uint32_t codes[8]; - VK_RESULT(map_string(ModeStrings[MODE_NONE], codes, 0, 0, &context->ui)); - LayerInput layer = { - .max_codes = 8, - .codes = codes, - .num_codes = strlen(ModeStrings[MODE_NONE]), .num_strings = 1, .strings = &string, }; @@ -756,7 +751,9 @@ VkResult mode_string_ui(ClientContext* context) { .size = {160, 40}, }; - return load_container(&container, &context->render, &context->ui); + VK_RESULT(load_container(&container, &context->render, &context->ui)); + Container* c = context_container(MODE_STRING_CONTAINER_ID, &context->ui); + return update_ui_string(ModeStrings[MODE_NONE], c, 0, 0, &context->ui, &context->render); } VkResult update_mode_string(ClientContext* context, EditorData* data) { diff --git a/client/src/gpu.c b/client/src/gpu.c index 25838a5..c8a9f7a 100644 --- a/client/src/gpu.c +++ b/client/src/gpu.c @@ -205,7 +205,7 @@ VkResult create_debug_messenger( VkDebugUtilsMessengerCreateInfoEXT messenger_info = { .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, - .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT, + .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, .pfnUserCallback = debug_callback, .pUserData = 0, }; diff --git a/client/src/ui.c b/client/src/ui.c index 380da7f..1243e7c 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -321,24 +321,38 @@ VkResult create_layer( Container* container) { VkResult result; - uint32_t max_strings = (input->num_strings > input->max_strings) ? input->num_strings : input->max_strings; - uint32_t max_codes = (input->num_codes > input->max_codes) ? input->num_codes : input->max_codes; + uint32_t max_strings = (input->num_strings > input->max_strings) ? input->num_strings : input->max_strings; uint32_t max_drawables = (input->num_drawables > input->max_drawables) ? input->num_drawables : input->max_drawables; + uint32_t total_max_codes = 0; + for(uint32_t s = 0; s < input->num_strings; s++) { + total_max_codes += input->strings[s].max_length; + } + if(max_strings > 0) { - container->layers[index].strings_buffer = malloc(sizeof(GPUString)*max_strings); + container->layers[index].strings_buffer = malloc(sizeof(GPUString)*max_strings); + container->layers[index].string_resources = malloc(sizeof(StringResources)*max_strings); + memset(container->layers[index].string_resources, 0, sizeof(StringResources)*max_strings); } if(max_drawables > 0) { container->layers[index].drawables_buffer = malloc(sizeof(GPUDrawable)*max_drawables); } - if(max_codes > 0) { - container->layers[index].codes_buffer = malloc(sizeof(uint32_t)*max_codes); + for(uint32_t s = 0; s < input->num_strings; s++) { + uint32_t max_len = input->strings[s].max_length; + if(max_len == 0) continue; + uint32_t codes_size = ((max_len + 3) / 4) * sizeof(uint32_t); + container->layers[index].string_resources[s].codes_buffer = malloc(codes_size); + memset(container->layers[index].string_resources[s].codes_buffer, 0, codes_size); + for(uint32_t f = 0; f < MAX_FRAMES_IN_FLIGHT; f++) { + VK_RESULT(create_storage_buffer(gpu->allocator, 0, codes_size, + &container->layers[index].string_resources[s].codes[f], + &container->layers[index].string_resources[s].codes_memory[f])); + } } for(uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - VK_RESULT(create_storage_buffer(gpu->allocator, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, sizeof(GPULayer), &container->layers[index].layer[i], &container->layers[index].layer_memory[i])); if(max_strings > 0) { VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(GPUString)*max_strings, &container->layers[index].strings[i], &container->layers[index].strings_memory[i])); @@ -351,8 +365,8 @@ VkResult create_layer( i, gpu); } - if(max_codes + max_drawables > 0) { - VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(GPUDrawable)*(max_drawables + max_codes), &container->layers[index].drawables[i], &container->layers[index].drawables_memory[i])); + if(total_max_codes + max_drawables > 0) { + VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(GPUDrawable)*(max_drawables + total_max_codes), &container->layers[index].drawables[i], &container->layers[index].drawables_memory[i])); VkDeviceAddress address = buffer_address(gpu->device, container->layers[index].drawables[i]); add_transfer( &address, @@ -362,17 +376,6 @@ VkResult create_layer( i, gpu); } - if(max_codes > 0) { - VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(uint32_t)*max_codes, &container->layers[index].codes[i], &container->layers[index].codes_memory[i])); - VkDeviceAddress address = buffer_address(gpu->device, container->layers[index].codes[i]); - add_transfer( - &address, - container->layers[index].layer[i], - offsetof(GPULayer, codes), - sizeof(VkDeviceAddress), - i, - gpu); - } container->layers[index].address[i] = buffer_address(gpu->device, container->layers[index].layer[i]); } @@ -396,15 +399,31 @@ VkResult create_layer( container->layers[index].data.dispatch_strings.y = 1; container->layers[index].data.dispatch_strings.z = 1; - container->layers[index].data.max_drawables = max_drawables + max_codes; + container->layers[index].data.max_drawables = max_drawables + total_max_codes; container->layers[index].data.max_strings = max_strings; - container->layers[index].data.max_codes = max_codes; container->layers[index].data.num_drawables = max_drawables; - add_transfers(&container->layers[index].data, container->layers[index].layer, 0, sizeof(GPULayer)-4*sizeof(VkDeviceAddress), gpu); + add_transfers(&container->layers[index].data, container->layers[index].layer, 0, sizeof(GPULayer)-3*sizeof(VkDeviceAddress), gpu); if(input->num_strings > 0) { memcpy(container->layers[index].strings_buffer, input->strings, sizeof(GPUString)*input->num_strings); + for(uint32_t s = 0; s < input->num_strings; s++) { + container->layers[index].strings_buffer[s].codes = 0; + } add_transfers(container->layers[index].strings_buffer, container->layers[index].strings, 0, sizeof(GPUString)*input->num_strings, gpu); + + for(uint32_t s = 0; s < input->num_strings; s++) { + if(input->strings[s].max_length == 0) continue; + for(uint32_t f = 0; f < MAX_FRAMES_IN_FLIGHT; f++) { + VkDeviceAddress addr = buffer_address(gpu->device, container->layers[index].string_resources[s].codes[f]); + add_transfer( + &addr, + container->layers[index].strings[f], + s * sizeof(GPUString) + offsetof(GPUString, codes), + sizeof(VkDeviceAddress), + f, + gpu); + } + } } if(input->num_drawables > 0) { @@ -412,11 +431,6 @@ VkResult create_layer( add_transfers(container->layers[index].drawables_buffer, container->layers[index].drawables, 0, sizeof(GPUDrawable)*input->num_drawables, gpu); } - if(input->num_codes > 0) { - memcpy(container->layers[index].codes_buffer, input->codes, sizeof(uint32_t)*input->num_codes); - add_transfers(container->layers[index].codes_buffer, container->layers[index].codes, 0, sizeof(uint32_t)*input->num_codes, gpu); - } - return VK_SUCCESS; } @@ -1170,14 +1184,13 @@ VkResult create_ui_context( } VkResult map_string( - const char * text, + const char* text, uint32_t* buffer, - uint32_t offset, uint32_t font, UIContext* context) { - size_t i = 0; - memset((uint8_t*)buffer + offset, 0, strlen(text)); - while(text[i] != '\0') { + size_t len = strlen(text); + memset(buffer, 0, ((len + 3) / 4) * sizeof(uint32_t)); + for(size_t i = 0; i < len; i++) { uint32_t mapped = 0xFFFFFFFF; for(uint32_t j = 0; j < context->fonts[font].num_symbols; j++) { if(context->fonts[font].charmap[j] == (uint32_t)text[i]) { @@ -1188,10 +1201,8 @@ VkResult map_string( if(mapped == 0xFFFFFFFF) { return VK_ERROR_UNKNOWN; } - buffer[(i + offset)/4] += mapped << ((i + offset) % 4)*8; - i += 1; + buffer[i/4] |= mapped << (i % 4)*8; } - return VK_SUCCESS; } @@ -1222,28 +1233,27 @@ VkResult update_ui_string( } Layer* layer = &container->layers[layer_index]; - layer->strings_buffer[string_index].length = strlen(string); - if(strlen(string) > 0) { - VK_RESULT(map_string( - string, - layer->codes_buffer, - layer->strings_buffer[string_index].offset, - layer->strings_buffer[string_index].font, - ui)); - VK_RESULT(add_transfers( - (uint8_t*)layer->codes_buffer + layer->strings_buffer[string_index].offset, - layer->codes, - layer->strings_buffer[string_index].offset, - strlen(string), - gpu)); + StringResources* sr = &layer->string_resources[string_index]; + uint32_t len = strlen(string); + + if(len > layer->strings_buffer[string_index].max_length) { + len = layer->strings_buffer[string_index].max_length; } + + layer->strings_buffer[string_index].length = len; + + if(len > 0) { + VK_RESULT(map_string(string, sr->codes_buffer, layer->strings_buffer[string_index].font, ui)); + VK_RESULT(add_transfers(sr->codes_buffer, sr->codes, 0, ((len + 3) / 4) * sizeof(uint32_t), gpu)); + } + VK_RESULT(add_transfers( &layer->strings_buffer[string_index].length, layer->strings, sizeof(GPUString)*string_index + offsetof(GPUString, length), sizeof(uint32_t), gpu)); - + return VK_SUCCESS; }