Changed strings to have their own code buffer instead of shared

main
noah metz 2026-07-12 16:13:48 -06:00
parent b9f6b69201
commit 62d3de16f7
6 changed files with 100 additions and 95 deletions

@ -72,9 +72,10 @@ typedef struct GPUStringStruct {
vec2 pos;
vec4 color;
float size;
uint32_t offset;
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 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;
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;
GPUDrawable* drawables;
} LayerInput;
@ -328,7 +328,6 @@ VkResult create_layer(
VkResult map_string(
const char* text,
uint32_t* buffer,
uint32_t offset,
uint32_t font,
UIContext* context);

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

@ -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;
@ -88,12 +89,10 @@ layout(std430, buffer_reference) readonly buffer Layer {
DispatchCommand dispatch;
uint max_drawables;
uint max_codes;
uint max_strings;
uint num_drawables;
StringList strings;
CodeList codes;
DrawableList drawables;
Container container;
};

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

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

@ -322,23 +322,37 @@ VkResult create_layer(
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_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].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;
}
@ -1172,12 +1186,11 @@ VkResult create_ui_context(
VkResult map_string(
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,21 +1233,20 @@ 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,