1 // Copyright 2019 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #include "dawn_native/d3d12/CommandRecordingContext.h" 15 #include "dawn_native/d3d12/CommandAllocatorManager.h" 16 #include "dawn_native/d3d12/D3D12Error.h" 17 #include "dawn_native/d3d12/DeviceD3D12.h" 18 #include "dawn_native/d3d12/HeapD3D12.h" 19 #include "dawn_native/d3d12/ResidencyManagerD3D12.h" 20 21 namespace dawn_native { namespace d3d12 { 22 AddToSharedTextureList(Texture * texture)23 void CommandRecordingContext::AddToSharedTextureList(Texture* texture) { 24 ASSERT(IsOpen()); 25 mSharedTextures.insert(texture); 26 } 27 Open(ID3D12Device * d3d12Device,CommandAllocatorManager * commandAllocationManager)28 MaybeError CommandRecordingContext::Open(ID3D12Device* d3d12Device, 29 CommandAllocatorManager* commandAllocationManager) { 30 ASSERT(!IsOpen()); 31 ID3D12CommandAllocator* commandAllocator; 32 DAWN_TRY_ASSIGN(commandAllocator, commandAllocationManager->ReserveCommandAllocator()); 33 if (mD3d12CommandList != nullptr) { 34 MaybeError error = CheckHRESULT(mD3d12CommandList->Reset(commandAllocator, nullptr), 35 "D3D12 resetting command list"); 36 if (error.IsError()) { 37 mD3d12CommandList.Reset(); 38 DAWN_TRY(std::move(error)); 39 } 40 } else { 41 ComPtr<ID3D12GraphicsCommandList> d3d12GraphicsCommandList; 42 DAWN_TRY(CheckHRESULT( 43 d3d12Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, commandAllocator, 44 nullptr, IID_PPV_ARGS(&d3d12GraphicsCommandList)), 45 "D3D12 creating direct command list")); 46 mD3d12CommandList = std::move(d3d12GraphicsCommandList); 47 // Store a cast to ID3D12GraphicsCommandList4. This is required to use the D3D12 render 48 // pass APIs introduced in Windows build 1809. 49 mD3d12CommandList.As(&mD3d12CommandList4); 50 } 51 52 mIsOpen = true; 53 54 return {}; 55 } 56 ExecuteCommandList(Device * device)57 MaybeError CommandRecordingContext::ExecuteCommandList(Device* device) { 58 if (IsOpen()) { 59 // Shared textures must be transitioned to common state after the last usage in order 60 // for them to be used by other APIs like D3D11. We ensure this by transitioning to the 61 // common state right before command list submission. TransitionUsageNow itself ensures 62 // no unnecessary transitions happen if the resources is already in the common state. 63 for (Texture* texture : mSharedTextures) { 64 texture->TrackAllUsageAndTransitionNow(this, D3D12_RESOURCE_STATE_COMMON); 65 } 66 67 MaybeError error = 68 CheckHRESULT(mD3d12CommandList->Close(), "D3D12 closing pending command list"); 69 if (error.IsError()) { 70 Release(); 71 DAWN_TRY(std::move(error)); 72 } 73 DAWN_TRY(device->GetResidencyManager()->EnsureHeapsAreResident( 74 mHeapsPendingUsage.data(), mHeapsPendingUsage.size())); 75 76 ID3D12CommandList* d3d12CommandList = GetCommandList(); 77 device->GetCommandQueue()->ExecuteCommandLists(1, &d3d12CommandList); 78 79 mIsOpen = false; 80 mSharedTextures.clear(); 81 mHeapsPendingUsage.clear(); 82 } 83 return {}; 84 } 85 TrackHeapUsage(Heap * heap,ExecutionSerial serial)86 void CommandRecordingContext::TrackHeapUsage(Heap* heap, ExecutionSerial serial) { 87 // Before tracking the heap, check the last serial it was recorded on to ensure we aren't 88 // tracking it more than once. 89 if (heap->GetLastUsage() < serial) { 90 heap->SetLastUsage(serial); 91 mHeapsPendingUsage.push_back(heap); 92 } 93 } 94 GetCommandList() const95 ID3D12GraphicsCommandList* CommandRecordingContext::GetCommandList() const { 96 ASSERT(mD3d12CommandList != nullptr); 97 ASSERT(IsOpen()); 98 return mD3d12CommandList.Get(); 99 } 100 101 // This function will fail on Windows versions prior to 1809. Support must be queried through 102 // the device before calling. GetCommandList4() const103 ID3D12GraphicsCommandList4* CommandRecordingContext::GetCommandList4() const { 104 ASSERT(IsOpen()); 105 ASSERT(mD3d12CommandList != nullptr); 106 return mD3d12CommandList4.Get(); 107 } 108 Release()109 void CommandRecordingContext::Release() { 110 mD3d12CommandList.Reset(); 111 mD3d12CommandList4.Reset(); 112 mIsOpen = false; 113 mSharedTextures.clear(); 114 mHeapsPendingUsage.clear(); 115 mTempBuffers.clear(); 116 } 117 IsOpen() const118 bool CommandRecordingContext::IsOpen() const { 119 return mIsOpen; 120 } 121 AddToTempBuffers(Ref<Buffer> tempBuffer)122 void CommandRecordingContext::AddToTempBuffers(Ref<Buffer> tempBuffer) { 123 mTempBuffers.emplace_back(tempBuffer); 124 } 125 126 }} // namespace dawn_native::d3d12 127