diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp index ea8c999f62..668c26bedb 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp @@ -1,4 +1,4 @@ -#ifdef _MSC_VER +#ifdef _MSC_VER #include "stdafx.h" #include "stdafx_d3d12.h" #include "D3D12PipelineState.h" @@ -321,7 +321,5 @@ std::pair D3D12GSRender::get_programs() const void D3D12GSRender::notify_tile_unbound(u32 tile) { - u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location); - m_rtts.invalidate_surface_address(addr, false); } #endif diff --git a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h index e54558d870..636b8df0ea 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h @@ -8,10 +8,226 @@ #include "D3D12Formats.h" #include "D3D12MemoryHelpers.h" -#include "../Common/surface_store.h" namespace rsx { +namespace utility +{ + std::vector get_rtt_indexes(surface_target color_target); + size_t get_aligned_pitch(surface_color_format format, u32 width); + size_t get_packed_pitch(surface_color_format format, u32 width); +} + +template +struct surface_store_deprecated +{ + template + void copy_pitched_src_to_dst(gsl::span dest, gsl::span src, size_t src_pitch_in_bytes, size_t width, size_t height) + { + for (unsigned row = 0; row < height; row++) + { + for (unsigned col = 0; col < width; col++) + dest[col] = src[col]; + src = src.subspan(src_pitch_in_bytes / sizeof(U)); + dest = dest.subspan(width); + } + } + +public: + using surface_storage_type = typename Traits::surface_storage_type; + using surface_type = typename Traits::surface_type; + using command_list_type = typename Traits::command_list_type; + using download_buffer_object = typename Traits::download_buffer_object; + +protected: + std::unordered_map m_render_targets_storage = {}; + std::unordered_map m_depth_stencil_storage = {}; + +public: + std::pair m_bound_render_targets_config = {}; + std::array, 4> m_bound_render_targets = {}; + std::pair m_bound_depth_stencil = {}; + + std::list invalidated_resources; + + surface_store_deprecated() = default; + ~surface_store_deprecated() = default; + surface_store_deprecated(const surface_store_deprecated&) = delete; + +protected: + /** + * 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. + */ + template + surface_type bind_address_as_render_targets( + command_list_type command_list, + u32 address, + surface_color_format color_format, + surface_antialiasing antialias, + size_t width, size_t height, size_t pitch, + Args&&... extra_params) + { + // Check if render target already exists + auto It = m_render_targets_storage.find(address); + if (It != m_render_targets_storage.end()) + { + surface_storage_type &rtt = It->second; + if (Traits::rtt_has_format_width_height(rtt, color_format, width, height)) + { + Traits::prepare_rtt_for_drawing(command_list, Traits::get(rtt)); + return Traits::get(rtt); + } + + invalidated_resources.push_back(std::move(rtt)); + m_render_targets_storage.erase(It); + } + + m_render_targets_storage[address] = Traits::create_new_surface(address, color_format, width, height, pitch, std::forward(extra_params)...); + return Traits::get(m_render_targets_storage[address]); + } + + template + surface_type bind_address_as_depth_stencil( + command_list_type command_list, + u32 address, + surface_depth_format depth_format, + surface_antialiasing antialias, + size_t width, size_t height, size_t pitch, + Args&&... extra_params) + { + auto It = m_depth_stencil_storage.find(address); + if (It != m_depth_stencil_storage.end()) + { + surface_storage_type &ds = It->second; + if (Traits::ds_has_format_width_height(ds, depth_format, width, height)) + { + Traits::prepare_ds_for_drawing(command_list, Traits::get(ds)); + return Traits::get(ds); + } + + invalidated_resources.push_back(std::move(ds)); + m_depth_stencil_storage.erase(It); + } + + m_depth_stencil_storage[address] = Traits::create_new_surface(address, depth_format, width, height, pitch, std::forward(extra_params)...); + return Traits::get(m_depth_stencil_storage[address]); + } +public: + /** + * Update bound color and depth surface. + * Must be called everytime surface format, clip, or addresses changes. + */ + template + void prepare_render_target( + command_list_type command_list, + surface_color_format color_format, surface_depth_format depth_format, + u32 clip_horizontal_reg, u32 clip_vertical_reg, + surface_target set_surface_target, + surface_antialiasing antialias, + const std::array &surface_addresses, u32 address_z, + const std::array &surface_pitch, u32 zeta_pitch, + Args&&... extra_params) + { + u32 clip_width = clip_horizontal_reg; + u32 clip_height = clip_vertical_reg; + + // Make previous RTTs sampleable + for (int i = m_bound_render_targets_config.first, count = 0; + count < m_bound_render_targets_config.second; + ++i, ++count) + { + auto &rtt = m_bound_render_targets[i]; + Traits::prepare_rtt_for_sampling(command_list, std::get<1>(rtt)); + rtt = std::make_pair(0, nullptr); + } + + const auto rtt_indices = utility::get_rtt_indexes(set_surface_target); + if (LIKELY(!rtt_indices.empty())) + { + m_bound_render_targets_config = { rtt_indices.front(), 0 }; + + // Create/Reuse requested rtts + for (u8 surface_index : rtt_indices) + { + if (surface_addresses[surface_index] == 0) + continue; + + m_bound_render_targets[surface_index] = std::make_pair(surface_addresses[surface_index], + bind_address_as_render_targets(command_list, surface_addresses[surface_index], color_format, antialias, + clip_width, clip_height, surface_pitch[surface_index], std::forward(extra_params)...)); + + m_bound_render_targets_config.second++; + } + } + else + { + m_bound_render_targets_config = { 0, 0 }; + } + + // Same for depth buffer + if (std::get<1>(m_bound_depth_stencil) != nullptr) + Traits::prepare_ds_for_sampling(command_list, std::get<1>(m_bound_depth_stencil)); + + m_bound_depth_stencil = std::make_pair(0, nullptr); + + if (!address_z) + return; + + m_bound_depth_stencil = std::make_pair(address_z, + bind_address_as_depth_stencil(command_list, address_z, depth_format, antialias, + clip_width, clip_height, zeta_pitch, std::forward(extra_params)...)); + } + + /** + * Search for given address in stored color surface + * Return an empty surface_type otherwise. + */ + surface_type get_texture_from_render_target_if_applicable(u32 address) + { + auto It = m_render_targets_storage.find(address); + if (It != m_render_targets_storage.end()) + return Traits::get(It->second); + return surface_type(); + } + + /** + * Search for given address in stored depth stencil surface + * Return an empty surface_type otherwise. + */ + surface_type get_texture_from_depth_stencil_if_applicable(u32 address) + { + auto It = m_depth_stencil_storage.find(address); + if (It != m_depth_stencil_storage.end()) + return Traits::get(It->second); + return surface_type(); + } + + /** + * Get bound color surface raw data. + */ + template + std::array, 4> get_render_targets_data( + surface_color_format color_format, size_t width, size_t height, + Args&& ...args + ) + { + return {}; + } + + /** + * Get bound color surface raw data. + */ + template + std::array, 2> get_depth_stencil_data( + surface_depth_format depth_format, size_t width, size_t height, + Args&& ...args + ) + { + return {}; + } +}; struct render_target_traits { @@ -55,18 +271,6 @@ struct render_target_traits return rtt; } - static - void get_surface_info(ID3D12Resource *surface, rsx::surface_format_info *info) - { - //TODO - auto desc = surface->GetDesc(); - info->rsx_pitch = static_cast(desc.Width); - info->native_pitch = static_cast(desc.Width); - info->surface_width = static_cast(desc.Width); - info->surface_height = static_cast(desc.Height); - info->bpp = 1; - } - static void prepare_rtt_for_drawing( ID3D12GraphicsCommandList* command_list, @@ -128,27 +332,6 @@ struct render_target_traits command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ)); } - static - void invalidate_surface_contents( - ID3D12GraphicsCommandList*, - ID3D12Resource*, - u32, size_t) - {} - - static - void notify_surface_invalidated(const ComPtr&) - {} - - static - void notify_surface_persist(const ComPtr&) - {} - - static - bool surface_is_pitch_compatible(const ComPtr&, size_t) - { - return true; - } - static bool rtt_has_format_width_height(const ComPtr &rtt, surface_color_format surface_color_format, size_t width, size_t height, bool=false) { @@ -170,30 +353,7 @@ struct render_target_traits ID3D12Device* device, ID3D12CommandQueue* command_queue, d3d12_data_heap &readback_heap, resource_storage &res_store ) { - ID3D12GraphicsCommandList* command_list = res_store.command_list.Get(); - DXGI_FORMAT dxgi_format = get_color_surface_format(color_format); - size_t row_pitch = rsx::utility::get_aligned_pitch(color_format, ::narrow(width)); - - size_t buffer_size = row_pitch * height; - size_t heap_offset = readback_heap.alloc(buffer_size); - - command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(rtt, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE)); - - command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(readback_heap.get_heap(), { heap_offset,{ dxgi_format, (UINT)width, (UINT)height, 1, (UINT)row_pitch } }), 0, 0, 0, - &CD3DX12_TEXTURE_COPY_LOCATION(rtt, 0), nullptr); - command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(rtt, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET)); - - CHECK_HRESULT(command_list->Close()); - command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)res_store.command_list.GetAddressOf()); - res_store.set_new_command_list(); - - ComPtr fence; - CHECK_HRESULT(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); - - return std::make_tuple(heap_offset, buffer_size, readback_heap.get_current_put_pos_minus_one(), fence, handle); + return {}; } static @@ -203,30 +363,7 @@ struct render_target_traits ID3D12Device* device, ID3D12CommandQueue* command_queue, d3d12_data_heap &readback_heap, resource_storage &res_store ) { - ID3D12GraphicsCommandList* command_list = res_store.command_list.Get(); - DXGI_FORMAT dxgi_format = (depth_format == surface_depth_format::z24s8) ? DXGI_FORMAT_R32_TYPELESS : DXGI_FORMAT_R16_TYPELESS; - - size_t row_pitch = align(width * 4, 256); - size_t buffer_size = row_pitch * height; - size_t heap_offset = readback_heap.alloc(buffer_size); - - command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE)); - - command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(readback_heap.get_heap(), { heap_offset,{ dxgi_format, (UINT)width, (UINT)height, 1, (UINT)row_pitch } }), 0, 0, 0, - &CD3DX12_TEXTURE_COPY_LOCATION(ds, 0), nullptr); - command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE)); - - CHECK_HRESULT(command_list->Close()); - command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)res_store.command_list.GetAddressOf()); - res_store.set_new_command_list(); - - ComPtr fence; - CHECK_HRESULT(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); - - return std::make_tuple(heap_offset, buffer_size, readback_heap.get_current_put_pos_minus_one(), fence, handle); + return {}; } static @@ -236,29 +373,7 @@ struct render_target_traits ID3D12Device* device, ID3D12CommandQueue* command_queue, d3d12_data_heap &readback_heap, resource_storage &res_store ) { - ID3D12GraphicsCommandList* command_list = res_store.command_list.Get(); - - size_t row_pitch = align(width, 256); - size_t buffer_size = row_pitch * height; - size_t heap_offset = readback_heap.alloc(buffer_size); - - command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE)); - - command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(readback_heap.get_heap(), { heap_offset,{ DXGI_FORMAT_R8_TYPELESS, (UINT)width, (UINT)height, 1, (UINT)row_pitch } }), 0, 0, 0, - &CD3DX12_TEXTURE_COPY_LOCATION(stencil, 1), nullptr); - command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(stencil, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE)); - - CHECK_HRESULT(command_list->Close()); - command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)res_store.command_list.GetAddressOf()); - res_store.set_new_command_list(); - - ComPtr fence; - CHECK_HRESULT(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); - - return std::make_tuple(heap_offset, buffer_size, readback_heap.get_current_put_pos_minus_one(), fence, handle); + return {}; } static @@ -291,7 +406,7 @@ struct render_target_traits } }; -struct render_targets : public rsx::surface_store +struct render_targets : public rsx::surface_store_deprecated { INT g_descriptor_stride_rtv;