Parcourir la source

Move texture transitions to backend

luboslenco il y a 3 mois
Parent
commit
4476760122
1 fichiers modifiés avec 63 ajouts et 26 suppressions
  1. 63 26
      base/sources/backends/direct3d12_gpu.c

+ 63 - 26
base/sources/backends/direct3d12_gpu.c

@@ -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) {