Skip to content

Commit

Permalink
Automatically synchronize CPU/GPU buffer accesses
Browse files Browse the repository at this point in the history
  • Loading branch information
RobDangerous committed Sep 30, 2024
1 parent 86de08f commit d637ced
Show file tree
Hide file tree
Showing 13 changed files with 86 additions and 11 deletions.
14 changes: 14 additions & 0 deletions Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,21 @@ void kope_d3d12_buffer_destroy(kope_g5_buffer *buffer) {
buffer->d3d12.resource->Release();
}

void *kope_d3d12_buffer_try_to_lock(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;
}
else {
return NULL;
}
}

void *kope_d3d12_buffer_lock(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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ extern "C" {
#endif

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_lock(kope_g5_buffer *buffer);

void kope_d3d12_buffer_unlock(kope_g5_buffer *buffer);

#ifdef __cplusplus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@
extern "C" {
#endif

struct kope_g5_device;

typedef struct kope_d3d12_buffer {
struct kope_g5_device *device;

struct ID3D12Resource *resource;
uint32_t resource_state;
size_t size;

bool cpu_accessible;
uint64_t latest_execution_index;
} kope_d3d12_buffer;

#ifdef __cplusplus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -727,3 +727,8 @@ void kope_d3d12_command_list_draw_indexed_indirect(kope_g5_command_list *list, k
void kope_d3d12_command_list_compute_indirect(kope_g5_command_list *list, kope_g5_buffer *indirect_buffer, uint64_t indirect_offset) {
list->d3d12.list->ExecuteIndirect(list->d3d12.compute_pipe->compute_command_signature, 1, indirect_buffer->d3d12.resource, indirect_offset, NULL, 0);
}

void kope_d3d12_command_list_queue_buffer_access(kope_g5_command_list *list, kope_g5_buffer *buffer) {
list->d3d12.queued_buffer_accesses[list->d3d12.queued_buffer_accesses_count] = buffer;
list->d3d12.queued_buffer_accesses_count += 1;
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ void kope_d3d12_command_list_draw_indexed_indirect(kope_g5_command_list *list, k

void kope_d3d12_command_list_compute_indirect(kope_g5_command_list *list, kope_g5_buffer *indirect_buffer, uint64_t indirect_offset);

void kope_d3d12_command_list_queue_buffer_access(kope_g5_command_list *list, kope_g5_buffer *buffer);

#ifdef __cplusplus
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ struct ID3D12Fence;
// allocators. Increasing this value exchanges more memory against potentially less wait-times (depending on actual command-list usage).
#define KOPE_D3D12_COMMAND_LIST_ALLOCATOR_COUNT 3

#define KOPE_D3D12_COMMAND_LIST_MAX_QUEUED_BUFFER_ACCESSES 256

typedef struct kope_d3d12_command_list {
struct kope_d3d12_device *device;

Expand Down Expand Up @@ -51,6 +53,9 @@ typedef struct kope_d3d12_command_list {
uint32_t timestamp_beginning_of_pass_write_index;
uint32_t timestamp_end_of_pass_write_index;

kope_g5_buffer *queued_buffer_accesses[KOPE_D3D12_COMMAND_LIST_MAX_QUEUED_BUFFER_ACCESSES];
uint32_t queued_buffer_accesses_count;

bool presenting;
} kope_d3d12_command_list;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,9 @@ static inline UINT D3D12CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT Pla
return MipSlice + (ArraySlice * MipLevels) + (PlaneSlice * MipLevels * ArraySize);
}

struct kope_g5_device;

static void wait_for_fence(struct kope_g5_device *device, ID3D12Fence *fence, HANDLE event, UINT64 completion_value);
static bool check_for_fence(ID3D12Fence *fence, UINT64 completion_value);

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ 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) {
kope_d3d12_command_list_queue_buffer_access(list, buffer);
}
}

void kope_d3d12_descriptor_set_prepare_srv_texture(kope_g5_command_list *list, const kope_g5_texture_view *texture_view) {
Expand All @@ -174,8 +178,8 @@ void kope_d3d12_descriptor_set_prepare_srv_texture(kope_g5_command_list *list, c
(D3D12_RESOURCE_STATES)
texture_view->texture->d3d12.resource_states[kope_d3d12_texture_resource_state_index(texture_view->texture, mip_level, array_layer)];
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
barrier.Transition.Subresource =
D3D12CalcSubresource(mip_level, array_layer, 0, texture_view->texture->d3d12.mip_level_count, texture_view->texture->d3d12.depth_or_array_layers);
barrier.Transition.Subresource = D3D12CalcSubresource(mip_level, array_layer, 0, texture_view->texture->d3d12.mip_level_count,
texture_view->texture->d3d12.depth_or_array_layers);

list->d3d12.list->ResourceBarrier(1, &barrier);

Expand Down
19 changes: 19 additions & 0 deletions Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,13 @@ void kope_d3d12_device_create_buffer(kope_g5_device *device, const kope_g5_buffe
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
}

buffer->d3d12.device = device;

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;

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)));
}
Expand Down Expand Up @@ -321,6 +328,8 @@ void kope_d3d12_device_create_command_list(kope_g5_device *device, kope_g5_comma

list->d3d12.blocking_frame_index = 0;

list->d3d12.queued_buffer_accesses_count = 0;

list->d3d12.presenting = false;

ID3D12DescriptorHeap *heaps[] = {list->d3d12.device->descriptor_heap, list->d3d12.device->sampler_heap};
Expand Down Expand Up @@ -519,6 +528,11 @@ static void wait_for_fence(kope_g5_device *device, ID3D12Fence *fence, HANDLE ev
}
}

static bool check_for_fence(ID3D12Fence *fence, UINT64 completion_value) {
// kinc_log(KINC_LOG_LEVEL_INFO, "Done: %llu Check: %llu", fence->GetCompletedValue(), completion_value);
return fence->GetCompletedValue() >= completion_value;
}

static void wait_for_frame(kope_g5_device *device, uint64_t frame_index) {
wait_for_fence(device, device->d3d12.frame_fence, device->d3d12.frame_event, frame_index);
}
Expand Down Expand Up @@ -548,6 +562,11 @@ void kope_d3d12_device_execute_command_list(kope_g5_device *device, kope_g5_comm

list->d3d12.list->Close();

for (uint32_t buffer_access_index = 0; buffer_access_index < list->d3d12.queued_buffer_accesses_count; ++buffer_access_index) {
list->d3d12.queued_buffer_accesses[buffer_access_index]->d3d12.latest_execution_index = device->d3d12.execution_index;
}
list->d3d12.queued_buffer_accesses_count = 0;

list->d3d12.allocator_execution_index[list->d3d12.current_allocator_index] = device->d3d12.execution_index;

ID3D12CommandList *lists[] = {list->d3d12.list};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,11 +335,11 @@ void kope_d3d12_render_pipeline_init(kope_d3d12_device *device, kope_d3d12_rende
device->device->CreateRootSignature(0, desc.VS.pShaderBytecode, desc.VS.BytecodeLength, IID_GRAPHICS_PPV_ARGS(&pipe->root_signature)));

D3D12_INDIRECT_ARGUMENT_DESC indirect_args[2];
indirect_args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;
indirect_args[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
indirect_args[1].Constant.RootParameterIndex = 0;
indirect_args[1].Constant.DestOffsetIn32BitValues = 0;
indirect_args[1].Constant.Num32BitValuesToSet = 1;
indirect_args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
indirect_args[0].Constant.RootParameterIndex = 0;
indirect_args[0].Constant.DestOffsetIn32BitValues = 0;
indirect_args[0].Constant.Num32BitValuesToSet = 1;
indirect_args[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;

D3D12_COMMAND_SIGNATURE_DESC command_signature_desc;
command_signature_desc.ByteStride = sizeof(kope_g5_draw_arguments);
Expand All @@ -348,7 +348,7 @@ void kope_d3d12_render_pipeline_init(kope_d3d12_device *device, kope_d3d12_rende

device->device->CreateCommandSignature(&command_signature_desc, pipe->root_signature, IID_GRAPHICS_PPV_ARGS(&pipe->draw_command_signature));

indirect_args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;
indirect_args[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;

command_signature_desc.ByteStride = sizeof(kope_g5_draw_indexed_arguments);

Expand Down
4 changes: 4 additions & 0 deletions Sources/kope/graphics5/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ 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_lock(kope_g5_buffer *buffer) {
return KOPE_G5_CALL1(buffer_lock, buffer);
}
Expand Down
3 changes: 2 additions & 1 deletion Sources/kope/graphics5/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ 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_lock(kope_g5_buffer *buffer); // TODO
void *kope_g5_buffer_try_to_lock(kope_g5_buffer *buffer);
void *kope_g5_buffer_lock(kope_g5_buffer *buffer);
void kope_g5_buffer_unlock(kope_g5_buffer *buffer);

#ifdef __cplusplus
Expand Down
8 changes: 6 additions & 2 deletions Sources/kope/graphics5/commandlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,20 +137,24 @@ KOPE_FUNC void kope_g5_command_list_draw_indexed(kope_g5_command_list *list, uin
int32_t base_vertex, uint32_t first_instance);

typedef struct kope_g5_draw_arguments {
#ifdef KINC_DIRECT3D12
uint32_t automatic_draw_index;
#endif
uint32_t vertex_count;
uint32_t instance_count;
uint32_t first_vertex;
uint32_t first_instance;
uint32_t automatic_draw_index;
} kope_g5_draw_arguments;

typedef struct kope_g5_draw_indexed_arguments {
#ifdef KINC_DIRECT3D12
uint32_t automatic_draw_index;
#endif
uint32_t index_count;
uint32_t instance_count;
uint32_t first_index;
int32_t base_vertex;
uint32_t first_instance;
uint32_t automatic_draw_index;
} kope_g5_draw_indexed_arguments;

typedef struct kope_g5_compute_arguments {
Expand Down

0 comments on commit d637ced

Please sign in to comment.