Made 2 transfer buffers per-frame so that the in-use buffer is not modified

main
noah metz 2024-10-29 13:48:06 -06:00
parent e2ffed91e2
commit e39a454c5f
4 changed files with 59 additions and 47 deletions

@ -72,6 +72,19 @@ typedef struct TransferInfoStruct {
VkBuffer buffer; VkBuffer buffer;
} TransferInfo; } TransferInfo;
typedef struct TransferBufferStruct {
VkBuffer buffer;
VmaAllocation memory;
void* mapped;
size_t written;
size_t max_size;
size_t max_count;
TransferInfo* infos;
uint32_t count;
} TransferBuffer;
typedef struct FrameContextStruct { typedef struct FrameContextStruct {
VkFence ready; VkFence ready;
VkSemaphore image; VkSemaphore image;
@ -86,16 +99,8 @@ typedef struct FrameContextStruct {
VkCommandBuffer compute_commands; VkCommandBuffer compute_commands;
VkCommandBuffer transfer_commands; VkCommandBuffer transfer_commands;
VkBuffer transfer_buffer;
VmaAllocation transfer_memory;
void* transfer_mapped;
size_t transfer_written;
size_t transfer_max_size;
size_t transfer_max_count;
TransferInfo* transfer_infos; TransferBuffer transfers[2];
uint32_t transfer_count;
} FrameContext; } FrameContext;
typedef struct RenderContextStruct { typedef struct RenderContextStruct {

@ -67,21 +67,22 @@ VkResult draw_frame(
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
}; };
if(frame->transfer_count > 0) { TransferBuffer* transfer = &frame->transfers[frame->transfer_index % 2];
if(transfer->count > 0) {
VkCommandBuffer transfer_commands = frame->transfer_commands; VkCommandBuffer transfer_commands = frame->transfer_commands;
VK_RESULT(vkResetCommandBuffer(transfer_commands, 0)); VK_RESULT(vkResetCommandBuffer(transfer_commands, 0));
VK_RESULT(vkBeginCommandBuffer(transfer_commands, &begin_info)); VK_RESULT(vkBeginCommandBuffer(transfer_commands, &begin_info));
VkDeviceSize src_offset = 0; VkDeviceSize src_offset = 0;
for(uint32_t tid = 0; tid < frame->transfer_count; tid++) { for(uint32_t tid = 0; tid < transfer->count; tid++) {
command_copy_buffer( command_copy_buffer(
transfer_commands, transfer_commands,
frame->transfer_buffer, transfer->buffer,
frame->transfer_infos[tid].buffer, transfer->infos[tid].buffer,
src_offset, src_offset,
frame->transfer_infos[tid].offset, transfer->infos[tid].offset,
frame->transfer_infos[tid].size); transfer->infos[tid].size);
src_offset += frame->transfer_infos[tid].size; src_offset += transfer->infos[tid].size;
} }
VK_RESULT(vkEndCommandBuffer(transfer_commands)); VK_RESULT(vkEndCommandBuffer(transfer_commands));
@ -106,8 +107,8 @@ VkResult draw_frame(
.pNext = &transfer_timeline, .pNext = &transfer_timeline,
}; };
VK_RESULT(vkQueueSubmit(context->transfer_queue.handle, 1, &transfer_submit, VK_NULL_HANDLE)); VK_RESULT(vkQueueSubmit(context->transfer_queue.handle, 1, &transfer_submit, VK_NULL_HANDLE));
frame->transfer_count = 0; transfer->count = 0;
frame->transfer_written = 0; transfer->written = 0;
VkCommandBuffer compute_commands = frame->compute_commands; VkCommandBuffer compute_commands = frame->compute_commands;
VK_RESULT(vkResetCommandBuffer(compute_commands, 0)); VK_RESULT(vkResetCommandBuffer(compute_commands, 0));

@ -798,11 +798,17 @@ VkResult create_frame_context(VkDevice device, VmaAllocator allocator, VkCommand
VK_RESULT(vkAllocateCommandBuffers(device, &command_info, &frame->compute_commands)); VK_RESULT(vkAllocateCommandBuffers(device, &command_info, &frame->compute_commands));
// TODO: better defaults // TODO: better defaults
frame->transfer_max_size = 1; frame->transfers[0].max_size = 1;
frame->transfer_max_count = 1; frame->transfers[0].max_count = 1;
VK_RESULT(create_transfer_buffer(allocator, frame->transfer_max_size, &frame->transfer_buffer, &frame->transfer_memory, &frame->transfer_mapped)); frame->transfers[0].count = 0;
frame->transfer_count = 0; frame->transfers[0].infos = malloc(sizeof(TransferInfo)*frame->transfers[0].max_count);
frame->transfer_infos = malloc(sizeof(TransferInfo)*frame->transfer_max_count); VK_RESULT(create_transfer_buffer(allocator, frame->transfers[0].max_size, &frame->transfers[0].buffer, &frame->transfers[0].memory, &frame->transfers[0].mapped));
frame->transfers[1].max_size = 1;
frame->transfers[1].max_count = 1;
frame->transfers[1].count = 0;
frame->transfers[1].infos = malloc(sizeof(TransferInfo)*frame->transfers[1].max_count);
VK_RESULT(create_transfer_buffer(allocator, frame->transfers[1].max_size, &frame->transfers[1].buffer, &frame->transfers[1].memory, &frame->transfers[1].mapped));
return VK_SUCCESS; return VK_SUCCESS;
} }
@ -1124,10 +1130,11 @@ VkResult add_transfer(
VkResult result; VkResult result;
FrameContext* frame = &gpu->frame[frame_index]; FrameContext* frame = &gpu->frame[frame_index];
TransferBuffer* transfer = &frame->transfers[frame->transfer_index % 2];
if(frame->transfer_written + size >= frame->transfer_max_size) { if(transfer->written + size >= transfer->max_size) {
uint32_t new_size = 2*frame->transfer_max_size; uint32_t new_size = 2*transfer->max_size;
while(frame->transfer_written + size >= new_size) { while(transfer->written + size >= new_size) {
new_size *= 2; new_size *= 2;
} }
VkBuffer new_transfer; VkBuffer new_transfer;
@ -1135,33 +1142,33 @@ VkResult add_transfer(
void* new_transfer_data; void* new_transfer_data;
VK_RESULT(create_transfer_buffer(gpu->allocator, new_size, &new_transfer, &new_transfer_memory, &new_transfer_data)); VK_RESULT(create_transfer_buffer(gpu->allocator, new_size, &new_transfer, &new_transfer_memory, &new_transfer_data));
memcpy(new_transfer_data, frame->transfer_mapped, frame->transfer_written); memcpy(new_transfer_data, transfer->mapped, transfer->written);
destroy_transfer_buffer(gpu->allocator, frame->transfer_buffer, frame->transfer_memory); destroy_transfer_buffer(gpu->allocator, transfer->buffer, transfer->memory);
frame->transfer_buffer = new_transfer; transfer->buffer = new_transfer;
frame->transfer_memory = new_transfer_memory; transfer->memory = new_transfer_memory;
frame->transfer_mapped = new_transfer_data; transfer->mapped = new_transfer_data;
frame->transfer_max_size = new_size; transfer->max_size = new_size;
} }
if(frame->transfer_count + 1 >= frame->transfer_max_count) { if(transfer->count + 1 >= transfer->max_count) {
void* new_infos = malloc(sizeof(TransferInfo)*2*frame->transfer_max_count); void* new_infos = malloc(sizeof(TransferInfo)*2*transfer->max_count);
if(new_infos == NULL) { if(new_infos == NULL) {
return VK_ERROR_OUT_OF_HOST_MEMORY; return VK_ERROR_OUT_OF_HOST_MEMORY;
} }
memcpy(new_infos, frame->transfer_infos, sizeof(TransferInfo)*frame->transfer_count); memcpy(new_infos, transfer->infos, sizeof(TransferInfo)*transfer->count);
free(frame->transfer_infos); free(transfer->infos);
frame->transfer_infos = new_infos; transfer->infos = new_infos;
frame->transfer_max_count *= 2; transfer->max_count *= 2;
} }
memcpy(frame->transfer_mapped + frame->transfer_written, data, size); memcpy(transfer->mapped + transfer->written, data, size);
frame->transfer_infos[frame->transfer_count].size = size; transfer->infos[transfer->count].size = size;
frame->transfer_infos[frame->transfer_count].buffer = buffer; transfer->infos[transfer->count].buffer = buffer;
frame->transfer_infos[frame->transfer_count].offset = offset; transfer->infos[transfer->count].offset = offset;
frame->transfer_written += size; transfer->written += size;
frame->transfer_count += 1; transfer->count += 1;
return VK_SUCCESS; return VK_SUCCESS;
} }

@ -189,7 +189,7 @@ VkResult main_thread(ClientContext* context) {
// //
double last_draw = 0; double last_draw = 0;
double draw_interval = 0.1; double draw_interval = 0.5;
double frame_count = 0; double frame_count = 0;
uint32_t* mapped_codes = context->ui.containers[0].layers[0].codes_buffer; uint32_t* mapped_codes = context->ui.containers[0].layers[0].codes_buffer;
GPUString* mapped_string = context->ui.containers[0].layers[0].strings_buffer; GPUString* mapped_string = context->ui.containers[0].layers[0].strings_buffer;
@ -204,7 +204,7 @@ VkResult main_thread(ClientContext* context) {
double frame_time = glfwGetTime(); double frame_time = glfwGetTime();
// //
if(frame_time - last_draw > draw_interval && context->render.current_frame == 1) { if(context->render.current_frame == 1) {
test = (test + 1) % 7; test = (test + 1) % 7;
mapped_string->length = test; mapped_string->length = test;
@ -223,7 +223,6 @@ VkResult main_thread(ClientContext* context) {
offsetof(GPUString, length), offsetof(GPUString, length),
sizeof(uint32_t), sizeof(uint32_t),
&context->render)); &context->render));
fprintf(stdout, "Added transfers for size %d on frame %d\n", mapped_string->length, context->render.current_frame);
} }
// //