• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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