From e76abf875f60585f622c0ff6ded239625d6b8f5a Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Fri, 30 Oct 2015 23:37:31 +0100 Subject: [PATCH] d3d12: Clean rtt related code --- rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp | 381 +--------- rpcs3/Emu/RSX/D3D12/D3D12GSRender.h | 4 +- rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.cpp | 706 +++++++++++++----- rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h | 29 +- rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp | 6 +- 5 files changed, 552 insertions(+), 574 deletions(-) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 62d60fe461..80059a1311 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -199,7 +199,7 @@ D3D12GSRender::D3D12GSRender() m_readbackResources.init(m_device.Get(), 1024 * 1024 * 128, D3D12_HEAP_TYPE_READBACK, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS); m_UAVHeap.init(m_device.Get(), 1024 * 1024 * 128, D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES); - m_rtts.Init(m_device.Get()); + m_rtts.init(m_device.Get()); m_constantsData.init(m_device.Get(), 1024 * 1024 * 64, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_NONE); m_vertexIndexData.init(m_device.Get(), 1024 * 1024 * 384, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_NONE); @@ -227,7 +227,6 @@ D3D12GSRender::~D3D12GSRender() m_convertRootSignature->Release(); m_perFrameStorage[0].release(); m_perFrameStorage[1].release(); - m_rtts.Release(); m_outputScalingPass.Release(); release_d2d_structures(); @@ -256,110 +255,6 @@ bool D3D12GSRender::domethod(u32 cmd, u32 arg) } } -namespace -{ - UINT get_num_rtt(u8 color_target) noexcept - { - switch (color_target) - { - case CELL_GCM_SURFACE_TARGET_NONE: return 0; - case CELL_GCM_SURFACE_TARGET_0: - case CELL_GCM_SURFACE_TARGET_1: return 1; - case CELL_GCM_SURFACE_TARGET_MRT1: return 2; - case CELL_GCM_SURFACE_TARGET_MRT2: return 3; - case CELL_GCM_SURFACE_TARGET_MRT3: return 4; - } - unreachable("Wrong color target"); - } - - std::vector get_rtt_indexes(u8 color_target) noexcept - { - switch (color_target) - { - case CELL_GCM_SURFACE_TARGET_NONE: return{}; - case CELL_GCM_SURFACE_TARGET_0: return{ 0 }; - case CELL_GCM_SURFACE_TARGET_1: return{ 1 }; - case CELL_GCM_SURFACE_TARGET_MRT1: return{ 0, 1 }; - case CELL_GCM_SURFACE_TARGET_MRT2: return{ 0, 1, 2 }; - case CELL_GCM_SURFACE_TARGET_MRT3: return{ 0, 1, 2, 3 }; - } - unreachable("Wrong color target"); - } - - std::array get_clear_color(u32 clear_color) noexcept - { - u8 clear_a = clear_color >> 24; - u8 clear_r = clear_color >> 16; - u8 clear_g = clear_color >> 8; - u8 clear_b = clear_color; - return - { - clear_r / 255.0f, - clear_g / 255.0f, - clear_b / 255.0f, - clear_a / 255.0f - }; - } - - u8 get_clear_stencil(u32 register_value) noexcept - { - return register_value & 0xff; - } -} - -void D3D12GSRender::clear_surface(u32 arg) -{ - std::chrono::time_point start_duration = std::chrono::system_clock::now(); - - std::chrono::time_point rtt_duration_start = std::chrono::system_clock::now(); - prepare_render_targets(getCurrentResourceStorage().command_list.Get()); - - std::chrono::time_point rtt_duration_end = std::chrono::system_clock::now(); - m_timers.m_rttDuration += std::chrono::duration_cast(rtt_duration_end - rtt_duration_start).count(); - -/* if (m_set_color_mask) - { - glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a); - checkForGlError("glColorMask"); - } - - if (m_set_scissor_horizontal && m_set_scissor_vertical) - { - glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); - checkForGlError("glScissor"); - }*/ - - // TODO: Merge depth and stencil clear when possible - if (arg & 0x1) - { - u32 clear_depth = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] >> 8; - u32 max_depth_value = m_surface.depth_format == CELL_GCM_SURFACE_Z16 ? 0x0000ffff : 0x00ffffff; - getCurrentResourceStorage().command_list->ClearDepthStencilView(m_rtts.m_depthStencilDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, clear_depth / (float)max_depth_value, 0, 0, nullptr); - } - - if (arg & 0x2) - getCurrentResourceStorage().command_list->ClearDepthStencilView(m_rtts.m_depthStencilDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_STENCIL, 0.f, - get_clear_stencil(rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE]), 0, nullptr); - - if (arg & 0xF0) - { - for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) - getCurrentResourceStorage().command_list->ClearRenderTargetView(CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.m_renderTargetsDescriptorsHeap->GetCPUDescriptorHandleForHeapStart()).Offset(i, g_descriptorStrideRTV), - get_clear_color(rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE]).data(), 0, nullptr); - } - - std::chrono::time_point end_duration = std::chrono::system_clock::now(); - m_timers.m_drawCallDuration += std::chrono::duration_cast(end_duration - start_duration).count(); - m_timers.m_drawCallCount++; - - if (rpcs3::config.rsx.d3d12.debug_output.value()) - { - ThrowIfFailed(getCurrentResourceStorage().command_list->Close()); - m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)getCurrentResourceStorage().command_list.GetAddressOf()); - getCurrentResourceStorage().set_new_command_list(); - } -} - void D3D12GSRender::end() { std::chrono::time_point start_duration = std::chrono::system_clock::now(); @@ -440,10 +335,7 @@ void D3D12GSRender::end() std::chrono::time_point texture_duration_end = std::chrono::system_clock::now(); m_timers.m_textureDuration += std::chrono::duration_cast(texture_duration_end - texture_duration_start).count(); - - size_t num_rtt = get_num_rtt(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]); - getCurrentResourceStorage().command_list->OMSetRenderTargets((UINT)num_rtt, &m_rtts.m_renderTargetsDescriptorsHeap->GetCPUDescriptorHandleForHeapStart(), true, - &CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.m_depthStencilDescriptorHeap->GetCPUDescriptorHandleForHeapStart())); + set_rtt_and_ds(getCurrentResourceStorage().command_list.Get()); int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16; int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16; @@ -564,9 +456,18 @@ void D3D12GSRender::flip(int buffer) } else { - if (m_rtts.m_currentlyBoundRenderTargets[0] != nullptr) - getCurrentResourceStorage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.m_currentlyBoundRenderTargets[0], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ)); - resource_to_flip = m_rtts.m_currentlyBoundRenderTargets[0]; + if (m_rtts.bound_render_targets[0] != nullptr) + { + getCurrentResourceStorage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_render_targets[0], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ)); + resource_to_flip = m_rtts.bound_render_targets[0]; + } + else if (m_rtts.bound_render_targets[1] != nullptr) + { + getCurrentResourceStorage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_render_targets[1], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ)); + resource_to_flip = m_rtts.bound_render_targets[1]; + } + else + resource_to_flip = nullptr; } getCurrentResourceStorage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET)); @@ -618,11 +519,15 @@ void D3D12GSRender::flip(int buffer) m_device->CreateSampler(&sampler_desc, CD3DX12_CPU_DESCRIPTOR_HANDLE(m_outputScalingPass.m_samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart()).Offset(m_swapChain->GetCurrentBackBufferIndex(), g_descriptorStrideSamplers)); - getCurrentResourceStorage().command_list->SetDescriptorHeaps(1, &m_outputScalingPass.m_textureDescriptorHeap); + ID3D12DescriptorHeap *descriptors_heaps[] = + { + m_outputScalingPass.m_textureDescriptorHeap, + m_outputScalingPass.m_samplerDescriptorHeap + }; + getCurrentResourceStorage().command_list->SetDescriptorHeaps(2, descriptors_heaps); getCurrentResourceStorage().command_list->SetGraphicsRootDescriptorTable(0, CD3DX12_GPU_DESCRIPTOR_HANDLE(m_outputScalingPass.m_textureDescriptorHeap->GetGPUDescriptorHandleForHeapStart()).Offset(m_swapChain->GetCurrentBackBufferIndex(), g_descriptorStrideSRVCBVUAV)); - getCurrentResourceStorage().command_list->SetDescriptorHeaps(1, &m_outputScalingPass.m_samplerDescriptorHeap); - getCurrentResourceStorage().command_list->SetGraphicsRootDescriptorTable(1, + getCurrentResourceStorage().command_list->SetGraphicsRootDescriptorTable(1, CD3DX12_GPU_DESCRIPTOR_HANDLE(m_outputScalingPass.m_samplerDescriptorHeap->GetGPUDescriptorHandleForHeapStart()).Offset(m_swapChain->GetCurrentBackBufferIndex(), g_descriptorStrideSamplers)); getCurrentResourceStorage().command_list->OMSetRenderTargets(1, @@ -634,13 +539,13 @@ void D3D12GSRender::flip(int buffer) vertex_buffer_view.SizeInBytes = 16 * sizeof(float); getCurrentResourceStorage().command_list->IASetVertexBuffers(0, 1, &vertex_buffer_view); getCurrentResourceStorage().command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - if (m_rtts.m_currentlyBoundRenderTargets[0] != nullptr) + if (resource_to_flip) getCurrentResourceStorage().command_list->DrawInstanced(4, 1, 0, 0); if (!rpcs3::config.rsx.d3d12.overlay.value()) getCurrentResourceStorage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); - if (is_flip_surface_in_global_memory(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]) && m_rtts.m_currentlyBoundRenderTargets[0] != nullptr) - getCurrentResourceStorage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.m_currentlyBoundRenderTargets[0], D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET)); + if (is_flip_surface_in_global_memory(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]) && resource_to_flip != nullptr) + getCurrentResourceStorage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(resource_to_flip, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET)); ThrowIfFailed(getCurrentResourceStorage().command_list->Close()); m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)getCurrentResourceStorage().command_list.GetAddressOf()); @@ -716,242 +621,4 @@ resource_storage& D3D12GSRender::getNonCurrentResourceStorage() { return m_perFrameStorage[1 - m_swapChain->GetCurrentBackBufferIndex()]; } - -namespace -{ -/** - * Create a write back buffer resource and populate command_list with copy command to fill it - * with color_surface data. - */ - ComPtr create_readback_buffer_and_download( - ID3D12Device *device, - ID3D12GraphicsCommandList * command_list, - data_heap &readback_heap, - ID3D12Resource * color_surface, - int color_surface_format - ) -{ - int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16; - int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16; - - DXGI_FORMAT dxgi_format = get_color_surface_format(color_surface_format); - size_t row_pitch; - switch (color_surface_format) - { - case CELL_GCM_SURFACE_A8R8G8B8: - row_pitch = align(clip_w * 4, 256); - break; - case CELL_GCM_SURFACE_F_W16Z16Y16X16: - row_pitch = align(clip_w * 8, 256); - break; - } - - size_t buffer_size = row_pitch * clip_h; - assert(readback_heap.can_alloc(buffer_size)); - size_t heapOffset = readback_heap.alloc(buffer_size); - ComPtr Result; - ThrowIfFailed( - device->CreatePlacedResource( - readback_heap.m_heap, - heapOffset, - &CD3DX12_RESOURCE_DESC::Buffer(row_pitch * clip_h), - D3D12_RESOURCE_STATE_COPY_DEST, - nullptr, - IID_PPV_ARGS(Result.GetAddressOf()) - ) - ); - - command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(color_surface, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE)); - - command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(Result.Get(), { 0, { dxgi_format, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0, - &CD3DX12_TEXTURE_COPY_LOCATION(color_surface, 0), nullptr); - command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(color_surface, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET)); - return Result; -} - -void copy_readback_buffer_to_dest(void *dest, ID3D12Resource *res, size_t dst_pitch, size_t src_pitch, size_t height) -{ - void *mapped_buffer; - ThrowIfFailed(res->Map(0, nullptr, &mapped_buffer)); - for (unsigned row = 0; row < height; row++) - { - u32 *casted_dest = (u32*)((char*)dest + row * dst_pitch); - u32 *casted_src = (u32*)((char*)mapped_buffer + row * src_pitch); - for (unsigned col = 0; col < src_pitch / 4; col++) - *casted_dest++ = _byteswap_ulong(*casted_src++); - } - res->Unmap(0, nullptr); -} -} - -void D3D12GSRender::copy_render_target_to_dma_location() -{ - // Add all buffer write - // Cell can't make any assumption about readyness of color/depth buffer - // Except when a semaphore is written by RSX - int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16; - int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16; - - ComPtr depth_buffer_write_dest, depth_format_conversion_buffer; - ComPtr descriptor_heap; - size_t depth_row_pitch = align(clip_w, 256); - - u32 context_dma_color[] = - { - rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_A], - rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_B], - rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_C], - rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_D], - }; - u32 m_context_dma_z = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]; - - bool need_transfer = false; - - if (m_context_dma_z && rpcs3::state.config.rsx.opengl.write_depth_buffer) - { - size_t uav_size = clip_w * clip_h * 2; - assert(m_UAVHeap.can_alloc(uav_size)); - size_t heap_offset = m_UAVHeap.alloc(uav_size); - - ThrowIfFailed( - m_device->CreatePlacedResource( - m_UAVHeap.m_heap, - heap_offset, - &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8_UNORM, clip_w, clip_h, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS), - D3D12_RESOURCE_STATE_UNORDERED_ACCESS, - nullptr, - IID_PPV_ARGS(depth_format_conversion_buffer.GetAddressOf()) - ) - ); - - size_t buffer_size = depth_row_pitch * clip_h; - assert(m_readbackResources.can_alloc(buffer_size)); - heap_offset = m_readbackResources.alloc(buffer_size); - - ThrowIfFailed( - m_device->CreatePlacedResource( - m_readbackResources.m_heap, - heap_offset, - &CD3DX12_RESOURCE_DESC::Buffer(buffer_size), - D3D12_RESOURCE_STATE_COPY_DEST, - nullptr, - IID_PPV_ARGS(depth_buffer_write_dest.GetAddressOf()) - ) - ); - - D3D12_DESCRIPTOR_HEAP_DESC descriptor_heap_desc = { D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV , 2, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE }; - ThrowIfFailed( - m_device->CreateDescriptorHeap(&descriptor_heap_desc, IID_PPV_ARGS(descriptor_heap.GetAddressOf())) - ); - D3D12_SHADER_RESOURCE_VIEW_DESC shader_resource_view_desc = {}; - m_surface.depth_format = get_depth_typeless_surface_format(m_surface.depth_format); - shader_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - shader_resource_view_desc.Texture2D.MipLevels = 1; - shader_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - m_device->CreateShaderResourceView(m_rtts.m_currentlyBoundDepthStencil, &shader_resource_view_desc, - CD3DX12_CPU_DESCRIPTOR_HANDLE(descriptor_heap->GetCPUDescriptorHandleForHeapStart())); - D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = {}; - uav_desc.Format = DXGI_FORMAT_R8_UNORM; - uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; - m_device->CreateUnorderedAccessView(depth_format_conversion_buffer.Get(), nullptr, &uav_desc, - CD3DX12_CPU_DESCRIPTOR_HANDLE(descriptor_heap->GetCPUDescriptorHandleForHeapStart()).Offset(1, g_descriptorStrideSRVCBVUAV)); - - // Convert - getCurrentResourceStorage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.m_currentlyBoundDepthStencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ)); - - getCurrentResourceStorage().command_list->SetPipelineState(m_convertPSO); - getCurrentResourceStorage().command_list->SetComputeRootSignature(m_convertRootSignature); - getCurrentResourceStorage().command_list->SetDescriptorHeaps(1, descriptor_heap.GetAddressOf()); - getCurrentResourceStorage().command_list->SetComputeRootDescriptorTable(0, descriptor_heap->GetGPUDescriptorHandleForHeapStart()); - getCurrentResourceStorage().command_list->Dispatch(clip_w / 8, clip_h / 8, 1); - - D3D12_RESOURCE_BARRIER barriers[] = - { - CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.m_currentlyBoundDepthStencil, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE), - CD3DX12_RESOURCE_BARRIER::UAV(depth_format_conversion_buffer.Get()), - }; - getCurrentResourceStorage().command_list->ResourceBarrier(2, barriers); - getCurrentResourceStorage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(depth_format_conversion_buffer.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE)); - getCurrentResourceStorage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(depth_buffer_write_dest.Get(), { 0, { DXGI_FORMAT_R8_UNORM, (UINT)clip_w, (UINT)clip_h, 1, (UINT)depth_row_pitch } }), 0, 0, 0, - &CD3DX12_TEXTURE_COPY_LOCATION(depth_buffer_write_dest.Get(), 0), nullptr); - - invalidateAddress(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], m_context_dma_z - 0xfeed0000)); - - need_transfer = true; - } - - ComPtr readback_buffers[4]; - if (rpcs3::state.config.rsx.opengl.write_color_buffers) - { - for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) - { - if (!context_dma_color[i]) - continue; - readback_buffers[i] = create_readback_buffer_and_download(m_device.Get(), getCurrentResourceStorage().command_list.Get(), m_readbackResources, m_rtts.m_currentlyBoundRenderTargets[0], m_surface.color_format); - invalidateAddress(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET], context_dma_color[i] - 0xfeed0000)); - need_transfer = true; - } - } - if (need_transfer) - { - ThrowIfFailed(getCurrentResourceStorage().command_list->Close()); - m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)getCurrentResourceStorage().command_list.GetAddressOf()); - getCurrentResourceStorage().set_new_command_list(); - } - - //Wait for result - wait_for_command_queue(m_device.Get(), m_commandQueueGraphic.Get()); - - if (m_context_dma_z && rpcs3::state.config.rsx.opengl.write_depth_buffer) - { - u32 address = rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], m_context_dma_z - 0xfeed0000); - auto ptr = vm::base(address); - char *depth_buffer = (char*)ptr; - unsigned char *mapped_buffer; - ThrowIfFailed(depth_buffer_write_dest->Map(0, nullptr, (void**)&mapped_buffer)); - - for (unsigned row = 0; row < (unsigned)clip_h; row++) - { - for (unsigned i = 0; i < (unsigned)clip_w; i++) - { - unsigned char c = mapped_buffer[row * depth_row_pitch + i]; - depth_buffer[4 * (row * clip_w + i)] = c; - depth_buffer[4 * (row * clip_w + i) + 1] = c; - depth_buffer[4 * (row * clip_w + i) + 2] = c; - depth_buffer[4 * (row * clip_w + i) + 3] = c; - } - } - } - - size_t srcPitch, dstPitch; - switch (m_surface.color_format) - { - case CELL_GCM_SURFACE_A8R8G8B8: - srcPitch = align(clip_w * 4, 256); - dstPitch = clip_w * 4; - break; - case CELL_GCM_SURFACE_F_W16Z16Y16X16: - srcPitch = align(clip_w * 8, 256); - dstPitch = clip_w * 8; - break; - } - - if (rpcs3::state.config.rsx.opengl.write_color_buffers) - { - void *dest_buffer[] = - { - vm::base(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET], context_dma_color[0] - 0xfeed0000)), - vm::base(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET], context_dma_color[1] - 0xfeed0000)), - vm::base(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET], context_dma_color[2] - 0xfeed0000)), - vm::base(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET], context_dma_color[3] - 0xfeed0000)) - }; - - for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) - { - if (!context_dma_color[i]) - continue; - copy_readback_buffer_to_dest(dest_buffer[i], readback_buffers[i].Get(), srcPitch, dstPitch, clip_h); - } - } -} #endif diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index d316a98ff3..d300a0d931 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -131,7 +131,7 @@ private: size_t m_count; /* m_IASet; std::vector m_vertex_buffer_views; @@ -159,6 +159,8 @@ private: bool load_program(); + void set_rtt_and_ds(ID3D12GraphicsCommandList *command_list); + /** * Create vertex and index buffers (if needed) and set them to cmdlist. * Non native primitive type are emulated by index buffers expansion. diff --git a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.cpp b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.cpp index 4e9345c9ef..7088951360 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.cpp @@ -13,6 +13,102 @@ #include "D3D12GSRender.h" #include "D3D12Formats.h" + +namespace +{ + UINT get_num_rtt(u8 color_target) noexcept + { + switch (color_target) + { + case CELL_GCM_SURFACE_TARGET_NONE: return 0; + case CELL_GCM_SURFACE_TARGET_0: + case CELL_GCM_SURFACE_TARGET_1: return 1; + case CELL_GCM_SURFACE_TARGET_MRT1: return 2; + case CELL_GCM_SURFACE_TARGET_MRT2: return 3; + case CELL_GCM_SURFACE_TARGET_MRT3: return 4; + } + unreachable("Wrong color target"); + } + + std::vector get_rtt_indexes(u8 color_target) noexcept + { + switch (color_target) + { + case CELL_GCM_SURFACE_TARGET_NONE: return{}; + case CELL_GCM_SURFACE_TARGET_0: return{ 0 }; + case CELL_GCM_SURFACE_TARGET_1: return{ 1 }; + case CELL_GCM_SURFACE_TARGET_MRT1: return{ 0, 1 }; + case CELL_GCM_SURFACE_TARGET_MRT2: return{ 0, 1, 2 }; + case CELL_GCM_SURFACE_TARGET_MRT3: return{ 0, 1, 2, 3 }; + } + unreachable("Wrong color target"); + } + + std::array get_clear_color(u32 clear_color) noexcept + { + u8 clear_a = clear_color >> 24; + u8 clear_r = clear_color >> 16; + u8 clear_g = clear_color >> 8; + u8 clear_b = clear_color; + return + { + clear_r / 255.0f, + clear_g / 255.0f, + clear_b / 255.0f, + clear_a / 255.0f + }; + } + + u8 get_clear_stencil(u32 register_value) noexcept + { + return register_value & 0xff; + } +} + +void D3D12GSRender::clear_surface(u32 arg) +{ + std::chrono::time_point start_duration = std::chrono::system_clock::now(); + + std::chrono::time_point rtt_duration_start = std::chrono::system_clock::now(); + prepare_render_targets(getCurrentResourceStorage().command_list.Get()); + + std::chrono::time_point rtt_duration_end = std::chrono::system_clock::now(); + m_timers.m_rttDuration += std::chrono::duration_cast(rtt_duration_end - rtt_duration_start).count(); + + if (arg & 0x1 || arg & 0x2) + m_rtts.bind_depth_stencil(m_device.Get(), m_surface.depth_format, m_rtts.depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart()); + + if (arg & 0x1) + { + u32 clear_depth = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] >> 8; + u32 max_depth_value = m_surface.depth_format == CELL_GCM_SURFACE_Z16 ? 0x0000ffff : 0x00ffffff; + getCurrentResourceStorage().command_list->ClearDepthStencilView(m_rtts.depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, clear_depth / (float)max_depth_value, 0, 0, nullptr); + } + + if (arg & 0x2) + getCurrentResourceStorage().command_list->ClearDepthStencilView(m_rtts.depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_STENCIL, 0.f, + get_clear_stencil(rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE]), 0, nullptr); + + if (arg & 0xF0) + { + size_t rtt_index = m_rtts.bind_render_targets(m_device.Get(), m_surface.color_format, m_rtts.render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart()); + for (unsigned i = 0; i < rtt_index; i++) + getCurrentResourceStorage().command_list->ClearRenderTargetView(CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart()).Offset(i, g_descriptorStrideRTV), + get_clear_color(rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE]).data(), 0, nullptr); + } + + std::chrono::time_point end_duration = std::chrono::system_clock::now(); + m_timers.m_drawCallDuration += std::chrono::duration_cast(end_duration - start_duration).count(); + m_timers.m_drawCallCount++; + + if (rpcs3::config.rsx.d3d12.debug_output.value()) + { + ThrowIfFailed(getCurrentResourceStorage().command_list->Close()); + m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)getCurrentResourceStorage().command_list.GetAddressOf()); + getCurrentResourceStorage().set_new_command_list(); + } +} + void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlist) { u32 surface_format = rsx::method_registers[NV4097_SET_SURFACE_FORMAT]; @@ -25,6 +121,49 @@ void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlis u32 clip_x = clip_horizontal; u32 clip_y = clip_vertical; + u32 context_dma_color[] = + { + rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_A], + rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_B], + rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_C], + rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_D] + }; + u32 offset_zeta = rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET]; + + u32 offset_color[] = + { + rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET], + rsx::method_registers[NV4097_SET_SURFACE_COLOR_BOFFSET], + rsx::method_registers[NV4097_SET_SURFACE_COLOR_COFFSET], + rsx::method_registers[NV4097_SET_SURFACE_COLOR_DOFFSET] + }; + u32 m_context_dma_z = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]; + + // FBO location has changed, previous data might be copied + u32 address_color[] = + { + context_dma_color[0] ? rsx::get_address(offset_color[0], context_dma_color[0]) : 0, + context_dma_color[1] ? rsx::get_address(offset_color[1], context_dma_color[1]) : 0, + context_dma_color[2] ? rsx::get_address(offset_color[2], context_dma_color[2]) : 0, + context_dma_color[3] ? rsx::get_address(offset_color[3], context_dma_color[3]) : 0, + }; + u32 address_z = offset_zeta ? rsx::get_address(offset_zeta, m_context_dma_z) : 0; + + // Exit early if there is no rtt changes + if (m_previous_address_a == address_color[0] && + m_previous_address_b == address_color[1] && + m_previous_address_c == address_color[2] && + m_previous_address_d == address_color[3] && + m_previous_address_z == address_z && + m_surface.format != surface_format) + return; + + m_previous_address_a = address_color[0]; + m_previous_address_b = address_color[1]; + m_previous_address_c = address_color[2]; + m_previous_address_d = address_color[3]; + m_previous_address_z = address_z; + if (m_surface.format != surface_format) { m_surface.unpack(surface_format); @@ -32,253 +171,420 @@ void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlis m_surface.height = clip_height; } - // Exit early if there is no rtt changes - if ((m_previous_address_a == rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET]) && - (m_previous_address_b == rsx::method_registers[NV4097_SET_SURFACE_COLOR_BOFFSET]) && - (m_previous_address_c == rsx::method_registers[NV4097_SET_SURFACE_COLOR_COFFSET]) && - (m_previous_address_d == rsx::method_registers[NV4097_SET_SURFACE_COLOR_DOFFSET]) && - (m_previous_address_z == rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET])) - return; - - m_previous_address_a = rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET]; - m_previous_address_b = rsx::method_registers[NV4097_SET_SURFACE_COLOR_BOFFSET]; - m_previous_address_c = rsx::method_registers[NV4097_SET_SURFACE_COLOR_COFFSET]; - m_previous_address_d = rsx::method_registers[NV4097_SET_SURFACE_COLOR_DOFFSET]; - m_previous_address_z = rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET]; - - u32 m_context_dma_color_a = rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_A]; - u32 m_context_dma_color_b = rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_B]; - u32 m_context_dma_color_c = rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_C]; - u32 m_context_dma_color_d = rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_D]; - u32 m_context_dma_z = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]; - - // FBO location has changed, previous data might be copied - u32 address_a = m_context_dma_color_a ? rsx::get_address(m_previous_address_a, m_context_dma_color_a - 0xfeed0000) : 0; - u32 address_b = m_context_dma_color_b ? rsx::get_address(m_previous_address_b, m_context_dma_color_b - 0xfeed0000) : 0; - u32 address_c = m_context_dma_color_c ? rsx::get_address(m_previous_address_c, m_context_dma_color_c - 0xfeed0000) : 0; - u32 address_d = m_context_dma_color_d ? rsx::get_address(m_previous_address_d, m_context_dma_color_d - 0xfeed0000) : 0; - u32 address_z = m_context_dma_z ? rsx::get_address(m_previous_address_z, m_context_dma_z - 0xfeed0000) : 0; - // Make previous RTTs sampleable for (unsigned i = 0; i < 4; i++) { - if (m_rtts.m_currentlyBoundRenderTargets[i] == nullptr) + if (m_rtts.bound_render_targets[i] == nullptr) continue; - copycmdlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.m_currentlyBoundRenderTargets[i], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ)); + copycmdlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_render_targets[i], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ)); } + // Reset bound data + memset(m_rtts.bound_render_targets_address, 0, 4 * sizeof(u32)); + memset(m_rtts.bound_render_targets, 0, 4 * sizeof(ID3D12Resource *)); + + + // Create/Reuse requested rtts + std::array clear_color = get_clear_color(rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE]); + for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) + { + m_rtts.bound_render_targets[i] = m_rtts.bind_address_as_render_targets(m_device.Get(), copycmdlist, address_color[i], clip_width, clip_height, m_surface.color_format, + clear_color); + m_rtts.bound_render_targets_address[i] = address_color[i]; + } + // Same for depth buffer - if (m_rtts.m_currentlyBoundDepthStencil != nullptr) - copycmdlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.m_currentlyBoundDepthStencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ)); - - memset(m_rtts.m_currentlyBoundRenderTargetsAddress, 0, 4 * sizeof(u32)); - memset(m_rtts.m_currentlyBoundRenderTargets, 0, 4 * sizeof(ID3D12Resource *)); - m_rtts.m_currentlyBoundDepthStencil = nullptr; - m_rtts.m_currentlyBoundDepthStencilAddress = 0; - - - D3D12_CPU_DESCRIPTOR_HANDLE Handle = m_rtts.m_renderTargetsDescriptorsHeap->GetCPUDescriptorHandleForHeapStart(); - size_t g_RTTIncrement = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - - DXGI_FORMAT dxgiFormat = get_color_surface_format(m_surface.color_format); - D3D12_RENDER_TARGET_VIEW_DESC rttViewDesc = {}; - rttViewDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - rttViewDesc.Format = dxgiFormat; - - u32 clear_color = rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE]; - u8 clear_a = clear_color >> 24; - u8 clear_r = clear_color >> 16; - u8 clear_g = clear_color >> 8; - u8 clear_b = clear_color; - std::array clearColor = - { - clear_r / 255.0f, - clear_g / 255.0f, - clear_b / 255.0f, - clear_a / 255.0f - }; - - switch (rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]) - { - case CELL_GCM_SURFACE_TARGET_0: - { - ID3D12Resource *rttA = m_rtts.bindAddressAsRenderTargets(m_device.Get(), copycmdlist, 0, address_a, clip_width, clip_height, m_surface.color_format, - clearColor); - m_device->CreateRenderTargetView(rttA, &rttViewDesc, Handle); - break; - } - case CELL_GCM_SURFACE_TARGET_1: - { - ID3D12Resource *rttB = m_rtts.bindAddressAsRenderTargets(m_device.Get(), copycmdlist, 0, address_b, clip_width, clip_height, m_surface.color_format, - clearColor); - m_device->CreateRenderTargetView(rttB, &rttViewDesc, Handle); - break; - } - case CELL_GCM_SURFACE_TARGET_MRT1: - { - ID3D12Resource *rttA = m_rtts.bindAddressAsRenderTargets(m_device.Get(), copycmdlist, 0, address_a, clip_width, clip_height, m_surface.color_format, - clearColor); - m_device->CreateRenderTargetView(rttA, &rttViewDesc, Handle); - Handle.ptr += g_RTTIncrement; - ID3D12Resource *rttB = m_rtts.bindAddressAsRenderTargets(m_device.Get(), copycmdlist, 1, address_b, clip_width, clip_height, m_surface.color_format, - clearColor); - m_device->CreateRenderTargetView(rttB, &rttViewDesc, Handle); - } - break; - case CELL_GCM_SURFACE_TARGET_MRT2: - { - ID3D12Resource *rttA = m_rtts.bindAddressAsRenderTargets(m_device.Get(), copycmdlist, 0, address_a, clip_width, clip_height, m_surface.color_format, - clearColor); - m_device->CreateRenderTargetView(rttA, &rttViewDesc, Handle); - Handle.ptr += g_RTTIncrement; - ID3D12Resource *rttB = m_rtts.bindAddressAsRenderTargets(m_device.Get(), copycmdlist, 1, address_b, clip_width, clip_height, m_surface.color_format, - clearColor); - m_device->CreateRenderTargetView(rttB, &rttViewDesc, Handle); - Handle.ptr += g_RTTIncrement; - ID3D12Resource *rttC = m_rtts.bindAddressAsRenderTargets(m_device.Get(), copycmdlist, 2, address_c, clip_width, clip_height, m_surface.color_format, - clearColor); - m_device->CreateRenderTargetView(rttC, &rttViewDesc, Handle); - break; - } - case CELL_GCM_SURFACE_TARGET_MRT3: - { - ID3D12Resource *rttA = m_rtts.bindAddressAsRenderTargets(m_device.Get(), copycmdlist, 0, address_a, clip_width, clip_height, m_surface.color_format, - clearColor); - m_device->CreateRenderTargetView(rttA, &rttViewDesc, Handle); - Handle.ptr += g_RTTIncrement; - ID3D12Resource *rttB = m_rtts.bindAddressAsRenderTargets(m_device.Get(), copycmdlist, 1, address_b, clip_width, clip_height, m_surface.color_format, - clearColor); - m_device->CreateRenderTargetView(rttB, &rttViewDesc, Handle); - Handle.ptr += g_RTTIncrement; - ID3D12Resource *rttC = m_rtts.bindAddressAsRenderTargets(m_device.Get(), copycmdlist, 2, address_c, clip_width, clip_height, m_surface.color_format, - clearColor); - m_device->CreateRenderTargetView(rttC, &rttViewDesc, Handle); - Handle.ptr += g_RTTIncrement; - ID3D12Resource *rttD = m_rtts.bindAddressAsRenderTargets(m_device.Get(), copycmdlist, 3, address_d, clip_width, clip_height, m_surface.color_format, - clearColor); - m_device->CreateRenderTargetView(rttD, &rttViewDesc, Handle); - break; - } - } - - ComPtr oldDS; - ID3D12Resource *ds = m_rtts.bindAddressAsDepthStencil(m_device.Get(), copycmdlist, address_z, clip_width, clip_height, m_surface.depth_format, 1., 0, oldDS); - if (oldDS) - getCurrentResourceStorage().dirty_textures.push_back(oldDS); - - D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = {}; - depthStencilViewDesc.Format = get_depth_stencil_surface_format(m_surface.depth_format); - depthStencilViewDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; - m_device->CreateDepthStencilView(ds, &depthStencilViewDesc, m_rtts.m_depthStencilDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); + if (m_rtts.bound_depth_stencil != nullptr) + copycmdlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ)); + m_rtts.bound_depth_stencil = nullptr; + m_rtts.bound_depth_stencil_address = 0; + if (!address_z) + return; + ComPtr old_depth_stencil_resource; + ID3D12Resource *ds = m_rtts.bind_address_as_depth_stencil(m_device.Get(), copycmdlist, address_z, clip_width, clip_height, m_surface.depth_format, 1., 0, old_depth_stencil_resource); + if (old_depth_stencil_resource) + getCurrentResourceStorage().dirty_textures.push_back(old_depth_stencil_resource); + m_rtts.bound_depth_stencil_address = address_z; + m_rtts.bound_depth_stencil = ds; } -ID3D12Resource *RenderTargets::bindAddressAsRenderTargets(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, size_t slot, u32 address, - size_t width, size_t height, u8 surfaceColorFormat, const std::array &clearColor) +size_t render_targets::bind_render_targets(ID3D12Device *device, u32 color_format, D3D12_CPU_DESCRIPTOR_HANDLE handle) { - ID3D12Resource* rtt; - auto It = m_renderTargets.find(address); - // TODO: Check if sizes match - if (It != m_renderTargets.end()) + DXGI_FORMAT dxgi_format = get_color_surface_format(color_format); + D3D12_RENDER_TARGET_VIEW_DESC rtt_view_desc = {}; + rtt_view_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + rtt_view_desc.Format = dxgi_format; + + size_t rtt_index = 0; + for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) { - rtt = It->second; + if (bound_render_targets[i] == nullptr) + continue; + device->CreateRenderTargetView(bound_render_targets[i], &rtt_view_desc, + CD3DX12_CPU_DESCRIPTOR_HANDLE(render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart()).Offset((INT)rtt_index * g_descriptor_stride_rtv)); + rtt_index++; + } + return rtt_index; +} + +size_t render_targets::bind_depth_stencil(ID3D12Device *device, u32 depth_format, D3D12_CPU_DESCRIPTOR_HANDLE handle) +{ + if (!bound_depth_stencil) + return 0; + D3D12_DEPTH_STENCIL_VIEW_DESC depth_stencil_view_desc = {}; + depth_stencil_view_desc.Format = get_depth_stencil_surface_format(depth_format); + depth_stencil_view_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + device->CreateDepthStencilView(bound_depth_stencil, &depth_stencil_view_desc, depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart()); + return 1; +} + +void D3D12GSRender::set_rtt_and_ds(ID3D12GraphicsCommandList *command_list) +{ + size_t num_rtt = m_rtts.bind_render_targets(m_device.Get(), m_surface.color_format, m_rtts.render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart()); + size_t num_ds = m_rtts.bind_depth_stencil(m_device.Get(), m_surface.depth_format, m_rtts.depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart()); + command_list->OMSetRenderTargets((UINT)num_rtt, num_rtt > 0 ? &m_rtts.render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart() : nullptr, !!num_rtt, + num_ds > 0 ? &CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart()) : nullptr); +} + +ID3D12Resource *render_targets::bind_address_as_render_targets(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, u32 address, + size_t width, size_t height, u8 surfaceColorFormat, const std::array &clear_color) +{ + auto It = render_targets_storage.find(address); + // TODO: Check if format and size match + if (It != render_targets_storage.end()) + { + ID3D12Resource* rtt; + rtt = It->second.Get(); cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(rtt, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET)); + return rtt; } - else - { + ComPtr rtt; LOG_WARNING(RSX, "Creating RTT"); - DXGI_FORMAT dxgiFormat = get_color_surface_format(surfaceColorFormat); - D3D12_CLEAR_VALUE clearColorValue = {}; - clearColorValue.Format = dxgiFormat; - clearColorValue.Color[0] = clearColor[0]; - clearColorValue.Color[1] = clearColor[1]; - clearColorValue.Color[2] = clearColor[2]; - clearColorValue.Color[3] = clearColor[3]; + DXGI_FORMAT dxgi_format = get_color_surface_format(surfaceColorFormat); + D3D12_CLEAR_VALUE clear_color_value = {}; + clear_color_value.Format = dxgi_format; + clear_color_value.Color[0] = clear_color[0]; + clear_color_value.Color[1] = clear_color[1]; + clear_color_value.Color[2] = clear_color[2]; + clear_color_value.Color[3] = clear_color[3]; - device->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), - D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Tex2D(dxgiFormat, (UINT)width, (UINT)height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET), - D3D12_RESOURCE_STATE_RENDER_TARGET, - &clearColorValue, - IID_PPV_ARGS(&rtt) - ); - m_renderTargets[address] = rtt; - } - m_currentlyBoundRenderTargetsAddress[slot] = address; - m_currentlyBoundRenderTargets[slot] = rtt; - return rtt; + device->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)width, (UINT)height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET), + D3D12_RESOURCE_STATE_RENDER_TARGET, + &clear_color_value, + IID_PPV_ARGS(rtt.GetAddressOf()) + ); + render_targets_storage[address] = rtt; + + return rtt.Get(); } -ID3D12Resource * RenderTargets::bindAddressAsDepthStencil(ID3D12Device * device, ID3D12GraphicsCommandList * cmdList, u32 address, size_t width, size_t height, u8 surfaceDepthFormat, float depthClear, u8 stencilClear, ComPtr &dirtyDS) +ID3D12Resource * render_targets::bind_address_as_depth_stencil(ID3D12Device * device, ID3D12GraphicsCommandList * cmdList, u32 address, size_t width, size_t height, u8 surfaceDepthFormat, float depthClear, u8 stencilClear, ComPtr &dirtyDS) { - - auto It = m_depthStencil.find(address); - m_currentlyBoundDepthStencilAddress = address; + auto It = depth_stencil_storage.find(address); // TODO: Check if surface depth format match - if (It != m_depthStencil.end()) + if (It != depth_stencil_storage.end()) { ComPtr ds = It->second; if (ds->GetDesc().Width == width && ds->GetDesc().Height == height) { // set the resource as depth write cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE)); - m_currentlyBoundDepthStencil = ds.Get(); return ds.Get(); } // If size doesn't match, remove ds from cache - m_depthStencil.erase(address); + depth_stencil_storage.erase(address); dirtyDS = ds; } - D3D12_CLEAR_VALUE clearDepthValue = {}; - clearDepthValue.DepthStencil.Depth = depthClear; + D3D12_CLEAR_VALUE clear_depth_value = {}; + clear_depth_value.DepthStencil.Depth = depthClear; - D3D12_HEAP_PROPERTIES heapProp = {}; - heapProp.Type = D3D12_HEAP_TYPE_DEFAULT; + DXGI_FORMAT dxgi_format = get_depth_typeless_surface_format(surfaceDepthFormat); + clear_depth_value.Format = get_depth_stencil_surface_clear_format(surfaceDepthFormat); - DXGI_FORMAT dxgiFormat = get_depth_typeless_surface_format(surfaceDepthFormat); - clearDepthValue.Format = get_depth_stencil_surface_clear_format(surfaceDepthFormat); - - ComPtr newds; + ComPtr new_depth_stencil; device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Tex2D(dxgiFormat, (UINT)width, (UINT)height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL), + &CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)width, (UINT)height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL), D3D12_RESOURCE_STATE_DEPTH_WRITE, - &clearDepthValue, - IID_PPV_ARGS(newds.GetAddressOf()) + &clear_depth_value, + IID_PPV_ARGS(new_depth_stencil.GetAddressOf()) ); - m_depthStencil[address] = newds; - m_currentlyBoundDepthStencil = newds.Get(); + depth_stencil_storage[address] = new_depth_stencil; - return newds.Get(); + return new_depth_stencil.Get(); } -void RenderTargets::Init(ID3D12Device *device)//, u8 surfaceDepthFormat, size_t width, size_t height, float clearColor[4], float clearDepth) +void render_targets::init(ID3D12Device *device)//, u8 surfaceDepthFormat, size_t width, size_t height, float clearColor[4], float clearDepth) { - D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc = {}; - descriptorHeapDesc.NumDescriptors = 1; - descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; - device->CreateDescriptorHeap(&descriptorHeapDesc, IID_PPV_ARGS(&m_depthStencilDescriptorHeap)); + D3D12_DESCRIPTOR_HEAP_DESC descriptor_heap_desc = {}; + descriptor_heap_desc.NumDescriptors = 1; + descriptor_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + device->CreateDescriptorHeap(&descriptor_heap_desc, IID_PPV_ARGS(depth_stencil_descriptor_heap.GetAddressOf())); - descriptorHeapDesc.NumDescriptors = 4; - descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - device->CreateDescriptorHeap(&descriptorHeapDesc, IID_PPV_ARGS(&m_renderTargetsDescriptorsHeap)); + descriptor_heap_desc.NumDescriptors = 4; + descriptor_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + device->CreateDescriptorHeap(&descriptor_heap_desc, IID_PPV_ARGS(render_targets_descriptors_heap.GetAddressOf())); - memset(m_currentlyBoundRenderTargetsAddress, 0, 4 * sizeof(u32)); - memset(m_currentlyBoundRenderTargets, 0, 4 * sizeof(ID3D12Resource*)); - m_currentlyBoundDepthStencil = nullptr; - m_currentlyBoundDepthStencilAddress = 0; + memset(bound_render_targets_address, 0, 4 * sizeof(u32)); + memset(bound_render_targets, 0, 4 * sizeof(ID3D12Resource*)); + bound_depth_stencil = nullptr; + bound_depth_stencil_address = 0; + g_descriptor_stride_rtv = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); } -void RenderTargets::Release() +namespace { - for (auto tmp : m_renderTargets) - tmp.second->Release(); - m_depthStencilDescriptorHeap->Release(); - m_renderTargetsDescriptorsHeap->Release(); - for (auto tmp : m_depthStencil) - tmp.second->Release(); + /** + * Create a write back buffer resource and populate command_list with copy command to fill it + * with color_surface data. + */ + ComPtr create_readback_buffer_and_download( + ID3D12Device *device, + ID3D12GraphicsCommandList * command_list, + data_heap &readback_heap, + ID3D12Resource * color_surface, + int color_surface_format + ) + { + int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16; + int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16; + + DXGI_FORMAT dxgi_format = get_color_surface_format(color_surface_format); + size_t row_pitch; + switch (color_surface_format) + { + case CELL_GCM_SURFACE_A8R8G8B8: + row_pitch = align(clip_w * 4, 256); + break; + case CELL_GCM_SURFACE_F_W16Z16Y16X16: + row_pitch = align(clip_w * 8, 256); + break; + } + + size_t buffer_size = row_pitch * clip_h; + assert(readback_heap.can_alloc(buffer_size)); + size_t heapOffset = readback_heap.alloc(buffer_size); + ComPtr Result; + ThrowIfFailed( + device->CreatePlacedResource( + readback_heap.m_heap, + heapOffset, + &CD3DX12_RESOURCE_DESC::Buffer(row_pitch * clip_h), + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(Result.GetAddressOf()) + ) + ); + + command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(color_surface, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE)); + + command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(Result.Get(), { 0,{ dxgi_format, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0, + &CD3DX12_TEXTURE_COPY_LOCATION(color_surface, 0), nullptr); + command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(color_surface, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET)); + return Result; + } + + void copy_readback_buffer_to_dest(void *dest, ID3D12Resource *res, size_t dst_pitch, size_t src_pitch, size_t height) + { + void *mapped_buffer; + ThrowIfFailed(res->Map(0, nullptr, &mapped_buffer)); + for (unsigned row = 0; row < height; row++) + { + u32 *casted_dest = (u32*)((char*)dest + row * dst_pitch); + u32 *casted_src = (u32*)((char*)mapped_buffer + row * src_pitch); + for (unsigned col = 0; col < src_pitch / 4; col++) + *casted_dest++ = _byteswap_ulong(*casted_src++); + } + res->Unmap(0, nullptr); + } + + void wait_for_command_queue(ID3D12Device *device, ID3D12CommandQueue *command_queue) + { + ComPtr fence; + ThrowIfFailed(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(fence.GetAddressOf()))); + HANDLE handle = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); + fence->SetEventOnCompletion(1, handle); + command_queue->Signal(fence.Get(), 1); + WaitForSingleObjectEx(handle, INFINITE, FALSE); + CloseHandle(handle); + } } + +void D3D12GSRender::copy_render_target_to_dma_location() +{ + // Add all buffer write + // Cell can't make any assumption about readyness of color/depth buffer + // Except when a semaphore is written by RSX + int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16; + int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16; + + ComPtr depth_buffer_write_dest, depth_format_conversion_buffer; + ComPtr descriptor_heap; + size_t depth_row_pitch = align(clip_w, 256); + + u32 context_dma_color[] = + { + rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_A], + rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_B], + rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_C], + rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_D], + }; + u32 m_context_dma_z = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]; + + bool need_transfer = false; + + if (m_context_dma_z && rpcs3::state.config.rsx.opengl.write_depth_buffer) + { + size_t uav_size = clip_w * clip_h * 2; + assert(m_UAVHeap.can_alloc(uav_size)); + size_t heap_offset = m_UAVHeap.alloc(uav_size); + + ThrowIfFailed( + m_device->CreatePlacedResource( + m_UAVHeap.m_heap, + heap_offset, + &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8_UNORM, clip_w, clip_h, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS), + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + nullptr, + IID_PPV_ARGS(depth_format_conversion_buffer.GetAddressOf()) + ) + ); + + size_t buffer_size = depth_row_pitch * clip_h; + assert(m_readbackResources.can_alloc(buffer_size)); + heap_offset = m_readbackResources.alloc(buffer_size); + + ThrowIfFailed( + m_device->CreatePlacedResource( + m_readbackResources.m_heap, + heap_offset, + &CD3DX12_RESOURCE_DESC::Buffer(buffer_size), + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(depth_buffer_write_dest.GetAddressOf()) + ) + ); + + D3D12_DESCRIPTOR_HEAP_DESC descriptor_heap_desc = { D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV , 2, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE }; + ThrowIfFailed( + m_device->CreateDescriptorHeap(&descriptor_heap_desc, IID_PPV_ARGS(descriptor_heap.GetAddressOf())) + ); + D3D12_SHADER_RESOURCE_VIEW_DESC shader_resource_view_desc = {}; + m_surface.depth_format = get_depth_typeless_surface_format(m_surface.depth_format); + shader_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + shader_resource_view_desc.Texture2D.MipLevels = 1; + shader_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + m_device->CreateShaderResourceView(m_rtts.bound_depth_stencil, &shader_resource_view_desc, + CD3DX12_CPU_DESCRIPTOR_HANDLE(descriptor_heap->GetCPUDescriptorHandleForHeapStart())); + D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = {}; + uav_desc.Format = DXGI_FORMAT_R8_UNORM; + uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + m_device->CreateUnorderedAccessView(depth_format_conversion_buffer.Get(), nullptr, &uav_desc, + CD3DX12_CPU_DESCRIPTOR_HANDLE(descriptor_heap->GetCPUDescriptorHandleForHeapStart()).Offset(1, g_descriptorStrideSRVCBVUAV)); + + // Convert + getCurrentResourceStorage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ)); + + getCurrentResourceStorage().command_list->SetPipelineState(m_convertPSO); + getCurrentResourceStorage().command_list->SetComputeRootSignature(m_convertRootSignature); + getCurrentResourceStorage().command_list->SetDescriptorHeaps(1, descriptor_heap.GetAddressOf()); + getCurrentResourceStorage().command_list->SetComputeRootDescriptorTable(0, descriptor_heap->GetGPUDescriptorHandleForHeapStart()); + getCurrentResourceStorage().command_list->Dispatch(clip_w / 8, clip_h / 8, 1); + + D3D12_RESOURCE_BARRIER barriers[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE), + CD3DX12_RESOURCE_BARRIER::UAV(depth_format_conversion_buffer.Get()), + }; + getCurrentResourceStorage().command_list->ResourceBarrier(2, barriers); + getCurrentResourceStorage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(depth_format_conversion_buffer.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE)); + getCurrentResourceStorage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(depth_buffer_write_dest.Get(), { 0,{ DXGI_FORMAT_R8_UNORM, (UINT)clip_w, (UINT)clip_h, 1, (UINT)depth_row_pitch } }), 0, 0, 0, + &CD3DX12_TEXTURE_COPY_LOCATION(depth_buffer_write_dest.Get(), 0), nullptr); + + invalidateAddress(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], m_context_dma_z - 0xfeed0000)); + + need_transfer = true; + } + + ComPtr readback_buffers[4]; + if (rpcs3::state.config.rsx.opengl.write_color_buffers) + { + for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) + { + if (!context_dma_color[i]) + continue; + readback_buffers[i] = create_readback_buffer_and_download(m_device.Get(), getCurrentResourceStorage().command_list.Get(), m_readbackResources, m_rtts.bound_render_targets[0], m_surface.color_format); + invalidateAddress(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET], context_dma_color[i] - 0xfeed0000)); + need_transfer = true; + } + } + if (need_transfer) + { + ThrowIfFailed(getCurrentResourceStorage().command_list->Close()); + m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)getCurrentResourceStorage().command_list.GetAddressOf()); + getCurrentResourceStorage().set_new_command_list(); + } + + //Wait for result + wait_for_command_queue(m_device.Get(), m_commandQueueGraphic.Get()); + + if (m_context_dma_z && rpcs3::state.config.rsx.opengl.write_depth_buffer) + { + u32 address = rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], m_context_dma_z - 0xfeed0000); + auto ptr = vm::base(address); + char *depth_buffer = (char*)ptr; + unsigned char *mapped_buffer; + ThrowIfFailed(depth_buffer_write_dest->Map(0, nullptr, (void**)&mapped_buffer)); + + for (unsigned row = 0; row < (unsigned)clip_h; row++) + { + for (unsigned i = 0; i < (unsigned)clip_w; i++) + { + unsigned char c = mapped_buffer[row * depth_row_pitch + i]; + depth_buffer[4 * (row * clip_w + i)] = c; + depth_buffer[4 * (row * clip_w + i) + 1] = c; + depth_buffer[4 * (row * clip_w + i) + 2] = c; + depth_buffer[4 * (row * clip_w + i) + 3] = c; + } + } + } + + size_t srcPitch, dstPitch; + switch (m_surface.color_format) + { + case CELL_GCM_SURFACE_A8R8G8B8: + srcPitch = align(clip_w * 4, 256); + dstPitch = clip_w * 4; + break; + case CELL_GCM_SURFACE_F_W16Z16Y16X16: + srcPitch = align(clip_w * 8, 256); + dstPitch = clip_w * 8; + break; + } + + if (rpcs3::state.config.rsx.opengl.write_color_buffers) + { + void *dest_buffer[] = + { + vm::base(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET], context_dma_color[0] - 0xfeed0000)), + vm::base(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET], context_dma_color[1] - 0xfeed0000)), + vm::base(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET], context_dma_color[2] - 0xfeed0000)), + vm::base(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET], context_dma_color[3] - 0xfeed0000)) + }; + + for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) + { + if (!context_dma_color[i]) + continue; + copy_readback_buffer_to_dest(dest_buffer[i], readback_buffers[i].Get(), srcPitch, dstPitch, clip_h); + } + } +} + #endif diff --git a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h index 0392ed8d69..0f0c065ea7 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h @@ -2,29 +2,32 @@ #include -struct RenderTargets +struct render_targets { - std::unordered_map m_renderTargets; - ID3D12Resource *m_currentlyBoundRenderTargets[4]; - u32 m_currentlyBoundRenderTargetsAddress[4]; - std::unordered_map > m_depthStencil; - ID3D12Resource *m_currentlyBoundDepthStencil; - u32 m_currentlyBoundDepthStencilAddress; - ID3D12DescriptorHeap *m_renderTargetsDescriptorsHeap; - ID3D12DescriptorHeap *m_depthStencilDescriptorHeap; + INT g_descriptor_stride_rtv; + std::unordered_map > render_targets_storage; + ID3D12Resource *bound_render_targets[4]; + u32 bound_render_targets_address[4]; + std::unordered_map > depth_stencil_storage; + ID3D12Resource *bound_depth_stencil; + u32 bound_depth_stencil_address; + ComPtr render_targets_descriptors_heap; + ComPtr depth_stencil_descriptor_heap; + + size_t bind_render_targets(ID3D12Device *, u32 color_format, D3D12_CPU_DESCRIPTOR_HANDLE); + size_t bind_depth_stencil(ID3D12Device *, u32 depth_format, D3D12_CPU_DESCRIPTOR_HANDLE); /** * If render target already exists at address, issue state change operation on cmdList. * Otherwise create one with width, height, clearColor info. * returns the corresponding render target resource. */ - ID3D12Resource *bindAddressAsRenderTargets(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, size_t slot, u32 address, + ID3D12Resource *bind_address_as_render_targets(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, u32 address, size_t width, size_t height, u8 surfaceColorFormat, const std::array &clearColor); - ID3D12Resource *bindAddressAsDepthStencil(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, u32 address, + ID3D12Resource *bind_address_as_depth_stencil(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, u32 address, size_t width, size_t height, u8 surfaceDepthFormat, float depthClear, u8 stencilClear, ComPtr &dirtyDS); - void Init(ID3D12Device *device); - void Release(); + void init(ID3D12Device *device); }; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp index 484b28e4e8..c72213c228 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp @@ -140,12 +140,12 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_ bool is_swizzled = !(textures[i].format() & CELL_GCM_TEXTURE_LN); ID3D12Resource *vram_texture; - std::unordered_map::const_iterator ItRTT = m_rtts.m_renderTargets.find(texaddr); + std::unordered_map >::const_iterator ItRTT = m_rtts.render_targets_storage.find(texaddr); std::pair > *cached_texture = m_textureCache.find_data_if_available(texaddr); bool isRenderTarget = false; - if (ItRTT != m_rtts.m_renderTargets.end()) + if (ItRTT != m_rtts.render_targets_storage.end()) { - vram_texture = ItRTT->second; + vram_texture = ItRTT->second.Get(); isRenderTarget = true; } else if (cached_texture != nullptr && (cached_texture->first == texture_entry(format, w, h, textures[i].mipmap())))