From 5be78ab3691967def5694fa6c03ff3de80481d8b Mon Sep 17 00:00:00 2001 From: Triang3l Date: Sat, 15 Sep 2018 23:41:16 +0300 Subject: [PATCH] [D3D12] Non-indexed triangle fans and resource creation refactoring --- .../gpu/d3d12/d3d12_command_processor.cc | 58 ++++----- src/xenia/gpu/d3d12/primitive_converter.cc | 112 ++++++++++++++++-- src/xenia/gpu/d3d12/primitive_converter.h | 33 +++++- src/xenia/gpu/d3d12/render_target_cache.cc | 18 +-- src/xenia/gpu/d3d12/shared_memory.cc | 21 +--- src/xenia/gpu/d3d12/texture_cache.cc | 6 +- src/xenia/ui/d3d12/d3d12_immediate_drawer.cc | 26 +--- src/xenia/ui/d3d12/d3d12_util.cc | 3 + src/xenia/ui/d3d12/d3d12_util.h | 18 +++ src/xenia/ui/d3d12/pools.cc | 18 +-- 10 files changed, 206 insertions(+), 107 deletions(-) diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 3a0dccfdc..1ca8f996a 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -442,23 +442,12 @@ ID3D12Resource* D3D12CommandProcessor::RequestScratchGPUBuffer( auto context = GetD3D12Context(); auto device = context->GetD3D12Provider()->GetDevice(); D3D12_RESOURCE_DESC buffer_desc; - buffer_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - buffer_desc.Alignment = 0; - buffer_desc.Width = size; - buffer_desc.Height = 1; - buffer_desc.DepthOrArraySize = 1; - buffer_desc.MipLevels = 1; - buffer_desc.Format = DXGI_FORMAT_UNKNOWN; - buffer_desc.SampleDesc.Count = 1; - buffer_desc.SampleDesc.Quality = 0; - buffer_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - buffer_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; - D3D12_HEAP_PROPERTIES heap_properties = {}; - heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; + ui::d3d12::util::FillBufferResourceDesc( + buffer_desc, size, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); ID3D12Resource* buffer; if (FAILED(device->CreateCommittedResource( - &heap_properties, D3D12_HEAP_FLAG_NONE, &buffer_desc, state, nullptr, - IID_PPV_ARGS(&buffer)))) { + &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, + &buffer_desc, state, nullptr, IID_PPV_ARGS(&buffer)))) { XELOGE("Failed to create a %u MB scratch GPU buffer", size >> 20); return nullptr; } @@ -624,11 +613,12 @@ bool D3D12CommandProcessor::SetupContext() { } primitive_converter_ = std::make_unique( - context, register_file_, memory_, shared_memory_.get()); - primitive_converter_->Initialize(); + this, register_file_, memory_, shared_memory_.get()); + if (!primitive_converter_->Initialize()) { + XELOGE("Failed to initialize the geometric primitive converter"); + return false; + } - D3D12_HEAP_PROPERTIES swap_texture_heap_properties = {}; - swap_texture_heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; D3D12_RESOURCE_DESC swap_texture_desc; swap_texture_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; swap_texture_desc.Alignment = 0; @@ -643,7 +633,7 @@ bool D3D12CommandProcessor::SetupContext() { swap_texture_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; // Can be sampled at any time, switch to render target when needed, then back. if (FAILED(device->CreateCommittedResource( - &swap_texture_heap_properties, D3D12_HEAP_FLAG_NONE, + &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, &swap_texture_desc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, IID_PPV_ARGS(&swap_texture_)))) { XELOGE("Failed to create the command processor front buffer"); @@ -1055,10 +1045,9 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type, uint32_t converted_index_count; PrimitiveConverter::ConversionResult conversion_result = primitive_converter_->ConvertPrimitives( - primitive_type, index_buffer_info->guest_base, - index_buffer_info->count, index_buffer_info->format, - index_buffer_info->endianness, index_buffer_view.BufferLocation, - converted_index_count); + primitive_type, index_buffer_info->guest_base, index_count, + index_buffer_info->format, index_buffer_info->endianness, + index_buffer_view.BufferLocation, converted_index_count); if (conversion_result == PrimitiveConverter::ConversionResult::kFailed) { return false; } @@ -1068,6 +1057,7 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type, } if (conversion_result == PrimitiveConverter::ConversionResult::kConverted) { index_buffer_view.SizeInBytes = converted_index_count * index_size; + index_count = converted_index_count; } else { uint32_t index_buffer_size = index_buffer_info->count * index_size; shared_memory_->RequestRange(index_base, index_buffer_size); @@ -1080,11 +1070,23 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type, SubmitBarriers(); command_list->DrawIndexedInstanced(index_count, 1, 0, 0, 0); } else { - // TODO(Triang3l): Get a static index buffer for unsupported primitive types - // from the primitive converter. + // Check if need to draw using a conversion index buffer. + uint32_t converted_index_count; + D3D12_GPU_VIRTUAL_ADDRESS conversion_gpu_address = + primitive_converter_->GetStaticIndexBuffer(primitive_type, index_count, + converted_index_count); shared_memory_->UseForReading(); SubmitBarriers(); - command_list->DrawInstanced(index_count, 1, 0, 0); + if (conversion_gpu_address) { + D3D12_INDEX_BUFFER_VIEW index_buffer_view; + index_buffer_view.BufferLocation = conversion_gpu_address; + index_buffer_view.SizeInBytes = converted_index_count * sizeof(uint16_t); + index_buffer_view.Format = DXGI_FORMAT_R16_UINT; + command_list->IASetIndexBuffer(&index_buffer_view); + command_list->DrawIndexedInstanced(converted_index_count, 1, 0, 0, 0); + } else { + command_list->DrawInstanced(index_count, 1, 0, 0); + } } return true; @@ -1164,7 +1166,7 @@ bool D3D12CommandProcessor::BeginFrame() { render_target_cache_->BeginFrame(); - primitive_converter_->BeginFrame(GetCurrentCommandList()); + primitive_converter_->BeginFrame(); return true; } diff --git a/src/xenia/gpu/d3d12/primitive_converter.cc b/src/xenia/gpu/d3d12/primitive_converter.cc index 8375e124f..36f7a00bc 100644 --- a/src/xenia/gpu/d3d12/primitive_converter.cc +++ b/src/xenia/gpu/d3d12/primitive_converter.cc @@ -9,40 +9,123 @@ #include "xenia/gpu/d3d12/primitive_converter.h" +#include + +#include "xenia/base/assert.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/platform.h" +#include "xenia/gpu/d3d12/d3d12_command_processor.h" +#include "xenia/ui/d3d12/d3d12_util.h" namespace xe { namespace gpu { namespace d3d12 { -PrimitiveConverter::PrimitiveConverter(ui::d3d12::D3D12Context* context, +PrimitiveConverter::PrimitiveConverter(D3D12CommandProcessor* command_processor, RegisterFile* register_file, Memory* memory, SharedMemory* shared_memory) - : context_(context), + : command_processor_(command_processor), register_file_(register_file), memory_(memory), shared_memory_(shared_memory) {} PrimitiveConverter::~PrimitiveConverter() { Shutdown(); } -void PrimitiveConverter::Initialize() { +bool PrimitiveConverter::Initialize() { + auto context = command_processor_->GetD3D12Context(); + auto device = context->GetD3D12Provider()->GetDevice(); + // There can be at most 65535 indices in a Xenos draw call, but they can be up // to 4 bytes large, and conversion can add more indices (almost triple the // count for triangle strips, for instance). buffer_pool_ = - std::make_unique(context_, 4 * 1024 * 1024); + std::make_unique(context, 4 * 1024 * 1024); + + // Create the static index buffer for non-indexed drawing. + D3D12_RESOURCE_DESC static_ib_desc; + ui::d3d12::util::FillBufferResourceDesc( + static_ib_desc, kStaticIBTotalCount * sizeof(uint16_t), + D3D12_RESOURCE_FLAG_NONE); + if (FAILED(device->CreateCommittedResource( + &ui::d3d12::util::kHeapPropertiesUpload, D3D12_HEAP_FLAG_NONE, + &static_ib_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + IID_PPV_ARGS(&static_ib_upload_)))) { + XELOGE( + "Failed to create the upload buffer for the primitive conversion " + "static index buffer"); + Shutdown(); + return false; + } + D3D12_RANGE static_ib_read_range; + static_ib_read_range.Begin = 0; + static_ib_read_range.End = 0; + void* static_ib_mapping; + if (FAILED(static_ib_upload_->Map(0, &static_ib_read_range, + &static_ib_mapping))) { + XELOGE( + "Failed to map the upload buffer for the primitive conversion " + "static index buffer"); + Shutdown(); + return false; + } + uint16_t* static_ib_data = reinterpret_cast(static_ib_mapping); + // Triangle fans as triangle lists. + // https://docs.microsoft.com/en-us/windows/desktop/direct3d9/triangle-fans + // Ordered as (v1, v2, v0), (v2, v3, v0). + uint16_t* static_ib_data_triangle_fan = + &static_ib_data[kStaticIBTriangleFanOffset]; + for (uint32_t i = 2; i < kMaxNonIndexedVertices; ++i) { + *(static_ib_data_triangle_fan++) = i; + *(static_ib_data_triangle_fan++) = i - 1; + *(static_ib_data_triangle_fan++) = 0; + } + static_ib_upload_->Unmap(0, nullptr); + // Not uploaded yet. + static_ib_upload_frame_ = UINT64_MAX; + if (FAILED(device->CreateCommittedResource( + &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, + &static_ib_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + IID_PPV_ARGS(&static_ib_)))) { + XELOGE("Failed to create the primitive conversion static index buffer"); + Shutdown(); + return false; + } + static_ib_gpu_address_ = static_ib_->GetGPUVirtualAddress(); + + return true; } -void PrimitiveConverter::Shutdown() { buffer_pool_.reset(); } +void PrimitiveConverter::Shutdown() { + ui::d3d12::util::ReleaseAndNull(static_ib_); + ui::d3d12::util::ReleaseAndNull(static_ib_upload_); + buffer_pool_.reset(); +} void PrimitiveConverter::ClearCache() { buffer_pool_->ClearCache(); } -void PrimitiveConverter::BeginFrame(ID3D12GraphicsCommandList* command_list) { +void PrimitiveConverter::BeginFrame() { buffer_pool_->BeginFrame(); - // TODO(Triang3l): Create the static index buffer for unindexed triangle fans. + + // Got a command list now - upload and transition the static index buffer if + // needed. + if (static_ib_upload_ != nullptr) { + auto context = command_processor_->GetD3D12Context(); + if (static_ib_upload_frame_ == UINT64_MAX) { + // Not uploaded yet - upload. + command_processor_->GetCurrentCommandList()->CopyResource( + static_ib_, static_ib_upload_); + command_processor_->PushTransitionBarrier( + static_ib_, D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_INDEX_BUFFER); + static_ib_upload_frame_ = context->GetCurrentFrame(); + } else if (context->GetLastCompletedFrame() >= static_ib_upload_frame_) { + // Completely uploaded - release the upload buffer. + static_ib_upload_->Release(); + static_ib_upload_ = nullptr; + } + } } void PrimitiveConverter::EndFrame() { buffer_pool_->EndFrame(); } @@ -194,6 +277,21 @@ void* PrimitiveConverter::AllocateIndices( return mapping + simd_offset; } +D3D12_GPU_VIRTUAL_ADDRESS PrimitiveConverter::GetStaticIndexBuffer( + PrimitiveType source_type, uint32_t index_count, + uint32_t& index_count_out) const { + if (index_count >= kMaxNonIndexedVertices) { + assert_always(); + return D3D12_GPU_VIRTUAL_ADDRESS(0); + } + if (source_type == PrimitiveType::kTriangleFan) { + index_count_out = (std::max(index_count, uint32_t(2)) - 2) * 3; + return static_ib_gpu_address_ + + kStaticIBTriangleFanOffset * sizeof(uint16_t); + } + return D3D12_GPU_VIRTUAL_ADDRESS(0); +} + } // namespace d3d12 } // namespace gpu } // namespace xe diff --git a/src/xenia/gpu/d3d12/primitive_converter.h b/src/xenia/gpu/d3d12/primitive_converter.h index ed1969e50..cad6260e9 100644 --- a/src/xenia/gpu/d3d12/primitive_converter.h +++ b/src/xenia/gpu/d3d12/primitive_converter.h @@ -24,6 +24,8 @@ namespace xe { namespace gpu { namespace d3d12 { +class D3D12CommandProcessor; + // Index buffer cache for primitive types not natively supported by Direct3D 12: // - Triangle and line strips with non-0xFFFF/0xFFFFFFFF reset index. // - Triangle fans. @@ -32,16 +34,16 @@ namespace d3d12 { // vertex count value). class PrimitiveConverter { public: - PrimitiveConverter(ui::d3d12::D3D12Context* context, + PrimitiveConverter(D3D12CommandProcessor* command_processor, RegisterFile* register_file, Memory* memory, SharedMemory* shared_memory); ~PrimitiveConverter(); - void Initialize(); + bool Initialize(); void Shutdown(); void ClearCache(); - void BeginFrame(ID3D12GraphicsCommandList* command_list); + void BeginFrame(); void EndFrame(); // Returns the primitive type that the original type will be converted to. @@ -70,6 +72,12 @@ class PrimitiveConverter { D3D12_GPU_VIRTUAL_ADDRESS& gpu_address_out, uint32_t& index_count_out); + // Returns the 16-bit index buffer for drawing unsupported non-indexed + // primitives in INDEX_BUFFER state, for non-indexed drawing. Returns 0 if + // conversion is not available (can draw natively). + D3D12_GPU_VIRTUAL_ADDRESS GetStaticIndexBuffer( + PrimitiveType source_type, uint32_t index_count, + uint32_t& index_count_out) const; // TODO(Triang3l): A function that returns a static index buffer for // non-indexed drawing of unsupported primitives @@ -81,13 +89,30 @@ class PrimitiveConverter { uint32_t simd_offset, D3D12_GPU_VIRTUAL_ADDRESS& gpu_address_out); - ui::d3d12::D3D12Context* context_; + D3D12CommandProcessor* command_processor_; RegisterFile* register_file_; Memory* memory_; SharedMemory* shared_memory_; std::unique_ptr buffer_pool_ = nullptr; + // Static index buffers for emulating unsupported primitive types when drawing + // without an index buffer. + // CPU-side, used only for uploading - destroyed once the copy commands have + // been completed. + ID3D12Resource* static_ib_upload_ = nullptr; + uint64_t static_ib_upload_frame_; + // GPU-side - used for drawing. + ID3D12Resource* static_ib_ = nullptr; + D3D12_GPU_VIRTUAL_ADDRESS static_ib_gpu_address_; + // In PM4 draw packets, 16 bits are used for the vertex count. + static constexpr uint32_t kMaxNonIndexedVertices = 65535; + static constexpr uint32_t kStaticIBTriangleFanOffset = 0; + static constexpr uint32_t kStaticIBTriangleFanCount = + (kMaxNonIndexedVertices - 2) * 3; + static constexpr uint32_t kStaticIBTotalCount = + kStaticIBTriangleFanOffset + kStaticIBTriangleFanCount; + struct ConvertedIndices { D3D12_GPU_VIRTUAL_ADDRESS gpu_address; PrimitiveType primitive_type; diff --git a/src/xenia/gpu/d3d12/render_target_cache.cc b/src/xenia/gpu/d3d12/render_target_cache.cc index 2aed64469..2acc6d52c 100644 --- a/src/xenia/gpu/d3d12/render_target_cache.cc +++ b/src/xenia/gpu/d3d12/render_target_cache.cc @@ -76,23 +76,13 @@ bool RenderTargetCache::Initialize() { // Create the buffer for reinterpreting EDRAM contents. D3D12_RESOURCE_DESC edram_buffer_desc; - edram_buffer_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - edram_buffer_desc.Alignment = 0; - edram_buffer_desc.Width = kEDRAMBufferSize; - edram_buffer_desc.Height = 1; - edram_buffer_desc.DepthOrArraySize = 1; - edram_buffer_desc.MipLevels = 1; - edram_buffer_desc.Format = DXGI_FORMAT_UNKNOWN; - edram_buffer_desc.SampleDesc.Count = 1; - edram_buffer_desc.SampleDesc.Quality = 0; - edram_buffer_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - edram_buffer_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; - D3D12_HEAP_PROPERTIES edram_buffer_heap_properties = {}; - edram_buffer_heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; + ui::d3d12::util::FillBufferResourceDesc( + edram_buffer_desc, kEDRAMBufferSize, + D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); // The first operation will be a clear. edram_buffer_state_ = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; if (FAILED(device->CreateCommittedResource( - &edram_buffer_heap_properties, D3D12_HEAP_FLAG_NONE, + &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, &edram_buffer_desc, edram_buffer_state_, nullptr, IID_PPV_ARGS(&edram_buffer_)))) { XELOGE("Failed to create the EDRAM buffer"); diff --git a/src/xenia/gpu/d3d12/shared_memory.cc b/src/xenia/gpu/d3d12/shared_memory.cc index 5ee49fa95..472241b89 100644 --- a/src/xenia/gpu/d3d12/shared_memory.cc +++ b/src/xenia/gpu/d3d12/shared_memory.cc @@ -42,19 +42,10 @@ bool SharedMemory::Initialize() { auto context = command_processor_->GetD3D12Context(); auto device = context->GetD3D12Provider()->GetDevice(); - buffer_state_ = D3D12_RESOURCE_STATE_COPY_DEST; D3D12_RESOURCE_DESC buffer_desc; - buffer_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - buffer_desc.Alignment = 0; - buffer_desc.Width = kBufferSize; - buffer_desc.Height = 1; - buffer_desc.DepthOrArraySize = 1; - buffer_desc.MipLevels = 1; - buffer_desc.Format = DXGI_FORMAT_UNKNOWN; - buffer_desc.SampleDesc.Count = 1; - buffer_desc.SampleDesc.Quality = 0; - buffer_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - buffer_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + ui::d3d12::util::FillBufferResourceDesc( + buffer_desc, kBufferSize, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); + buffer_state_ = D3D12_RESOURCE_STATE_COPY_DEST; if (FLAGS_d3d12_tiled_resources) { if (FAILED(device->CreateReservedResource( &buffer_desc, buffer_state_, nullptr, IID_PPV_ARGS(&buffer_)))) { @@ -63,11 +54,9 @@ bool SharedMemory::Initialize() { return false; } } else { - D3D12_HEAP_PROPERTIES heap_properties = {}; - heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; if (FAILED(device->CreateCommittedResource( - &heap_properties, D3D12_HEAP_FLAG_NONE, &buffer_desc, buffer_state_, - nullptr, IID_PPV_ARGS(&buffer_)))) { + &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, + &buffer_desc, buffer_state_, nullptr, IID_PPV_ARGS(&buffer_)))) { XELOGE("Shared memory: Failed to create the 512 MB buffer"); Shutdown(); return false; diff --git a/src/xenia/gpu/d3d12/texture_cache.cc b/src/xenia/gpu/d3d12/texture_cache.cc index 8a32127a0..07a00156e 100644 --- a/src/xenia/gpu/d3d12/texture_cache.cc +++ b/src/xenia/gpu/d3d12/texture_cache.cc @@ -819,14 +819,12 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) { desc.Flags = D3D12_RESOURCE_FLAG_NONE; auto device = command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice(); - D3D12_HEAP_PROPERTIES heap_properties = {}; - heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; // Assuming untiling will be the next operation. D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_COPY_DEST; ID3D12Resource* resource; if (FAILED(device->CreateCommittedResource( - &heap_properties, D3D12_HEAP_FLAG_NONE, &desc, state, nullptr, - IID_PPV_ARGS(&resource)))) { + &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, &desc, + state, nullptr, IID_PPV_ARGS(&resource)))) { LogTextureKeyAction(key, "Failed to create"); return nullptr; } diff --git a/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc b/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc index 7e86c4652..03158cfc3 100644 --- a/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc +++ b/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc @@ -62,8 +62,6 @@ bool D3D12ImmediateTexture::Initialize(ID3D12Device* device) { // The first operation will likely be copying the contents. state_ = D3D12_RESOURCE_STATE_COPY_DEST; - D3D12_HEAP_PROPERTIES heap_properties = {}; - heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; D3D12_RESOURCE_DESC resource_desc; resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; resource_desc.Alignment = 0; @@ -77,8 +75,8 @@ bool D3D12ImmediateTexture::Initialize(ID3D12Device* device) { resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE; if (FAILED(device->CreateCommittedResource( - &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, state_, - nullptr, IID_PPV_ARGS(&resource_)))) { + &util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, &resource_desc, + state_, nullptr, IID_PPV_ARGS(&resource_)))) { XELOGE("Failed to create a %ux%u texture for immediate drawing", width, height); return false; @@ -173,8 +171,7 @@ bool D3D12ImmediateDrawer::Initialize() { root_signature_desc.pStaticSamplers = nullptr; root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; - root_signature_ = - ui::d3d12::util::CreateRootSignature(device, root_signature_desc); + root_signature_ = util::CreateRootSignature(device, root_signature_desc); if (root_signature_ == nullptr) { XELOGE("Failed to create the immediate drawer root signature"); Shutdown(); @@ -362,23 +359,12 @@ void D3D12ImmediateDrawer::UpdateTexture(ImmediateTexture* texture, UINT64 upload_size; device->GetCopyableFootprints(&texture_desc, 0, 1, 0, &upload_footprint, nullptr, nullptr, &upload_size); - D3D12_HEAP_PROPERTIES heap_properties = {}; - heap_properties.Type = D3D12_HEAP_TYPE_UPLOAD; D3D12_RESOURCE_DESC buffer_desc; - buffer_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - buffer_desc.Alignment = 0; - buffer_desc.Width = upload_size; - buffer_desc.Height = 1; - buffer_desc.DepthOrArraySize = 1; - buffer_desc.MipLevels = 1; - buffer_desc.Format = DXGI_FORMAT_UNKNOWN; - buffer_desc.SampleDesc.Count = 1; - buffer_desc.SampleDesc.Quality = 0; - buffer_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - buffer_desc.Flags = D3D12_RESOURCE_FLAG_NONE; + util::FillBufferResourceDesc(buffer_desc, upload_size, + D3D12_RESOURCE_FLAG_NONE); ID3D12Resource* buffer; if (FAILED(device->CreateCommittedResource( - &heap_properties, D3D12_HEAP_FLAG_NONE, &buffer_desc, + &util::kHeapPropertiesUpload, D3D12_HEAP_FLAG_NONE, &buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&buffer)))) { XELOGE( "Failed to create an upload buffer for a %ux%u texture for " diff --git a/src/xenia/ui/d3d12/d3d12_util.cc b/src/xenia/ui/d3d12/d3d12_util.cc index 844cc9159..629627347 100644 --- a/src/xenia/ui/d3d12/d3d12_util.cc +++ b/src/xenia/ui/d3d12/d3d12_util.cc @@ -17,6 +17,9 @@ namespace ui { namespace d3d12 { namespace util { +const D3D12_HEAP_PROPERTIES kHeapPropertiesDefault = {D3D12_HEAP_TYPE_DEFAULT}; +const D3D12_HEAP_PROPERTIES kHeapPropertiesUpload = {D3D12_HEAP_TYPE_UPLOAD}; + ID3D12RootSignature* CreateRootSignature( ID3D12Device* device, const D3D12_ROOT_SIGNATURE_DESC& desc) { ID3DBlob* blob; diff --git a/src/xenia/ui/d3d12/d3d12_util.h b/src/xenia/ui/d3d12/d3d12_util.h index effca89fb..af7e48e19 100644 --- a/src/xenia/ui/d3d12/d3d12_util.h +++ b/src/xenia/ui/d3d12/d3d12_util.h @@ -17,6 +17,9 @@ namespace ui { namespace d3d12 { namespace util { +extern const D3D12_HEAP_PROPERTIES kHeapPropertiesDefault; +extern const D3D12_HEAP_PROPERTIES kHeapPropertiesUpload; + template inline bool ReleaseAndNull(T& object) { if (object != nullptr) { @@ -35,6 +38,21 @@ ID3D12PipelineState* CreateComputePipeline(ID3D12Device* device, size_t shader_size, ID3D12RootSignature* root_signature); +inline void FillBufferResourceDesc(D3D12_RESOURCE_DESC& desc, UINT64 size, + D3D12_RESOURCE_FLAGS flags) { + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Alignment = 0; + desc.Width = size; + desc.Height = 1; + desc.DepthOrArraySize = 1; + desc.MipLevels = 1; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = flags; +} + void CreateRawBufferSRV(ID3D12Device* device, D3D12_CPU_DESCRIPTOR_HANDLE handle, ID3D12Resource* buffer, uint32_t size, diff --git a/src/xenia/ui/d3d12/pools.cc b/src/xenia/ui/d3d12/pools.cc index a79b7542c..ccc5786ea 100644 --- a/src/xenia/ui/d3d12/pools.cc +++ b/src/xenia/ui/d3d12/pools.cc @@ -13,6 +13,7 @@ #include "xenia/base/assert.h" #include "xenia/base/logging.h" +#include "xenia/ui/d3d12/d3d12_util.h" namespace xe { namespace ui { @@ -157,23 +158,12 @@ bool UploadBufferPool::BeginNextPage() { if (unsent_ == nullptr) { auto device = context_->GetD3D12Provider()->GetDevice(); - D3D12_HEAP_PROPERTIES heap_properties = {}; - heap_properties.Type = D3D12_HEAP_TYPE_UPLOAD; D3D12_RESOURCE_DESC buffer_desc; - buffer_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - buffer_desc.Alignment = 0; - buffer_desc.Width = page_size_; - buffer_desc.Height = 1; - buffer_desc.DepthOrArraySize = 1; - buffer_desc.MipLevels = 1; - buffer_desc.Format = DXGI_FORMAT_UNKNOWN; - buffer_desc.SampleDesc.Count = 1; - buffer_desc.SampleDesc.Quality = 0; - buffer_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - buffer_desc.Flags = D3D12_RESOURCE_FLAG_NONE; + util::FillBufferResourceDesc(buffer_desc, page_size_, + D3D12_RESOURCE_FLAG_NONE); ID3D12Resource* buffer_resource; if (FAILED(device->CreateCommittedResource( - &heap_properties, D3D12_HEAP_FLAG_NONE, &buffer_desc, + &util::kHeapPropertiesUpload, D3D12_HEAP_FLAG_NONE, &buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&buffer_resource)))) { XELOGE("Failed to create a D3D upload buffer with %u bytes", page_size_);