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/core/SkTraceEvent.h"
11 #include "src/gpu/GrScissorState.h"
12 #include "src/gpu/d3d/GrD3DAttachment.h"
13 #include "src/gpu/d3d/GrD3DBuffer.h"
14 #include "src/gpu/d3d/GrD3DCommandSignature.h"
15 #include "src/gpu/d3d/GrD3DGpu.h"
16 #include "src/gpu/d3d/GrD3DPipeline.h"
17 #include "src/gpu/d3d/GrD3DRenderTarget.h"
18 #include "src/gpu/d3d/GrD3DTexture.h"
19 #include "src/gpu/d3d/GrD3DTextureResource.h"
20 #include "src/gpu/d3d/GrD3DUtil.h"
21
GrD3DCommandList(gr_cp<ID3D12CommandAllocator> allocator,gr_cp<ID3D12GraphicsCommandList> commandList)22 GrD3DCommandList::GrD3DCommandList(gr_cp<ID3D12CommandAllocator> allocator,
23 gr_cp<ID3D12GraphicsCommandList> commandList)
24 : fCommandList(std::move(commandList))
25 , fAllocator(std::move(allocator)) {
26 }
27
close()28 bool GrD3DCommandList::close() {
29 SkASSERT(fIsActive);
30 this->submitResourceBarriers();
31 HRESULT hr = fCommandList->Close();
32 SkDEBUGCODE(fIsActive = false;)
33 return SUCCEEDED(hr);
34 }
35
submit(ID3D12CommandQueue * queue)36 GrD3DCommandList::SubmitResult GrD3DCommandList::submit(ID3D12CommandQueue* queue) {
37 SkASSERT(fIsActive);
38 if (!this->hasWork()) {
39 this->callFinishedCallbacks();
40 return SubmitResult::kNoWork;
41 }
42
43 if (!this->close()) {
44 return SubmitResult::kFailure;
45 }
46 SkASSERT(!fIsActive);
47 ID3D12CommandList* ppCommandLists[] = { fCommandList.get() };
48 queue->ExecuteCommandLists(1, ppCommandLists);
49
50 return SubmitResult::kSuccess;
51 }
52
reset()53 void GrD3DCommandList::reset() {
54 SkASSERT(!fIsActive);
55 GR_D3D_CALL_ERRCHECK(fAllocator->Reset());
56 GR_D3D_CALL_ERRCHECK(fCommandList->Reset(fAllocator.get(), nullptr));
57 this->onReset();
58
59 this->releaseResources();
60
61 SkDEBUGCODE(fIsActive = true;)
62 fHasWork = false;
63 }
64
releaseResources()65 void GrD3DCommandList::releaseResources() {
66 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
67 if (fTrackedResources.count() == 0 && fTrackedRecycledResources.count() == 0) {
68 return;
69 }
70 SkASSERT(!fIsActive);
71 for (int i = 0; i < fTrackedRecycledResources.count(); ++i) {
72 auto resource = fTrackedRecycledResources[i].release();
73 resource->recycle();
74 }
75
76 fTrackedResources.reset();
77 fTrackedRecycledResources.reset();
78 fTrackedGpuBuffers.reset();
79
80 this->callFinishedCallbacks();
81 }
82
addFinishedCallback(sk_sp<GrRefCntedCallback> callback)83 void GrD3DCommandList::addFinishedCallback(sk_sp<GrRefCntedCallback> callback) {
84 fFinishedCallbacks.push_back(std::move(callback));
85 }
86
87 ////////////////////////////////////////////////////////////////////////////////
88 // GraphicsCommandList commands
89 ////////////////////////////////////////////////////////////////////////////////
90
resourceBarrier(sk_sp<GrManagedResource> resource,int numBarriers,const D3D12_RESOURCE_TRANSITION_BARRIER * barriers)91 void GrD3DCommandList::resourceBarrier(sk_sp<GrManagedResource> resource,
92 int numBarriers,
93 const D3D12_RESOURCE_TRANSITION_BARRIER* barriers) {
94 SkASSERT(fIsActive);
95 SkASSERT(barriers);
96 for (int i = 0; i < numBarriers; ++i) {
97 // D3D will apply barriers in order so we can just add onto the end
98 D3D12_RESOURCE_BARRIER& newBarrier = fResourceBarriers.push_back();
99 newBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
100 newBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
101 newBarrier.Transition = barriers[i];
102 }
103
104 fHasWork = true;
105 if (resource) {
106 this->addResource(std::move(resource));
107 }
108 }
109
uavBarrier(sk_sp<GrManagedResource> resource,ID3D12Resource * uavResource)110 void GrD3DCommandList::uavBarrier(sk_sp<GrManagedResource> resource,
111 ID3D12Resource* uavResource) {
112 SkASSERT(fIsActive);
113 // D3D will apply barriers in order so we can just add onto the end
114 D3D12_RESOURCE_BARRIER& newBarrier = fResourceBarriers.push_back();
115 newBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
116 newBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
117 newBarrier.UAV.pResource = uavResource;
118
119 fHasWork = true;
120 if (resource) {
121 this->addResource(std::move(resource));
122 }
123 }
124
aliasingBarrier(sk_sp<GrManagedResource> beforeManagedResource,ID3D12Resource * beforeResource,sk_sp<GrManagedResource> afterManagedResource,ID3D12Resource * afterResource)125 void GrD3DCommandList::aliasingBarrier(sk_sp<GrManagedResource> beforeManagedResource,
126 ID3D12Resource* beforeResource,
127 sk_sp<GrManagedResource> afterManagedResource,
128 ID3D12Resource* afterResource) {
129 SkASSERT(fIsActive);
130 // D3D will apply barriers in order so we can just add onto the end
131 D3D12_RESOURCE_BARRIER& newBarrier = fResourceBarriers.push_back();
132 newBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;
133 newBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
134 newBarrier.Aliasing.pResourceBefore = beforeResource;
135 newBarrier.Aliasing.pResourceAfter = afterResource;
136
137 fHasWork = true;
138 if (beforeResource) {
139 SkASSERT(beforeManagedResource);
140 this->addResource(std::move(beforeManagedResource));
141 }
142 // Aliasing barriers can accept a null pointer for the second resource,
143 // but at this point we're not using that feature.
144 SkASSERT(afterResource);
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(GrD3DGpu * gpu)270 std::unique_ptr<GrD3DDirectCommandList> GrD3DDirectCommandList::Make(GrD3DGpu* gpu) {
271 ID3D12Device* device = gpu->device();
272 gr_cp<ID3D12CommandAllocator> allocator;
273 GR_D3D_CALL_ERRCHECK(device->CreateCommandAllocator(
274 D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&allocator)));
275
276 gr_cp<ID3D12GraphicsCommandList> commandList;
277 GR_D3D_CALL_ERRCHECK(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
278 allocator.get(), nullptr,
279 IID_PPV_ARGS(&commandList)));
280
281 auto grCL = new GrD3DDirectCommandList(std::move(allocator), std::move(commandList),
282 gpu->d3dCaps().resolveSubresourceRegionSupport());
283 return std::unique_ptr<GrD3DDirectCommandList>(grCL);
284 }
285
GrD3DDirectCommandList(gr_cp<ID3D12CommandAllocator> allocator,gr_cp<ID3D12GraphicsCommandList> commandList,bool resolveSubregionSupported)286 GrD3DDirectCommandList::GrD3DDirectCommandList(gr_cp<ID3D12CommandAllocator> allocator,
287 gr_cp<ID3D12GraphicsCommandList> commandList,
288 bool resolveSubregionSupported)
289 : GrD3DCommandList(std::move(allocator), std::move(commandList))
290 , fResolveSubregionSupported(resolveSubregionSupported) {
291 sk_bzero(fCurrentGraphicsRootDescTable, sizeof(fCurrentGraphicsRootDescTable));
292 sk_bzero(fCurrentComputeRootDescTable, sizeof(fCurrentComputeRootDescTable));
293 }
294
onReset()295 void GrD3DDirectCommandList::onReset() {
296 fCurrentPipeline = nullptr;
297 fCurrentGraphicsRootSignature = nullptr;
298 fCurrentComputeRootSignature = nullptr;
299 fCurrentVertexBuffer = nullptr;
300 fCurrentVertexStride = 0;
301 fCurrentInstanceBuffer = nullptr;
302 fCurrentInstanceStride = 0;
303 fCurrentIndexBuffer = nullptr;
304 fCurrentGraphicsConstantBufferAddress = 0;
305 fCurrentComputeConstantBufferAddress = 0;
306 sk_bzero(fCurrentGraphicsRootDescTable, sizeof(fCurrentGraphicsRootDescTable));
307 sk_bzero(fCurrentComputeRootDescTable, sizeof(fCurrentComputeRootDescTable));
308 fCurrentSRVCRVDescriptorHeap = nullptr;
309 fCurrentSamplerDescriptorHeap = nullptr;
310 }
311
setPipelineState(const sk_sp<GrD3DPipeline> & pipeline)312 void GrD3DDirectCommandList::setPipelineState(const sk_sp<GrD3DPipeline>& pipeline) {
313 SkASSERT(fIsActive);
314 if (pipeline.get() != fCurrentPipeline) {
315 fCommandList->SetPipelineState(pipeline->d3dPipelineState());
316 this->addResource(std::move(pipeline));
317 fCurrentPipeline = pipeline.get();
318 }
319 }
320
setStencilRef(unsigned int stencilRef)321 void GrD3DDirectCommandList::setStencilRef(unsigned int stencilRef) {
322 SkASSERT(fIsActive);
323 fCommandList->OMSetStencilRef(stencilRef);
324 }
325
setBlendFactor(const float blendFactor[4])326 void GrD3DDirectCommandList::setBlendFactor(const float blendFactor[4]) {
327 SkASSERT(fIsActive);
328 fCommandList->OMSetBlendFactor(blendFactor);
329 }
330
setPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY primitiveTopology)331 void GrD3DDirectCommandList::setPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY primitiveTopology) {
332 SkASSERT(fIsActive);
333 fCommandList->IASetPrimitiveTopology(primitiveTopology);
334 }
335
setScissorRects(unsigned int numRects,const D3D12_RECT * rects)336 void GrD3DDirectCommandList::setScissorRects(unsigned int numRects, const D3D12_RECT* rects) {
337 SkASSERT(fIsActive);
338 fCommandList->RSSetScissorRects(numRects, rects);
339 }
340
setViewports(unsigned int numViewports,const D3D12_VIEWPORT * viewports)341 void GrD3DDirectCommandList::setViewports(unsigned int numViewports,
342 const D3D12_VIEWPORT* viewports) {
343 SkASSERT(fIsActive);
344 fCommandList->RSSetViewports(numViewports, viewports);
345 }
346
setGraphicsRootSignature(const sk_sp<GrD3DRootSignature> & rootSig)347 void GrD3DDirectCommandList::setGraphicsRootSignature(const sk_sp<GrD3DRootSignature>& rootSig) {
348 SkASSERT(fIsActive);
349 if (fCurrentGraphicsRootSignature != rootSig.get()) {
350 fCommandList->SetGraphicsRootSignature(rootSig->rootSignature());
351 this->addResource(rootSig);
352 fCurrentGraphicsRootSignature = rootSig.get();
353 // need to reset the current descriptor tables as well
354 sk_bzero(fCurrentGraphicsRootDescTable, sizeof(fCurrentGraphicsRootDescTable));
355 }
356 }
357
setComputeRootSignature(const sk_sp<GrD3DRootSignature> & rootSig)358 void GrD3DDirectCommandList::setComputeRootSignature(const sk_sp<GrD3DRootSignature>& rootSig) {
359 SkASSERT(fIsActive);
360 if (fCurrentComputeRootSignature != rootSig.get()) {
361 fCommandList->SetComputeRootSignature(rootSig->rootSignature());
362 this->addResource(rootSig);
363 fCurrentComputeRootSignature = rootSig.get();
364 // need to reset the current descriptor tables as well
365 sk_bzero(fCurrentComputeRootDescTable, sizeof(fCurrentComputeRootDescTable));
366 }
367 }
368
setVertexBuffers(unsigned int startSlot,sk_sp<const GrBuffer> vertexBuffer,size_t vertexStride,sk_sp<const GrBuffer> instanceBuffer,size_t instanceStride)369 void GrD3DDirectCommandList::setVertexBuffers(unsigned int startSlot,
370 sk_sp<const GrBuffer> vertexBuffer,
371 size_t vertexStride,
372 sk_sp<const GrBuffer> instanceBuffer,
373 size_t instanceStride) {
374 if (fCurrentVertexBuffer != vertexBuffer.get() ||
375 fCurrentVertexStride != vertexStride ||
376 fCurrentInstanceBuffer != instanceBuffer.get() ||
377 fCurrentInstanceStride != instanceStride) {
378
379 fCurrentVertexBuffer = vertexBuffer.get();
380 fCurrentVertexStride = vertexStride;
381 fCurrentInstanceBuffer = instanceBuffer.get();
382 fCurrentInstanceStride = instanceStride;
383
384 D3D12_VERTEX_BUFFER_VIEW views[2];
385 int numViews = 0;
386 if (vertexBuffer) {
387 auto* d3dBuffer = static_cast<const GrD3DBuffer*>(vertexBuffer.get());
388 views[numViews].BufferLocation = d3dBuffer->d3dResource()->GetGPUVirtualAddress();
389 views[numViews].SizeInBytes = vertexBuffer->size();
390 views[numViews++].StrideInBytes = vertexStride;
391 this->addGrBuffer(std::move(vertexBuffer));
392 }
393 if (instanceBuffer) {
394 auto* d3dBuffer = static_cast<const GrD3DBuffer*>(instanceBuffer.get());
395 views[numViews].BufferLocation = d3dBuffer->d3dResource()->GetGPUVirtualAddress();
396 views[numViews].SizeInBytes = instanceBuffer->size();
397 views[numViews++].StrideInBytes = instanceStride;
398 this->addGrBuffer(std::move(instanceBuffer));
399 }
400 fCommandList->IASetVertexBuffers(startSlot, numViews, views);
401 }
402 }
403
setIndexBuffer(sk_sp<const GrBuffer> indexBuffer)404 void GrD3DDirectCommandList::setIndexBuffer(sk_sp<const GrBuffer> indexBuffer) {
405 if (fCurrentIndexBuffer != indexBuffer.get()) {
406 auto* d3dBuffer = static_cast<const GrD3DBuffer*>(indexBuffer.get());
407
408 D3D12_INDEX_BUFFER_VIEW view = {};
409 view.BufferLocation = d3dBuffer->d3dResource()->GetGPUVirtualAddress();
410 view.SizeInBytes = indexBuffer->size();
411 view.Format = DXGI_FORMAT_R16_UINT;
412 fCommandList->IASetIndexBuffer(&view);
413
414 fCurrentIndexBuffer = indexBuffer.get();
415 this->addGrBuffer(std::move(indexBuffer));
416 }
417 }
418
drawInstanced(unsigned int vertexCount,unsigned int instanceCount,unsigned int startVertex,unsigned int startInstance)419 void GrD3DDirectCommandList::drawInstanced(unsigned int vertexCount, unsigned int instanceCount,
420 unsigned int startVertex, unsigned int startInstance) {
421 SkASSERT(fIsActive);
422 this->addingWork();
423 fCommandList->DrawInstanced(vertexCount, instanceCount, startVertex, startInstance);
424 }
425
drawIndexedInstanced(unsigned int indexCount,unsigned int instanceCount,unsigned int startIndex,unsigned int baseVertex,unsigned int startInstance)426 void GrD3DDirectCommandList::drawIndexedInstanced(unsigned int indexCount,
427 unsigned int instanceCount,
428 unsigned int startIndex,
429 unsigned int baseVertex,
430 unsigned int startInstance) {
431 SkASSERT(fIsActive);
432 this->addingWork();
433 fCommandList->DrawIndexedInstanced(indexCount, instanceCount, startIndex, baseVertex,
434 startInstance);
435 }
436
executeIndirect(const sk_sp<GrD3DCommandSignature> commandSignature,unsigned int maxCommandCount,const GrD3DBuffer * argumentBuffer,size_t argumentBufferOffset)437 void GrD3DDirectCommandList::executeIndirect(const sk_sp<GrD3DCommandSignature> commandSignature,
438 unsigned int maxCommandCount,
439 const GrD3DBuffer* argumentBuffer,
440 size_t argumentBufferOffset) {
441 SkASSERT(fIsActive);
442 this->addingWork();
443 this->addResource(commandSignature);
444 fCommandList->ExecuteIndirect(commandSignature->commandSignature(), maxCommandCount,
445 argumentBuffer->d3dResource(), argumentBufferOffset,
446 nullptr, 0);
447 this->addGrBuffer(sk_ref_sp<const GrBuffer>(argumentBuffer));
448 }
449
450
dispatch(unsigned int threadGroupCountX,unsigned int threadGroupCountY,unsigned int threadGroupCountZ)451 void GrD3DDirectCommandList::dispatch(unsigned int threadGroupCountX,
452 unsigned int threadGroupCountY,
453 unsigned int threadGroupCountZ) {
454 SkASSERT(fIsActive);
455 this->addingWork();
456 fCommandList->Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ);
457 }
458
clearRenderTargetView(const GrD3DRenderTarget * renderTarget,std::array<float,4> color,const D3D12_RECT * rect)459 void GrD3DDirectCommandList::clearRenderTargetView(const GrD3DRenderTarget* renderTarget,
460 std::array<float, 4> color,
461 const D3D12_RECT* rect) {
462 this->addingWork();
463 this->addResource(renderTarget->resource());
464 const GrD3DTextureResource* msaaTextureResource = renderTarget->msaaTextureResource();
465 if (msaaTextureResource && msaaTextureResource != renderTarget) {
466 this->addResource(msaaTextureResource->resource());
467 }
468 unsigned int numRects = rect ? 1 : 0;
469 fCommandList->ClearRenderTargetView(renderTarget->colorRenderTargetView(), color.data(),
470 numRects, rect);
471 }
472
clearDepthStencilView(const GrD3DAttachment * stencil,uint8_t stencilClearValue,const D3D12_RECT * rect)473 void GrD3DDirectCommandList::clearDepthStencilView(const GrD3DAttachment* stencil,
474 uint8_t stencilClearValue,
475 const D3D12_RECT* rect) {
476 this->addingWork();
477 this->addResource(stencil->resource());
478 unsigned int numRects = rect ? 1 : 0;
479 fCommandList->ClearDepthStencilView(stencil->view(), D3D12_CLEAR_FLAG_STENCIL, 0,
480 stencilClearValue, numRects, rect);
481 }
482
setRenderTarget(const GrD3DRenderTarget * renderTarget)483 void GrD3DDirectCommandList::setRenderTarget(const GrD3DRenderTarget* renderTarget) {
484 this->addingWork();
485 this->addResource(renderTarget->resource());
486 const GrD3DTextureResource* msaaTextureResource = renderTarget->msaaTextureResource();
487 if (msaaTextureResource && msaaTextureResource != renderTarget) {
488 this->addResource(msaaTextureResource->resource());
489 }
490 D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = renderTarget->colorRenderTargetView();
491
492 D3D12_CPU_DESCRIPTOR_HANDLE dsDescriptor;
493 D3D12_CPU_DESCRIPTOR_HANDLE* dsDescriptorPtr = nullptr;
494 if (auto stencil = renderTarget->getStencilAttachment()) {
495 GrD3DAttachment* d3dStencil = static_cast<GrD3DAttachment*>(stencil);
496 this->addResource(d3dStencil->resource());
497 dsDescriptor = d3dStencil->view();
498 dsDescriptorPtr = &dsDescriptor;
499 }
500
501 fCommandList->OMSetRenderTargets(1, &rtvDescriptor, false, dsDescriptorPtr);
502 }
503
resolveSubresourceRegion(const GrD3DTextureResource * dstTexture,unsigned int dstX,unsigned int dstY,const GrD3DTextureResource * srcTexture,D3D12_RECT * srcRect)504 void GrD3DDirectCommandList::resolveSubresourceRegion(const GrD3DTextureResource* dstTexture,
505 unsigned int dstX, unsigned int dstY,
506 const GrD3DTextureResource* srcTexture,
507 D3D12_RECT* srcRect) {
508 SkASSERT(dstTexture->dxgiFormat() == srcTexture->dxgiFormat());
509 SkASSERT(dstTexture->currentState() == D3D12_RESOURCE_STATE_RESOLVE_DEST);
510 SkASSERT(srcTexture->currentState() == D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
511 this->addingWork();
512 this->addResource(dstTexture->resource());
513 this->addResource(srcTexture->resource());
514
515 if (fResolveSubregionSupported) {
516 gr_cp<ID3D12GraphicsCommandList1> commandList1;
517 HRESULT result = fCommandList->QueryInterface(IID_PPV_ARGS(&commandList1));
518 if (SUCCEEDED(result)) {
519 commandList1->ResolveSubresourceRegion(dstTexture->d3dResource(), 0, dstX, dstY,
520 srcTexture->d3dResource(), 0, srcRect,
521 srcTexture->dxgiFormat(),
522 D3D12_RESOLVE_MODE_AVERAGE);
523 return;
524 }
525 }
526
527 fCommandList->ResolveSubresource(dstTexture->d3dResource(), 0, srcTexture->d3dResource(), 0,
528 srcTexture->dxgiFormat());
529 }
530
setGraphicsRootConstantBufferView(unsigned int rootParameterIndex,D3D12_GPU_VIRTUAL_ADDRESS bufferLocation)531 void GrD3DDirectCommandList::setGraphicsRootConstantBufferView(
532 unsigned int rootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS bufferLocation) {
533 SkASSERT(rootParameterIndex ==
534 (unsigned int) GrD3DRootSignature::ParamIndex::kConstantBufferView);
535 if (bufferLocation != fCurrentGraphicsConstantBufferAddress) {
536 fCommandList->SetGraphicsRootConstantBufferView(rootParameterIndex, bufferLocation);
537 fCurrentGraphicsConstantBufferAddress = bufferLocation;
538 }
539 }
540
setComputeRootConstantBufferView(unsigned int rootParameterIndex,D3D12_GPU_VIRTUAL_ADDRESS bufferLocation)541 void GrD3DDirectCommandList::setComputeRootConstantBufferView(
542 unsigned int rootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS bufferLocation) {
543 SkASSERT(rootParameterIndex ==
544 (unsigned int)GrD3DRootSignature::ParamIndex::kConstantBufferView);
545 if (bufferLocation != fCurrentComputeConstantBufferAddress) {
546 fCommandList->SetComputeRootConstantBufferView(rootParameterIndex, bufferLocation);
547 fCurrentComputeConstantBufferAddress = bufferLocation;
548 }
549 }
550
setGraphicsRootDescriptorTable(unsigned int rootParameterIndex,D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor)551 void GrD3DDirectCommandList::setGraphicsRootDescriptorTable(
552 unsigned int rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor) {
553 SkASSERT(rootParameterIndex ==
554 (unsigned int)GrD3DRootSignature::ParamIndex::kSamplerDescriptorTable ||
555 rootParameterIndex ==
556 (unsigned int)GrD3DRootSignature::ParamIndex::kShaderViewDescriptorTable);
557 if (fCurrentGraphicsRootDescTable[rootParameterIndex].ptr != baseDescriptor.ptr) {
558 fCommandList->SetGraphicsRootDescriptorTable(rootParameterIndex, baseDescriptor);
559 fCurrentGraphicsRootDescTable[rootParameterIndex] = baseDescriptor;
560 }
561 }
562
setComputeRootDescriptorTable(unsigned int rootParameterIndex,D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor)563 void GrD3DDirectCommandList::setComputeRootDescriptorTable(
564 unsigned int rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor) {
565 SkASSERT(rootParameterIndex ==
566 (unsigned int)GrD3DRootSignature::ParamIndex::kSamplerDescriptorTable ||
567 rootParameterIndex ==
568 (unsigned int)GrD3DRootSignature::ParamIndex::kShaderViewDescriptorTable);
569 if (fCurrentComputeRootDescTable[rootParameterIndex].ptr != baseDescriptor.ptr) {
570 fCommandList->SetComputeRootDescriptorTable(rootParameterIndex, baseDescriptor);
571 fCurrentComputeRootDescTable[rootParameterIndex] = baseDescriptor;
572 }
573 }
574
575 // We don't need to add these resources to the command list.
576 // They're added when we first allocate from a heap in a given submit.
setDescriptorHeaps(ID3D12DescriptorHeap * srvCrvDescriptorHeap,ID3D12DescriptorHeap * samplerDescriptorHeap)577 void GrD3DDirectCommandList::setDescriptorHeaps(ID3D12DescriptorHeap* srvCrvDescriptorHeap,
578 ID3D12DescriptorHeap* samplerDescriptorHeap) {
579 if (srvCrvDescriptorHeap != fCurrentSRVCRVDescriptorHeap ||
580 samplerDescriptorHeap != fCurrentSamplerDescriptorHeap) {
581 ID3D12DescriptorHeap* heaps[2] = {
582 srvCrvDescriptorHeap,
583 samplerDescriptorHeap
584 };
585
586 fCommandList->SetDescriptorHeaps(2, heaps);
587 fCurrentSRVCRVDescriptorHeap = srvCrvDescriptorHeap;
588 fCurrentSamplerDescriptorHeap = samplerDescriptorHeap;
589 }
590 }
591
addSampledTextureRef(GrD3DTexture * texture)592 void GrD3DDirectCommandList::addSampledTextureRef(GrD3DTexture* texture) {
593 this->addResource(texture->resource());
594 }
595
596 ////////////////////////////////////////////////////////////////////////////////////////////////////
597
Make(GrD3DGpu * gpu)598 std::unique_ptr<GrD3DCopyCommandList> GrD3DCopyCommandList::Make(GrD3DGpu* gpu) {
599 ID3D12Device* device = gpu->device();
600 gr_cp<ID3D12CommandAllocator> allocator;
601 GR_D3D_CALL_ERRCHECK(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
602 IID_PPV_ARGS(&allocator)));
603
604 gr_cp<ID3D12GraphicsCommandList> commandList;
605 GR_D3D_CALL_ERRCHECK(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COPY, allocator.get(),
606 nullptr, IID_PPV_ARGS(&commandList)));
607 auto grCL = new GrD3DCopyCommandList(std::move(allocator), std::move(commandList));
608 return std::unique_ptr<GrD3DCopyCommandList>(grCL);
609 }
610
GrD3DCopyCommandList(gr_cp<ID3D12CommandAllocator> allocator,gr_cp<ID3D12GraphicsCommandList> commandList)611 GrD3DCopyCommandList::GrD3DCopyCommandList(gr_cp<ID3D12CommandAllocator> allocator,
612 gr_cp<ID3D12GraphicsCommandList> commandList)
613 : GrD3DCommandList(std::move(allocator), std::move(commandList)) {
614 }
615