Move texture transitions to backend

This commit is contained in:
luboslenco
2025-06-11 14:36:23 +02:00
parent 7c72f33be1
commit 4476760122
+63 -26
View File
@@ -32,6 +32,9 @@ int window_height;
int window_new_width;
int window_new_height;
int window_current_backbuffer;
iron_gpu_texture_t *window_render_target;
iron_gpu_texture_t *current_render_targets[8];
int current_render_targets_count = 0;
bool window_vsync;
ID3D12Device *device = NULL;
@@ -303,13 +306,15 @@ int iron_gpu_max_bound_textures(void) {
return IRON_INTERNAL_G5_TEXTURE_COUNT;
}
void iron_gpu_begin(iron_gpu_texture_t *renderTarget) {
void iron_gpu_begin(iron_gpu_texture_t *render_target) {
if (began) {
return;
}
began = true;
window_render_target = render_target;
window_current_backbuffer = (window_current_backbuffer + 1) % QUEUE_SLOT_COUNT;
if (window_new_width != window_width || window_new_height != window_height) {
window_swapChain->lpVtbl->ResizeBuffers(window_swapChain, QUEUE_SLOT_COUNT, window_new_width, window_new_height, DXGI_FORMAT_R8G8B8A8_UNORM, 0);
setup_swapchain();
@@ -383,9 +388,19 @@ void iron_gpu_command_list_begin(struct iron_gpu_command_list *list) {
list->impl._commandAllocator->lpVtbl->Reset(list->impl._commandAllocator);
list->impl._commandList->lpVtbl->Reset(list->impl._commandList, list->impl._commandAllocator, NULL);
}
iron_gpu_command_list_framebuffer_to_render_target_barrier(list, window_render_target);
}
void iron_gpu_command_list_end(struct iron_gpu_command_list *list) {
iron_gpu_command_list_render_target_to_framebuffer_barrier(list, window_render_target);
if (current_render_targets_count > 0 && current_render_targets[0] != window_render_target) {
for (int i = 0; i < current_render_targets_count; ++i) {
iron_gpu_command_list_render_target_to_texture_barrier(list, current_render_targets[i]);
}
current_render_targets_count = 0;
}
list->impl._commandList->lpVtbl->Close(list->impl._commandList);
ID3D12CommandList *commandLists[] = {(ID3D12CommandList *)list->impl._commandList};
@@ -418,27 +433,33 @@ void iron_gpu_command_list_framebuffer_to_render_target_barrier(struct iron_gpu_
}
void iron_gpu_command_list_texture_to_render_target_barrier(struct iron_gpu_command_list *list, iron_gpu_texture_t *renderTarget) {
D3D12_RESOURCE_BARRIER barrier = {
.Transition.pResource = renderTarget->impl.renderTarget,
.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
.Transition.StateBefore = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET,
.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
};
list->impl._commandList->lpVtbl->ResourceBarrier(list->impl._commandList, 1, &barrier);
if (renderTarget->state != IRON_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET) {
D3D12_RESOURCE_BARRIER barrier = {
.Transition.pResource = renderTarget->impl.renderTarget,
.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
.Transition.StateBefore = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET,
.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
};
list->impl._commandList->lpVtbl->ResourceBarrier(list->impl._commandList, 1, &barrier);
renderTarget->state = IRON_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET;
}
}
void iron_gpu_command_list_render_target_to_texture_barrier(struct iron_gpu_command_list *list, iron_gpu_texture_t *renderTarget) {
D3D12_RESOURCE_BARRIER barrier = {
.Transition.pResource = renderTarget->impl.renderTarget,
.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET,
.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
};
list->impl._commandList->lpVtbl->ResourceBarrier(list->impl._commandList, 1, &barrier);
if (renderTarget->state != IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE) {
D3D12_RESOURCE_BARRIER barrier = {
.Transition.pResource = renderTarget->impl.renderTarget,
.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET,
.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
};
list->impl._commandList->lpVtbl->ResourceBarrier(list->impl._commandList, 1, &barrier);
renderTarget->state = IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE;
}
}
void iron_gpu_command_list_set_constant_buffer(struct iron_gpu_command_list *list, iron_gpu_buffer_t *buffer, int offset, size_t size) {
@@ -567,6 +588,23 @@ void iron_gpu_command_list_set_render_targets(struct iron_gpu_command_list *list
iron_gpu_texture_t *render_target = targets[0];
if (current_render_targets_count > 0 && current_render_targets[0] != window_render_target) {
for (int i = 0; i < current_render_targets_count; ++i) {
iron_gpu_command_list_render_target_to_texture_barrier(list, current_render_targets[i]);
}
}
if (render_target != window_render_target) {
for (int i = 0; i < count; ++i) {
iron_gpu_command_list_texture_to_render_target_barrier(list, targets[i]);
}
}
for (int i = 0; i < count; ++i) {
current_render_targets[i] = targets[i];
}
current_render_targets_count = count;
D3D12_CPU_DESCRIPTOR_HANDLE target_descriptors[16];
for (int i = 0; i < count; ++i) {
targets[i]->impl.renderTargetDescriptorHeap->lpVtbl->GetCPUDescriptorHandleForHeapStart(targets[i]->impl.renderTargetDescriptorHeap, &target_descriptors[i]);
@@ -713,14 +751,13 @@ void iron_gpu_command_list_get_render_target_pixels(iron_gpu_command_list_t *lis
}
// Copy render target to readback buffer
D3D12_RESOURCE_STATES sourceState = D3D12_RESOURCE_STATE_RENDER_TARGET;
{
D3D12_RESOURCE_BARRIER barrier = {
.Transition.pResource = render_target->impl.renderTarget,
.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
.Transition.StateBefore = sourceState,
.Transition.StateBefore = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE,
.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
};
@@ -752,7 +789,7 @@ void iron_gpu_command_list_get_render_target_pixels(iron_gpu_command_list_t *lis
.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE,
.Transition.StateAfter = sourceState,
.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
};
list->impl._commandList->lpVtbl->ResourceBarrier(list->impl._commandList, 1, &barrier);
@@ -1302,12 +1339,12 @@ static void render_target_init(iron_gpu_texture_t *render_target, int width, int
device->lpVtbl->CreateRenderTargetView(device, render_target->impl.renderTarget, &viewDesc, handle);
}
else {
HRESULT result = device->lpVtbl->CreateCommittedResource(device, &heapProperties, D3D12_HEAP_FLAG_NONE, &texResourceDesc, D3D12_RESOURCE_STATE_RENDER_TARGET,
HRESULT result = device->lpVtbl->CreateCommittedResource(device, &heapProperties, D3D12_HEAP_FLAG_NONE, &texResourceDesc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
&clearValue, &IID_ID3D12Resource, &render_target->impl.renderTarget);
if (result != S_OK) {
for (int i = 0; i < 10; ++i) {
iron_memory_emergency();
result = device->lpVtbl->CreateCommittedResource(device, &heapProperties, D3D12_HEAP_FLAG_NONE, &texResourceDesc, D3D12_RESOURCE_STATE_RENDER_TARGET,
result = device->lpVtbl->CreateCommittedResource(device, &heapProperties, D3D12_HEAP_FLAG_NONE, &texResourceDesc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
&clearValue, &IID_ID3D12Resource, &render_target->impl.renderTarget);
if (result == S_OK) {
break;
@@ -1447,14 +1484,14 @@ static void render_target_init(iron_gpu_texture_t *render_target, int width, int
void iron_gpu_render_target_init(iron_gpu_texture_t *target, int width, int height, iron_image_format_t format, int depthBufferBits) {
render_target_init(target, width, height, format, depthBufferBits, -1);
target->_uploaded = true;
target->state = IRON_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET;
target->state = IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE;
}
void iron_gpu_render_target_init_framebuffer(iron_gpu_texture_t *target, int width, int height, iron_image_format_t format, int depthBufferBits) {
render_target_init(target, width, height, format, depthBufferBits, framebuffer_count);
framebuffer_count += 1;
target->_uploaded = true;
target->state = IRON_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET;
target->state = IRON_INTERNAL_RENDER_TARGET_STATE_TEXTURE;
}
void iron_gpu_render_target_set_depth_from(iron_gpu_texture_t *render_target, iron_gpu_texture_t *source) {