From fed33be62b839ba4140160f78634facd9f15ec67 Mon Sep 17 00:00:00 2001 From: Triang3l Date: Sun, 6 Sep 2020 00:52:30 +0300 Subject: [PATCH] [D3D12] Non-zeroed heaps on 2004 --- docs/building.md | 2 +- premake5.lua | 6 ++-- .../gpu/d3d12/d3d12_command_processor.cc | 28 +++++++++------- src/xenia/gpu/d3d12/primitive_converter.cc | 12 ++++--- src/xenia/gpu/d3d12/render_target_cache.cc | 33 +++++++++++-------- src/xenia/gpu/d3d12/shared_memory.cc | 19 ++++++----- src/xenia/gpu/d3d12/texture_cache.cc | 12 ++++--- src/xenia/ui/d3d12/d3d12_immediate_drawer.cc | 22 +++++++------ src/xenia/ui/d3d12/d3d12_provider.cc | 26 +++++++++++---- src/xenia/ui/d3d12/d3d12_provider.h | 4 +++ src/xenia/ui/d3d12/pools.cc | 11 ++++--- src/xenia/ui/d3d12/pools.h | 6 ++-- 12 files changed, 110 insertions(+), 71 deletions(-) diff --git a/docs/building.md b/docs/building.md index d8334793f..6aafc521e 100644 --- a/docs/building.md +++ b/docs/building.md @@ -12,7 +12,7 @@ drivers. * [Visual Studio 2019 or Visual Studio 2017](https://www.visualstudio.com/downloads/) * [Python 3.6+](https://www.python.org/downloads/) * Ensure Python is in PATH. -* Windows 10 SDK +* Windows 10 SDK version 10.0.19041.0 (for Visual Studio 2019, this or any newer version) ``` git clone https://github.com/xenia-project/xenia.git diff --git a/premake5.lua b/premake5.lua index e0c8f8d92..622a4da2c 100644 --- a/premake5.lua +++ b/premake5.lua @@ -202,10 +202,10 @@ solution("xenia") platforms({"Linux"}) elseif os.istarget("windows") then platforms({"Windows"}) - -- Minimum version to support ID3D12GraphicsCommandList1 (for - -- SetSamplePositions). + -- 10.0.15063.0: ID3D12GraphicsCommandList1::SetSamplePositions. + -- 10.0.19041.0: D3D12_HEAP_FLAG_CREATE_NOT_ZEROED. filter("action:vs2017") - systemversion("10.0.15063.0") + systemversion("10.0.19041.0") filter("action:vs2019") systemversion("10.0") filter({}) diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index e9831347d..23163a609 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -646,14 +646,16 @@ ID3D12Resource* D3D12CommandProcessor::RequestScratchGPUBuffer( size = xe::align(size, kScratchBufferSizeIncrement); - auto device = GetD3D12Context().GetD3D12Provider().GetDevice(); + auto& provider = GetD3D12Context().GetD3D12Provider(); + auto device = provider.GetDevice(); D3D12_RESOURCE_DESC buffer_desc; ui::d3d12::util::FillBufferResourceDesc( buffer_desc, size, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); ID3D12Resource* buffer; if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, - &buffer_desc, state, nullptr, IID_PPV_ARGS(&buffer)))) { + &ui::d3d12::util::kHeapPropertiesDefault, + provider.GetHeapFlagCreateNotZeroed(), &buffer_desc, state, nullptr, + IID_PPV_ARGS(&buffer)))) { XELOGE("Failed to create a {} MB scratch GPU buffer", size >> 20); return nullptr; } @@ -889,7 +891,7 @@ bool D3D12CommandProcessor::SetupContext() { // Initialize resource binding. constant_buffer_pool_ = - std::make_unique(device, 1024 * 1024); + std::make_unique(provider, 1024 * 1024); if (bindless_resources_used_) { D3D12_DESCRIPTOR_HEAP_DESC view_bindless_heap_desc; view_bindless_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; @@ -1181,6 +1183,9 @@ bool D3D12CommandProcessor::SetupContext() { return false; } + D3D12_HEAP_FLAGS heap_flag_create_not_zeroed = + provider.GetHeapFlagCreateNotZeroed(); + // Create gamma ramp resources. The PWL gamma ramp is 16-bit, but 6 bits are // hardwired to zero, so DXGI_FORMAT_R10G10B10A2_UNORM can be used for it too. // https://www.x.org/docs/AMD/old/42590_m76_rrg_1.01o.pdf @@ -1202,7 +1207,7 @@ bool D3D12CommandProcessor::SetupContext() { // The first action will be uploading. gamma_ramp_texture_state_ = D3D12_RESOURCE_STATE_COPY_DEST; if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, + &ui::d3d12::util::kHeapPropertiesDefault, heap_flag_create_not_zeroed, &gamma_ramp_desc, gamma_ramp_texture_state_, nullptr, IID_PPV_ARGS(&gamma_ramp_texture_)))) { XELOGE("Failed to create the gamma ramp texture"); @@ -1218,7 +1223,7 @@ bool D3D12CommandProcessor::SetupContext() { ui::d3d12::util::FillBufferResourceDesc( gamma_ramp_desc, gamma_ramp_upload_size, D3D12_RESOURCE_FLAG_NONE); if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesUpload, D3D12_HEAP_FLAG_NONE, + &ui::d3d12::util::kHeapPropertiesUpload, heap_flag_create_not_zeroed, &gamma_ramp_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&gamma_ramp_upload_)))) { XELOGE("Failed to create the gamma ramp upload buffer"); @@ -1246,7 +1251,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( - &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, + &ui::d3d12::util::kHeapPropertiesDefault, heap_flag_create_not_zeroed, &swap_texture_desc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, IID_PPV_ARGS(&swap_texture_)))) { XELOGE("Failed to create the command processor front buffer"); @@ -4286,15 +4291,16 @@ ID3D12Resource* D3D12CommandProcessor::RequestReadbackBuffer(uint32_t size) { } size = xe::align(size, kReadbackBufferSizeIncrement); if (size > readback_buffer_size_) { - auto device = GetD3D12Context().GetD3D12Provider().GetDevice(); + auto& provider = GetD3D12Context().GetD3D12Provider(); + auto device = provider.GetDevice(); D3D12_RESOURCE_DESC buffer_desc; ui::d3d12::util::FillBufferResourceDesc(buffer_desc, size, D3D12_RESOURCE_FLAG_NONE); ID3D12Resource* buffer; if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesReadback, D3D12_HEAP_FLAG_NONE, - &buffer_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, - IID_PPV_ARGS(&buffer)))) { + &ui::d3d12::util::kHeapPropertiesReadback, + provider.GetHeapFlagCreateNotZeroed(), &buffer_desc, + D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&buffer)))) { XELOGE("Failed to create a {} MB readback buffer", size >> 20); return nullptr; } diff --git a/src/xenia/gpu/d3d12/primitive_converter.cc b/src/xenia/gpu/d3d12/primitive_converter.cc index 4884865d0..ab2138b47 100644 --- a/src/xenia/gpu/d3d12/primitive_converter.cc +++ b/src/xenia/gpu/d3d12/primitive_converter.cc @@ -47,14 +47,16 @@ PrimitiveConverter::PrimitiveConverter(D3D12CommandProcessor& command_processor, PrimitiveConverter::~PrimitiveConverter() { Shutdown(); } bool PrimitiveConverter::Initialize() { - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + auto device = provider.GetDevice(); + D3D12_HEAP_FLAGS heap_flag_create_not_zeroed = + provider.GetHeapFlagCreateNotZeroed(); // 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(device, 4 * 1024 * 1024); + std::make_unique(provider, 4 * 1024 * 1024); // Create the static index buffer for non-indexed drawing. D3D12_RESOURCE_DESC static_ib_desc; @@ -62,7 +64,7 @@ bool PrimitiveConverter::Initialize() { static_ib_desc, kStaticIBTotalCount * sizeof(uint16_t), D3D12_RESOURCE_FLAG_NONE); if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesUpload, D3D12_HEAP_FLAG_NONE, + &ui::d3d12::util::kHeapPropertiesUpload, heap_flag_create_not_zeroed, &static_ib_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&static_ib_upload_)))) { XELOGE( @@ -108,7 +110,7 @@ bool PrimitiveConverter::Initialize() { // Not uploaded yet. static_ib_upload_submission_ = UINT64_MAX; if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, + &ui::d3d12::util::kHeapPropertiesDefault, heap_flag_create_not_zeroed, &static_ib_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&static_ib_)))) { XELOGE("Failed to create the primitive conversion static index buffer"); diff --git a/src/xenia/gpu/d3d12/render_target_cache.cc b/src/xenia/gpu/d3d12/render_target_cache.cc index 0c09b6864..3530c8f5a 100644 --- a/src/xenia/gpu/d3d12/render_target_cache.cc +++ b/src/xenia/gpu/d3d12/render_target_cache.cc @@ -137,8 +137,6 @@ bool RenderTargetCache::Initialize(const TextureCache& texture_cache) { uint32_t edram_buffer_size = GetEdramBufferSize(); // Create the buffer for reinterpreting EDRAM contents. - // No need to clear it in the first frame, memory is zeroed out when allocated - // on Windows. D3D12_RESOURCE_DESC edram_buffer_desc; ui::d3d12::util::FillBufferResourceDesc( edram_buffer_desc, edram_buffer_size, @@ -147,8 +145,15 @@ bool RenderTargetCache::Initialize(const TextureCache& texture_cache) { edram_buffer_state_ = edram_rov_used_ ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + // Request zeroed (though no guarantee) when not using ROV so the host 32-bit + // depth buffer will be initialized to deterministic values (because it's + // involved in comparison with converted 24-bit values - whether the 32-bit + // value is up to date is determined by whether it's equal to the 24-bit + // value in the main EDRAM buffer when converted to 24-bit). if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, + &ui::d3d12::util::kHeapPropertiesDefault, + edram_rov_used_ ? provider.GetHeapFlagCreateNotZeroed() + : D3D12_HEAP_FLAG_NONE, &edram_buffer_desc, edram_buffer_state_, nullptr, IID_PPV_ARGS(&edram_buffer_)))) { XELOGE("Failed to create the EDRAM buffer"); @@ -1451,10 +1456,11 @@ bool RenderTargetCache::InitializeTraceSubmitDownloads() { ui::d3d12::util::FillBufferResourceDesc(edram_snapshot_download_buffer_desc, xenos::kEdramSizeBytes, D3D12_RESOURCE_FLAG_NONE); - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + auto device = provider.GetDevice(); if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesReadback, D3D12_HEAP_FLAG_NONE, + &ui::d3d12::util::kHeapPropertiesReadback, + provider.GetHeapFlagCreateNotZeroed(), &edram_snapshot_download_buffer_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&edram_snapshot_download_buffer_)))) { @@ -1493,10 +1499,9 @@ void RenderTargetCache::RestoreEdramSnapshot(const void* snapshot) { return; } auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); if (!edram_snapshot_restore_pool_) { edram_snapshot_restore_pool_ = - std::make_unique(device, + std::make_unique(provider, xenos::kEdramSizeBytes); } ID3D12Resource* upload_buffer; @@ -1603,14 +1608,15 @@ bool RenderTargetCache::MakeHeapResident(uint32_t heap_index) { if (heaps_[heap_index] != nullptr) { return true; } - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + auto device = provider.GetDevice(); D3D12_HEAP_DESC heap_desc = {}; heap_desc.SizeInBytes = kHeap4MBPages << 22; heap_desc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT; // TODO(Triang3l): If real MSAA is added, alignment must be 4 MB. heap_desc.Alignment = 0; - heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES; + heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES | + provider.GetHeapFlagCreateNotZeroed(); if (FAILED( device->CreateHeap(&heap_desc, IID_PPV_ARGS(&heaps_[heap_index])))) { XELOGE("Failed to create a {} MB heap for render targets", @@ -1756,8 +1762,9 @@ RenderTargetCache::RenderTarget* RenderTargetCache::FindOrCreateRenderTarget( } #else if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, - &resource_desc, state, nullptr, IID_PPV_ARGS(&resource)))) { + &ui::d3d12::util::kHeapPropertiesDefault, + provider.GetHeapFlagCreateNotZeroed(), &resource_desc, state, nullptr, + IID_PPV_ARGS(&resource)))) { XELOGE( "Failed to create a committed resource for {}x{} {} render target with " "format {}", diff --git a/src/xenia/gpu/d3d12/shared_memory.cc b/src/xenia/gpu/d3d12/shared_memory.cc index f2d2e6296..c24336664 100644 --- a/src/xenia/gpu/d3d12/shared_memory.cc +++ b/src/xenia/gpu/d3d12/shared_memory.cc @@ -73,8 +73,9 @@ bool SharedMemory::Initialize() { "resources yet."); } if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, - &buffer_desc, buffer_state_, nullptr, IID_PPV_ARGS(&buffer_)))) { + &ui::d3d12::util::kHeapPropertiesDefault, + provider.GetHeapFlagCreateNotZeroed(), &buffer_desc, buffer_state_, + nullptr, IID_PPV_ARGS(&buffer_)))) { XELOGE("Shared memory: Failed to create the 512 MB buffer"); Shutdown(); return false; @@ -153,7 +154,7 @@ bool SharedMemory::Initialize() { system_page_flags_.resize((page_count_ + 63) / 64); upload_buffer_pool_ = std::make_unique( - device, + provider, xe::align(uint32_t(4 * 1024 * 1024), uint32_t(1) << page_size_log2_)); memory_invalidation_callback_handle_ = @@ -370,7 +371,8 @@ bool SharedMemory::EnsureTilesResident(uint32_t start, uint32_t length) { D3D12_HEAP_DESC heap_desc = {}; heap_desc.SizeInBytes = kHeapSize; heap_desc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT; - heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; + heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS | + provider.GetHeapFlagCreateNotZeroed(); if (FAILED(device->CreateHeap(&heap_desc, IID_PPV_ARGS(&heaps_[i])))) { XELOGE("Shared memory: Failed to create a tile heap"); return false; @@ -890,11 +892,12 @@ bool SharedMemory::InitializeTraceSubmitDownloads() { ui::d3d12::util::FillBufferResourceDesc( gpu_written_buffer_desc, gpu_written_page_count << page_size_log2_, D3D12_RESOURCE_FLAG_NONE); - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + auto device = provider.GetDevice(); if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesReadback, D3D12_HEAP_FLAG_NONE, - &gpu_written_buffer_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + &ui::d3d12::util::kHeapPropertiesReadback, + provider.GetHeapFlagCreateNotZeroed(), &gpu_written_buffer_desc, + D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&trace_gpu_written_buffer_)))) { XELOGE( "Shared memory: Failed to create a {} KB GPU-written memory download " diff --git a/src/xenia/gpu/d3d12/texture_cache.cc b/src/xenia/gpu/d3d12/texture_cache.cc index 01c7812c9..0ec94c132 100644 --- a/src/xenia/gpu/d3d12/texture_cache.cc +++ b/src/xenia/gpu/d3d12/texture_cache.cc @@ -1633,7 +1633,8 @@ bool TextureCache::EnsureScaledResolveBufferResident(uint32_t start_unscaled, D3D12_HEAP_DESC heap_desc = {}; heap_desc.SizeInBytes = kScaledResolveHeapSize; heap_desc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT; - heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; + heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS | + provider.GetHeapFlagCreateNotZeroed(); if (FAILED(device->CreateHeap(&heap_desc, IID_PPV_ARGS(&scaled_resolve_heaps_[i])))) { XELOGE("Texture cache: Failed to create a scaled resolve tile heap"); @@ -1953,14 +1954,15 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) { // Untiling through a buffer instead of using unordered access because copying // is not done that often. desc.Flags = D3D12_RESOURCE_FLAG_NONE; - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + auto device = provider.GetDevice(); // Assuming untiling will be the next operation. D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_COPY_DEST; ID3D12Resource* resource; if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, &desc, - state, nullptr, IID_PPV_ARGS(&resource)))) { + &ui::d3d12::util::kHeapPropertiesDefault, + provider.GetHeapFlagCreateNotZeroed(), &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 6bc92e8c0..0c958ebd3 100644 --- a/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc +++ b/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc @@ -33,7 +33,7 @@ class D3D12ImmediateTexture : public ImmediateTexture { ImmediateTextureFilter filter, bool repeat); ~D3D12ImmediateTexture() override; - bool Initialize(ID3D12Device* device); + bool Initialize(D3D12Provider& provider); void Shutdown(); ID3D12Resource* GetResource() const { return resource_; } @@ -59,7 +59,7 @@ D3D12ImmediateTexture::D3D12ImmediateTexture(uint32_t width, uint32_t height, D3D12ImmediateTexture::~D3D12ImmediateTexture() { Shutdown(); } -bool D3D12ImmediateTexture::Initialize(ID3D12Device* device) { +bool D3D12ImmediateTexture::Initialize(D3D12Provider& provider) { // The first operation will likely be copying the contents. state_ = D3D12_RESOURCE_STATE_COPY_DEST; @@ -75,9 +75,9 @@ bool D3D12ImmediateTexture::Initialize(ID3D12Device* device) { resource_desc.SampleDesc.Quality = 0; resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE; - if (FAILED(device->CreateCommittedResource( - &util::kHeapPropertiesDefault, D3D12_HEAP_FLAG_NONE, &resource_desc, - state_, nullptr, IID_PPV_ARGS(&resource_)))) { + if (FAILED(provider.GetDevice()->CreateCommittedResource( + &util::kHeapPropertiesDefault, provider.GetHeapFlagCreateNotZeroed(), + &resource_desc, state_, nullptr, IID_PPV_ARGS(&resource_)))) { XELOGE("Failed to create a {}x{} texture for immediate drawing", width, height); return false; @@ -288,7 +288,7 @@ bool D3D12ImmediateDrawer::Initialize() { // Create pools for draws. vertex_buffer_pool_ = - std::make_unique(device, 2 * 1024 * 1024); + std::make_unique(provider, 2 * 1024 * 1024); texture_descriptor_pool_ = std::make_unique( device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 2048); texture_descriptor_pool_heap_index_ = DescriptorHeapPool::kHeapIndexInvalid; @@ -326,7 +326,7 @@ std::unique_ptr D3D12ImmediateDrawer::CreateTexture( const uint8_t* data) { auto texture = std::make_unique(width, height, filter, repeat); - texture->Initialize(context_.GetD3D12Provider().GetDevice()); + texture->Initialize(context_.GetD3D12Provider()); if (data != nullptr) { UpdateTexture(texture.get(), data); } @@ -343,7 +343,8 @@ void D3D12ImmediateDrawer::UpdateTexture(ImmediateTexture* texture, } uint32_t width = d3d_texture->width, height = d3d_texture->height; - auto device = context_.GetD3D12Provider().GetDevice(); + auto& provider = context_.GetD3D12Provider(); + auto device = provider.GetDevice(); // Create and fill the upload buffer. D3D12_RESOURCE_DESC texture_desc = texture_resource->GetDesc(); @@ -356,8 +357,9 @@ void D3D12ImmediateDrawer::UpdateTexture(ImmediateTexture* texture, D3D12_RESOURCE_FLAG_NONE); ID3D12Resource* buffer; if (FAILED(device->CreateCommittedResource( - &util::kHeapPropertiesUpload, D3D12_HEAP_FLAG_NONE, &buffer_desc, - D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&buffer)))) { + &util::kHeapPropertiesUpload, provider.GetHeapFlagCreateNotZeroed(), + &buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + IID_PPV_ARGS(&buffer)))) { XELOGE( "Failed to create an upload buffer for a {}x{} texture for " "immediate drawing", diff --git a/src/xenia/ui/d3d12/d3d12_provider.cc b/src/xenia/ui/d3d12/d3d12_provider.cc index 77e4e70aa..0231a5bec 100644 --- a/src/xenia/ui/d3d12/d3d12_provider.cc +++ b/src/xenia/ui/d3d12/d3d12_provider.cc @@ -409,17 +409,29 @@ bool D3D12Provider::Initialize() { virtual_address_bits_per_resource_ = virtual_address_support.MaxGPUVirtualAddressBitsPerResource; } + // D3D12_HEAP_FLAG_CREATE_NOT_ZEROED requires Windows 10 2004 (indicated by + // the availability of ID3D12Device8 or D3D12_FEATURE_D3D12_OPTIONS7). + heap_flag_create_not_zeroed_ = D3D12_HEAP_FLAG_NONE; + D3D12_FEATURE_DATA_D3D12_OPTIONS7 options7; + if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, + &options7, sizeof(options7)))) { + heap_flag_create_not_zeroed_ = D3D12_HEAP_FLAG_CREATE_NOT_ZEROED; + } XELOGD3D( - "Direct3D 12 device features:\n" - "Max GPU virtual address bits per resource: {}\n" - "Programmable sample positions: tier {}\n" - "Rasterizer-ordered views: {}\n" - "Resource binding: tier {}\n" - "Tiled resources: tier {}\n", + "Direct3D 12 device and OS features:\n" + "* Max GPU virtual address bits per resource: {}\n" + "* Programmable sample positions: tier {}\n" + "* Rasterizer-ordered views: {}\n" + "* Resource binding: tier {}\n" + "* Tiled resources: tier {}\n" + "* Non-zeroed heap creation: {}\n", virtual_address_bits_per_resource_, uint32_t(programmable_sample_positions_tier_), rasterizer_ordered_views_supported_ ? "yes" : "no", - uint32_t(resource_binding_tier_), uint32_t(tiled_resources_tier_)); + uint32_t(resource_binding_tier_), uint32_t(tiled_resources_tier_), + (heap_flag_create_not_zeroed_ & D3D12_HEAP_FLAG_CREATE_NOT_ZEROED) + ? "yes" + : "no"); // Get the graphics analysis interface, will silently fail if PIX is not // attached. diff --git a/src/xenia/ui/d3d12/d3d12_provider.h b/src/xenia/ui/d3d12/d3d12_provider.h index 122f16e2f..1c8694fd0 100644 --- a/src/xenia/ui/d3d12/d3d12_provider.h +++ b/src/xenia/ui/d3d12/d3d12_provider.h @@ -84,6 +84,9 @@ class D3D12Provider : public GraphicsProvider { uint32_t GetVirtualAddressBitsPerResource() const { return virtual_address_bits_per_resource_; } + D3D12_HEAP_FLAGS GetHeapFlagCreateNotZeroed() const { + return heap_flag_create_not_zeroed_; + } // Proxies for Direct3D 12 functions since they are loaded dynamically. inline HRESULT SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc, @@ -164,6 +167,7 @@ class D3D12Provider : public GraphicsProvider { D3D12_RESOURCE_BINDING_TIER resource_binding_tier_; D3D12_TILED_RESOURCES_TIER tiled_resources_tier_; uint32_t virtual_address_bits_per_resource_; + D3D12_HEAP_FLAGS heap_flag_create_not_zeroed_; }; } // namespace d3d12 diff --git a/src/xenia/ui/d3d12/pools.cc b/src/xenia/ui/d3d12/pools.cc index deff80b12..7b892caa9 100644 --- a/src/xenia/ui/d3d12/pools.cc +++ b/src/xenia/ui/d3d12/pools.cc @@ -19,8 +19,8 @@ namespace xe { namespace ui { namespace d3d12 { -UploadBufferPool::UploadBufferPool(ID3D12Device* device, uint32_t page_size) - : device_(device), page_size_(page_size) {} +UploadBufferPool::UploadBufferPool(D3D12Provider& provider, uint32_t page_size) + : provider_(provider), page_size_(page_size) {} UploadBufferPool::~UploadBufferPool() { ClearCache(); } @@ -101,9 +101,10 @@ uint8_t* UploadBufferPool::Request(uint64_t submission_index, uint32_t size, util::FillBufferResourceDesc(new_buffer_desc, page_size_, D3D12_RESOURCE_FLAG_NONE); ID3D12Resource* new_buffer; - if (FAILED(device_->CreateCommittedResource( - &util::kHeapPropertiesUpload, D3D12_HEAP_FLAG_NONE, - &new_buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + if (FAILED(provider_.GetDevice()->CreateCommittedResource( + &util::kHeapPropertiesUpload, + provider_.GetHeapFlagCreateNotZeroed(), &new_buffer_desc, + D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&new_buffer)))) { XELOGE("Failed to create a D3D upload buffer with {} bytes", page_size_); diff --git a/src/xenia/ui/d3d12/pools.h b/src/xenia/ui/d3d12/pools.h index 4499bd08f..21606cc42 100644 --- a/src/xenia/ui/d3d12/pools.h +++ b/src/xenia/ui/d3d12/pools.h @@ -12,7 +12,7 @@ #include -#include "xenia/ui/d3d12/d3d12_api.h" +#include "xenia/ui/d3d12/d3d12_provider.h" namespace xe { namespace ui { @@ -23,7 +23,7 @@ namespace d3d12 { class UploadBufferPool { public: - UploadBufferPool(ID3D12Device* device, uint32_t page_size); + UploadBufferPool(D3D12Provider& provider, uint32_t page_size); ~UploadBufferPool(); void Reclaim(uint64_t completed_submission_index); @@ -41,7 +41,7 @@ class UploadBufferPool { D3D12_GPU_VIRTUAL_ADDRESS* gpu_address_out); private: - ID3D12Device* device_; + D3D12Provider& provider_; uint32_t page_size_; struct Page {