From f5dba58d07944aff251d9d68d1af5a4d9bf30e6d Mon Sep 17 00:00:00 2001 From: Robert Konrad Date: Tue, 1 Oct 2024 22:43:31 +0200 Subject: [PATCH] Support partial buffer locks --- .../Sources/kope/direct3d12/buffer.cpp | 71 ++++++++++++++++--- .../kope/direct3d12/buffer_functions.h | 8 ++- .../Sources/kope/direct3d12/buffer_structs.h | 7 +- .../Sources/kope/direct3d12/commandlist.cpp | 2 +- .../Sources/kope/direct3d12/descriptorset.cpp | 2 +- .../Sources/kope/direct3d12/device.cpp | 6 +- Sources/kope/graphics5/buffer.c | 16 +++-- Sources/kope/graphics5/buffer.h | 6 +- Sources/kope/graphics5/device.h | 2 + 9 files changed, 97 insertions(+), 23 deletions(-) diff --git a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer.cpp b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer.cpp index d54bf7507..08acae418 100644 --- a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer.cpp @@ -14,26 +14,79 @@ void kope_d3d12_buffer_destroy(kope_g5_buffer *buffer) { buffer->d3d12.resource->Release(); } -void *kope_d3d12_buffer_try_to_lock(kope_g5_buffer *buffer) { +void *kope_d3d12_buffer_try_to_lock_all(kope_g5_buffer *buffer) { if (check_for_fence(buffer->d3d12.device->d3d12.execution_fence, buffer->d3d12.latest_execution_index)) { - void *data = NULL; - buffer->d3d12.resource->Map(0, NULL, &data); - return data; + buffer->d3d12.locked_data_offset = 0; + buffer->d3d12.locked_data_size = UINT64_MAX; + + buffer->d3d12.resource->Map(0, NULL, &buffer->d3d12.locked_data); + return buffer->d3d12.locked_data; } else { return NULL; } } -void *kope_d3d12_buffer_lock(kope_g5_buffer *buffer) { +void *kope_d3d12_buffer_lock_all(kope_g5_buffer *buffer) { wait_for_fence(buffer->d3d12.device, buffer->d3d12.device->d3d12.execution_fence, buffer->d3d12.device->d3d12.execution_event, buffer->d3d12.latest_execution_index); - void *data = NULL; - buffer->d3d12.resource->Map(0, NULL, &data); - return data; + buffer->d3d12.locked_data_offset = 0; + buffer->d3d12.locked_data_size = UINT64_MAX; + + buffer->d3d12.resource->Map(0, NULL, &buffer->d3d12.locked_data); + return buffer->d3d12.locked_data; +} + +void *kope_d3d12_buffer_try_to_lock(kope_g5_buffer *buffer, uint64_t offset, uint64_t size) { + if (check_for_fence(buffer->d3d12.device->d3d12.execution_fence, buffer->d3d12.latest_execution_index)) { + D3D12_RANGE read_range; + D3D12_RANGE *read_range_pointer = NULL; + + if (buffer->d3d12.cpu_read) { + read_range.Begin = offset; + read_range.End = offset + size; + read_range_pointer = &read_range; + } + + buffer->d3d12.locked_data_offset = offset; + buffer->d3d12.locked_data_size = size; + + buffer->d3d12.resource->Map(0, read_range_pointer, &buffer->d3d12.locked_data); + return buffer->d3d12.locked_data; + } + else { + return NULL; + } +} + +void *kope_d3d12_buffer_lock(kope_g5_buffer *buffer, uint64_t offset, uint64_t size) { + wait_for_fence(buffer->d3d12.device, buffer->d3d12.device->d3d12.execution_fence, buffer->d3d12.device->d3d12.execution_event, + buffer->d3d12.latest_execution_index); + D3D12_RANGE read_range; + D3D12_RANGE *read_range_pointer = NULL; + + if (buffer->d3d12.cpu_read) { + read_range.Begin = offset; + read_range.End = offset + size; + read_range_pointer = &read_range; + } + + buffer->d3d12.locked_data_offset = offset; + buffer->d3d12.locked_data_size = size; + + buffer->d3d12.resource->Map(0, read_range_pointer, &buffer->d3d12.locked_data); + return buffer->d3d12.locked_data; } void kope_d3d12_buffer_unlock(kope_g5_buffer *buffer) { - buffer->d3d12.resource->Unmap(0, NULL); // doesn't actually do anything in D3D12, just helps with debugging + D3D12_RANGE written; + D3D12_RANGE *written_pointer = NULL; + + if (buffer->d3d12.cpu_write && buffer->d3d12.locked_data_size < UINT64_MAX) { + written.Begin = buffer->d3d12.locked_data_offset; + written.End = buffer->d3d12.locked_data_offset + buffer->d3d12.locked_data_size; + } + + buffer->d3d12.resource->Unmap(0, written_pointer); } diff --git a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer_functions.h b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer_functions.h index 7fc55afe7..2238d0d8c 100644 --- a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer_functions.h +++ b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer_functions.h @@ -11,9 +11,13 @@ void kope_d3d12_buffer_set_name(kope_g5_buffer *buffer, const char *name); void kope_d3d12_buffer_destroy(kope_g5_buffer *buffer); -void *kope_d3d12_buffer_try_to_lock(kope_g5_buffer *buffer); +void *kope_d3d12_buffer_try_to_lock_all(kope_g5_buffer *buffer); -void *kope_d3d12_buffer_lock(kope_g5_buffer *buffer); +void *kope_d3d12_buffer_lock_all(kope_g5_buffer *buffer); + +void *kope_d3d12_buffer_try_to_lock(kope_g5_buffer *buffer, uint64_t offset, uint64_t size); + +void *kope_d3d12_buffer_lock(kope_g5_buffer *buffer, uint64_t offset, uint64_t size); void kope_d3d12_buffer_unlock(kope_g5_buffer *buffer); diff --git a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer_structs.h b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer_structs.h index 1d8a9e688..21b2c2375 100644 --- a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer_structs.h +++ b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer_structs.h @@ -18,7 +18,12 @@ typedef struct kope_d3d12_buffer { uint32_t resource_state; size_t size; - bool cpu_accessible; + void *locked_data; + uint64_t locked_data_offset; + uint64_t locked_data_size; + + bool cpu_write; + bool cpu_read; uint64_t latest_execution_index; } kope_d3d12_buffer; diff --git a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/commandlist.cpp b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/commandlist.cpp index 5d40071b0..640df4ae5 100644 --- a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/commandlist.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/commandlist.cpp @@ -571,7 +571,7 @@ void kope_d3d12_command_list_prepare_raytracing_hierarchy(kope_g5_command_list * void kope_d3d12_command_list_update_raytracing_hierarchy(kope_g5_command_list *list, kinc_matrix4x4_t *volume_transforms, uint32_t volumes_count, kope_g5_raytracing_hierarchy *hierarchy) { - D3D12_RAYTRACING_INSTANCE_DESC *descs = (D3D12_RAYTRACING_INSTANCE_DESC *)kope_g5_buffer_lock(&hierarchy->d3d12.instances); + D3D12_RAYTRACING_INSTANCE_DESC *descs = (D3D12_RAYTRACING_INSTANCE_DESC *)kope_g5_buffer_lock_all(&hierarchy->d3d12.instances); for (uint32_t volume_index = 0; volume_index < hierarchy->d3d12.volumes_count; ++volume_index) { descs[volume_index].Transform[0][0] = volume_transforms[volume_index].m[0]; diff --git a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/descriptorset.cpp b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/descriptorset.cpp index 1d06145ea..f66a3b3e6 100644 --- a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/descriptorset.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/descriptorset.cpp @@ -160,7 +160,7 @@ void kope_d3d12_descriptor_set_prepare_cbv_buffer(kope_g5_command_list *list, ko buffer->d3d12.resource_state = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; } - if (buffer->d3d12.cpu_accessible) { + if (buffer->d3d12.cpu_read || buffer->d3d12.cpu_write) { kope_d3d12_command_list_queue_buffer_access(list, buffer); } } diff --git a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/device.cpp b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/device.cpp index 8bd674586..3a8433c74 100644 --- a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/device.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/device.cpp @@ -261,8 +261,8 @@ void kope_d3d12_device_create_buffer(kope_g5_device *device, const kope_g5_buffe buffer->d3d12.latest_execution_index = 0; - buffer->d3d12.cpu_accessible = - (parameters->usage_flags & KOPE_G5_BUFFER_USAGE_CPU_READ) != 0 || (parameters->usage_flags & KOPE_G5_BUFFER_USAGE_CPU_WRITE) != 0; + buffer->d3d12.cpu_read = (parameters->usage_flags & KOPE_G5_BUFFER_USAGE_CPU_READ) != 0; + buffer->d3d12.cpu_write = (parameters->usage_flags & KOPE_G5_BUFFER_USAGE_CPU_WRITE) != 0; kinc_microsoft_affirm(device->d3d12.device->CreateCommittedResource( &props, D3D12_HEAP_FLAG_NONE, &desc, (D3D12_RESOURCE_STATES)buffer->d3d12.resource_state, NULL, IID_GRAPHICS_PPV_ARGS(&buffer->d3d12.resource))); @@ -705,7 +705,7 @@ void kope_d3d12_device_create_raytracing_hierarchy(kope_g5_device *device, kope_ instances_params.usage_flags = KOPE_G5_BUFFER_USAGE_CPU_WRITE; kope_g5_device_create_buffer(device, &instances_params, &hierarchy->d3d12.instances); - D3D12_RAYTRACING_INSTANCE_DESC *descs = (D3D12_RAYTRACING_INSTANCE_DESC *)kope_g5_buffer_lock(&hierarchy->d3d12.instances); + D3D12_RAYTRACING_INSTANCE_DESC *descs = (D3D12_RAYTRACING_INSTANCE_DESC *)kope_g5_buffer_lock_all(&hierarchy->d3d12.instances); for (uint32_t volume_index = 0; volume_index < hierarchy->d3d12.volumes_count; ++volume_index) { memset(&descs[volume_index], 0, sizeof(D3D12_RAYTRACING_INSTANCE_DESC)); descs[volume_index].InstanceID = volume_index; diff --git a/Sources/kope/graphics5/buffer.c b/Sources/kope/graphics5/buffer.c index 2d00b16ed..a428a1c19 100644 --- a/Sources/kope/graphics5/buffer.c +++ b/Sources/kope/graphics5/buffer.c @@ -16,12 +16,20 @@ void kope_g5_buffer_destroy(kope_g5_buffer *buffer) { KOPE_G5_CALL1(buffer_destroy, buffer); } -void *kope_g5_buffer_try_to_lock(kope_g5_buffer *buffer) { - return KOPE_G5_CALL1(buffer_try_to_lock, buffer); +void *kope_g5_buffer_try_to_lock_all(kope_g5_buffer *buffer) { + return KOPE_G5_CALL1(buffer_try_to_lock_all, buffer); } -void *kope_g5_buffer_lock(kope_g5_buffer *buffer) { - return KOPE_G5_CALL1(buffer_lock, buffer); +void *kope_g5_buffer_lock_all(kope_g5_buffer *buffer) { + return KOPE_G5_CALL1(buffer_lock_all, buffer); +} + +void *kope_g5_buffer_try_to_lock(kope_g5_buffer *buffer, uint64_t offset, uint64_t size) { + return KOPE_G5_CALL3(buffer_try_to_lock, buffer, offset, size); +} + +void *kope_g5_buffer_lock(kope_g5_buffer *buffer, uint64_t offset, uint64_t size) { + return KOPE_G5_CALL3(buffer_lock, buffer, offset, size); } void kope_g5_buffer_unlock(kope_g5_buffer *buffer) { diff --git a/Sources/kope/graphics5/buffer.h b/Sources/kope/graphics5/buffer.h index e61208653..cedb20996 100644 --- a/Sources/kope/graphics5/buffer.h +++ b/Sources/kope/graphics5/buffer.h @@ -28,8 +28,10 @@ typedef struct kope_g5_buffer { void kope_g5_buffer_set_name(kope_g5_buffer *buffer, const char *name); void kope_g5_buffer_destroy(kope_g5_buffer *buffer); -void *kope_g5_buffer_try_to_lock(kope_g5_buffer *buffer); -void *kope_g5_buffer_lock(kope_g5_buffer *buffer); +void *kope_g5_buffer_try_to_lock_all(kope_g5_buffer *buffer); +void *kope_g5_buffer_lock_all(kope_g5_buffer *buffer); +void *kope_g5_buffer_try_to_lock(kope_g5_buffer *buffer, uint64_t offset, uint64_t size); +void *kope_g5_buffer_lock(kope_g5_buffer *buffer, uint64_t offset, uint64_t size); void kope_g5_buffer_unlock(kope_g5_buffer *buffer); #ifdef __cplusplus diff --git a/Sources/kope/graphics5/device.h b/Sources/kope/graphics5/device.h index e972ad427..c76e5b9fb 100644 --- a/Sources/kope/graphics5/device.h +++ b/Sources/kope/graphics5/device.h @@ -81,6 +81,8 @@ typedef struct kope_g5_texture_parameters { KOPE_FUNC void kope_g5_device_create_texture(kope_g5_device *device, const kope_g5_texture_parameters *parameters, kope_g5_texture *texture); +#define KOPE_G5_MAX_FRAMEBUFFERS 3 + KOPE_FUNC kope_g5_texture *kope_g5_device_get_framebuffer(kope_g5_device *device); typedef enum kope_g5_address_mode { KOPE_G5_ADDRESS_MODE_CLAMP_TO_EDGE, KOPE_G5_ADDRESS_MODE_REPEAT, KOPE_G5_ADDRESS_MODE_MIRROR_REPEAT } kope_g5_address_mode;