1 /*
2 * Copyright 2020 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "src/gpu/d3d/GrD3DCommandList.h"
9
10 #include "src/gpu/GrScissorState.h"
11 #include "src/gpu/d3d/GrD3DAttachment.h"
12 #include "src/gpu/d3d/GrD3DBuffer.h"
13 #include "src/gpu/d3d/GrD3DCommandSignature.h"
14 #include "src/gpu/d3d/GrD3DGpu.h"
15 #include "src/gpu/d3d/GrD3DPipeline.h"
16 #include "src/gpu/d3d/GrD3DRenderTarget.h"
17 #include "src/gpu/d3d/GrD3DTexture.h"
18 #include "src/gpu/d3d/GrD3DTextureResource.h"
19 #include "src/gpu/d3d/GrD3DUtil.h"
20
GrD3DCommandList(gr_cp<ID3D12CommandAllocator> allocator,gr_cp<ID3D12GraphicsCommandList> commandList)21 GrD3DCommandList::GrD3DCommandList(gr_cp<ID3D12CommandAllocator> allocator,
22 gr_cp<ID3D12GraphicsCommandList> commandList)
23 : fCommandList(std::move(commandList))
24 , fAllocator(std::move(allocator)) {
25 }
26
close()27 bool GrD3DCommandList::close() {
28 SkASSERT(fIsActive);
29 this->submitResourceBarriers();
30 HRESULT hr = fCommandList->Close();
31 SkDEBUGCODE(fIsActive = false;)
32 return SUCCEEDED(hr);
33 }
34
submit(ID3D12CommandQueue * queue)35 GrD3DCommandList::SubmitResult GrD3DCommandList::submit(ID3D12CommandQueue* queue) {
36 SkASSERT(fIsActive);
37 if (!this->hasWork()) {
38 this->callFinishedCallbacks();
39 return SubmitResult::kNoWork;
40 }
41
42 if (!this->close()) {
43 return SubmitResult::kFailure;
44 }
45 SkASSERT(!fIsActive);
46 ID3D12CommandList* ppCommandLists[] = { fCommandList.get() };
47 queue->ExecuteCommandLists(1, ppCommandLists);
48
49 return SubmitResult::kSuccess;
50 }
51
reset()52 void GrD3DCommandList::reset() {
53 SkASSERT(!fIsActive);
54 GR_D3D_CALL_ERRCHECK(fAllocator->Reset());
55 GR_D3D_CALL_ERRCHECK(fCommandList->Reset(fAllocator.get(), nullptr));
56 this->onReset();
57
58 this->releaseResources();
59
60 SkDEBUGCODE(fIsActive = true;)
61 fHasWork = false;
62 }
63
releaseResources()64 void GrD3DCommandList::releaseResources() {
65 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
66 if (fTrackedResources.count() == 0 && fTrackedRecycledResources.count() == 0) {
67 return;
68 }
69 SkASSERT(!fIsActive);
70 for (int i = 0; i < fTrackedResources.count(); ++i) {
71 fTrackedResources[i]->notifyFinishedWithWorkOnGpu();
72 }
73 for (int i = 0; i < fTrackedRecycledResources.count(); ++i) {
74 fTrackedRecycledResources[i]->notifyFinishedWithWorkOnGpu();
75 auto resource = fTrackedRecycledResources[i].release();
76 resource->recycle();
77 }
78
79 fTrackedResources.reset();
80 fTrackedRecycledResources.reset();
81 fTrackedGpuBuffers.reset();
82
83 this->callFinishedCallbacks();
84 }
85
addFinishedCallback(sk_sp<GrRefCntedCallback> callback)86 void GrD3DCommandList::addFinishedCallback(sk_sp<GrRefCntedCallback> callback) {
87 fFinishedCallbacks.push_back(std::move(callback));
88 }
89
90 ////////////////////////////////////////////////////////////////////////////////
91 // GraphicsCommandList commands
92 ////////////////////////////////////////////////////////////////////////////////
93
resourceBarrier(sk_sp<GrManagedResource> resource,int numBarriers,const D3D12_RESOURCE_TRANSITION_BARRIER * barriers)94 void GrD3DCommandList::resourceBarrier(sk_sp<GrManagedResource> resource,
95 int numBarriers,
96 const D3D12_RESOURCE_TRANSITION_BARRIER* barriers) {
97 SkASSERT(fIsActive);
98 SkASSERT(barriers);
99 for (int i = 0; i < numBarriers; ++i) {
100 // D3D will apply barriers in order so we can just add onto the end
101 D3D12_RESOURCE_BARRIER& newBarrier = fResourceBarriers.push_back();
102 newBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
103 newBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
104 newBarrier.Transition = barriers[i];
105 }
106
107 fHasWork = true;
108 if (resource) {
109 this->addResource(std::move(resource));
110 }
111 }
112
uavBarrier(sk_sp<GrManagedResource> resource,ID3D12Resource * uavResource)113 void GrD3DCommandList::uavBarrier(sk_sp<GrManagedResource> resource,
114 ID3D12Resource* uavResource) {
115 SkASSERT(fIsActive);
116 // D3D will apply barriers in order so we can just add onto the end
117 D3D12_RESOURCE_BARRIER& newBarrier = fResourceBarriers.push_back();
118 newBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
119 newBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
120 newBarrier.UAV.pResource = uavResource;
121
122 fHasWork = true;
123 if (resource) {
124 this->addResource(std::move(resource));
125 }
126 }
127
aliasingBarrier(sk_sp<GrManagedResource> beforeManagedResource,ID3D12Resource * beforeResource,sk_sp<GrManagedResource> afterManagedResource,ID3D12Resource * afterResource)128 void GrD3DCommandList::aliasingBarrier(sk_sp<GrManagedResource> beforeManagedResource,
129 ID3D12Resource* beforeResource,
130 sk_sp<GrManagedResource> afterManagedResource,
131 ID3D12Resource* afterResource) {
132 SkASSERT(fIsActive);
133 // D3D will apply barriers in order so we can just add onto the end
134 D3D12_RESOURCE_BARRIER& newBarrier = fResourceBarriers.push_back();
135 newBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;
136 newBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
137 newBarrier.Aliasing.pResourceBefore = beforeResource;
138 newBarrier.Aliasing.pResourceAfter = afterResource;
139
140 fHasWork = true;
141 // Aliasing barriers can accept a null pointer for one of the resources,
142 // but at this point we're not using that feature.
143 SkASSERT(beforeManagedResource);
144 this->addResource(std::move(beforeManagedResource));
145 SkASSERT(afterManagedResource);
146 this->addResource(std::move(afterManagedResource));
147 }
148
submitResourceBarriers()149 void GrD3DCommandList::submitResourceBarriers() {
150 SkASSERT(fIsActive);
151
152 if (fResourceBarriers.count()) {
153 fCommandList->ResourceBarrier(fResourceBarriers.count(), fResourceBarriers.begin());
154 fResourceBarriers.reset();
155 }
156 SkASSERT(!fResourceBarriers.count());
157 }
158
copyBufferToTexture(ID3D12Resource * srcBuffer,const GrD3DTextureResource * dstTexture,uint32_t subresourceCount,D3D12_PLACED_SUBRESOURCE_FOOTPRINT * bufferFootprints,int left,int top)159 void GrD3DCommandList::copyBufferToTexture(ID3D12Resource* srcBuffer,
160 const GrD3DTextureResource* dstTexture,
161 uint32_t subresourceCount,
162 D3D12_PLACED_SUBRESOURCE_FOOTPRINT* bufferFootprints,
163 int left, int top) {
164 SkASSERT(fIsActive);
165 SkASSERT(subresourceCount == 1 || (left == 0 && top == 0));
166
167 this->addingWork();
168 this->addResource(dstTexture->resource());
169
170 for (uint32_t subresource = 0; subresource < subresourceCount; ++subresource) {
171 D3D12_TEXTURE_COPY_LOCATION src = {};
172 src.pResource = srcBuffer;
173 src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
174 src.PlacedFootprint = bufferFootprints[subresource];
175
176 D3D12_TEXTURE_COPY_LOCATION dst = {};
177 dst.pResource = dstTexture->d3dResource();
178 dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
179 dst.SubresourceIndex = subresource;
180
181 fCommandList->CopyTextureRegion(&dst, left, top, 0, &src, nullptr);
182 }
183 }
184
copyTextureRegionToTexture(sk_sp<GrManagedResource> dst,const D3D12_TEXTURE_COPY_LOCATION * dstLocation,UINT dstX,UINT dstY,sk_sp<GrManagedResource> src,const D3D12_TEXTURE_COPY_LOCATION * srcLocation,const D3D12_BOX * srcBox)185 void GrD3DCommandList::copyTextureRegionToTexture(sk_sp<GrManagedResource> dst,
186 const D3D12_TEXTURE_COPY_LOCATION* dstLocation,
187 UINT dstX, UINT dstY,
188 sk_sp<GrManagedResource> src,
189 const D3D12_TEXTURE_COPY_LOCATION* srcLocation,
190 const D3D12_BOX* srcBox) {
191 SkASSERT(fIsActive);
192 SkASSERT(dst);
193 this->addingWork();
194 this->addResource(dst);
195 this->addResource(std::move(src));
196 fCommandList->CopyTextureRegion(dstLocation, dstX, dstY, 0, srcLocation, srcBox);
197 }
198
copyTextureRegionToBuffer(sk_sp<const GrBuffer> dst,const D3D12_TEXTURE_COPY_LOCATION * dstLocation,UINT dstX,UINT dstY,sk_sp<GrManagedResource> src,const D3D12_TEXTURE_COPY_LOCATION * srcLocation,const D3D12_BOX * srcBox)199 void GrD3DCommandList::copyTextureRegionToBuffer(sk_sp<const GrBuffer> dst,
200 const D3D12_TEXTURE_COPY_LOCATION* dstLocation,
201 UINT dstX,
202 UINT dstY,
203 sk_sp<GrManagedResource> src,
204 const D3D12_TEXTURE_COPY_LOCATION* srcLocation,
205 const D3D12_BOX* srcBox) {
206 SkASSERT(fIsActive);
207 SkASSERT(dst);
208 this->addingWork();
209 this->addGrBuffer(std::move(dst));
210 this->addResource(std::move(src));
211 fCommandList->CopyTextureRegion(dstLocation, dstX, dstY, 0, srcLocation, srcBox);
212 }
213
214
copyTextureToTexture(const GrD3DTexture * dst,const GrD3DTexture * src,UINT subresourceIndex)215 void GrD3DCommandList::copyTextureToTexture(const GrD3DTexture* dst, const GrD3DTexture* src,
216 UINT subresourceIndex) {
217 SkASSERT(fIsActive);
218 SkASSERT(src);
219 SkASSERT(dst);
220 SkASSERT(src->width() == dst->width() && src->height() == dst->height());
221
222 this->addingWork();
223 ID3D12Resource* dstTexture = dst->d3dResource();
224 ID3D12Resource* srcTexture = src->d3dResource();
225 if (subresourceIndex == (UINT)-1) {
226 fCommandList->CopyResource(dstTexture, srcTexture);
227 } else {
228 SkASSERT(subresourceIndex < src->mipLevels() &&
229 subresourceIndex < dst->mipLevels());
230 D3D12_TEXTURE_COPY_LOCATION srcLoc = {};
231 srcLoc.pResource = srcTexture;
232 srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
233 srcLoc.SubresourceIndex = subresourceIndex;
234
235 D3D12_TEXTURE_COPY_LOCATION dstLoc = {};
236 dstLoc.pResource = dstTexture;
237 dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
238 dstLoc.SubresourceIndex = subresourceIndex;
239
240 fCommandList->CopyTextureRegion(&dstLoc, 0, 0, 0, &srcLoc, nullptr);
241 }
242 this->addResource(dst->resource());
243 this->addResource(src->resource());
244 }
245
copyBufferToBuffer(sk_sp<GrD3DBuffer> dst,uint64_t dstOffset,ID3D12Resource * srcBuffer,uint64_t srcOffset,uint64_t numBytes)246 void GrD3DCommandList::copyBufferToBuffer(sk_sp<GrD3DBuffer> dst, uint64_t dstOffset,
247 ID3D12Resource* srcBuffer, uint64_t srcOffset,
248 uint64_t numBytes) {
249 SkASSERT(fIsActive);
250
251 this->addingWork();
252 ID3D12Resource* dstBuffer = dst->d3dResource();
253 uint64_t dstSize = dstBuffer->GetDesc().Width;
254 uint64_t srcSize = srcBuffer->GetDesc().Width;
255 if (dstSize == srcSize && srcSize == numBytes) {
256 fCommandList->CopyResource(dstBuffer, srcBuffer);
257 } else {
258 fCommandList->CopyBufferRegion(dstBuffer, dstOffset, srcBuffer, srcOffset, numBytes);
259 }
260 this->addGrBuffer(std::move(dst));
261 }
262
addingWork()263 void GrD3DCommandList::addingWork() {
264 this->submitResourceBarriers();
265 fHasWork = true;
266 }
267
268 ////////////////////////////////////////////////////////////////////////////////////////////////////
269
Make(ID3D12Device * device)270 std::unique_ptr<GrD3DDirectCommandList> GrD3DDirectCommandList::Make(ID3D12Device* device) {
271 gr_cp<ID3D12CommandAllocator> allocator;
272 GR_D3D_CALL_ERRCHECK(device->CreateCommandAllocator(
273 D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&allocator)));
274
275 gr_cp<ID3D12GraphicsCommandList> commandList;
276 GR_D3D_CALL_ERRCHECK(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
277 allocator.get(), nullptr,
278 IID_PPV_ARGS(&commandList)));
279
280 auto grCL = new GrD3DDirectCommandList(std::move(allocator), std::move(commandList));
281 return std::unique_ptr<GrD3DDirectCommandList>(grCL);
282 }
283
GrD3DDirectCommandList(gr_cp<ID3D12CommandAllocator> allocator,gr_cp<ID3D12GraphicsCommandList> commandList)284 GrD3DDirectCommandList::GrD3DDirectCommandList(gr_cp<ID3D12CommandAllocator> allocator,
285 gr_cp<ID3D12GraphicsCommandList> commandList)
286 : GrD3DCommandList(std::move(allocator), std::move(commandList)) {
287 sk_bzero(fCurrentGraphicsRootDescTable, sizeof(fCurrentGraphicsRootDescTable));
288 sk_bzero(fCurrentComputeRootDescTable, sizeof(fCurrentComputeRootDescTable));
289 }
290
onReset()291 void GrD3DDirectCommandList::onReset() {
292 fCurrentPipeline = nullptr;
293 fCurrentGraphicsRootSignature = nullptr;
294 fCurrentComputeRootSignature = nullptr;
295 fCurrentVertexBuffer = nullptr;
296 fCurrentVertexStride = 0;
297 fCurrentInstanceBuffer = nullptr;
298 fCurrentInstanceStride = 0;
299 fCurrentIndexBuffer = nullptr;
300 fCurrentGraphicsConstantBufferAddress = 0;
301 fCurrentComputeConstantBufferAddress = 0;
302 sk_bzero(fCurrentGraphicsRootDescTable, sizeof(fCurrentGraphicsRootDescTable));
303 sk_bzero(fCurrentComputeRootDescTable, sizeof(fCurrentComputeRootDescTable));
304 fCurrentSRVCRVDescriptorHeap = nullptr;
305 fCurrentSamplerDescriptorHeap = nullptr;
306 }
307
setPipelineState(const sk_sp<GrD3DPipeline> & pipeline)308 void GrD3DDirectCommandList::setPipelineState(const sk_sp<GrD3DPipeline>& pipeline) {
309 SkASSERT(fIsActive);
310 if (pipeline.get() != fCurrentPipeline) {
311 fCommandList->SetPipelineState(pipeline->d3dPipelineState());
312 this->addResource(std::move(pipeline));
313 fCurrentPipeline = pipeline.get();
314 this->setDefaultSamplePositions();
315 }
316 }
317
setStencilRef(unsigned int stencilRef)318 void GrD3DDirectCommandList::setStencilRef(unsigned int stencilRef) {
319 SkASSERT(fIsActive);
320 fCommandList->OMSetStencilRef(stencilRef);
321 }
322
setBlendFactor(const float blendFactor[4])323 void GrD3DDirectCommandList::setBlendFactor(const float blendFactor[4]) {
324 SkASSERT(fIsActive);
325 fCommandList->OMSetBlendFactor(blendFactor);
326 }
327
setPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY primitiveTopology)328 void GrD3DDirectCommandList::setPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY primitiveTopology) {
329 SkASSERT(fIsActive);
330 fCommandList->IASetPrimitiveTopology(primitiveTopology);
331 }
332
setScissorRects(unsigned int numRects,const D3D12_RECT * rects)333 void GrD3DDirectCommandList::setScissorRects(unsigned int numRects, const D3D12_RECT* rects) {
334 SkASSERT(fIsActive);
335 fCommandList->RSSetScissorRects(numRects, rects);
336 }
337
setViewports(unsigned int numViewports,const D3D12_VIEWPORT * viewports)338 void GrD3DDirectCommandList::setViewports(unsigned int numViewports,
339 const D3D12_VIEWPORT* viewports) {
340 SkASSERT(fIsActive);
341 fCommandList->RSSetViewports(numViewports, viewports);
342 }
343
setCenteredSamplePositions(unsigned int numSamples)344 void GrD3DDirectCommandList::setCenteredSamplePositions(unsigned int numSamples) {
345 if (!fUsingCenteredSamples && numSamples > 1) {
346 gr_cp<ID3D12GraphicsCommandList1> commandList1;
347 GR_D3D_CALL_ERRCHECK(fCommandList->QueryInterface(IID_PPV_ARGS(&commandList1)));
348 static D3D12_SAMPLE_POSITION kCenteredSampleLocations[16] = {};
349 commandList1->SetSamplePositions(numSamples, 1, kCenteredSampleLocations);
350 fUsingCenteredSamples = true;
351 }
352 }
353
setDefaultSamplePositions()354 void GrD3DDirectCommandList::setDefaultSamplePositions() {
355 if (fUsingCenteredSamples) {
356 gr_cp<ID3D12GraphicsCommandList1> commandList1;
357 GR_D3D_CALL_ERRCHECK(fCommandList->QueryInterface(IID_PPV_ARGS(&commandList1)));
358 commandList1->SetSamplePositions(0, 0, nullptr);
359 fUsingCenteredSamples = false;
360 }
361 }
362
setGraphicsRootSignature(const sk_sp<GrD3DRootSignature> & rootSig)363 void GrD3DDirectCommandList::setGraphicsRootSignature(const sk_sp<GrD3DRootSignature>& rootSig) {
364 SkASSERT(fIsActive);
365 if (fCurrentGraphicsRootSignature != rootSig.get()) {
366 fCommandList->SetGraphicsRootSignature(rootSig->rootSignature());
367 this->addResource(rootSig);
368 fCurrentGraphicsRootSignature = rootSig.get();
369 // need to reset the current descriptor tables as well
370 sk_bzero(fCurrentGraphicsRootDescTable, sizeof(fCurrentGraphicsRootDescTable));
371 }
372 }
373
setComputeRootSignature(const sk_sp<GrD3DRootSignature> & rootSig)374 void GrD3DDirectCommandList::setComputeRootSignature(const sk_sp<GrD3DRootSignature>& rootSig) {
375 SkASSERT(fIsActive);
376 if (fCurrentComputeRootSignature != rootSig.get()) {
377 fCommandList->SetComputeRootSignature(rootSig->rootSignature());
378 this->addResource(rootSig);
379 fCurrentComputeRootSignature = rootSig.get();
380 // need to reset the current descriptor tables as well
381 sk_bzero(fCurrentComputeRootDescTable, sizeof(fCurrentComputeRootDescTable));
382 }
383 }
384
setVertexBuffers(unsigned int startSlot,sk_sp<const GrBuffer> vertexBuffer,size_t vertexStride,sk_sp<const GrBuffer> instanceBuffer,size_t instanceStride)385 void GrD3DDirectCommandList::setVertexBuffers(unsigned int startSlot,
386 sk_sp<const GrBuffer> vertexBuffer,
387 size_t vertexStride,
388 sk_sp<const GrBuffer> instanceBuffer,
389 size_t instanceStride) {
390 if (fCurrentVertexBuffer != vertexBuffer.get() ||
391 fCurrentVertexStride != vertexStride ||
392 fCurrentInstanceBuffer != instanceBuffer.get() ||
393 fCurrentInstanceStride != instanceStride) {
394
395 fCurrentVertexBuffer = vertexBuffer.get();
396 fCurrentVertexStride = vertexStride;
397 fCurrentInstanceBuffer = instanceBuffer.get();
398 fCurrentInstanceStride = instanceStride;
399
400 D3D12_VERTEX_BUFFER_VIEW views[2];
401 int numViews = 0;
402 if (vertexBuffer) {
403 auto* d3dBuffer = static_cast<const GrD3DBuffer*>(vertexBuffer.get());
404 views[numViews].BufferLocation = d3dBuffer->d3dResource()->GetGPUVirtualAddress();
405 views[numViews].SizeInBytes = vertexBuffer->size();
406 views[numViews++].StrideInBytes = vertexStride;
407 this->addGrBuffer(std::move(vertexBuffer));
408 }
409 if (instanceBuffer) {
410 auto* d3dBuffer = static_cast<const GrD3DBuffer*>(instanceBuffer.get());
411 views[numViews].BufferLocation = d3dBuffer->d3dResource()->GetGPUVirtualAddress();
412 views[numViews].SizeInBytes = instanceBuffer->size();
413 views[numViews++].StrideInBytes = instanceStride;
414 this->addGrBuffer(std::move(instanceBuffer));
415 }
416 fCommandList->IASetVertexBuffers(startSlot, numViews, views);
417 }
418 }
419
setIndexBuffer(sk_sp<const GrBuffer> indexBuffer)420 void GrD3DDirectCommandList::setIndexBuffer(sk_sp<const GrBuffer> indexBuffer) {
421 if (fCurrentIndexBuffer != indexBuffer.get()) {
422 auto* d3dBuffer = static_cast<const GrD3DBuffer*>(indexBuffer.get());
423
424 D3D12_INDEX_BUFFER_VIEW view = {};
425 view.BufferLocation = d3dBuffer->d3dResource()->GetGPUVirtualAddress();
426 view.SizeInBytes = indexBuffer->size();
427 view.Format = DXGI_FORMAT_R16_UINT;
428 fCommandList->IASetIndexBuffer(&view);
429
430 fCurrentIndexBuffer = indexBuffer.get();
431 this->addGrBuffer(std::move(indexBuffer));
432 }
433 }
434
drawInstanced(unsigned int vertexCount,unsigned int instanceCount,unsigned int startVertex,unsigned int startInstance)435 void GrD3DDirectCommandList::drawInstanced(unsigned int vertexCount, unsigned int instanceCount,
436 unsigned int startVertex, unsigned int startInstance) {
437 SkASSERT(fIsActive);
438 this->addingWork();
439 fCommandList->DrawInstanced(vertexCount, instanceCount, startVertex, startInstance);
440 }
441
drawIndexedInstanced(unsigned int indexCount,unsigned int instanceCount,unsigned int startIndex,unsigned int baseVertex,unsigned int startInstance)442 void GrD3DDirectCommandList::drawIndexedInstanced(unsigned int indexCount,
443 unsigned int instanceCount,
444 unsigned int startIndex,
445 unsigned int baseVertex,
446 unsigned int startInstance) {
447 SkASSERT(fIsActive);
448 this->addingWork();
449 fCommandList->DrawIndexedInstanced(indexCount, instanceCount, startIndex, baseVertex,
450 startInstance);
451 }
452
executeIndirect(const sk_sp<GrD3DCommandSignature> commandSignature,unsigned int maxCommandCount,const GrD3DBuffer * argumentBuffer,size_t argumentBufferOffset)453 void GrD3DDirectCommandList::executeIndirect(const sk_sp<GrD3DCommandSignature> commandSignature,
454 unsigned int maxCommandCount,
455 const GrD3DBuffer* argumentBuffer,
456 size_t argumentBufferOffset) {
457 SkASSERT(fIsActive);
458 this->addingWork();
459 this->addResource(commandSignature);
460 fCommandList->ExecuteIndirect(commandSignature->commandSignature(), maxCommandCount,
461 argumentBuffer->d3dResource(), argumentBufferOffset,
462 nullptr, 0);
463 this->addGrBuffer(sk_ref_sp<const GrBuffer>(argumentBuffer));
464 }
465
466
dispatch(unsigned int threadGroupCountX,unsigned int threadGroupCountY,unsigned int threadGroupCountZ)467 void GrD3DDirectCommandList::dispatch(unsigned int threadGroupCountX,
468 unsigned int threadGroupCountY,
469 unsigned int threadGroupCountZ) {
470 SkASSERT(fIsActive);
471 this->addingWork();
472 fCommandList->Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ);
473 }
474
clearRenderTargetView(const GrD3DRenderTarget * renderTarget,std::array<float,4> color,const D3D12_RECT * rect)475 void GrD3DDirectCommandList::clearRenderTargetView(const GrD3DRenderTarget* renderTarget,
476 std::array<float, 4> color,
477 const D3D12_RECT* rect) {
478 this->addingWork();
479 this->addResource(renderTarget->resource());
480 const GrD3DTextureResource* msaaTextureResource = renderTarget->msaaTextureResource();
481 if (msaaTextureResource && msaaTextureResource != renderTarget) {
482 this->addResource(msaaTextureResource->resource());
483 }
484 unsigned int numRects = rect ? 1 : 0;
485 fCommandList->ClearRenderTargetView(renderTarget->colorRenderTargetView(), color.data(),
486 numRects, rect);
487 }
488
clearDepthStencilView(const GrD3DAttachment * stencil,uint8_t stencilClearValue,const D3D12_RECT * rect)489 void GrD3DDirectCommandList::clearDepthStencilView(const GrD3DAttachment* stencil,
490 uint8_t stencilClearValue,
491 const D3D12_RECT* rect) {
492 this->addingWork();
493 this->addResource(stencil->resource());
494 unsigned int numRects = rect ? 1 : 0;
495 fCommandList->ClearDepthStencilView(stencil->view(), D3D12_CLEAR_FLAG_STENCIL, 0,
496 stencilClearValue, numRects, rect);
497 }
498
setRenderTarget(const GrD3DRenderTarget * renderTarget)499 void GrD3DDirectCommandList::setRenderTarget(const GrD3DRenderTarget* renderTarget) {
500 this->addingWork();
501 this->addResource(renderTarget->resource());
502 const GrD3DTextureResource* msaaTextureResource = renderTarget->msaaTextureResource();
503 if (msaaTextureResource && msaaTextureResource != renderTarget) {
504 this->addResource(msaaTextureResource->resource());
505 }
506 D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = renderTarget->colorRenderTargetView();
507
508 D3D12_CPU_DESCRIPTOR_HANDLE dsDescriptor;
509 D3D12_CPU_DESCRIPTOR_HANDLE* dsDescriptorPtr = nullptr;
510 if (auto stencil = renderTarget->getStencilAttachment()) {
511 GrD3DAttachment* d3dStencil = static_cast<GrD3DAttachment*>(stencil);
512 this->addResource(d3dStencil->resource());
513 dsDescriptor = d3dStencil->view();
514 dsDescriptorPtr = &dsDescriptor;
515 }
516
517 fCommandList->OMSetRenderTargets(1, &rtvDescriptor, false, dsDescriptorPtr);
518 }
519
resolveSubresourceRegion(const GrD3DTextureResource * dstTexture,unsigned int dstX,unsigned int dstY,const GrD3DTextureResource * srcTexture,D3D12_RECT * srcRect)520 void GrD3DDirectCommandList::resolveSubresourceRegion(const GrD3DTextureResource* dstTexture,
521 unsigned int dstX, unsigned int dstY,
522 const GrD3DTextureResource* srcTexture,
523 D3D12_RECT* srcRect) {
524 SkASSERT(dstTexture->dxgiFormat() == srcTexture->dxgiFormat());
525 SkASSERT(dstTexture->currentState() == D3D12_RESOURCE_STATE_RESOLVE_DEST);
526 SkASSERT(srcTexture->currentState() == D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
527 this->addingWork();
528 this->addResource(dstTexture->resource());
529 this->addResource(srcTexture->resource());
530
531 gr_cp<ID3D12GraphicsCommandList1> commandList1;
532 HRESULT result = fCommandList->QueryInterface(IID_PPV_ARGS(&commandList1));
533 if (SUCCEEDED(result)) {
534 commandList1->ResolveSubresourceRegion(dstTexture->d3dResource(), 0, dstX, dstY,
535 srcTexture->d3dResource(), 0, srcRect,
536 srcTexture->dxgiFormat(),
537 D3D12_RESOLVE_MODE_AVERAGE);
538 } else {
539 fCommandList->ResolveSubresource(dstTexture->d3dResource(), 0, srcTexture->d3dResource(), 0,
540 srcTexture->dxgiFormat());
541 }
542 }
543
setGraphicsRootConstantBufferView(unsigned int rootParameterIndex,D3D12_GPU_VIRTUAL_ADDRESS bufferLocation)544 void GrD3DDirectCommandList::setGraphicsRootConstantBufferView(
545 unsigned int rootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS bufferLocation) {
546 SkASSERT(rootParameterIndex ==
547 (unsigned int) GrD3DRootSignature::ParamIndex::kConstantBufferView);
548 if (bufferLocation != fCurrentGraphicsConstantBufferAddress) {
549 fCommandList->SetGraphicsRootConstantBufferView(rootParameterIndex, bufferLocation);
550 fCurrentGraphicsConstantBufferAddress = bufferLocation;
551 }
552 }
553
setComputeRootConstantBufferView(unsigned int rootParameterIndex,D3D12_GPU_VIRTUAL_ADDRESS bufferLocation)554 void GrD3DDirectCommandList::setComputeRootConstantBufferView(
555 unsigned int rootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS bufferLocation) {
556 SkASSERT(rootParameterIndex ==
557 (unsigned int)GrD3DRootSignature::ParamIndex::kConstantBufferView);
558 if (bufferLocation != fCurrentComputeConstantBufferAddress) {
559 fCommandList->SetComputeRootConstantBufferView(rootParameterIndex, bufferLocation);
560 fCurrentComputeConstantBufferAddress = bufferLocation;
561 }
562 }
563
setGraphicsRootDescriptorTable(unsigned int rootParameterIndex,D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor)564 void GrD3DDirectCommandList::setGraphicsRootDescriptorTable(
565 unsigned int rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor) {
566 SkASSERT(rootParameterIndex ==
567 (unsigned int)GrD3DRootSignature::ParamIndex::kSamplerDescriptorTable ||
568 rootParameterIndex ==
569 (unsigned int)GrD3DRootSignature::ParamIndex::kShaderViewDescriptorTable);
570 if (fCurrentGraphicsRootDescTable[rootParameterIndex].ptr != baseDescriptor.ptr) {
571 fCommandList->SetGraphicsRootDescriptorTable(rootParameterIndex, baseDescriptor);
572 fCurrentGraphicsRootDescTable[rootParameterIndex] = baseDescriptor;
573 }
574 }
575
setComputeRootDescriptorTable(unsigned int rootParameterIndex,D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor)576 void GrD3DDirectCommandList::setComputeRootDescriptorTable(
577 unsigned int rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor) {
578 SkASSERT(rootParameterIndex ==
579 (unsigned int)GrD3DRootSignature::ParamIndex::kSamplerDescriptorTable ||
580 rootParameterIndex ==
581 (unsigned int)GrD3DRootSignature::ParamIndex::kShaderViewDescriptorTable);
582 if (fCurrentComputeRootDescTable[rootParameterIndex].ptr != baseDescriptor.ptr) {
583 fCommandList->SetComputeRootDescriptorTable(rootParameterIndex, baseDescriptor);
584 fCurrentComputeRootDescTable[rootParameterIndex] = baseDescriptor;
585 }
586 }
587
setDescriptorHeaps(sk_sp<GrRecycledResource> srvCrvHeapResource,ID3D12DescriptorHeap * srvCrvDescriptorHeap,sk_sp<GrRecycledResource> samplerHeapResource,ID3D12DescriptorHeap * samplerDescriptorHeap)588 void GrD3DDirectCommandList::setDescriptorHeaps(sk_sp<GrRecycledResource> srvCrvHeapResource,
589 ID3D12DescriptorHeap* srvCrvDescriptorHeap,
590 sk_sp<GrRecycledResource> samplerHeapResource,
591 ID3D12DescriptorHeap* samplerDescriptorHeap) {
592 if (srvCrvDescriptorHeap != fCurrentSRVCRVDescriptorHeap ||
593 samplerDescriptorHeap != fCurrentSamplerDescriptorHeap) {
594 ID3D12DescriptorHeap* heaps[2] = {
595 srvCrvDescriptorHeap,
596 samplerDescriptorHeap
597 };
598
599 fCommandList->SetDescriptorHeaps(2, heaps);
600 this->addRecycledResource(std::move(srvCrvHeapResource));
601 this->addRecycledResource(std::move(samplerHeapResource));
602 fCurrentSRVCRVDescriptorHeap = srvCrvDescriptorHeap;
603 fCurrentSamplerDescriptorHeap = samplerDescriptorHeap;
604 }
605 }
606
addSampledTextureRef(GrD3DTexture * texture)607 void GrD3DDirectCommandList::addSampledTextureRef(GrD3DTexture* texture) {
608 this->addResource(texture->resource());
609 }
610
611 ////////////////////////////////////////////////////////////////////////////////////////////////////
612
Make(ID3D12Device * device)613 std::unique_ptr<GrD3DCopyCommandList> GrD3DCopyCommandList::Make(ID3D12Device* device) {
614 gr_cp<ID3D12CommandAllocator> allocator;
615 GR_D3D_CALL_ERRCHECK(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
616 IID_PPV_ARGS(&allocator)));
617
618 gr_cp<ID3D12GraphicsCommandList> commandList;
619 GR_D3D_CALL_ERRCHECK(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COPY, allocator.get(),
620 nullptr, IID_PPV_ARGS(&commandList)));
621 auto grCL = new GrD3DCopyCommandList(std::move(allocator), std::move(commandList));
622 return std::unique_ptr<GrD3DCopyCommandList>(grCL);
623 }
624
GrD3DCopyCommandList(gr_cp<ID3D12CommandAllocator> allocator,gr_cp<ID3D12GraphicsCommandList> commandList)625 GrD3DCopyCommandList::GrD3DCopyCommandList(gr_cp<ID3D12CommandAllocator> allocator,
626 gr_cp<ID3D12GraphicsCommandList> commandList)
627 : GrD3DCommandList(std::move(allocator), std::move(commandList)) {
628 }
629