diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index ea1141342..2be359787 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -555,7 +555,8 @@ void D3D12CommandProcessor::SetSamplePositions(MsaaSamples sample_positions) { // for ROV output. There's hardly any difference between 2,6 (of 0 and 3 with // 4x MSAA) and 4,4 anyway. // https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12graphicscommandlist1-setsamplepositions - if (cvars::d3d12_ssaa_custom_sample_positions && !IsROVUsedForEDRAM()) { + if (cvars::d3d12_ssaa_custom_sample_positions && !IsROVUsedForEDRAM() && + command_list_1_) { auto provider = GetD3D12Context()->GetD3D12Provider(); auto tier = provider->GetProgrammableSamplePositionsTier(); if (tier >= 2) { @@ -738,10 +739,31 @@ bool D3D12CommandProcessor::SetupContext() { frame_completed_ = 0; std::memset(closed_frame_submissions_, 0, sizeof(closed_frame_submissions_)); - command_list_writable_first_ = nullptr; - command_list_writable_last_ = nullptr; - command_list_submitted_first_ = nullptr; - command_list_submitted_last_ = nullptr; + // Create the command list and one allocator because it's needed for a command + // list. + ID3D12CommandAllocator* command_allocator; + if (FAILED(device->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&command_allocator)))) { + XELOGE("Failed to create a command allocator"); + return false; + } + command_allocator_writable_first_ = new CommandAllocator; + command_allocator_writable_first_->command_allocator = command_allocator; + command_allocator_writable_first_->last_usage_submission = 0; + command_allocator_writable_first_->next = nullptr; + command_allocator_writable_last_ = command_allocator_writable_first_; + command_allocator_submitted_first_ = nullptr; + command_allocator_submitted_last_ = nullptr; + if (FAILED(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, + command_allocator, nullptr, + IID_PPV_ARGS(&command_list_)))) { + XELOGE("Failed to create the graphics command list"); + return false; + } + // Initially in open state, wait until a deferred command list submission. + command_list_->Close(); + // Optional - added in Creators Update (SDK 10.0.15063.0). + command_list_->QueryInterface(IID_PPV_ARGS(&command_list_1_)); deferred_command_list_ = std::make_unique(this); constant_buffer_pool_ = @@ -974,7 +996,9 @@ void D3D12CommandProcessor::ShutdownContext() { shared_memory_.reset(); deferred_command_list_.reset(); - ClearCommandListCache(); + ui::d3d12::util::ReleaseAndNull(command_list_1_); + ui::d3d12::util::ReleaseAndNull(command_list_); + ClearCommandAllocatorCache(); frame_open_ = false; frame_current_ = 1; @@ -1824,23 +1848,25 @@ void D3D12CommandProcessor::BeginSubmission(bool is_guest_command) { } } - // Reclaim command lists. - while (command_list_submitted_first_) { - if (command_list_submitted_first_->last_usage_submission > + // Reclaim command allocators. + while (command_allocator_submitted_first_) { + if (command_allocator_submitted_first_->last_usage_submission > submission_completed_) { break; } - if (command_list_writable_last_) { - command_list_writable_last_->next = command_list_submitted_first_; + if (command_allocator_writable_last_) { + command_allocator_writable_last_->next = + command_allocator_submitted_first_; } else { - command_list_writable_first_ = command_list_submitted_first_; + command_allocator_writable_first_ = command_allocator_submitted_first_; } - command_list_writable_last_ = command_list_submitted_first_; - command_list_submitted_first_ = command_list_submitted_first_->next; - command_list_writable_last_->next = nullptr; + command_allocator_writable_last_ = command_allocator_submitted_first_; + command_allocator_submitted_first_ = + command_allocator_submitted_first_->next; + command_allocator_writable_last_->next = nullptr; } - if (!command_list_submitted_first_) { - command_list_submitted_last_ = nullptr; + if (!command_allocator_submitted_first_) { + command_allocator_submitted_last_ = nullptr; } // Delete transient buffers marked for deletion. @@ -1858,8 +1884,9 @@ void D3D12CommandProcessor::BeginSubmission(bool is_guest_command) { if (!submission_open_) { submission_open_ = true; - // Start a new deferred command list - will create the real one in the end - // of submission. + // Start a new deferred command list - will submit it to the real one in the + // end of the submission (when async pipeline state object creation requests + // are fulfilled). deferred_command_list_->Reset(); // Reset cached state of the command list. @@ -1928,22 +1955,22 @@ void D3D12CommandProcessor::BeginSubmission(bool is_guest_command) { bool D3D12CommandProcessor::EndSubmission(bool is_swap) { auto provider = GetD3D12Context()->GetD3D12Provider(); - // Make sure there is a command list to submit to. - if (submission_open_ && !command_list_writable_first_) { - std::unique_ptr new_command_list = - ui::d3d12::CommandList::Create(provider->GetDevice(), - provider->GetDirectQueue(), - D3D12_COMMAND_LIST_TYPE_DIRECT); - if (!new_command_list) { + // Make sure there is a command allocator to write commands to. + if (submission_open_ && !command_allocator_writable_first_) { + ID3D12CommandAllocator* command_allocator; + if (FAILED(provider->GetDevice()->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&command_allocator)))) { + XELOGE("Failed to create a command allocator"); // Try to submit later. Completely dropping the submission is not // permitted because resources would be left in an undefined state. return false; } - command_list_writable_first_ = new CommandList; - command_list_writable_first_->command_list = std::move(new_command_list); - command_list_writable_first_->last_usage_submission = 0; - command_list_writable_first_->next = nullptr; - command_list_writable_last_ = command_list_writable_first_; + command_allocator_writable_first_ = new CommandAllocator; + command_allocator_writable_first_->command_allocator = command_allocator; + command_allocator_writable_first_->last_usage_submission = 0; + command_allocator_writable_first_->next = nullptr; + command_allocator_writable_last_ = command_allocator_writable_first_; } bool is_closing_frame = is_swap && frame_open_; @@ -1961,28 +1988,33 @@ bool D3D12CommandProcessor::EndSubmission(bool is_swap) { // destroyed between frames. SubmitBarriers(); + auto direct_queue = provider->GetDirectQueue(); + // Submit the command list. - auto current_command_list = - command_list_writable_first_->command_list.get(); - current_command_list->BeginRecording(); - deferred_command_list_->Execute(current_command_list->GetCommandList(), - current_command_list->GetCommandList1()); - current_command_list->Execute(); - command_list_writable_first_->last_usage_submission = submission_current_; - if (command_list_submitted_last_) { - command_list_submitted_last_->next = command_list_writable_first_; + ID3D12CommandAllocator* command_allocator = + command_allocator_writable_first_->command_allocator; + command_allocator->Reset(); + command_list_->Reset(command_allocator, nullptr); + deferred_command_list_->Execute(command_list_, command_list_1_); + command_list_->Close(); + ID3D12CommandList* execute_command_lists[] = {command_list_}; + direct_queue->ExecuteCommandLists(1, execute_command_lists); + command_allocator_writable_first_->last_usage_submission = + submission_current_; + if (command_allocator_submitted_last_) { + command_allocator_submitted_last_->next = + command_allocator_writable_first_; } else { - command_list_submitted_first_ = command_list_writable_first_; + command_allocator_submitted_first_ = command_allocator_writable_first_; } - command_list_submitted_last_ = command_list_writable_first_; - command_list_writable_first_ = command_list_writable_first_->next; - command_list_submitted_last_->next = nullptr; - if (!command_list_writable_first_) { - command_list_writable_last_ = nullptr; + command_allocator_submitted_last_ = command_allocator_writable_first_; + command_allocator_writable_first_ = command_allocator_writable_first_->next; + command_allocator_submitted_last_->next = nullptr; + if (!command_allocator_writable_first_) { + command_allocator_writable_last_ = nullptr; } - provider->GetDirectQueue()->Signal(submission_fence_, - submission_current_++); + direct_queue->Signal(submission_fence_, submission_current_++); submission_open_ = false; } @@ -2005,7 +2037,7 @@ bool D3D12CommandProcessor::EndSubmission(bool is_swap) { cache_clear_requested_ = false; AwaitAllSubmissionsCompletion(); - ClearCommandListCache(); + ClearCommandAllocatorCache(); ui::d3d12::util::ReleaseAndNull(scratch_buffer_); scratch_buffer_size_ = 0; @@ -2047,19 +2079,21 @@ void D3D12CommandProcessor::AwaitAllSubmissionsCompletion() { submission_completed_ = submission_current_ - 1; } -void D3D12CommandProcessor::ClearCommandListCache() { - while (command_list_submitted_first_) { - auto next = command_list_submitted_first_->next; - delete command_list_submitted_first_; - command_list_submitted_first_ = next; +void D3D12CommandProcessor::ClearCommandAllocatorCache() { + while (command_allocator_submitted_first_) { + auto next = command_allocator_submitted_first_->next; + command_allocator_submitted_first_->command_allocator->Release(); + delete command_allocator_submitted_first_; + command_allocator_submitted_first_ = next; } - command_list_submitted_last_ = nullptr; - while (command_list_writable_first_) { - auto next = command_list_writable_first_->next; - delete command_list_writable_first_; - command_list_writable_first_ = next; + command_allocator_submitted_last_ = nullptr; + while (command_allocator_writable_first_) { + auto next = command_allocator_writable_first_->next; + command_allocator_writable_first_->command_allocator->Release(); + delete command_allocator_writable_first_; + command_allocator_writable_first_ = next; } - command_list_writable_last_ = nullptr; + command_allocator_writable_last_ = nullptr; } void D3D12CommandProcessor::UpdateFixedFunctionState(bool primitive_two_faced) { diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.h b/src/xenia/gpu/d3d12/d3d12_command_processor.h index 18d191b28..25fbe4001 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.h +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.h @@ -28,7 +28,6 @@ #include "xenia/gpu/dxbc_shader_translator.h" #include "xenia/gpu/xenos.h" #include "xenia/kernel/kernel_state.h" -#include "xenia/ui/d3d12/command_list.h" #include "xenia/ui/d3d12/d3d12_context.h" #include "xenia/ui/d3d12/pools.h" @@ -238,7 +237,7 @@ class D3D12CommandProcessor : public CommandProcessor { bool EndSubmission(bool is_swap); void AwaitAllSubmissionsCompletion(); // Need to await submission completion before calling. - void ClearCommandListCache(); + void ClearCommandAllocatorCache(); void UpdateFixedFunctionState(bool primitive_two_faced); void UpdateSystemConstantValues( @@ -278,15 +277,17 @@ class D3D12CommandProcessor : public CommandProcessor { // Submission indices of frames that have already been submitted. uint64_t closed_frame_submissions_[kQueueFrames] = {}; - struct CommandList { - std::unique_ptr command_list; + struct CommandAllocator { + ID3D12CommandAllocator* command_allocator; uint64_t last_usage_submission; - CommandList* next; + CommandAllocator* next; }; - CommandList* command_list_writable_first_ = nullptr; - CommandList* command_list_writable_last_ = nullptr; - CommandList* command_list_submitted_first_ = nullptr; - CommandList* command_list_submitted_last_ = nullptr; + CommandAllocator* command_allocator_writable_first_ = nullptr; + CommandAllocator* command_allocator_writable_last_ = nullptr; + CommandAllocator* command_allocator_submitted_first_ = nullptr; + CommandAllocator* command_allocator_submitted_last_ = nullptr; + ID3D12GraphicsCommandList* command_list_ = nullptr; + ID3D12GraphicsCommandList1* command_list_1_ = nullptr; std::unique_ptr deferred_command_list_ = nullptr; std::unique_ptr shared_memory_ = nullptr; diff --git a/src/xenia/ui/d3d12/command_list.cc b/src/xenia/ui/d3d12/command_list.cc deleted file mode 100644 index fbf2e18f3..000000000 --- a/src/xenia/ui/d3d12/command_list.cc +++ /dev/null @@ -1,81 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2018 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/d3d12/command_list.h" - -#include "xenia/base/logging.h" - -namespace xe { -namespace ui { -namespace d3d12 { - -std::unique_ptr CommandList::Create(ID3D12Device* device, - ID3D12CommandQueue* queue, - D3D12_COMMAND_LIST_TYPE type) { - std::unique_ptr command_list( - new CommandList(device, queue, type)); - if (!command_list->Initialize()) { - return nullptr; - } - return command_list; -} - -CommandList::CommandList(ID3D12Device* device, ID3D12CommandQueue* queue, - D3D12_COMMAND_LIST_TYPE type) - : device_(device), queue_(queue), type_(type) {} - -CommandList::~CommandList() { - if (command_list_1_ != nullptr) { - command_list_1_->Release(); - } - if (command_list_ != nullptr) { - command_list_->Release(); - } - if (command_allocator_ != nullptr) { - command_allocator_->Release(); - } -} - -bool CommandList::Initialize() { - if (FAILED(device_->CreateCommandAllocator( - type_, IID_PPV_ARGS(&command_allocator_)))) { - XELOGE("Failed to create a command allocator"); - return false; - } - if (FAILED(device_->CreateCommandList(0, type_, command_allocator_, nullptr, - IID_PPV_ARGS(&command_list_)))) { - XELOGE("Failed to create a graphics command list"); - command_allocator_->Release(); - command_allocator_ = nullptr; - return false; - } - // Optional - added in Creators Update (SDK 10.0.15063.0). - command_list_->QueryInterface(IID_PPV_ARGS(&command_list_1_)); - // A command list is initially open, need to close it before resetting. - command_list_->Close(); - return true; -} - -ID3D12GraphicsCommandList* CommandList::BeginRecording() { - command_allocator_->Reset(); - command_list_->Reset(command_allocator_, nullptr); - return command_list_; -} - -void CommandList::AbortRecording() { command_list_->Close(); } - -void CommandList::Execute() { - command_list_->Close(); - ID3D12CommandList* execute_lists[] = {command_list_}; - queue_->ExecuteCommandLists(1, execute_lists); -} - -} // namespace d3d12 -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/d3d12/command_list.h b/src/xenia/ui/d3d12/command_list.h deleted file mode 100644 index 6fc209794..000000000 --- a/src/xenia/ui/d3d12/command_list.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2018 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_D3D12_COMMAND_LIST_H_ -#define XENIA_UI_D3D12_COMMAND_LIST_H_ - -#include - -#include "xenia/ui/d3d12/d3d12_api.h" - -namespace xe { -namespace ui { -namespace d3d12 { - -class CommandList { - public: - ~CommandList(); - - static std::unique_ptr Create(ID3D12Device* device, - ID3D12CommandQueue* queue, - D3D12_COMMAND_LIST_TYPE type); - - ID3D12GraphicsCommandList* GetCommandList() const { return command_list_; } - ID3D12GraphicsCommandList1* GetCommandList1() const { - return command_list_1_; - } - - ID3D12GraphicsCommandList* BeginRecording(); - void AbortRecording(); - void Execute(); - - protected: - CommandList(ID3D12Device* device, ID3D12CommandQueue* queue, - D3D12_COMMAND_LIST_TYPE type); - bool Initialize(); - - ID3D12Device* device_; - ID3D12CommandQueue* queue_; - D3D12_COMMAND_LIST_TYPE type_; - - ID3D12CommandAllocator* command_allocator_ = nullptr; - ID3D12GraphicsCommandList* command_list_ = nullptr; - ID3D12GraphicsCommandList1* command_list_1_ = nullptr; -}; - -} // namespace d3d12 -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_D3D12_CPU_FENCE_H_ diff --git a/src/xenia/ui/d3d12/d3d12_context.cc b/src/xenia/ui/d3d12/d3d12_context.cc index 9117a5298..c5736b189 100644 --- a/src/xenia/ui/d3d12/d3d12_context.cc +++ b/src/xenia/ui/d3d12/d3d12_context.cc @@ -26,7 +26,7 @@ namespace xe { namespace ui { namespace d3d12 { -constexpr uint32_t D3D12Context::kSwapCommandListCount; +constexpr uint32_t D3D12Context::kSwapCommandAllocatorCount; constexpr uint32_t D3D12Context::kSwapChainBufferCount; D3D12Context::D3D12Context(D3D12Provider* provider, Window* target_window) @@ -113,15 +113,25 @@ bool D3D12Context::Initialize() { return false; } - // Create command lists for compositing. - for (uint32_t i = 0; i < kSwapCommandListCount; ++i) { - swap_command_lists_[i] = CommandList::Create( - device, direct_queue, D3D12_COMMAND_LIST_TYPE_DIRECT); - if (swap_command_lists_[i] == nullptr) { + // Create the command list for compositing. + for (uint32_t i = 0; i < kSwapCommandAllocatorCount; ++i) { + if (FAILED(device->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&swap_command_allocators_[i])))) { + XELOGE("Failed to create a composition command allocator"); Shutdown(); return false; } } + if (FAILED(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, + swap_command_allocators_[0], nullptr, + IID_PPV_ARGS(&swap_command_list_)))) { + XELOGE("Failed to create the composition graphics command list"); + Shutdown(); + return false; + } + // Initially in open state, wait until BeginSwap. + swap_command_list_->Close(); // Initialize the immediate mode drawer if not offscreen. immediate_drawer_ = std::make_unique(this); @@ -163,6 +173,10 @@ bool D3D12Context::InitializeSwapChainBuffers() { } void D3D12Context::Shutdown() { + if (!target_window_) { + return; + } + if (!context_lost_ && swap_fence_ && swap_fence_->GetCompletedValue() + 1 < swap_fence_current_value_) { swap_fence_->SetEventOnCompletion(swap_fence_current_value_ - 1, @@ -172,8 +186,14 @@ void D3D12Context::Shutdown() { immediate_drawer_.reset(); - for (uint32_t i = 0; i < kSwapCommandListCount; ++i) { - swap_command_lists_[i].reset(); + util::ReleaseAndNull(swap_command_list_); + for (uint32_t i = 0; i < kSwapCommandAllocatorCount; ++i) { + auto& swap_command_allocator = swap_command_allocators_[i]; + if (!swap_command_allocator) { + break; + } + swap_command_allocator->Release(); + swap_command_allocator = nullptr; } if (swap_chain_) { @@ -186,12 +206,10 @@ void D3D12Context::Shutdown() { swap_chain_buffer = nullptr; } - if (swap_chain_rtv_heap_) { - swap_chain_rtv_heap_->Release(); - swap_chain_rtv_heap_ = nullptr; - } + util::ReleaseAndNull(swap_chain_rtv_heap_); swap_chain_->Release(); + swap_chain_ = nullptr; } // First release the fence since it may reference the event. @@ -253,24 +271,27 @@ void D3D12Context::BeginSwap() { } } - // Wait for a swap command list to become free. - // Command list 0 is used when swap_fence_current_value_ is 1, 4, 7... + // Wait for a swap command allocator to become free. + // Command allocator 0 is used when swap_fence_current_value_ is 1, 4, 7... swap_fence_completed_value_ = swap_fence_->GetCompletedValue(); - if (swap_fence_completed_value_ + kSwapCommandListCount < + if (swap_fence_completed_value_ + kSwapCommandAllocatorCount < swap_fence_current_value_) { swap_fence_->SetEventOnCompletion( - swap_fence_current_value_ - kSwapCommandListCount, + swap_fence_current_value_ - kSwapCommandAllocatorCount, swap_fence_completion_event_); WaitForSingleObject(swap_fence_completion_event_, INFINITE); swap_fence_completed_value_ = swap_fence_->GetCompletedValue(); } + // Start the command list. + uint32_t command_allocator_index = + uint32_t((swap_fence_current_value_ + (kSwapCommandAllocatorCount - 1)) % + kSwapCommandAllocatorCount); + auto command_allocator = swap_command_allocators_[command_allocator_index]; + command_allocator->Reset(); + swap_command_list_->Reset(command_allocator, nullptr); + // Bind the back buffer as a render target and clear it. - uint32_t command_list_index = - uint32_t((swap_fence_current_value_ + (kSwapCommandListCount - 1)) % - kSwapCommandListCount); - auto command_list = swap_command_lists_[command_list_index].get(); - auto graphics_command_list = command_list->BeginRecording(); D3D12_RESOURCE_BARRIER barrier; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; @@ -279,9 +300,9 @@ void D3D12Context::BeginSwap() { barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; - graphics_command_list->ResourceBarrier(1, &barrier); + swap_command_list_->ResourceBarrier(1, &barrier); D3D12_CPU_DESCRIPTOR_HANDLE back_buffer_rtv = GetSwapChainBackBufferRTV(); - graphics_command_list->OMSetRenderTargets(1, &back_buffer_rtv, TRUE, nullptr); + swap_command_list_->OMSetRenderTargets(1, &back_buffer_rtv, TRUE, nullptr); float clear_color[4]; if (cvars::d3d12_random_clear_color) { clear_color[0] = rand() / float(RAND_MAX); // NOLINT(runtime/threadsafe_fn) @@ -293,8 +314,8 @@ void D3D12Context::BeginSwap() { clear_color[2] = 238.0f / 255.0f; } clear_color[3] = 1.0f; - graphics_command_list->ClearRenderTargetView(back_buffer_rtv, clear_color, 0, - nullptr); + swap_command_list_->ClearRenderTargetView(back_buffer_rtv, clear_color, 0, + nullptr); } void D3D12Context::EndSwap() { @@ -302,12 +323,9 @@ void D3D12Context::EndSwap() { return; } + auto direct_queue = GetD3D12Provider()->GetDirectQueue(); + // Switch the back buffer to presentation state. - uint32_t command_list_index = - uint32_t((swap_fence_current_value_ + (kSwapCommandListCount - 1)) % - kSwapCommandListCount); - auto command_list = swap_command_lists_[command_list_index].get(); - auto graphics_command_list = command_list->GetCommandList(); D3D12_RESOURCE_BARRIER barrier; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; @@ -316,9 +334,12 @@ void D3D12Context::EndSwap() { barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; - graphics_command_list->ResourceBarrier(1, &barrier); + swap_command_list_->ResourceBarrier(1, &barrier); - command_list->Execute(); + // Submit the command list. + swap_command_list_->Close(); + ID3D12CommandList* execute_command_lists[] = {swap_command_list_}; + direct_queue->ExecuteCommandLists(1, execute_command_lists); // Present and check if the context was lost. HRESULT result = swap_chain_->Present(0, 0); @@ -329,8 +350,7 @@ void D3D12Context::EndSwap() { } // Signal the fence to wait for frame resources to become free again. - GetD3D12Provider()->GetDirectQueue()->Signal(swap_fence_, - swap_fence_current_value_++); + direct_queue->Signal(swap_fence_, swap_fence_current_value_++); // Get the back buffer index for the next frame. swap_chain_back_buffer_index_ = swap_chain_->GetCurrentBackBufferIndex(); diff --git a/src/xenia/ui/d3d12/d3d12_context.h b/src/xenia/ui/d3d12/d3d12_context.h index bd26c3a40..2c20816a4 100644 --- a/src/xenia/ui/d3d12/d3d12_context.h +++ b/src/xenia/ui/d3d12/d3d12_context.h @@ -12,7 +12,6 @@ #include -#include "xenia/ui/d3d12/command_list.h" #include "xenia/ui/d3d12/d3d12_immediate_drawer.h" #include "xenia/ui/d3d12/d3d12_provider.h" #include "xenia/ui/graphics_context.h" @@ -68,10 +67,7 @@ class D3D12Context : public GraphicsContext { return swap_fence_completed_value_; } ID3D12GraphicsCommandList* GetSwapCommandList() const { - uint32_t command_list_index = - uint32_t((swap_fence_current_value_ + (kSwapCommandListCount - 1)) % - kSwapCommandListCount); - return swap_command_lists_[command_list_index]->GetCommandList(); + return swap_command_list_; } private: @@ -99,11 +95,13 @@ class D3D12Context : public GraphicsContext { HANDLE swap_fence_completion_event_ = nullptr; ID3D12Fence* swap_fence_ = nullptr; - static constexpr uint32_t kSwapCommandListCount = 3; - std::unique_ptr swap_command_lists_[kSwapCommandListCount] = {}; - // Current is - // ((swap_fence_current_value_ + (kSwapCommandListCount - 1))) % - // kSwapCommandListCount. + static constexpr uint32_t kSwapCommandAllocatorCount = 3; + ID3D12CommandAllocator* swap_command_allocators_[kSwapCommandAllocatorCount] = + {}; + // Current command allocator is: + // ((swap_fence_current_value_ + (kSwapCommandAllocatorCount - 1))) % + // kSwapCommandAllocatorCount. + ID3D12GraphicsCommandList* swap_command_list_ = nullptr; std::unique_ptr immediate_drawer_ = nullptr; };