diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Formats.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Formats.cpp index 7242c78462..932c0ca136 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Formats.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Formats.cpp @@ -106,14 +106,15 @@ D3D12_STENCIL_OP get_stencil_op(u32 op) noexcept case CELL_GCM_KEEP: return D3D12_STENCIL_OP_KEEP; case CELL_GCM_ZERO: return D3D12_STENCIL_OP_ZERO; case CELL_GCM_REPLACE: return D3D12_STENCIL_OP_REPLACE; - default: // Jet Set Radio set some garbage, turns out OP_INCR is the intended behavior. case CELL_GCM_INCR: return D3D12_STENCIL_OP_INCR; case CELL_GCM_DECR: return D3D12_STENCIL_OP_DECR; case CELL_GCM_INCR_WRAP: case CELL_GCM_DECR_WRAP: unreachable("Unsupported Stencil Op %d"); } - unreachable("Wrong Stencil Op %d"); + // Jet Set Radio uses an unknow op but INCR seems to be the intended one + LOG_WARNING(RSX, "Unknow stencil op %x, fallback to INCR", op); + return D3D12_STENCIL_OP_INCR; } D3D12_COMPARISON_FUNC get_compare_func(u32 op) noexcept @@ -237,7 +238,7 @@ namespace case CELL_GCM_TEXTURE_NEAREST: min = D3D12_FILTER_TYPE_POINT; mip = D3D12_FILTER_TYPE_POINT; - return;; + return; case CELL_GCM_TEXTURE_LINEAR: min = D3D12_FILTER_TYPE_LINEAR; mip = D3D12_FILTER_TYPE_POINT; @@ -259,7 +260,10 @@ namespace mip = D3D12_FILTER_TYPE_LINEAR; return; case CELL_GCM_TEXTURE_CONVOLUTION_MIN: - unreachable("Unsupported min filter"); + LOG_WARNING(RSX, "CELL_GCM_TEXTURE_CONVOLUTION_MIN not supported, fallback to bilinear filtering"); + min = D3D12_FILTER_TYPE_LINEAR; + mip = D3D12_FILTER_TYPE_POINT; + return; } unreachable("Wrong min filter"); } @@ -271,7 +275,9 @@ namespace case CELL_GCM_TEXTURE_NEAREST: return D3D12_FILTER_TYPE_POINT; case CELL_GCM_TEXTURE_LINEAR: return D3D12_FILTER_TYPE_LINEAR; } - unreachable("Wrong mag filter"); + // Catherine uses this + LOG_WARNING(RSX, "Unknow mag filter used %x, fallback to bilinear filtering", mag_filter); + return D3D12_FILTER_TYPE_LINEAR; } } @@ -327,6 +333,7 @@ DXGI_FORMAT get_color_surface_format(u8 format) noexcept { case CELL_GCM_SURFACE_A8R8G8B8: return DXGI_FORMAT_R8G8B8A8_UNORM; case CELL_GCM_SURFACE_F_W16Z16Y16X16: return DXGI_FORMAT_R16G16B16A16_FLOAT; + case CELL_GCM_SURFACE_F_X32: return DXGI_FORMAT_R32_FLOAT; } unreachable("Wrong color surface format"); } @@ -351,7 +358,7 @@ DXGI_FORMAT get_depth_stencil_surface_clear_format(u8 format) noexcept unreachable("Wrong depth stencil surface format"); } -DXGI_FORMAT get_depth_typeless_surface_format(u8 format) noexcept +DXGI_FORMAT get_depth_stencil_typeless_surface_format(u8 format) noexcept { switch (format) { @@ -361,6 +368,16 @@ DXGI_FORMAT get_depth_typeless_surface_format(u8 format) noexcept unreachable("Wrong depth stencil surface format"); } +DXGI_FORMAT get_depth_samplable_surface_format(u8 format) noexcept +{ + switch (format) + { + case CELL_GCM_SURFACE_Z16: return DXGI_FORMAT_R16_FLOAT; + case CELL_GCM_SURFACE_Z24S8: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + } + unreachable("Wrong depth stencil surface format"); +} + BOOL get_front_face_ccw(u32 set_front_face_value) noexcept { switch (set_front_face_value) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Formats.h b/rpcs3/Emu/RSX/D3D12/D3D12Formats.h index 45fdac4114..df21fe501a 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Formats.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12Formats.h @@ -79,9 +79,14 @@ DXGI_FORMAT get_depth_stencil_surface_format(u8 format) noexcept; DXGI_FORMAT get_depth_stencil_surface_clear_format(u8 format) noexcept; /** - * Convert depth surface format to DXGI_FORMAT using typeless for stencil + * Convert depth surface format to a typeless DXGI_FORMAT */ -DXGI_FORMAT get_depth_typeless_surface_format(u8 format) noexcept; +DXGI_FORMAT get_depth_stencil_typeless_surface_format(u8 format) noexcept; + +/** +* Convert depth surface format to a DXGI_FORMAT that can be depth sampled +*/ +DXGI_FORMAT get_depth_samplable_surface_format(u8 format) noexcept; /** * Convert front face value to bool value telling wheter front face is counterclockwise or not diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index dc66e8f33e..eb772ca656 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -197,14 +197,14 @@ D3D12GSRender::D3D12GSRender() IID_PPV_ARGS(&m_dummy_texture)) ); - m_readback_resources.init(m_device.Get(), 1024 * 1024 * 128, D3D12_HEAP_TYPE_READBACK, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS); + m_readback_resources.init(m_device.Get(), 1024 * 1024 * 128, D3D12_HEAP_TYPE_READBACK, D3D12_RESOURCE_STATE_COPY_DEST); m_uav_heap.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_constants_data.init(m_device.Get(), 1024 * 1024 * 64, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_NONE); - m_vertex_index_data.init(m_device.Get(), 1024 * 1024 * 384, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_NONE); - m_texture_upload_data.init(m_device.Get(), 1024 * 1024 * 512, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_NONE); + m_constants_data.init(m_device.Get(), 1024 * 1024 * 64, D3D12_HEAP_TYPE_UPLOAD, D3D12_RESOURCE_STATE_GENERIC_READ); + m_vertex_index_data.init(m_device.Get(), 1024 * 1024 * 384, D3D12_HEAP_TYPE_UPLOAD, D3D12_RESOURCE_STATE_GENERIC_READ); + m_texture_upload_data.init(m_device.Get(), 1024 * 1024 * 512, D3D12_HEAP_TYPE_UPLOAD, D3D12_RESOURCE_STATE_GENERIC_READ); if (rpcs3::config.rsx.d3d12.overlay.value()) init_d2d_structures(); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index c306d9ee56..614472f346 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -121,7 +121,7 @@ private: // Texture storage data_heap m_texture_upload_data; data_heap m_uav_heap; - data_heap m_readback_resources; + data_heap m_readback_resources; struct { diff --git a/rpcs3/Emu/RSX/D3D12/D3D12MemoryHelpers.h b/rpcs3/Emu/RSX/D3D12/D3D12MemoryHelpers.h index 33c026a93c..0704ca89ea 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12MemoryHelpers.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12MemoryHelpers.h @@ -27,15 +27,15 @@ struct init_heap template<> struct init_heap { - static ID3D12Resource* init(ID3D12Device *device, size_t heap_size, D3D12_HEAP_TYPE type, D3D12_HEAP_FLAGS flags) + static ID3D12Resource* init(ID3D12Device *device, size_t heap_size, D3D12_HEAP_TYPE type, D3D12_RESOURCE_STATES state) { ID3D12Resource *result; D3D12_HEAP_PROPERTIES heap_properties = {}; heap_properties.Type = type; ThrowIfFailed(device->CreateCommittedResource(&heap_properties, - flags, + D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(heap_size), - D3D12_RESOURCE_STATE_GENERIC_READ, + state, nullptr, IID_PPV_ARGS(&result)) ); @@ -60,10 +60,11 @@ struct data_heap size_t m_put_pos; // Start of free space size_t m_get_pos; // End of free space - void init(ID3D12Device *device, size_t heap_size, D3D12_HEAP_TYPE type, D3D12_HEAP_FLAGS flags) + template + void init(ID3D12Device *device, size_t heap_size, D3D12_HEAP_TYPE type, arg_type... args) { m_size = heap_size; - m_heap = init_heap::init(device, heap_size, type, flags); + m_heap = init_heap::init(device, heap_size, type, args...); m_put_pos = 0; m_get_pos = heap_size - 1; } diff --git a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.cpp b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.cpp index 373b2d1a87..3269f41c63 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.cpp @@ -196,8 +196,11 @@ void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlis 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])) { + ComPtr old_render_target_resource; 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); + clear_color, old_render_target_resource); + if (old_render_target_resource) + get_current_resource_storage().dirty_textures.push_back(old_render_target_resource); m_rtts.bound_render_targets_address[i] = address_color[i]; } @@ -261,20 +264,26 @@ void D3D12GSRender::set_rtt_and_ds(ID3D12GraphicsCommandList *command_list) } 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) + size_t width, size_t height, u8 surfaceColorFormat, const std::array &clear_color, ComPtr &dirtyRTT) { + DXGI_FORMAT dxgi_format = get_color_surface_format(surfaceColorFormat); auto It = render_targets_storage.find(address); // TODO: Check if format and size match if (It != render_targets_storage.end()) { - ID3D12Resource* rtt; + ComPtr 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; + if (rtt->GetDesc().Format == dxgi_format) + { + cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(rtt.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET)); + return rtt.Get(); + } + render_targets_storage.erase(address); + dirtyRTT = rtt; } ComPtr rtt; LOG_WARNING(RSX, "Creating RTT"); - 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]; @@ -318,7 +327,7 @@ ID3D12Resource * render_targets::bind_address_as_depth_stencil(ID3D12Device * de D3D12_CLEAR_VALUE clear_depth_value = {}; clear_depth_value.DepthStencil.Depth = depthClear; - DXGI_FORMAT dxgi_format = get_depth_typeless_surface_format(surfaceDepthFormat); + DXGI_FORMAT dxgi_format = get_depth_stencil_typeless_surface_format(surfaceDepthFormat); clear_depth_value.Format = get_depth_stencil_surface_clear_format(surfaceDepthFormat); ComPtr new_depth_stencil; @@ -348,13 +357,12 @@ void render_targets::init(ID3D12Device *device)//, u8 surfaceDepthFormat, size_t 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( + * Populate command_list with copy command with color_surface data and return offset in readback buffer + */ + size_t download_to_readback_buffer( ID3D12Device *device, ID3D12GraphicsCommandList * command_list, - data_heap &readback_heap, + data_heap &readback_heap, ID3D12Resource * color_surface, int color_surface_format ) @@ -376,31 +384,22 @@ namespace 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()) - ) - ); + size_t heap_offset = readback_heap.alloc(buffer_size); 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, + command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(readback_heap.m_heap, { heap_offset, { 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; + return heap_offset; } - void copy_readback_buffer_to_dest(void *dest, ID3D12Resource *res, size_t dst_pitch, size_t src_pitch, size_t height) + void copy_readback_buffer_to_dest(void *dest, data_heap &readback_heap, size_t offset_in_heap, size_t dst_pitch, size_t src_pitch, size_t height) { - void *mapped_buffer; - ThrowIfFailed(res->Map(0, nullptr, &mapped_buffer)); + void *buffer; + // TODO: Use exact range + ThrowIfFailed(readback_heap.m_heap->Map(0, nullptr, &buffer)); + void *mapped_buffer = (char*)buffer + offset_in_heap; for (unsigned row = 0; row < height; row++) { u32 *casted_dest = (u32*)((char*)dest + row * dst_pitch); @@ -408,7 +407,7 @@ namespace for (unsigned col = 0; col < src_pitch / 4; col++) *casted_dest++ = _byteswap_ulong(*casted_src++); } - res->Unmap(0, nullptr); + readback_heap.m_heap->Unmap(0, nullptr); } void wait_for_command_queue(ID3D12Device *device, ID3D12CommandQueue *command_queue) @@ -431,9 +430,10 @@ void D3D12GSRender::copy_render_target_to_dma_location() 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 depth_format_conversion_buffer; ComPtr descriptor_heap; size_t depth_row_pitch = align(clip_w, 256); + size_t depth_buffer_offset_in_heap = 0; u32 context_dma_color[] = { @@ -444,6 +444,24 @@ void D3D12GSRender::copy_render_target_to_dma_location() }; u32 m_context_dma_z = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]; + 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 offset_zeta = rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET]; + + u32 address_color[] = + { + rsx::get_address(offset_color[0], context_dma_color[0]), + rsx::get_address(offset_color[1], context_dma_color[1]), + rsx::get_address(offset_color[2], context_dma_color[2]), + rsx::get_address(offset_color[3], context_dma_color[3]), + }; + u32 address_z = rsx::get_address(offset_zeta, m_context_dma_z); + bool need_transfer = false; if (m_context_dma_z && rpcs3::state.config.rsx.opengl.write_depth_buffer) @@ -463,27 +481,12 @@ void D3D12GSRender::copy_render_target_to_dma_location() ) ); - size_t buffer_size = depth_row_pitch * clip_h; - assert(m_readback_resources.can_alloc(buffer_size)); - heap_offset = m_readback_resources.alloc(buffer_size); - - ThrowIfFailed( - m_device->CreatePlacedResource( - m_readback_resources.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.Format = get_depth_samplable_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; @@ -511,23 +514,23 @@ void D3D12GSRender::copy_render_target_to_dma_location() }; get_current_resource_storage().command_list->ResourceBarrier(2, barriers); get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(depth_format_conversion_buffer.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE)); - get_current_resource_storage().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); + get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.m_heap, { depth_buffer_offset_in_heap,{ DXGI_FORMAT_R8_UNORM, (UINT)clip_w, (UINT)clip_h, 1, (UINT)depth_row_pitch } }), 0, 0, 0, + &CD3DX12_TEXTURE_COPY_LOCATION(depth_format_conversion_buffer.Get(), 0), nullptr); - invalidate_address(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], m_context_dma_z - 0xfeed0000)); + invalidate_address(address_z); need_transfer = true; } - ComPtr readback_buffers[4]; + size_t color_buffer_offset_in_heap[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]) + if (!address_color[i]) continue; - readback_buffers[i] = create_readback_buffer_and_download(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, m_rtts.bound_render_targets[0], m_surface.color_format); - invalidate_address(rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET], context_dma_color[i] - 0xfeed0000)); + color_buffer_offset_in_heap[i] = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, m_rtts.bound_render_targets[i], m_surface.color_format); + invalidate_address(address_color[i]); need_transfer = true; } } @@ -541,13 +544,14 @@ void D3D12GSRender::copy_render_target_to_dma_location() //Wait for result wait_for_command_queue(m_device.Get(), m_command_queue.Get()); - if (m_context_dma_z && rpcs3::state.config.rsx.opengl.write_depth_buffer) + if (address_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); + auto ptr = vm::base(address_z); char *depth_buffer = (char*)ptr; - unsigned char *mapped_buffer; - ThrowIfFailed(depth_buffer_write_dest->Map(0, nullptr, (void**)&mapped_buffer)); + void *buffer; + // TODO: Use exact range + ThrowIfFailed(m_readback_resources.m_heap->Map(0, nullptr, &buffer)); + unsigned char *mapped_buffer = (unsigned char*)buffer + depth_buffer_offset_in_heap; for (unsigned row = 0; row < (unsigned)clip_h; row++) { @@ -560,6 +564,7 @@ void D3D12GSRender::copy_render_target_to_dma_location() depth_buffer[4 * (row * clip_w + i) + 3] = c; } } + m_readback_resources.m_heap->Unmap(0, nullptr); } size_t srcPitch, dstPitch; @@ -579,17 +584,17 @@ void D3D12GSRender::copy_render_target_to_dma_location() { 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)) + vm::base(address_color[0]), + vm::base(address_color[1]), + vm::base(address_color[2]), + vm::base(address_color[3]), }; for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) { - if (!context_dma_color[i]) + if (!address_color[i]) continue; - copy_readback_buffer_to_dest(dest_buffer[i], readback_buffers[i].Get(), srcPitch, dstPitch, clip_h); + copy_readback_buffer_to_dest(dest_buffer[i], m_readback_resources, color_buffer_offset_in_heap[i], srcPitch, dstPitch, clip_h); } } } @@ -597,7 +602,7 @@ void D3D12GSRender::copy_render_target_to_dma_location() void D3D12GSRender::copy_render_targets_to_memory(void *buffer, u8 rtt) { - ComPtr readback_buffer = create_readback_buffer_and_download(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, m_rtts.bound_render_targets[rtt], m_surface.color_format); + size_t heap_offset = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, m_rtts.bound_render_targets[rtt], m_surface.color_format); ThrowIfFailed(get_current_resource_storage().command_list->Close()); m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf()); @@ -620,7 +625,7 @@ void D3D12GSRender::copy_render_targets_to_memory(void *buffer, u8 rtt) dstPitch = clip_w * 8; break; } - copy_readback_buffer_to_dest(buffer, readback_buffer.Get(), srcPitch, dstPitch, clip_h); + copy_readback_buffer_to_dest(buffer, m_readback_resources, heap_offset, srcPitch, dstPitch, clip_h); } void D3D12GSRender::copy_depth_buffer_to_memory(void *buffer) @@ -630,24 +635,13 @@ void D3D12GSRender::copy_depth_buffer_to_memory(void *buffer) size_t row_pitch = align(clip_w * 4, 256); - ComPtr readback_buffer; size_t buffer_size = row_pitch * clip_h; assert(m_readback_resources.can_alloc(buffer_size)); - size_t heapOffset = m_readback_resources.alloc(buffer_size); - ThrowIfFailed( - m_device->CreatePlacedResource( - m_readback_resources.m_heap, - heapOffset, - &CD3DX12_RESOURCE_DESC::Buffer(buffer_size), - D3D12_RESOURCE_STATE_COPY_DEST, - nullptr, - IID_PPV_ARGS(readback_buffer.GetAddressOf()) - ) - ); + size_t heap_offset = m_readback_resources.alloc(buffer_size); get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE)); - get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(readback_buffer.Get(), { 0,{ DXGI_FORMAT_R32_TYPELESS, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0, + get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.m_heap, { heap_offset,{ DXGI_FORMAT_R32_TYPELESS, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0, &CD3DX12_TEXTURE_COPY_LOCATION(m_rtts.bound_depth_stencil, 0), nullptr); get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE)); @@ -658,8 +652,9 @@ void D3D12GSRender::copy_depth_buffer_to_memory(void *buffer) wait_for_command_queue(m_device.Get(), m_command_queue.Get()); m_readback_resources.m_get_pos = m_readback_resources.get_current_put_pos_minus_one(); - void *mapped_buffer; - ThrowIfFailed(readback_buffer->Map(0, nullptr, &mapped_buffer)); + void *temp_buffer; + ThrowIfFailed(m_readback_resources.m_heap->Map(0, nullptr, &temp_buffer)); + void *mapped_buffer = (char*)temp_buffer + heap_offset; for (unsigned row = 0; row < clip_h; row++) { u32 *casted_dest = (u32*)((char*)buffer + row * clip_w * 4); @@ -667,7 +662,7 @@ void D3D12GSRender::copy_depth_buffer_to_memory(void *buffer) for (unsigned col = 0; col < row_pitch / 4; col++) *casted_dest++ = *casted_src++; } - readback_buffer->Unmap(0, nullptr); + m_readback_resources.m_heap->Unmap(0, nullptr); } @@ -678,24 +673,13 @@ void D3D12GSRender::copy_stencil_buffer_to_memory(void *buffer) size_t row_pitch = align(clip_w * 4, 256); - ComPtr readback_buffer; size_t buffer_size = row_pitch * clip_h; assert(m_readback_resources.can_alloc(buffer_size)); - size_t heapOffset = m_readback_resources.alloc(buffer_size); - ThrowIfFailed( - m_device->CreatePlacedResource( - m_readback_resources.m_heap, - heapOffset, - &CD3DX12_RESOURCE_DESC::Buffer(buffer_size), - D3D12_RESOURCE_STATE_COPY_DEST, - nullptr, - IID_PPV_ARGS(readback_buffer.GetAddressOf()) - ) - ); + size_t heap_offset = m_readback_resources.alloc(buffer_size); get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE)); - get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(readback_buffer.Get(), { 0,{ DXGI_FORMAT_R8_TYPELESS, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0, + get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.m_heap, { heap_offset, { DXGI_FORMAT_R8_TYPELESS, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0, &CD3DX12_TEXTURE_COPY_LOCATION(m_rtts.bound_depth_stencil, 1), nullptr); get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE)); @@ -706,8 +690,9 @@ void D3D12GSRender::copy_stencil_buffer_to_memory(void *buffer) wait_for_command_queue(m_device.Get(), m_command_queue.Get()); m_readback_resources.m_get_pos = m_readback_resources.get_current_put_pos_minus_one(); - void *mapped_buffer; - ThrowIfFailed(readback_buffer->Map(0, nullptr, &mapped_buffer)); + void *temp_buffer; + ThrowIfFailed(m_readback_resources.m_heap->Map(0, nullptr, &temp_buffer)); + void *mapped_buffer = (char*)temp_buffer + heap_offset; for (unsigned row = 0; row < clip_h; row++) { char *casted_dest = (char*)buffer + row * clip_w; @@ -715,7 +700,7 @@ void D3D12GSRender::copy_stencil_buffer_to_memory(void *buffer) for (unsigned col = 0; col < row_pitch; col++) *casted_dest++ = *casted_src++; } - readback_buffer->Unmap(0, nullptr); + m_readback_resources.m_heap->Unmap(0, nullptr); } #endif diff --git a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h index 80eb3d1b0e..1b0fd69747 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h @@ -21,7 +21,7 @@ struct render_targets * returns the corresponding render target resource. */ ID3D12Resource *bind_address_as_render_targets(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, u32 address, - size_t width, size_t height, u8 surfaceColorFormat, const std::array &clearColor); + size_t width, size_t height, u8 surfaceColorFormat, const std::array &clearColor, ComPtr &dirtyDS); 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);