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;
} 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 {
VkFence ready;
VkSemaphore image;
@ -86,16 +99,8 @@ typedef struct FrameContextStruct {
VkCommandBuffer compute_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;
uint32_t transfer_count;
TransferBuffer transfers[2];
} FrameContext;
typedef struct RenderContextStruct {

@ -67,21 +67,22 @@ VkResult draw_frame(
.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;
VK_RESULT(vkResetCommandBuffer(transfer_commands, 0));
VK_RESULT(vkBeginCommandBuffer(transfer_commands, &begin_info));
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(
transfer_commands,
frame->transfer_buffer,
frame->transfer_infos[tid].buffer,
transfer->buffer,
transfer->infos[tid].buffer,
src_offset,
frame->transfer_infos[tid].offset,
frame->transfer_infos[tid].size);
src_offset += frame->transfer_infos[tid].size;
transfer->infos[tid].offset,
transfer->infos[tid].size);
src_offset += transfer->infos[tid].size;
}
VK_RESULT(vkEndCommandBuffer(transfer_commands));
@ -106,8 +107,8 @@ VkResult draw_frame(
.pNext = &transfer_timeline,
};
VK_RESULT(vkQueueSubmit(context->transfer_queue.handle, 1, &transfer_submit, VK_NULL_HANDLE));
frame->transfer_count = 0;
frame->transfer_written = 0;
transfer->count = 0;
transfer->written = 0;
VkCommandBuffer compute_commands = frame->compute_commands;
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));
// TODO: better defaults
frame->transfer_max_size = 1;
frame->transfer_max_count = 1;
VK_RESULT(create_transfer_buffer(allocator, frame->transfer_max_size, &frame->transfer_buffer, &frame->transfer_memory, &frame->transfer_mapped));
frame->transfer_count = 0;
frame->transfer_infos = malloc(sizeof(TransferInfo)*frame->transfer_max_count);
frame->transfers[0].max_size = 1;
frame->transfers[0].max_count = 1;
frame->transfers[0].count = 0;
frame->transfers[0].infos = malloc(sizeof(TransferInfo)*frame->transfers[0].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;
}
@ -1124,10 +1130,11 @@ VkResult add_transfer(
VkResult result;
FrameContext* frame = &gpu->frame[frame_index];
TransferBuffer* transfer = &frame->transfers[frame->transfer_index % 2];
if(frame->transfer_written + size >= frame->transfer_max_size) {
uint32_t new_size = 2*frame->transfer_max_size;
while(frame->transfer_written + size >= new_size) {
if(transfer->written + size >= transfer->max_size) {
uint32_t new_size = 2*transfer->max_size;
while(transfer->written + size >= new_size) {
new_size *= 2;
}
VkBuffer new_transfer;
@ -1135,33 +1142,33 @@ VkResult add_transfer(
void* 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);
destroy_transfer_buffer(gpu->allocator, frame->transfer_buffer, frame->transfer_memory);
frame->transfer_buffer = new_transfer;
frame->transfer_memory = new_transfer_memory;
frame->transfer_mapped = new_transfer_data;
frame->transfer_max_size = new_size;
memcpy(new_transfer_data, transfer->mapped, transfer->written);
destroy_transfer_buffer(gpu->allocator, transfer->buffer, transfer->memory);
transfer->buffer = new_transfer;
transfer->memory = new_transfer_memory;
transfer->mapped = new_transfer_data;
transfer->max_size = new_size;
}
if(frame->transfer_count + 1 >= frame->transfer_max_count) {
void* new_infos = malloc(sizeof(TransferInfo)*2*frame->transfer_max_count);
if(transfer->count + 1 >= transfer->max_count) {
void* new_infos = malloc(sizeof(TransferInfo)*2*transfer->max_count);
if(new_infos == NULL) {
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
memcpy(new_infos, frame->transfer_infos, sizeof(TransferInfo)*frame->transfer_count);
free(frame->transfer_infos);
frame->transfer_infos = new_infos;
frame->transfer_max_count *= 2;
memcpy(new_infos, transfer->infos, sizeof(TransferInfo)*transfer->count);
free(transfer->infos);
transfer->infos = new_infos;
transfer->max_count *= 2;
}
memcpy(frame->transfer_mapped + frame->transfer_written, data, size);
frame->transfer_infos[frame->transfer_count].size = size;
frame->transfer_infos[frame->transfer_count].buffer = buffer;
frame->transfer_infos[frame->transfer_count].offset = offset;
memcpy(transfer->mapped + transfer->written, data, size);
transfer->infos[transfer->count].size = size;
transfer->infos[transfer->count].buffer = buffer;
transfer->infos[transfer->count].offset = offset;
frame->transfer_written += size;
frame->transfer_count += 1;
transfer->written += size;
transfer->count += 1;
return VK_SUCCESS;
}

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