diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 39279357a..737fa8cbc 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -794,7 +794,10 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type, return true; } -bool D3D12CommandProcessor::IssueCopy() { return true; } +bool D3D12CommandProcessor::IssueCopy() { + BeginFrame(); + return render_target_cache_->Resolve(shared_memory_.get()); +} bool D3D12CommandProcessor::BeginFrame() { if (current_queue_frame_ != UINT32_MAX) { diff --git a/src/xenia/gpu/d3d12/render_target_cache.cc b/src/xenia/gpu/d3d12/render_target_cache.cc index d718838b4..424067b67 100644 --- a/src/xenia/gpu/d3d12/render_target_cache.cc +++ b/src/xenia/gpu/d3d12/render_target_cache.cc @@ -34,29 +34,24 @@ namespace d3d12 { #include "xenia/gpu/d3d12/shaders/bin/edram_store_depth_float_cs.h" #include "xenia/gpu/d3d12/shaders/bin/edram_store_depth_unorm_cs.h" -const RenderTargetCache::EDRAMLoadStorePipelineInfo - RenderTargetCache::edram_load_store_pipeline_info_[size_t( - RenderTargetCache::EDRAMLoadStorePipelineIndex::kCount)] = { +const RenderTargetCache::EDRAMLoadStoreModeInfo + RenderTargetCache::edram_load_store_mode_info_[size_t( + RenderTargetCache::EDRAMLoadStoreMode::kCount)] = { {edram_load_color_32bpp_cs, sizeof(edram_load_color_32bpp_cs), - L"EDRAM Load 32bpp Color"}, - {edram_store_color_32bpp_cs, sizeof(edram_store_color_32bpp_cs), - L"EDRAM Store 32bpp Color"}, + L"EDRAM Load 32bpp Color", edram_store_color_32bpp_cs, + sizeof(edram_store_color_32bpp_cs), L"EDRAM Store 32bpp Color"}, {edram_load_color_64bpp_cs, sizeof(edram_load_color_64bpp_cs), - L"EDRAM Load 64bpp Color"}, - {edram_store_color_64bpp_cs, sizeof(edram_store_color_64bpp_cs), - L"EDRAM Store 64bpp Color"}, + L"EDRAM Load 64bpp Color", edram_store_color_64bpp_cs, + sizeof(edram_store_color_64bpp_cs), L"EDRAM Store 64bpp Color"}, {edram_load_color_7e3_cs, sizeof(edram_load_color_7e3_cs), - L"EDRAM Load 7e3 Color"}, - {edram_store_color_7e3_cs, sizeof(edram_store_color_7e3_cs), - L"EDRAM Store 7e3 Color"}, + L"EDRAM Load 7e3 Color", edram_store_color_7e3_cs, + sizeof(edram_store_color_7e3_cs), L"EDRAM Store 7e3 Color"}, {edram_load_depth_unorm_cs, sizeof(edram_load_depth_unorm_cs), - L"EDRAM Load UNorm Depth"}, - {edram_store_depth_unorm_cs, sizeof(edram_store_depth_unorm_cs), - L"EDRAM Store UNorm Depth"}, + L"EDRAM Load UNorm Depth", edram_store_depth_unorm_cs, + sizeof(edram_store_depth_unorm_cs), L"EDRAM Store UNorm Depth"}, {edram_load_depth_float_cs, sizeof(edram_load_depth_float_cs), - L"EDRAM Load Float Depth"}, - {edram_store_depth_float_cs, sizeof(edram_store_depth_float_cs), - L"EDRAM Store Float Depth"}, + L"EDRAM Load Float Depth", edram_store_depth_float_cs, + sizeof(edram_store_depth_float_cs), L"EDRAM Store Float Depth"}, }; RenderTargetCache::RenderTargetCache(D3D12CommandProcessor* command_processor, @@ -163,18 +158,28 @@ bool RenderTargetCache::Initialize() { pipeline_desc.CachedPSO.pCachedBlob = nullptr; pipeline_desc.CachedPSO.CachedBlobSizeInBytes = 0; pipeline_desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - for (uint32_t i = 0; i < uint32_t(EDRAMLoadStorePipelineIndex::kCount); ++i) { - const EDRAMLoadStorePipelineInfo& pipeline_info = - edram_load_store_pipeline_info_[i]; - pipeline_desc.CS.pShaderBytecode = pipeline_info.shader; - pipeline_desc.CS.BytecodeLength = pipeline_info.shader_size; + for (uint32_t i = 0; i < uint32_t(EDRAMLoadStoreMode::kCount); ++i) { + // Load. + const EDRAMLoadStoreModeInfo& mode_info = edram_load_store_mode_info_[i]; + pipeline_desc.CS.pShaderBytecode = mode_info.load_shader; + pipeline_desc.CS.BytecodeLength = mode_info.load_shader_size; if (FAILED(device->CreateComputePipelineState( - &pipeline_desc, IID_PPV_ARGS(&edram_load_store_pipelines_[i])))) { - XELOGE("Failed to create EDRAM load/store pipeline for mode %u", i); + &pipeline_desc, IID_PPV_ARGS(&edram_load_pipelines_[i])))) { + XELOGE("Failed to create EDRAM load pipeline for mode %u", i); Shutdown(); return false; } - edram_load_store_pipelines_[i]->SetName(pipeline_info.name); + edram_load_pipelines_[i]->SetName(mode_info.load_pipeline_name); + // Store. + pipeline_desc.CS.pShaderBytecode = mode_info.store_shader; + pipeline_desc.CS.BytecodeLength = mode_info.store_shader_size; + if (FAILED(device->CreateComputePipelineState( + &pipeline_desc, IID_PPV_ARGS(&edram_store_pipelines_[i])))) { + XELOGE("Failed to create EDRAM store pipeline for mode %u", i); + Shutdown(); + return false; + } + edram_store_pipelines_[i]->SetName(mode_info.store_pipeline_name); } return true; @@ -183,6 +188,16 @@ bool RenderTargetCache::Initialize() { void RenderTargetCache::Shutdown() { ClearCache(); + for (uint32_t i = 0; i < uint32_t(EDRAMLoadStoreMode::kCount); ++i) { + if (edram_load_pipelines_[i] != nullptr) { + edram_load_pipelines_[i]->Release(); + edram_load_pipelines_[i] = nullptr; + } + if (edram_store_pipelines_[i] != nullptr) { + edram_store_pipelines_[i]->Release(); + edram_store_pipelines_[i] = nullptr; + } + } if (edram_load_store_root_signature_ != nullptr) { edram_load_store_root_signature_->Release(); edram_load_store_root_signature_ = nullptr; @@ -713,6 +728,22 @@ bool RenderTargetCache::UpdateRenderTargets() { return true; } +bool RenderTargetCache::Resolve(SharedMemory* shared_memory) { + bool copied = ResolveCopy(shared_memory); + // TODO(Triang3l): Clear. + return copied; +} + +bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory) { + auto command_list = command_processor_->GetCurrentCommandList(); + if (command_list == nullptr) { + return false; + } + auto& regs = *register_file_; + + return true; +} + void RenderTargetCache::EndFrame() { StoreRenderTargetsToEDRAM(); ClearBindings(); @@ -918,6 +949,23 @@ RenderTargetCache::RenderTarget* RenderTargetCache::FindOrCreateRenderTarget( return render_target; } +RenderTargetCache::EDRAMLoadStoreMode RenderTargetCache::GetLoadStoreMode( + bool is_depth, uint32_t format) { + if (is_depth) { + return DepthRenderTargetFormat(format) == DepthRenderTargetFormat::kD24FS8 + ? EDRAMLoadStoreMode::kDepthFloat + : EDRAMLoadStoreMode::kDepthUnorm; + } + ColorRenderTargetFormat color_format = ColorRenderTargetFormat(format); + if (color_format == ColorRenderTargetFormat::k_2_10_10_10_FLOAT || + color_format == + ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16) { + return EDRAMLoadStoreMode::kColor7e3; + } + return IsColorFormat64bpp(color_format) ? EDRAMLoadStoreMode::kColor64bpp + : EDRAMLoadStoreMode::kColor32bpp; +} + void RenderTargetCache::StoreRenderTargetsToEDRAM() { auto command_list = command_processor_->GetCurrentCommandList(); if (command_list == nullptr) { @@ -1042,42 +1090,9 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() { for (uint32_t i = 0; i < store_binding_count; ++i) { const RenderTargetBinding& binding = current_bindings_[store_bindings[i]]; const RenderTarget* render_target = binding.render_target; - EDRAMLoadStorePipelineIndex pipeline_index; bool is_64bpp = false; - if (render_target->key.is_depth) { - if (DepthRenderTargetFormat(render_target->key.format) == - DepthRenderTargetFormat::kD24FS8) { - pipeline_index = EDRAMLoadStorePipelineIndex::kDepthFloatStore; - } else { - pipeline_index = EDRAMLoadStorePipelineIndex::kDepthUnormStore; - } - } else { - switch (ColorRenderTargetFormat(render_target->key.format)) { - case ColorRenderTargetFormat::k_8_8_8_8: - case ColorRenderTargetFormat::k_8_8_8_8_GAMMA: - case ColorRenderTargetFormat::k_2_10_10_10: - case ColorRenderTargetFormat::k_16_16: - case ColorRenderTargetFormat::k_16_16_FLOAT: - case ColorRenderTargetFormat::k_2_10_10_10_AS_16_16_16_16: - case ColorRenderTargetFormat::k_32_FLOAT: - pipeline_index = EDRAMLoadStorePipelineIndex::kColor32bppStore; - break; - case ColorRenderTargetFormat::k_16_16_16_16: - case ColorRenderTargetFormat::k_16_16_16_16_FLOAT: - case ColorRenderTargetFormat::k_32_32_FLOAT: - pipeline_index = EDRAMLoadStorePipelineIndex::kColor64bppStore; - is_64bpp = true; - break; - case ColorRenderTargetFormat::k_2_10_10_10_FLOAT: - case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: - pipeline_index = EDRAMLoadStorePipelineIndex::kColor7e3Store; - break; - default: - assert_unhandled_case(render_target->key.format); - continue; - } - } + // Copy from the render target planes and set up the layout. D3D12_TEXTURE_COPY_LOCATION location_source, location_dest; location_source.pResource = render_target->resource; location_source.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; @@ -1090,7 +1105,12 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() { nullptr); EDRAMLoadStoreRootConstants root_constants; root_constants.base_tiles = binding.edram_base; - root_constants.pitch_tiles = surface_pitch_tiles * (is_64bpp ? 2 : 1); + root_constants.pitch_tiles = surface_pitch_tiles; + if (!render_target->key.is_depth && + IsColorFormat64bpp( + ColorRenderTargetFormat(render_target->key.format))) { + root_constants.pitch_tiles *= 2; + } root_constants.rt_color_depth_pitch = location_dest.PlacedFootprint.Footprint.RowPitch; if (render_target->key.is_depth) { @@ -1119,8 +1139,9 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() { // Store the data. command_list->SetComputeRoot32BitConstants( 0, sizeof(root_constants) / sizeof(uint32_t), &root_constants, 0); - command_processor_->SetPipeline( - edram_load_store_pipelines_[size_t(pipeline_index)]); + EDRAMLoadStoreMode mode = GetLoadStoreMode(render_target->key.is_depth, + render_target->key.format); + command_processor_->SetPipeline(edram_store_pipelines_[size_t(mode)]); command_list->Dispatch(root_constants.pitch_tiles, binding.edram_dirty_rows, 1); @@ -1251,49 +1272,17 @@ void RenderTargetCache::LoadRenderTargetsFromEDRAM( // Something is wrong with the resolve. return; } - const RenderTarget* render_target = render_targets[i]; - EDRAMLoadStorePipelineIndex pipeline_index; - bool is_64bpp = false; - if (render_target->key.is_depth) { - if (DepthRenderTargetFormat(render_target->key.format) == - DepthRenderTargetFormat::kD24FS8) { - pipeline_index = EDRAMLoadStorePipelineIndex::kDepthFloatLoad; - } else { - pipeline_index = EDRAMLoadStorePipelineIndex::kDepthUnormLoad; - } - } else { - switch (ColorRenderTargetFormat(render_target->key.format)) { - case ColorRenderTargetFormat::k_8_8_8_8: - case ColorRenderTargetFormat::k_8_8_8_8_GAMMA: - case ColorRenderTargetFormat::k_2_10_10_10: - case ColorRenderTargetFormat::k_16_16: - case ColorRenderTargetFormat::k_16_16_FLOAT: - case ColorRenderTargetFormat::k_2_10_10_10_AS_16_16_16_16: - case ColorRenderTargetFormat::k_32_FLOAT: - pipeline_index = EDRAMLoadStorePipelineIndex::kColor32bppLoad; - break; - case ColorRenderTargetFormat::k_16_16_16_16: - case ColorRenderTargetFormat::k_16_16_16_16_FLOAT: - case ColorRenderTargetFormat::k_32_32_FLOAT: - pipeline_index = EDRAMLoadStorePipelineIndex::kColor64bppLoad; - is_64bpp = true; - break; - case ColorRenderTargetFormat::k_2_10_10_10_FLOAT: - case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: - pipeline_index = EDRAMLoadStorePipelineIndex::kColor7e3Load; - break; - default: - assert_unhandled_case(render_target->key.format); - continue; - } - } // Set up the layout. EDRAMLoadStoreRootConstants root_constants; root_constants.base_tiles = edram_bases[i]; - root_constants.pitch_tiles = - render_target->key.width_ss_div_80 * (is_64bpp ? 2 : 1); + root_constants.pitch_tiles = render_target->key.width_ss_div_80; + if (!render_target->key.is_depth && + IsColorFormat64bpp( + ColorRenderTargetFormat(render_target->key.format))) { + root_constants.pitch_tiles *= 2; + } root_constants.rt_color_depth_pitch = render_target->footprints[0].Footprint.RowPitch; if (render_target->key.is_depth) { @@ -1328,8 +1317,9 @@ void RenderTargetCache::LoadRenderTargetsFromEDRAM( // Load the data. command_list->SetComputeRoot32BitConstants( 0, sizeof(root_constants) / sizeof(uint32_t), &root_constants, 0); - command_processor_->SetPipeline( - edram_load_store_pipelines_[size_t(pipeline_index)]); + EDRAMLoadStoreMode mode = GetLoadStoreMode(render_target->key.is_depth, + render_target->key.format); + command_processor_->SetPipeline(edram_load_pipelines_[size_t(mode)]); command_list->Dispatch(root_constants.pitch_tiles, edram_rows, 1); // Commit the UAV write and transition the copy buffer to copy source. @@ -1346,7 +1336,7 @@ void RenderTargetCache::LoadRenderTargetsFromEDRAM( copy_buffer_state = D3D12_RESOURCE_STATE_COPY_SOURCE; command_list->ResourceBarrier(2, barriers); - // Copy to the render targets. + // Copy to the render target planes. D3D12_TEXTURE_COPY_LOCATION location_source, location_dest; location_source.pResource = copy_buffer; location_source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; diff --git a/src/xenia/gpu/d3d12/render_target_cache.h b/src/xenia/gpu/d3d12/render_target_cache.h index 4dc756f50..5e829a9e5 100644 --- a/src/xenia/gpu/d3d12/render_target_cache.h +++ b/src/xenia/gpu/d3d12/render_target_cache.h @@ -215,6 +215,10 @@ class RenderTargetCache { const PipelineRenderTarget* GetCurrentPipelineRenderTargets() const { return current_pipeline_render_targets_; } + // Performs the resolve to a shared memory area according to the current + // register values, and also clears the EDRAM buffer if needed. Must be in a + // frame for calling. + bool Resolve(SharedMemory* shared_memory); void EndFrame(); static inline bool IsColorFormat64bpp(ColorRenderTargetFormat format) { @@ -234,25 +238,24 @@ class RenderTargetCache { } private: - enum class EDRAMLoadStorePipelineIndex { - kColor32bppLoad, - kColor32bppStore, - kColor64bppLoad, - kColor64bppStore, - kColor7e3Load, - kColor7e3Store, - kDepthUnormLoad, - kDepthUnormStore, - kDepthFloatLoad, - kDepthFloatStore, + enum class EDRAMLoadStoreMode { + kColor32bpp, + kColor64bpp, + kColor7e3, + kDepthUnorm, + kDepthFloat, kCount }; - struct EDRAMLoadStorePipelineInfo { - const void* shader; - size_t shader_size; - const WCHAR* name; + struct EDRAMLoadStoreModeInfo { + const void* load_shader; + size_t load_shader_size; + const WCHAR* load_pipeline_name; + + const void* store_shader; + size_t store_shader_size; + const WCHAR* store_pipeline_name; }; union RenderTargetKey { @@ -320,6 +323,7 @@ class RenderTargetCache { RenderTarget* FindOrCreateRenderTarget(RenderTargetKey key, uint32_t heap_page_first); + static EDRAMLoadStoreMode GetLoadStoreMode(bool is_depth, uint32_t format); // Must be in a frame to call. Stores the dirty areas of the currently bound // render targets and marks them as clean. void StoreRenderTargetsToEDRAM(); @@ -330,6 +334,9 @@ class RenderTargetCache { RenderTarget* const* render_targets, const uint32_t* edram_bases); + // Performs the copy part of resolving. + bool ResolveCopy(SharedMemory* shared_memory); + D3D12CommandProcessor* command_processor_; RegisterFile* register_file_; @@ -348,11 +355,12 @@ class RenderTargetCache { uint32_t rt_stencil_pitch; }; // EDRAM buffer load/store pipelines. - static const EDRAMLoadStorePipelineInfo - edram_load_store_pipeline_info_[size_t( - EDRAMLoadStorePipelineIndex::kCount)]; - ID3D12PipelineState* edram_load_store_pipelines_[size_t( - EDRAMLoadStorePipelineIndex::kCount)] = {}; + static const EDRAMLoadStoreModeInfo + edram_load_store_mode_info_[size_t(EDRAMLoadStoreMode::kCount)]; + ID3D12PipelineState* + edram_load_pipelines_[size_t(EDRAMLoadStoreMode::kCount)] = {}; + ID3D12PipelineState* + edram_store_pipelines_[size_t(EDRAMLoadStoreMode::kCount)] = {}; // 32 MB heaps backing used render targets resources, created when needed. // 24 MB proved to be not enough to store a single render target occupying the