diff --git a/src/xenia/gpu/d3d12/render_target_cache.cc b/src/xenia/gpu/d3d12/render_target_cache.cc index b6bd66e86..aa657ec9d 100644 --- a/src/xenia/gpu/d3d12/render_target_cache.cc +++ b/src/xenia/gpu/d3d12/render_target_cache.cc @@ -78,9 +78,7 @@ bool RenderTargetCache::Initialize() { D3D12_RESOURCE_DESC edram_buffer_desc; edram_buffer_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; edram_buffer_desc.Alignment = 0; - // First 10 MB is guest pixel data, second 10 MB is 32-bit depth when using - // D24FS8 so loads/stores don't corrupt multipass rendering. - edram_buffer_desc.Width = 2 * 2048 * 5120; + edram_buffer_desc.Width = kEDRAMBufferSize; edram_buffer_desc.Height = 1; edram_buffer_desc.DepthOrArraySize = 1; edram_buffer_desc.MipLevels = 1; @@ -1038,16 +1036,8 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory, 0, 2, 2, descriptor_cpu_start, descriptor_gpu_start) == 0) { return false; } - D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc; - srv_desc.Format = DXGI_FORMAT_R32_TYPELESS; - srv_desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - srv_desc.Buffer.FirstElement = 0; - srv_desc.Buffer.NumElements = 2 * 2048 * 1280; - srv_desc.Buffer.StructureByteStride = 0; - srv_desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; - device->CreateShaderResourceView(edram_buffer_, &srv_desc, - descriptor_cpu_start); + ui::d3d12::util::CreateRawBufferSRV(device, descriptor_cpu_start, + edram_buffer_, kEDRAMBufferSize); shared_memory->CreateRawUAV( provider->OffsetViewDescriptor(descriptor_cpu_start, 1)); @@ -1202,27 +1192,11 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory, 0, sizeof(load_root_constants) / sizeof(uint32_t), &load_root_constants, 0); - D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc; - srv_desc.Format = DXGI_FORMAT_R32_TYPELESS; - srv_desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - srv_desc.Buffer.FirstElement = 0; - srv_desc.Buffer.NumElements = 2048 * 1280; - srv_desc.Buffer.StructureByteStride = 0; - srv_desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; - device->CreateShaderResourceView(edram_buffer_, &srv_desc, - descriptor_cpu_start); - D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc; - uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; - uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - uav_desc.Buffer.FirstElement = 0; - uav_desc.Buffer.NumElements = render_target->copy_buffer_size >> 2; - uav_desc.Buffer.StructureByteStride = 0; - uav_desc.Buffer.CounterOffsetInBytes = 0; - uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; - device->CreateUnorderedAccessView( - copy_buffer, nullptr, &uav_desc, - provider->OffsetViewDescriptor(descriptor_cpu_start, 1)); + ui::d3d12::util::CreateRawBufferSRV(device, descriptor_cpu_start, + edram_buffer_, kEDRAMBufferSize); + ui::d3d12::util::CreateRawBufferUAV( + device, provider->OffsetViewDescriptor(descriptor_cpu_start, 1), + copy_buffer, render_target->copy_buffer_size); command_list->SetComputeRootDescriptorTable(1, descriptor_gpu_start); command_processor_->SetComputePipeline( @@ -1330,8 +1304,10 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory, 0, sizeof(resolve_root_constants) / sizeof(uint32_t), &resolve_root_constants, 0); - srv_desc.Format = GetColorDXGIFormat(ColorRenderTargetFormat(src_format)); - srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + D3D12_SHADER_RESOURCE_VIEW_DESC rt_srv_desc; + rt_srv_desc.Format = + GetColorDXGIFormat(ColorRenderTargetFormat(src_format)); + rt_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; if (dest_swap) { switch (ColorRenderTargetFormat(src_format)) { case ColorRenderTargetFormat::k_8_8_8_8: @@ -1342,22 +1318,22 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory, case ColorRenderTargetFormat::k_16_16_16_16_FLOAT: case ColorRenderTargetFormat::k_2_10_10_10_AS_16_16_16_16: case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: - srv_desc.Shader4ComponentMapping = + rt_srv_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(2, 1, 0, 3); break; default: - srv_desc.Shader4ComponentMapping = + rt_srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; } } else { - srv_desc.Shader4ComponentMapping = + rt_srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; } - srv_desc.Texture2D.MostDetailedMip = 0; - srv_desc.Texture2D.MipLevels = 1; - srv_desc.Texture2D.PlaneSlice = 0; - srv_desc.Texture2D.ResourceMinLODClamp = 0.0f; - device->CreateShaderResourceView(render_target->resource, &srv_desc, + rt_srv_desc.Texture2D.MostDetailedMip = 0; + rt_srv_desc.Texture2D.MipLevels = 1; + rt_srv_desc.Texture2D.PlaneSlice = 0; + rt_srv_desc.Texture2D.ResourceMinLODClamp = 0.0f; + device->CreateShaderResourceView(render_target->resource, &rt_srv_desc, descriptor_cpu_start); command_list->SetGraphicsRootDescriptorTable(1, descriptor_gpu_start); @@ -1507,16 +1483,8 @@ bool RenderTargetCache::ResolveClear(uint32_t edram_base, command_list->SetComputeRootSignature(edram_clear_root_signature_); command_list->SetComputeRoot32BitConstants( 0, sizeof(root_constants) / sizeof(uint32_t), &root_constants, 0); - D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc; - uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; - uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - uav_desc.Buffer.FirstElement = 0; - uav_desc.Buffer.NumElements = 2 * 2048 * 1280; - uav_desc.Buffer.StructureByteStride = 0; - uav_desc.Buffer.CounterOffsetInBytes = 0; - uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; - device->CreateUnorderedAccessView(edram_buffer_, nullptr, &uav_desc, - descriptor_cpu_start); + ui::d3d12::util::CreateRawBufferUAV(device, descriptor_cpu_start, + edram_buffer_, kEDRAMBufferSize); command_list->SetComputeRootDescriptorTable(1, descriptor_gpu_start); command_list->Dispatch(row_tiles, rows, 1); command_processor_->PushUAVBarrier(edram_buffer_); @@ -2040,31 +2008,15 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() { D3D12_RESOURCE_STATE_UNORDERED_ACCESS); edram_buffer_state_ = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; - // Prepare for storing. + // Set up the bindings. auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider(); auto device = provider->GetDevice(); - D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc; - srv_desc.Format = DXGI_FORMAT_R32_TYPELESS; - srv_desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - srv_desc.Buffer.FirstElement = 0; - srv_desc.Buffer.NumElements = copy_buffer_size >> 2; - srv_desc.Buffer.StructureByteStride = 0; - srv_desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; - device->CreateShaderResourceView(copy_buffer, &srv_desc, - descriptor_cpu_start); - D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc; - uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; - uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - uav_desc.Buffer.FirstElement = 0; - uav_desc.Buffer.NumElements = 2 * 2048 * 1280; - uav_desc.Buffer.StructureByteStride = 0; - uav_desc.Buffer.CounterOffsetInBytes = 0; - uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; - device->CreateUnorderedAccessView( - edram_buffer_, nullptr, &uav_desc, - provider->OffsetViewDescriptor(descriptor_cpu_start, 1)); command_list->SetComputeRootSignature(edram_load_store_root_signature_); + ui::d3d12::util::CreateRawBufferSRV(device, descriptor_cpu_start, copy_buffer, + copy_buffer_size); + ui::d3d12::util::CreateRawBufferUAV( + device, provider->OffsetViewDescriptor(descriptor_cpu_start, 1), + edram_buffer_, kEDRAMBufferSize); command_list->SetComputeRootDescriptorTable(1, descriptor_gpu_start); // Sort the bindings in ascending order of EDRAM base so data in the render @@ -2209,28 +2161,12 @@ void RenderTargetCache::LoadRenderTargetsFromEDRAM( // Set up the bindings. auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider(); auto device = provider->GetDevice(); - D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc; - srv_desc.Format = DXGI_FORMAT_R32_TYPELESS; - srv_desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - srv_desc.Buffer.FirstElement = 0; - srv_desc.Buffer.NumElements = 2 * 2048 * 1280; - srv_desc.Buffer.StructureByteStride = 0; - srv_desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; - device->CreateShaderResourceView(edram_buffer_, &srv_desc, - descriptor_cpu_start); - D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc; - uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; - uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - uav_desc.Buffer.FirstElement = 0; - uav_desc.Buffer.NumElements = copy_buffer_size >> 2; - uav_desc.Buffer.StructureByteStride = 0; - uav_desc.Buffer.CounterOffsetInBytes = 0; - uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; - device->CreateUnorderedAccessView( - copy_buffer, nullptr, &uav_desc, - provider->OffsetViewDescriptor(descriptor_cpu_start, 1)); command_list->SetComputeRootSignature(edram_load_store_root_signature_); + ui::d3d12::util::CreateRawBufferSRV(device, descriptor_cpu_start, + edram_buffer_, kEDRAMBufferSize); + ui::d3d12::util::CreateRawBufferUAV( + device, provider->OffsetViewDescriptor(descriptor_cpu_start, 1), + copy_buffer, copy_buffer_size); command_list->SetComputeRootDescriptorTable(1, descriptor_gpu_start); // Load each render target. diff --git a/src/xenia/gpu/d3d12/render_target_cache.h b/src/xenia/gpu/d3d12/render_target_cache.h index acf35bc3e..0a66a20c8 100644 --- a/src/xenia/gpu/d3d12/render_target_cache.h +++ b/src/xenia/gpu/d3d12/render_target_cache.h @@ -417,6 +417,10 @@ class RenderTargetCache { // The EDRAM buffer allowing color and depth data to be reinterpreted. ID3D12Resource* edram_buffer_ = nullptr; + // Two 10 MB pages, one containing color and integer depth data, another with + // 32-bit float depth when 20e4 depth is used to allow for multipass drawing + // without precision loss in case of EDRAM store/load. + static constexpr uint32_t kEDRAMBufferSize = 2 * 2048 * 5120; D3D12_RESOURCE_STATES edram_buffer_state_; bool edram_buffer_cleared_; diff --git a/src/xenia/gpu/d3d12/shared_memory.cc b/src/xenia/gpu/d3d12/shared_memory.cc index 158d1decd..5ee49fa95 100644 --- a/src/xenia/gpu/d3d12/shared_memory.cc +++ b/src/xenia/gpu/d3d12/shared_memory.cc @@ -18,6 +18,7 @@ #include "xenia/base/memory.h" #include "xenia/base/profiling.h" #include "xenia/gpu/d3d12/d3d12_command_processor.h" +#include "xenia/ui/d3d12/d3d12_util.h" namespace xe { namespace gpu { @@ -528,31 +529,15 @@ void SharedMemory::UseForWriting() { } void SharedMemory::CreateSRV(D3D12_CPU_DESCRIPTOR_HANDLE handle) { - auto device = - command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice(); - D3D12_SHADER_RESOURCE_VIEW_DESC desc; - desc.Format = DXGI_FORMAT_R32_TYPELESS; - desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - desc.Buffer.FirstElement = 0; - desc.Buffer.NumElements = kBufferSize >> 2; - desc.Buffer.StructureByteStride = 0; - desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; - device->CreateShaderResourceView(buffer_, &desc, handle); + ui::d3d12::util::CreateRawBufferSRV( + command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice(), + handle, buffer_, kBufferSize); } void SharedMemory::CreateRawUAV(D3D12_CPU_DESCRIPTOR_HANDLE handle) { - auto device = - command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice(); - D3D12_UNORDERED_ACCESS_VIEW_DESC desc; - desc.Format = DXGI_FORMAT_R32_TYPELESS; - desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - desc.Buffer.FirstElement = 0; - desc.Buffer.NumElements = kBufferSize >> 2; - desc.Buffer.StructureByteStride = 0; - desc.Buffer.CounterOffsetInBytes = 0; - desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; - device->CreateUnorderedAccessView(buffer_, nullptr, &desc, handle); + ui::d3d12::util::CreateRawBufferUAV( + command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice(), + handle, buffer_, kBufferSize); } } // namespace d3d12 diff --git a/src/xenia/gpu/d3d12/texture_cache.cc b/src/xenia/gpu/d3d12/texture_cache.cc index 27f970e4c..52e45f12c 100644 --- a/src/xenia/gpu/d3d12/texture_cache.cc +++ b/src/xenia/gpu/d3d12/texture_cache.cc @@ -569,15 +569,8 @@ bool TextureCache::TileResolvedTexture( tile_constants.host_pitch = uint32_t(footprint.Footprint.RowPitch); command_list->SetComputeRoot32BitConstants( 0, sizeof(tile_constants) / sizeof(uint32_t), &tile_constants, 0); - D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc; - srv_desc.Format = DXGI_FORMAT_R32_TYPELESS; - srv_desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - srv_desc.Buffer.FirstElement = 0; - srv_desc.Buffer.NumElements = buffer_size; - srv_desc.Buffer.StructureByteStride = 0; - srv_desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; - device->CreateShaderResourceView(buffer, &srv_desc, descriptor_cpu_start); + ui::d3d12::util::CreateRawBufferSRV(device, descriptor_cpu_start, buffer, + buffer_size); shared_memory_->CreateRawUAV( provider->OffsetViewDescriptor(descriptor_cpu_start, 1)); command_list->SetComputeRootDescriptorTable(1, descriptor_gpu_start); @@ -958,17 +951,9 @@ bool TextureCache::LoadTextureData(Texture* texture) { } shared_memory_->UseForReading(); shared_memory_->CreateSRV(descriptor_cpu_start); - D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc; - uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; - uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - uav_desc.Buffer.FirstElement = 0; - uav_desc.Buffer.NumElements = UINT(host_slice_size >> 2); - uav_desc.Buffer.StructureByteStride = 0; - uav_desc.Buffer.CounterOffsetInBytes = 0; - uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; - device->CreateUnorderedAccessView( - copy_buffer, nullptr, &uav_desc, - provider->OffsetViewDescriptor(descriptor_cpu_start, 1)); + ui::d3d12::util::CreateRawBufferUAV( + device, provider->OffsetViewDescriptor(descriptor_cpu_start, 1), + copy_buffer, uint32_t(host_slice_size)); command_processor_->SetComputePipeline(pipeline); command_list->SetComputeRootSignature(load_root_signature_); command_list->SetComputeRootDescriptorTable(1, descriptor_gpu_start); diff --git a/src/xenia/ui/d3d12/d3d12_util.cc b/src/xenia/ui/d3d12/d3d12_util.cc index 7f267950e..844cc9159 100644 --- a/src/xenia/ui/d3d12/d3d12_util.cc +++ b/src/xenia/ui/d3d12/d3d12_util.cc @@ -9,6 +9,7 @@ #include "xenia/ui/d3d12/d3d12_util.h" +#include "xenia/base/assert.h" #include "xenia/base/logging.h" namespace xe { @@ -57,6 +58,40 @@ ID3D12PipelineState* CreateComputePipeline( return pipeline; } +void CreateRawBufferSRV(ID3D12Device* device, + D3D12_CPU_DESCRIPTOR_HANDLE handle, + ID3D12Resource* buffer, uint32_t size, + uint64_t offset) { + assert_false(size & (D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT - 1)); + assert_false(offset & (D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT - 1)); + D3D12_SHADER_RESOURCE_VIEW_DESC desc; + desc.Format = DXGI_FORMAT_R32_TYPELESS; + desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + desc.Buffer.FirstElement = offset >> 2; + desc.Buffer.NumElements = size >> 2; + desc.Buffer.StructureByteStride = 0; + desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; + device->CreateShaderResourceView(buffer, &desc, handle); +} + +void CreateRawBufferUAV(ID3D12Device* device, + D3D12_CPU_DESCRIPTOR_HANDLE handle, + ID3D12Resource* buffer, uint32_t size, + uint64_t offset) { + assert_false(size & (D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT - 1)); + assert_false(offset & (D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT - 1)); + D3D12_UNORDERED_ACCESS_VIEW_DESC desc; + desc.Format = DXGI_FORMAT_R32_TYPELESS; + desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + desc.Buffer.FirstElement = offset >> 2; + desc.Buffer.NumElements = size >> 2; + desc.Buffer.StructureByteStride = 0; + desc.Buffer.CounterOffsetInBytes = 0; + desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; + device->CreateUnorderedAccessView(buffer, nullptr, &desc, handle); +} + } // namespace util } // namespace d3d12 } // namespace ui diff --git a/src/xenia/ui/d3d12/d3d12_util.h b/src/xenia/ui/d3d12/d3d12_util.h index 26f9ff9d3..effca89fb 100644 --- a/src/xenia/ui/d3d12/d3d12_util.h +++ b/src/xenia/ui/d3d12/d3d12_util.h @@ -35,6 +35,15 @@ ID3D12PipelineState* CreateComputePipeline(ID3D12Device* device, size_t shader_size, ID3D12RootSignature* root_signature); +void CreateRawBufferSRV(ID3D12Device* device, + D3D12_CPU_DESCRIPTOR_HANDLE handle, + ID3D12Resource* buffer, uint32_t size, + uint64_t offset = 0); +void CreateRawBufferUAV(ID3D12Device* device, + D3D12_CPU_DESCRIPTOR_HANDLE handle, + ID3D12Resource* buffer, uint32_t size, + uint64_t offset = 0); + } // namespace util } // namespace d3d12 } // namespace ui