Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
GrD3DGpu.cpp
Go to the documentation of this file.
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
9
16#include "src/core/SkMipmap.h"
34
35#if defined(GR_TEST_UTILS)
36#include <DXProgrammableCapture.h>
37#endif
38
39using namespace skia_private;
40
44
48
49
50std::unique_ptr<GrGpu> GrD3DGpu::Make(const GrD3DBackendContext& backendContext,
51 const GrContextOptions& contextOptions,
52 GrDirectContext* direct) {
54 if (!memoryAllocator) {
55 // We were not given a memory allocator at creation
57 backendContext.fAdapter.get(), backendContext.fDevice.get());
58 }
59 if (!memoryAllocator) {
60 SkDEBUGFAIL("No supplied Direct3D memory allocator and unable to create one internally.");
61 return nullptr;
62 }
63
64 return std::unique_ptr<GrGpu>(new GrD3DGpu(direct,
65 contextOptions,
66 backendContext,
68}
69
70// This constant determines how many OutstandingCommandLists are allocated together as a block in
71// the deque. As such it needs to balance allocating too much memory vs. incurring
72// allocation/deallocation thrashing. It should roughly correspond to the max number of outstanding
73// command lists we expect to see.
74static const int kDefaultOutstandingAllocCnt = 8;
75
76// constants have to be aligned to 256
77constexpr int kConstantAlignment = 256;
78
79GrD3DGpu::GrD3DGpu(GrDirectContext* direct, const GrContextOptions& contextOptions,
80 const GrD3DBackendContext& backendContext,
82 : INHERITED(direct)
83 , fDevice(backendContext.fDevice)
84 , fQueue(backendContext.fQueue)
85 , fMemoryAllocator(std::move(allocator))
86 , fResourceProvider(this)
87 , fStagingBufferManager(this)
88 , fConstantsRingBuffer(this, 128 * 1024, kConstantAlignment, GrGpuBufferType::kVertex)
89 , fOutstandingCommandLists(sizeof(OutstandingCommandList), kDefaultOutstandingAllocCnt) {
90 this->initCaps(sk_make_sp<GrD3DCaps>(contextOptions,
91 backendContext.fAdapter.get(),
92 backendContext.fDevice.get()));
93
94 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
95 SkASSERT(fCurrentDirectCommandList);
96
97 SkASSERT(fCurrentFenceValue == 0);
98 GR_D3D_CALL_ERRCHECK(fDevice->CreateFence(fCurrentFenceValue, D3D12_FENCE_FLAG_NONE,
99 IID_PPV_ARGS(&fFence)));
100
101#if defined(GR_TEST_UTILS)
102 HRESULT getAnalysis = DXGIGetDebugInterface1(0, IID_PPV_ARGS(&fGraphicsAnalysis));
103 if (FAILED(getAnalysis)) {
104 fGraphicsAnalysis = nullptr;
105 }
106#endif
107}
108
110 this->destroyResources();
111}
112
113void GrD3DGpu::destroyResources() {
114 if (fCurrentDirectCommandList) {
115 fCurrentDirectCommandList->close();
116 fCurrentDirectCommandList->reset();
117 }
118
119 // We need to make sure everything has finished on the queue.
120 this->waitForQueueCompletion();
121
122 SkDEBUGCODE(uint64_t fenceValue = fFence->GetCompletedValue();)
123
124 // We used a placement new for each object in fOutstandingCommandLists, so we're responsible
125 // for calling the destructor on each of them as well.
126 while (!fOutstandingCommandLists.empty()) {
127 OutstandingCommandList* list = (OutstandingCommandList*)fOutstandingCommandLists.front();
128 SkASSERT(list->fFenceValue <= fenceValue);
129 // No reason to recycle the command lists since we are destroying all resources anyways.
130 list->~OutstandingCommandList();
131 fOutstandingCommandLists.pop_front();
132 }
133
134 fStagingBufferManager.reset();
135
136 fResourceProvider.destroyResources();
137}
138
140 GrRenderTarget* rt,
141 bool /*useMSAASurface*/,
143 GrSurfaceOrigin origin,
144 const SkIRect& bounds,
145 const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
147 const TArray<GrSurfaceProxy*, true>& sampledProxies,
148 GrXferBarrierFlags renderPassXferBarriers) {
149 if (!fCachedOpsRenderPass) {
150 fCachedOpsRenderPass.reset(new GrD3DOpsRenderPass(this));
151 }
152
153 if (!fCachedOpsRenderPass->set(rt, origin, bounds, colorInfo, stencilInfo, sampledProxies)) {
154 return nullptr;
155 }
156 return fCachedOpsRenderPass.get();
157}
158
159bool GrD3DGpu::submitDirectCommandList(SyncQueue sync) {
160 SkASSERT(fCurrentDirectCommandList);
161
162 fResourceProvider.prepForSubmit();
163 for (int i = 0; i < fMipmapCPUDescriptors.size(); ++i) {
164 fResourceProvider.recycleShaderView(fMipmapCPUDescriptors[i]);
165 }
166 fMipmapCPUDescriptors.clear();
167
168 GrD3DDirectCommandList::SubmitResult sResult = fCurrentDirectCommandList->submit(fQueue.get());
170 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
171 return false;
172 } else if (sResult == GrD3DDirectCommandList::SubmitResult::kNoWork) {
173 if (sync == SyncQueue::kForce) {
174 this->waitForQueueCompletion();
175 this->checkForFinishedCommandLists();
176 }
177 return true;
178 }
179
180 // We just submitted the command list so make sure all GrD3DPipelineState's mark their cached
181 // uniform data as dirty.
182 fResourceProvider.markPipelineStateUniformsDirty();
183
184 GR_D3D_CALL_ERRCHECK(fQueue->Signal(fFence.get(), ++fCurrentFenceValue));
185 new (fOutstandingCommandLists.push_back()) OutstandingCommandList(
186 std::move(fCurrentDirectCommandList), fCurrentFenceValue);
187
188 if (sync == SyncQueue::kForce) {
189 this->waitForQueueCompletion();
190 }
191
192 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
193
194 // This should be done after we have a new command list in case the freeing of any resources
195 // held by a finished command list causes us send a new command to the gpu (like changing the
196 // resource state.
197 this->checkForFinishedCommandLists();
198
199 SkASSERT(fCurrentDirectCommandList);
200 return true;
201}
202
203void GrD3DGpu::checkForFinishedCommandLists() {
204 uint64_t currentFenceValue = fFence->GetCompletedValue();
205
206 // Iterate over all the outstanding command lists to see if any have finished. The commands
207 // lists are in order from oldest to newest, so we start at the front to check if their fence
208 // value is less than the last signaled value. If so we pop it off and move onto the next.
209 // Repeat till we find a command list that has not finished yet (and all others afterwards are
210 // also guaranteed to not have finished).
211 OutstandingCommandList* front = (OutstandingCommandList*)fOutstandingCommandLists.front();
212 while (front && front->fFenceValue <= currentFenceValue) {
213 std::unique_ptr<GrD3DDirectCommandList> currList(std::move(front->fCommandList));
214 // Since we used placement new we are responsible for calling the destructor manually.
215 front->~OutstandingCommandList();
216 fOutstandingCommandLists.pop_front();
217 fResourceProvider.recycleDirectCommandList(std::move(currList));
218 front = (OutstandingCommandList*)fOutstandingCommandLists.front();
219 }
220}
221
222void GrD3DGpu::waitForQueueCompletion() {
223 if (fFence->GetCompletedValue() < fCurrentFenceValue) {
224 HANDLE fenceEvent;
225 fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
226 SkASSERT(fenceEvent);
227 GR_D3D_CALL_ERRCHECK(fFence->SetEventOnCompletion(fCurrentFenceValue, fenceEvent));
228 WaitForSingleObject(fenceEvent, INFINITE);
229 CloseHandle(fenceEvent);
230 }
231}
232
234 SkASSERT(fCachedOpsRenderPass.get() == renderPass);
235
236 fCachedOpsRenderPass->submit();
237 fCachedOpsRenderPass.reset();
238}
239
241 const SkIRect& bounds) {
242 this->didWriteToSurface(target, origin, &bounds);
243}
244
246 GrGpuFinishedContext finishedContext) {
247 SkASSERT(finishedProc);
248 this->addFinishedCallback(skgpu::RefCntedCallback::Make(finishedProc, finishedContext));
249}
250
251void GrD3DGpu::addFinishedCallback(sk_sp<skgpu::RefCntedCallback> finishedCallback) {
252 SkASSERT(finishedCallback);
253 // Besides the current command list, we also add the finishedCallback to the newest outstanding
254 // command list. Our contract for calling the proc is that all previous submitted command lists
255 // have finished when we call it. However, if our current command list has no work when it is
256 // flushed it will drop its ref to the callback immediately. But the previous work may not have
257 // finished. It is safe to only add the proc to the newest outstanding commandlist cause that
258 // must finish after all previously submitted command lists.
259 OutstandingCommandList* back = (OutstandingCommandList*)fOutstandingCommandLists.back();
260 if (back) {
261 back->fCommandList->addFinishedCallback(finishedCallback);
262 }
263 fCurrentDirectCommandList->addFinishedCallback(std::move(finishedCallback));
264}
265
266sk_sp<GrD3DTexture> GrD3DGpu::createD3DTexture(SkISize dimensions,
267 DXGI_FORMAT dxgiFormat,
268 GrRenderable renderable,
269 int renderTargetSampleCnt,
270 skgpu::Budgeted budgeted,
271 GrProtected isProtected,
272 int mipLevelCount,
273 GrMipmapStatus mipmapStatus,
274 std::string_view label) {
275 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
276 if (renderable == GrRenderable::kYes) {
277 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
278 }
279
280 // This desc refers to a texture that will be read by the client. Thus even if msaa is
281 // requested, this describes the resolved texture. Therefore we always have samples set
282 // to 1.
283 SkASSERT(mipLevelCount > 0);
284 D3D12_RESOURCE_DESC resourceDesc = {};
285 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
286 // TODO: will use 4MB alignment for MSAA textures and 64KB for everything else
287 // might want to manually set alignment to 4KB for smaller textures
288 resourceDesc.Alignment = 0;
289 resourceDesc.Width = dimensions.fWidth;
290 resourceDesc.Height = dimensions.fHeight;
291 resourceDesc.DepthOrArraySize = 1;
292 resourceDesc.MipLevels = mipLevelCount;
293 resourceDesc.Format = dxgiFormat;
294 resourceDesc.SampleDesc.Count = 1;
295 resourceDesc.SampleDesc.Quality = DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN;
296 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
297 resourceDesc.Flags = usageFlags;
298
299 if (renderable == GrRenderable::kYes) {
301 this, budgeted, dimensions, renderTargetSampleCnt, resourceDesc, isProtected,
302 mipmapStatus, label);
303 } else {
304 return GrD3DTexture::MakeNewTexture(this, budgeted, dimensions, resourceDesc, isProtected,
305 mipmapStatus, label);
306 }
307}
308
310 const GrBackendFormat& format,
311 GrRenderable renderable,
312 int renderTargetSampleCnt,
313 skgpu::Budgeted budgeted,
314 GrProtected isProtected,
315 int mipLevelCount,
316 uint32_t levelClearMask,
317 std::string_view label) {
318 DXGI_FORMAT dxgiFormat;
319 SkAssertResult(format.asDxgiFormat(&dxgiFormat));
321
322 GrMipmapStatus mipmapStatus = mipLevelCount > 1 ? GrMipmapStatus::kDirty
324
325 sk_sp<GrD3DTexture> tex = this->createD3DTexture(dimensions, dxgiFormat, renderable,
326 renderTargetSampleCnt, budgeted, isProtected,
327 mipLevelCount, mipmapStatus, label);
328 if (!tex) {
329 return nullptr;
330 }
331
332 if (levelClearMask) {
333 // TODO
334 }
335
336 return std::move(tex);
337}
338
339static void copy_compressed_data(char* mapPtr, DXGI_FORMAT dxgiFormat,
340 D3D12_PLACED_SUBRESOURCE_FOOTPRINT* placedFootprints,
341 UINT* numRows, UINT64* rowSizeInBytes,
342 const void* compressedData, int numMipLevels) {
343 SkASSERT(compressedData && numMipLevels);
345 SkASSERT(mapPtr);
346
347 const char* src = static_cast<const char*>(compressedData);
348 for (int currentMipLevel = 0; currentMipLevel < numMipLevels; currentMipLevel++) {
349 // copy data into the buffer, skipping any trailing bytes
350 char* dst = mapPtr + placedFootprints[currentMipLevel].Offset;
351 SkRectMemcpy(dst, placedFootprints[currentMipLevel].Footprint.RowPitch,
352 src, rowSizeInBytes[currentMipLevel], rowSizeInBytes[currentMipLevel],
353 numRows[currentMipLevel]);
354 src += numRows[currentMipLevel] * rowSizeInBytes[currentMipLevel];
355 }
356}
357
359 const GrBackendFormat& format,
360 skgpu::Budgeted budgeted,
361 skgpu::Mipmapped mipmapped,
362 GrProtected isProtected,
363 const void* data,
364 size_t dataSize) {
365 DXGI_FORMAT dxgiFormat;
366 SkAssertResult(format.asDxgiFormat(&dxgiFormat));
368
371 compression, dimensions, mipmapped == skgpu::Mipmapped::kYes));
372
373 int mipLevelCount = 1;
374 if (mipmapped == skgpu::Mipmapped::kYes) {
375 mipLevelCount = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
376 }
377 GrMipmapStatus mipmapStatus = mipLevelCount > 1 ? GrMipmapStatus::kValid
379
380 sk_sp<GrD3DTexture> d3dTex = this->createD3DTexture(
381 dimensions,
382 dxgiFormat,
383 GrRenderable::kNo,
384 1,
385 budgeted,
386 isProtected,
387 mipLevelCount,
388 mipmapStatus,
389 /*label=*/"D3DGpu_CreateCompressedTexture");
390 if (!d3dTex) {
391 return nullptr;
392 }
393
394 ID3D12Resource* d3dResource = d3dTex->d3dResource();
395 SkASSERT(d3dResource);
396 D3D12_RESOURCE_DESC desc = d3dResource->GetDesc();
397 // Either upload only the first miplevel or all miplevels
398 SkASSERT(1 == mipLevelCount || mipLevelCount == (int)desc.MipLevels);
399
400 AutoTMalloc<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> placedFootprints(mipLevelCount);
401 AutoTMalloc<UINT> numRows(mipLevelCount);
402 AutoTMalloc<UINT64> rowSizeInBytes(mipLevelCount);
403 UINT64 combinedBufferSize;
404 // We reset the width and height in the description to match our subrectangle size
405 // so we don't end up allocating more space than we need.
406 desc.Width = dimensions.width();
407 desc.Height = dimensions.height();
408 fDevice->GetCopyableFootprints(&desc, 0, mipLevelCount, 0, placedFootprints.get(),
409 numRows.get(), rowSizeInBytes.get(), &combinedBufferSize);
410 SkASSERT(combinedBufferSize);
411
412 GrStagingBufferManager::Slice slice = fStagingBufferManager.allocateStagingBufferSlice(
413 combinedBufferSize, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
414 if (!slice.fBuffer) {
415 return nullptr;
416 }
417
418 char* bufferData = (char*)slice.fOffsetMapPtr;
419
420 copy_compressed_data(bufferData, desc.Format, placedFootprints.get(), numRows.get(),
421 rowSizeInBytes.get(), data, mipLevelCount);
422
423 // Update the offsets in the footprints to be relative to the slice's offset
424 for (int i = 0; i < mipLevelCount; ++i) {
425 placedFootprints[i].Offset += slice.fOffset;
426 }
427
428 ID3D12Resource* d3dBuffer = static_cast<GrD3DBuffer*>(slice.fBuffer)->d3dResource();
429 fCurrentDirectCommandList->copyBufferToTexture(d3dBuffer, d3dTex.get(), mipLevelCount,
430 placedFootprints.get(), 0, 0);
431
432 return std::move(d3dTex);
433}
434
436 if (const GrRenderTarget* rt = surf->asRenderTarget()) {
437 return rt->numSamples();
438 }
439 return 0;
440}
441
442bool GrD3DGpu::onCopySurface(GrSurface* dst, const SkIRect& dstRect,
443 GrSurface* src, const SkIRect& srcRect,
445 if (srcRect.size() != dstRect.size()) {
446 return false;
447 }
448 if (src->isProtected() && !dst->isProtected()) {
449 SkDebugf("Can't copy from protected memory to non-protected");
450 return false;
451 }
452
453 int dstSampleCnt = get_surface_sample_cnt(dst);
454 int srcSampleCnt = get_surface_sample_cnt(src);
455
456 GrD3DTextureResource* dstTexResource;
457 GrD3DTextureResource* srcTexResource;
458 GrRenderTarget* dstRT = dst->asRenderTarget();
459 if (dstRT) {
460 GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(dstRT);
461 dstTexResource = d3dRT->numSamples() > 1 ? d3dRT->msaaTextureResource() : d3dRT;
462 } else {
463 SkASSERT(dst->asTexture());
464 dstTexResource = static_cast<GrD3DTexture*>(dst->asTexture());
465 }
466 GrRenderTarget* srcRT = src->asRenderTarget();
467 if (srcRT) {
468 GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(srcRT);
469 srcTexResource = d3dRT->numSamples() > 1 ? d3dRT->msaaTextureResource() : d3dRT;
470 } else {
471 SkASSERT(src->asTexture());
472 srcTexResource = static_cast<GrD3DTexture*>(src->asTexture());
473 }
474
475 DXGI_FORMAT dstFormat = dstTexResource->dxgiFormat();
476 DXGI_FORMAT srcFormat = srcTexResource->dxgiFormat();
477
478 const SkIPoint dstPoint = dstRect.topLeft();
479 if (this->d3dCaps().canCopyAsResolve(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt)) {
480 this->copySurfaceAsResolve(dst, src, srcRect, dstPoint);
481 return true;
482 }
483
484 if (this->d3dCaps().canCopyTexture(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt)) {
485 this->copySurfaceAsCopyTexture(dst, src, dstTexResource, srcTexResource, srcRect, dstPoint);
486 return true;
487 }
488
489 return false;
490}
491
492void GrD3DGpu::copySurfaceAsCopyTexture(GrSurface* dst, GrSurface* src,
493 GrD3DTextureResource* dstResource,
494 GrD3DTextureResource* srcResource,
495 const SkIRect& srcRect, const SkIPoint& dstPoint) {
496#ifdef SK_DEBUG
497 int dstSampleCnt = get_surface_sample_cnt(dst);
498 int srcSampleCnt = get_surface_sample_cnt(src);
499 DXGI_FORMAT dstFormat = dstResource->dxgiFormat();
500 DXGI_FORMAT srcFormat;
501 SkAssertResult(dst->backendFormat().asDxgiFormat(&srcFormat));
502 SkASSERT(this->d3dCaps().canCopyTexture(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt));
503#endif
504 if (src->isProtected() && !dst->isProtected()) {
505 SkDebugf("Can't copy from protected memory to non-protected");
506 return;
507 }
508
509 dstResource->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
510 srcResource->setResourceState(this, D3D12_RESOURCE_STATE_COPY_SOURCE);
511
512 D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
513 dstLocation.pResource = dstResource->d3dResource();
514 dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
515 dstLocation.SubresourceIndex = 0;
516
517 D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
518 srcLocation.pResource = srcResource->d3dResource();
519 srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
520 srcLocation.SubresourceIndex = 0;
521
522 D3D12_BOX srcBox = {};
523 srcBox.left = srcRect.fLeft;
524 srcBox.top = srcRect.fTop;
525 srcBox.right = srcRect.fRight;
526 srcBox.bottom = srcRect.fBottom;
527 srcBox.front = 0;
528 srcBox.back = 1;
529 // TODO: use copyResource if copying full resource and sizes match
530 fCurrentDirectCommandList->copyTextureRegionToTexture(dstResource->resource(),
531 &dstLocation,
532 dstPoint.fX, dstPoint.fY,
533 srcResource->resource(),
534 &srcLocation,
535 &srcBox);
536
537 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
538 srcRect.width(), srcRect.height());
539 // The rect is already in device space so we pass in kTopLeft so no flip is done.
540 this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
541}
542
543void GrD3DGpu::copySurfaceAsResolve(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
544 const SkIPoint& dstPoint) {
545 GrD3DRenderTarget* srcRT = static_cast<GrD3DRenderTarget*>(src->asRenderTarget());
546 SkASSERT(srcRT);
547
548 this->resolveTexture(dst, dstPoint.fX, dstPoint.fY, srcRT, srcRect);
549 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
550 srcRect.width(), srcRect.height());
551 // The rect is already in device space so we pass in kTopLeft so no flip is done.
552 this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
553}
554
555void GrD3DGpu::resolveTexture(GrSurface* dst, int32_t dstX, int32_t dstY,
556 GrD3DRenderTarget* src, const SkIRect& srcIRect) {
557 SkASSERT(dst);
558 SkASSERT(src && src->numSamples() > 1 && src->msaaTextureResource());
559
560 D3D12_RECT srcRect = { srcIRect.fLeft, srcIRect.fTop, srcIRect.fRight, srcIRect.fBottom };
561
562 GrD3DTextureResource* dstTextureResource;
563 GrRenderTarget* dstRT = dst->asRenderTarget();
564 if (dstRT) {
565 dstTextureResource = static_cast<GrD3DRenderTarget*>(dstRT);
566 } else {
567 SkASSERT(dst->asTexture());
568 dstTextureResource = static_cast<GrD3DTexture*>(dst->asTexture());
569 }
570
571 dstTextureResource->setResourceState(this, D3D12_RESOURCE_STATE_RESOLVE_DEST);
572 src->msaaTextureResource()->setResourceState(this, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
573
574 fCurrentDirectCommandList->resolveSubresourceRegion(dstTextureResource, dstX, dstY,
575 src->msaaTextureResource(), &srcRect);
576}
577
579 SkASSERT(target->numSamples() > 1);
580 GrD3DRenderTarget* rt = static_cast<GrD3DRenderTarget*>(target);
582
583 this->resolveTexture(target, resolveRect.fLeft, resolveRect.fTop, rt, resolveRect);
584}
585
587 SkIRect rect,
588 GrColorType surfaceColorType,
589 GrColorType dstColorType,
590 void* buffer,
591 size_t rowBytes) {
593
594 if (surfaceColorType != dstColorType) {
595 return false;
596 }
597
598 GrD3DTextureResource* texResource = nullptr;
599 GrD3DRenderTarget* rt = static_cast<GrD3DRenderTarget*>(surface->asRenderTarget());
600 if (rt) {
601 texResource = rt;
602 } else {
603 texResource = static_cast<GrD3DTexture*>(surface->asTexture());
604 }
605
606 if (!texResource) {
607 return false;
608 }
609
610 D3D12_RESOURCE_DESC desc = texResource->d3dResource()->GetDesc();
611 D3D12_PLACED_SUBRESOURCE_FOOTPRINT placedFootprint;
612 UINT64 transferTotalBytes;
613 fDevice->GetCopyableFootprints(&desc, 0, 1, 0, &placedFootprint,
614 nullptr, nullptr, &transferTotalBytes);
615 SkASSERT(transferTotalBytes);
617 this->getContext()->priv().resourceProvider();
618 sk_sp<GrGpuBuffer> transferBuffer = resourceProvider->createBuffer(
619 transferTotalBytes,
623 if (!transferBuffer) {
624 return false;
625 }
626
627 this->readOrTransferPixels(texResource, rect, transferBuffer, placedFootprint);
628 this->submitDirectCommandList(SyncQueue::kForce);
629
630 // Copy back to CPU buffer
631 size_t bpp = GrColorTypeBytesPerPixel(dstColorType);
632 if (GrDxgiFormatBytesPerBlock(texResource->dxgiFormat()) != bpp) {
633 return false;
634 }
635 size_t tightRowBytes = bpp * rect.width();
636
637 const void* mappedMemory = transferBuffer->map();
638 if (!mappedMemory) {
639 return false;
640 }
641
643 rowBytes,
644 mappedMemory,
645 placedFootprint.Footprint.RowPitch,
646 tightRowBytes,
647 rect.height());
648
649 transferBuffer->unmap();
650
651 return true;
652}
653
654void GrD3DGpu::readOrTransferPixels(GrD3DTextureResource* texResource,
655 SkIRect rect,
656 sk_sp<GrGpuBuffer> transferBuffer,
657 const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& placedFootprint) {
658 // Set up src location and box
659 D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
660 srcLocation.pResource = texResource->d3dResource();
661 SkASSERT(srcLocation.pResource);
662 srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
663 srcLocation.SubresourceIndex = 0;
664
665 D3D12_BOX srcBox = {};
666 srcBox.left = rect.left();
667 srcBox.top = rect.top();
668 srcBox.right = rect.right();
669 srcBox.bottom = rect.bottom();
670 srcBox.front = 0;
671 srcBox.back = 1;
672
673 // Set up dst location
674 D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
675 dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
676 dstLocation.PlacedFootprint = placedFootprint;
677 GrD3DBuffer* d3dBuf = static_cast<GrD3DBuffer*>(transferBuffer.get());
678 dstLocation.pResource = d3dBuf->d3dResource();
679
680 // Need to change the resource state to COPY_SOURCE in order to download from it
681 texResource->setResourceState(this, D3D12_RESOURCE_STATE_COPY_SOURCE);
682
683 fCurrentDirectCommandList->copyTextureRegionToBuffer(transferBuffer, &dstLocation, 0, 0,
684 texResource->resource(), &srcLocation,
685 &srcBox);
686}
687
689 SkIRect rect,
690 GrColorType surfaceColorType,
691 GrColorType srcColorType,
692 const GrMipLevel texels[],
693 int mipLevelCount,
694 bool prepForTexSampling) {
695 GrD3DTexture* d3dTex = static_cast<GrD3DTexture*>(surface->asTexture());
696 if (!d3dTex) {
697 return false;
698 }
699
700 // Make sure we have at least the base level
701 if (!mipLevelCount || !texels[0].fPixels) {
702 return false;
703 }
704
706 bool success = false;
707
708 // Need to change the resource state to COPY_DEST in order to upload to it
709 d3dTex->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
710
711 SkASSERT(mipLevelCount <= d3dTex->maxMipmapLevel() + 1);
712 success = this->uploadToTexture(d3dTex, rect, srcColorType, texels, mipLevelCount);
713
714 if (prepForTexSampling) {
715 d3dTex->setResourceState(this, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
716 }
717
718 return success;
719}
720
721bool GrD3DGpu::uploadToTexture(GrD3DTexture* tex,
722 SkIRect rect,
724 const GrMipLevel* texels,
725 int mipLevelCount) {
726 SkASSERT(this->d3dCaps().isFormatTexturable(tex->dxgiFormat()));
727 // The assumption is either that we have no mipmaps, or that our rect is the entire texture
728 SkASSERT(mipLevelCount == 1 || rect == SkIRect::MakeSize(tex->dimensions()));
729
730 // We assume that if the texture has mip levels, we either upload to all the levels or just the
731 // first.
732 SkASSERT(mipLevelCount == 1 || mipLevelCount == (tex->maxMipmapLevel() + 1));
733
734 if (rect.isEmpty()) {
735 return false;
736 }
737
738 SkASSERT(this->d3dCaps().surfaceSupportsWritePixels(tex));
739 SkASSERT(this->d3dCaps().areColorTypeAndFormatCompatible(colorType, tex->backendFormat()));
740
741 ID3D12Resource* d3dResource = tex->d3dResource();
742 SkASSERT(d3dResource);
743 D3D12_RESOURCE_DESC desc = d3dResource->GetDesc();
744 // Either upload only the first miplevel or all miplevels
745 SkASSERT(1 == mipLevelCount || mipLevelCount == (int)desc.MipLevels);
746
747 if (1 == mipLevelCount && !texels[0].fPixels) {
748 return true; // no data to upload
749 }
750
751 for (int i = 0; i < mipLevelCount; ++i) {
752 // We do not allow any gaps in the mip data
753 if (!texels[i].fPixels) {
754 return false;
755 }
756 }
757
758 AutoTMalloc<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> placedFootprints(mipLevelCount);
759 UINT64 combinedBufferSize;
760 // We reset the width and height in the description to match our subrectangle size
761 // so we don't end up allocating more space than we need.
762 desc.Width = rect.width();
763 desc.Height = rect.height();
764 fDevice->GetCopyableFootprints(&desc, 0, mipLevelCount, 0, placedFootprints.get(),
765 nullptr, nullptr, &combinedBufferSize);
767 SkASSERT(combinedBufferSize);
768
769 GrStagingBufferManager::Slice slice = fStagingBufferManager.allocateStagingBufferSlice(
770 combinedBufferSize, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
771 if (!slice.fBuffer) {
772 return false;
773 }
774
775 char* bufferData = (char*)slice.fOffsetMapPtr;
776
777 int currentWidth = rect.width();
778 int currentHeight = rect.height();
779 for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
780 if (texels[currentMipLevel].fPixels) {
781
782 const size_t trimRowBytes = currentWidth * bpp;
783 const size_t srcRowBytes = texels[currentMipLevel].fRowBytes;
784
785 char* dst = bufferData + placedFootprints[currentMipLevel].Offset;
786
787 // copy data into the buffer, skipping any trailing bytes
788 const char* src = (const char*)texels[currentMipLevel].fPixels;
789 SkRectMemcpy(dst, placedFootprints[currentMipLevel].Footprint.RowPitch,
790 src, srcRowBytes, trimRowBytes, currentHeight);
791 }
792 currentWidth = std::max(1, currentWidth / 2);
793 currentHeight = std::max(1, currentHeight / 2);
794 }
795
796 // Update the offsets in the footprints to be relative to the slice's offset
797 for (int i = 0; i < mipLevelCount; ++i) {
798 placedFootprints[i].Offset += slice.fOffset;
799 }
800
801 ID3D12Resource* d3dBuffer = static_cast<GrD3DBuffer*>(slice.fBuffer)->d3dResource();
802 fCurrentDirectCommandList->copyBufferToTexture(d3dBuffer,
803 tex,
804 mipLevelCount,
805 placedFootprints.get(),
806 rect.left(),
807 rect.top());
808
809 if (mipLevelCount < (int)desc.MipLevels) {
810 tex->markMipmapsDirty();
811 }
812
813 return true;
814}
815
817 size_t srcOffset,
819 size_t dstOffset,
820 size_t size) {
821 if (!this->currentCommandList()) {
822 return false;
823 }
824
825 sk_sp<GrD3DBuffer> d3dSrc(static_cast<GrD3DBuffer*>(src.release()));
826 sk_sp<GrD3DBuffer> d3dDst(static_cast<GrD3DBuffer*>(dst.release()));
827
828 fCurrentDirectCommandList->copyBufferToBuffer(std::move(d3dDst),
829 dstOffset,
830 d3dSrc->d3dResource(),
831 srcOffset,
832 size);
833
834 // copyBufferToBuffer refs the dst but not the src
835 this->currentCommandList()->addGrBuffer(std::move(src));
836
837 return true;
838}
839
841 SkIRect rect,
842 GrColorType surfaceColorType,
843 GrColorType bufferColorType,
844 sk_sp<GrGpuBuffer> transferBuffer,
845 size_t bufferOffset,
846 size_t rowBytes) {
847 if (!this->currentCommandList()) {
848 return false;
849 }
850
851 if (!transferBuffer) {
852 return false;
853 }
854
855 size_t bpp = GrColorTypeBytesPerPixel(bufferColorType);
856 if (GrBackendFormatBytesPerPixel(texture->backendFormat()) != bpp) {
857 return false;
858 }
859
860 // D3D requires offsets for texture transfers to be aligned to this value
861 if (SkToBool(bufferOffset & (D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT-1))) {
862 return false;
863 }
864
865 GrD3DTexture* d3dTex = static_cast<GrD3DTexture*>(texture);
866 if (!d3dTex) {
867 return false;
868 }
869
870 SkDEBUGCODE(DXGI_FORMAT format = d3dTex->dxgiFormat());
871
872 // Can't transfer compressed data
874
876
877 SkASSERT(SkIRect::MakeSize(texture->dimensions()).contains(rect));
878
879 // Set up copy region
880 D3D12_PLACED_SUBRESOURCE_FOOTPRINT placedFootprint = {};
881 ID3D12Resource* d3dResource = d3dTex->d3dResource();
882 SkASSERT(d3dResource);
883 D3D12_RESOURCE_DESC desc = d3dResource->GetDesc();
884 desc.Width = rect.width();
885 desc.Height = rect.height();
886 UINT64 totalBytes;
887 fDevice->GetCopyableFootprints(&desc, 0, 1, 0, &placedFootprint,
888 nullptr, nullptr, &totalBytes);
889 placedFootprint.Offset = bufferOffset;
890
891 // Change state of our target so it can be copied to
892 d3dTex->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
893
894 // Copy the buffer to the image.
895 ID3D12Resource* d3dBuffer = static_cast<GrD3DBuffer*>(transferBuffer.get())->d3dResource();
896 fCurrentDirectCommandList->copyBufferToTexture(d3dBuffer,
897 d3dTex,
898 1,
899 &placedFootprint,
900 rect.left(),
901 rect.top());
902 this->currentCommandList()->addGrBuffer(std::move(transferBuffer));
903
904 d3dTex->markMipmapsDirty();
905 return true;
906}
907
909 SkIRect rect,
910 GrColorType surfaceColorType,
911 GrColorType bufferColorType,
912 sk_sp<GrGpuBuffer> transferBuffer,
913 size_t offset) {
914 if (!this->currentCommandList()) {
915 return false;
916 }
917 SkASSERT(surface);
918 SkASSERT(transferBuffer);
919 // TODO
920 //if (fProtectedContext == GrProtected::kYes) {
921 // return false;
922 //}
923
924 // D3D requires offsets for texture transfers to be aligned to this value
925 if (SkToBool(offset & (D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT-1))) {
926 return false;
927 }
928
929 GrD3DTextureResource* texResource = nullptr;
930 GrD3DRenderTarget* rt = static_cast<GrD3DRenderTarget*>(surface->asRenderTarget());
931 if (rt) {
932 texResource = rt;
933 } else {
934 texResource = static_cast<GrD3DTexture*>(surface->asTexture());
935 }
936
937 if (!texResource) {
938 return false;
939 }
940
941 SkDEBUGCODE(DXGI_FORMAT format = texResource->dxgiFormat());
943
944 D3D12_RESOURCE_DESC desc = texResource->d3dResource()->GetDesc();
945 desc.Width = rect.width();
946 desc.Height = rect.height();
947 D3D12_PLACED_SUBRESOURCE_FOOTPRINT placedFootprint;
948 UINT64 transferTotalBytes;
949 fDevice->GetCopyableFootprints(&desc, 0, 1, offset, &placedFootprint,
950 nullptr, nullptr, &transferTotalBytes);
951 SkASSERT(transferTotalBytes);
952
953 this->readOrTransferPixels(texResource, rect, transferBuffer, placedFootprint);
954
955 // TODO: It's not clear how to ensure the transfer is done before we read from the buffer,
956 // other than maybe doing a resource state transition.
957
958 return true;
959}
960
962 if (!info.fResource.get()) {
963 return false;
964 }
965 return true;
966}
967
969 if (!caps.isFormatTexturable(info.fFormat)) {
970 return false;
971 }
972 // We don't support sampling from multisampled textures.
973 if (info.fSampleCount != 1) {
974 return false;
975 }
976 return true;
977}
978
980 int sampleCnt) {
981 if (!caps.isFormatRenderable(info.fFormat, sampleCnt)) {
982 return false;
983 }
984 return true;
985}
986
989 GrWrapCacheable wrapType,
990 GrIOType ioType) {
991 GrD3DTextureResourceInfo textureInfo;
992 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
993 return nullptr;
994 }
995
996 if (!check_resource_info(textureInfo)) {
997 return nullptr;
998 }
999
1000 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
1001 return nullptr;
1002 }
1003
1004 // TODO: support protected context
1005 if (tex.isProtected()) {
1006 return nullptr;
1007 }
1008
1009 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
1010 SkASSERT(state);
1011 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, ioType, textureInfo,
1012 std::move(state));
1013}
1014
1016 GrWrapOwnership ownership,
1017 GrWrapCacheable wrapType) {
1018 return this->onWrapBackendTexture(tex, ownership, wrapType, kRead_GrIOType);
1019}
1020
1022 int sampleCnt,
1023 GrWrapOwnership ownership,
1024 GrWrapCacheable cacheable) {
1025 GrD3DTextureResourceInfo textureInfo;
1026 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
1027 return nullptr;
1028 }
1029
1030 if (!check_resource_info(textureInfo)) {
1031 return nullptr;
1032 }
1033
1034 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
1035 return nullptr;
1036 }
1037 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
1038 return nullptr;
1039 }
1040
1041 // TODO: support protected context
1042 if (tex.isProtected()) {
1043 return nullptr;
1044 }
1045
1046 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
1047
1048 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
1049 SkASSERT(state);
1050
1052 sampleCnt, cacheable,
1053 textureInfo, std::move(state));
1054}
1055
1058 if (!rt.getD3DTextureResourceInfo(&info)) {
1059 return nullptr;
1060 }
1061
1062 if (!check_resource_info(info)) {
1063 return nullptr;
1064 }
1065
1066 if (!check_rt_resource_info(this->d3dCaps(), info, rt.sampleCnt())) {
1067 return nullptr;
1068 }
1069
1070 // TODO: support protected context
1071 if (rt.isProtected()) {
1072 return nullptr;
1073 }
1074
1075 sk_sp<GrD3DResourceState> state = rt.getGrD3DResourceState();
1076
1078 this, rt.dimensions(), rt.sampleCnt(), info, std::move(state));
1079
1080 // We don't allow the client to supply a premade stencil buffer. We always create one if needed.
1081 SkASSERT(!rt.stencilBits());
1082 if (tgt) {
1083 SkASSERT(tgt->canAttemptStencilAttachment(tgt->numSamples() > 1));
1084 }
1085
1086 return std::move(tgt);
1087}
1088
1089static bool is_odd(int x) {
1090 return x > 1 && SkToBool(x & 0x1);
1091}
1092
1093// TODO: enable when sRGB shader supported
1094//static bool is_srgb(DXGI_FORMAT format) {
1095// // the only one we support at the moment
1096// return (format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
1097//}
1098
1099static bool is_bgra(DXGI_FORMAT format) {
1100 // the only one we support at the moment
1101 return (format == DXGI_FORMAT_B8G8R8A8_UNORM);
1102}
1103
1105 auto * d3dTex = static_cast<GrD3DTexture*>(tex);
1107 int width = tex->width();
1108 int height = tex->height();
1109
1110 // determine if we can read from and mipmap this format
1111 const GrD3DCaps & caps = this->d3dCaps();
1112 if (!caps.isFormatTexturable(d3dTex->dxgiFormat()) ||
1113 !caps.mipmapSupport()) {
1114 return false;
1115 }
1116
1117 sk_sp<GrD3DTexture> uavTexture;
1118 sk_sp<GrD3DTexture> bgraAliasTexture;
1119 DXGI_FORMAT originalFormat = d3dTex->dxgiFormat();
1120 D3D12_RESOURCE_DESC originalDesc = d3dTex->d3dResource()->GetDesc();
1121 // if the format is unordered accessible and resource flag is set, use resource for uav
1122 if (caps.isFormatUnorderedAccessible(originalFormat) &&
1123 (originalDesc.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)) {
1124 uavTexture = sk_ref_sp(d3dTex);
1125 } else {
1126 // need to make a copy and use that for our uav
1127 D3D12_RESOURCE_DESC uavDesc = originalDesc;
1128 uavDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
1129 // if the format is unordered accessible, copy to resource with same format and flag set
1130 if (!caps.isFormatUnorderedAccessible(originalFormat)) {
1131 // for the BGRA and sRGB cases, we find a suitable RGBA format to use instead
1132 if (is_bgra(originalFormat)) {
1133 uavDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1134 // Technically if this support is not available we should not be doing
1135 // aliasing. However, on Intel the BGRA and RGBA swizzle appears to be
1136 // the same so it still works. We may need to disable BGRA support
1137 // on a case-by-base basis if this doesn't hold true in general.
1138 if (caps.standardSwizzleLayoutSupport()) {
1139 uavDesc.Layout = D3D12_TEXTURE_LAYOUT_64KB_STANDARD_SWIZZLE;
1140 }
1141 // TODO: enable when sRGB shader supported
1142 //} else if (is_srgb(originalFormat)) {
1143 // uavDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1144 } else {
1145 return false;
1146 }
1147 }
1148 // TODO: make this a scratch texture
1149 GrProtected grProtected = tex->isProtected() ? GrProtected::kYes : GrProtected::kNo;
1150 uavTexture = GrD3DTexture::MakeNewTexture(this,
1152 tex->dimensions(),
1153 uavDesc,
1154 grProtected,
1156 /*label=*/"RegenerateMipMapLevels");
1157 if (!uavTexture) {
1158 return false;
1159 }
1160
1161 d3dTex->setResourceState(this, D3D12_RESOURCE_STATE_COPY_SOURCE);
1162 if (!caps.isFormatUnorderedAccessible(originalFormat) && is_bgra(originalFormat)) {
1163 // for BGRA, we alias this uavTexture with a BGRA texture and copy to that
1164 bgraAliasTexture = GrD3DTexture::MakeAliasingTexture(this, uavTexture, originalDesc,
1165 D3D12_RESOURCE_STATE_COPY_DEST);
1166 // make the BGRA version the active alias
1167 this->currentCommandList()->aliasingBarrier(nullptr,
1168 nullptr,
1169 bgraAliasTexture->resource(),
1170 bgraAliasTexture->d3dResource());
1171 // copy top miplevel to bgraAliasTexture (should already be in COPY_DEST state)
1172 this->currentCommandList()->copyTextureToTexture(bgraAliasTexture.get(), d3dTex, 0);
1173 // make the RGBA version the active alias
1174 this->currentCommandList()->aliasingBarrier(bgraAliasTexture->resource(),
1175 bgraAliasTexture->d3dResource(),
1176 uavTexture->resource(),
1177 uavTexture->d3dResource());
1178 } else {
1179 // copy top miplevel to uavTexture
1180 uavTexture->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
1181 this->currentCommandList()->copyTextureToTexture(uavTexture.get(), d3dTex, 0);
1182 }
1183 }
1184
1185 uint32_t levelCount = d3dTex->mipLevels();
1186 // SkMipmap doesn't include the base level in the level count so we have to add 1
1187 SkASSERT((int)levelCount == SkMipmap::ComputeLevelCount(tex->width(), tex->height()) + 1);
1188
1189 sk_sp<GrD3DRootSignature> rootSig = fResourceProvider.findOrCreateRootSignature(1, 1);
1191
1192 // TODO: use linear vs. srgb shader based on texture format
1194 if (!pipeline) {
1195 return false;
1196 }
1197 this->currentCommandList()->setPipelineState(std::move(pipeline));
1198
1199 // set sampler
1201 std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> samplers(1);
1202 samplers[0] = fResourceProvider.findOrCreateCompatibleSampler(samplerState);
1203 this->currentCommandList()->addSampledTextureRef(uavTexture.get());
1204 sk_sp<GrD3DDescriptorTable> samplerTable = fResourceProvider.findOrCreateSamplerTable(samplers);
1205
1206 // Transition the top subresource to be readable in the compute shader
1207 D3D12_RESOURCE_STATES currentResourceState = uavTexture->currentState();
1208 D3D12_RESOURCE_TRANSITION_BARRIER barrier;
1209 barrier.pResource = uavTexture->d3dResource();
1210 barrier.Subresource = 0;
1211 barrier.StateBefore = currentResourceState;
1212 barrier.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
1213 this->addResourceBarriers(uavTexture->resource(), 1, &barrier);
1214
1215 // Generate the miplevels
1216 for (unsigned int dstMip = 1; dstMip < levelCount; ++dstMip) {
1217 unsigned int srcMip = dstMip - 1;
1218 width = std::max(1, width / 2);
1219 height = std::max(1, height / 2);
1220
1221 unsigned int sampleMode = 0;
1222 if (is_odd(width) && is_odd(height)) {
1223 sampleMode = 1;
1224 } else if (is_odd(width)) {
1225 sampleMode = 2;
1226 } else if (is_odd(height)) {
1227 sampleMode = 3;
1228 }
1229
1230 // set constants
1231 struct {
1232 SkSize inverseSize;
1233 uint32_t mipLevel;
1234 uint32_t sampleMode;
1235 } constantData = { {1.f / width, 1.f / height}, srcMip, sampleMode };
1236
1237 D3D12_GPU_VIRTUAL_ADDRESS constantsAddress =
1238 fResourceProvider.uploadConstantData(&constantData, sizeof(constantData));
1241 constantsAddress);
1242
1243 std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> shaderViews;
1244 // create SRV
1246 fResourceProvider.createShaderResourceView(uavTexture->d3dResource(), srcMip, 1);
1247 shaderViews.push_back(srvHandle.fHandle);
1248 fMipmapCPUDescriptors.push_back(srvHandle);
1249 // create UAV
1251 fResourceProvider.createUnorderedAccessView(uavTexture->d3dResource(), dstMip);
1252 shaderViews.push_back(uavHandle.fHandle);
1253 fMipmapCPUDescriptors.push_back(uavHandle);
1254
1255 // set up shaderView descriptor table
1257 fResourceProvider.findOrCreateShaderViewTable(shaderViews);
1258
1259 // bind both descriptor tables
1260 this->currentCommandList()->setDescriptorHeaps(srvTable->heap(), samplerTable->heap());
1263 srvTable->baseGpuDescriptor());
1266 samplerTable->baseGpuDescriptor());
1267
1268 // Transition resource state of dstMip subresource so we can write to it
1269 barrier.Subresource = dstMip;
1270 barrier.StateBefore = currentResourceState;
1271 barrier.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
1272 this->addResourceBarriers(uavTexture->resource(), 1, &barrier);
1273
1274 // Using the form (x+7)/8 ensures that the remainder is covered as well
1275 this->currentCommandList()->dispatch((width+7)/8, (height+7)/8);
1276
1277 // guarantee UAV writes have completed
1278 this->currentCommandList()->uavBarrier(uavTexture->resource(), uavTexture->d3dResource());
1279
1280 // Transition resource state of dstMip subresource so we can read it in the next stage
1281 barrier.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
1282 barrier.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
1283 this->addResourceBarriers(uavTexture->resource(), 1, &barrier);
1284 }
1285
1286 // copy back if necessary
1287 if (uavTexture.get() != d3dTex) {
1288 d3dTex->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
1289 if (bgraAliasTexture) {
1290 // make the BGRA version the active alias
1291 this->currentCommandList()->aliasingBarrier(uavTexture->resource(),
1292 uavTexture->d3dResource(),
1293 bgraAliasTexture->resource(),
1294 bgraAliasTexture->d3dResource());
1295 // copy from bgraAliasTexture to d3dTex
1296 bgraAliasTexture->setResourceState(this, D3D12_RESOURCE_STATE_COPY_SOURCE);
1297 this->currentCommandList()->copyTextureToTexture(d3dTex, bgraAliasTexture.get());
1298 } else {
1299 barrier.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
1300 barrier.StateBefore = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
1301 barrier.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
1302 this->addResourceBarriers(uavTexture->resource(), 1, &barrier);
1303 this->currentCommandList()->copyTextureToTexture(d3dTex, uavTexture.get());
1304 }
1305 } else {
1306 // For simplicity our resource state tracking considers all subresources to have the same
1307 // state. However, we've changed that state one subresource at a time without going through
1308 // the tracking system, so we need to patch up the resource states back to the original.
1309 barrier.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
1310 barrier.StateBefore = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
1311 barrier.StateAfter = currentResourceState;
1312 this->addResourceBarriers(d3dTex->resource(), 1, &barrier);
1313 }
1314
1315 return true;
1316}
1317
1320 GrAccessPattern accessPattern) {
1321 return GrD3DBuffer::Make(this, sizeInBytes, type, accessPattern);
1322}
1323
1325 SkISize dimensions, int numStencilSamples) {
1326 DXGI_FORMAT sFmt = this->d3dCaps().preferredStencilFormat();
1327
1329 return GrD3DAttachment::MakeStencil(this, dimensions, numStencilSamples, sFmt);
1330}
1331
1332bool GrD3DGpu::createTextureResourceForBackendSurface(DXGI_FORMAT dxgiFormat,
1333 SkISize dimensions,
1334 GrTexturable texturable,
1335 GrRenderable renderable,
1336 skgpu::Mipmapped mipmapped,
1337 int sampleCnt,
1339 GrProtected isProtected) {
1340 SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
1341
1342 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
1343 return false;
1344 }
1345
1346 if (texturable == GrTexturable::kYes && !this->d3dCaps().isFormatTexturable(dxgiFormat)) {
1347 return false;
1348 }
1349
1350 if (renderable == GrRenderable::kYes && !this->d3dCaps().isFormatRenderable(dxgiFormat, 1)) {
1351 return false;
1352 }
1353
1354 int numMipLevels = 1;
1355 if (mipmapped == skgpu::Mipmapped::kYes) {
1356 numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
1357 }
1358
1359 // create the texture
1360 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
1361 if (renderable == GrRenderable::kYes) {
1362 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
1363 }
1364
1365 D3D12_RESOURCE_DESC resourceDesc = {};
1366 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
1367 resourceDesc.Alignment = 0; // use default alignment
1368 resourceDesc.Width = dimensions.fWidth;
1369 resourceDesc.Height = dimensions.fHeight;
1370 resourceDesc.DepthOrArraySize = 1;
1371 resourceDesc.MipLevels = numMipLevels;
1372 resourceDesc.Format = dxgiFormat;
1373 resourceDesc.SampleDesc.Count = sampleCnt;
1374 resourceDesc.SampleDesc.Quality = DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN;
1375 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
1376 resourceDesc.Flags = usageFlags;
1377
1378 D3D12_CLEAR_VALUE* clearValuePtr = nullptr;
1379 D3D12_CLEAR_VALUE clearValue = {};
1380 if (renderable == GrRenderable::kYes) {
1381 clearValue.Format = dxgiFormat;
1382 // Assume transparent black
1383 clearValue.Color[0] = 0;
1384 clearValue.Color[1] = 0;
1385 clearValue.Color[2] = 0;
1386 clearValue.Color[3] = 0;
1387 clearValuePtr = &clearValue;
1388 }
1389
1390 D3D12_RESOURCE_STATES initialState = (renderable == GrRenderable::kYes)
1391 ? D3D12_RESOURCE_STATE_RENDER_TARGET
1392 : D3D12_RESOURCE_STATE_COPY_DEST;
1393 if (!GrD3DTextureResource::InitTextureResourceInfo(this, resourceDesc, initialState,
1394 isProtected, clearValuePtr, info)) {
1395 SkDebugf("Failed to init texture resource info\n");
1396 return false;
1397 }
1398
1399 return true;
1400}
1401
1403 const GrBackendFormat& format,
1404 GrRenderable renderable,
1405 skgpu::Mipmapped mipmapped,
1406 GrProtected isProtected,
1407 std::string_view label) {
1408 const GrD3DCaps& caps = this->d3dCaps();
1409
1410 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
1411 return {};
1412 }
1413
1414 DXGI_FORMAT dxgiFormat;
1415 if (!format.asDxgiFormat(&dxgiFormat)) {
1416 return {};
1417 }
1418
1419 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
1420 if (!caps.isFormatTexturable(dxgiFormat)) {
1421 return {};
1422 }
1423
1425 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
1426 renderable, mipmapped, 1, &info,
1427 isProtected)) {
1428 return {};
1429 }
1430
1431 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
1432}
1433
1434static bool copy_color_data(const GrD3DCaps& caps,
1435 char* mapPtr,
1436 DXGI_FORMAT dxgiFormat,
1437 SkISize dimensions,
1438 D3D12_PLACED_SUBRESOURCE_FOOTPRINT* placedFootprints,
1439 std::array<float, 4> color) {
1440 auto colorType = caps.getFormatColorType(dxgiFormat);
1442 return false;
1443 }
1444 GrImageInfo ii(colorType, kUnpremul_SkAlphaType, nullptr, dimensions);
1445 if (!GrClearImage(ii, mapPtr, placedFootprints[0].Footprint.RowPitch, color)) {
1446 return false;
1447 }
1448
1449 return true;
1450}
1451
1453 sk_sp<skgpu::RefCntedCallback> finishedCallback,
1454 std::array<float, 4> color) {
1456 SkAssertResult(backendTexture.getD3DTextureResourceInfo(&info));
1458
1459 sk_sp<GrD3DResourceState> state = backendTexture.getGrD3DResourceState();
1460 SkASSERT(state);
1462 GrD3DTexture::MakeWrappedTexture(this, backendTexture.dimensions(),
1464 kRW_GrIOType, info, std::move(state));
1465 if (!texture) {
1466 return false;
1467 }
1468
1469 GrD3DDirectCommandList* cmdList = this->currentCommandList();
1470 if (!cmdList) {
1471 return false;
1472 }
1473
1474 texture->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
1475
1476 ID3D12Resource* d3dResource = texture->d3dResource();
1477 SkASSERT(d3dResource);
1478 D3D12_RESOURCE_DESC desc = d3dResource->GetDesc();
1479 unsigned int mipLevelCount = 1;
1480 if (backendTexture.fMipmapped == skgpu::Mipmapped::kYes) {
1481 mipLevelCount = SkMipmap::ComputeLevelCount(backendTexture.dimensions()) + 1;
1482 }
1483 SkASSERT(mipLevelCount == info.fLevelCount);
1484 AutoSTMalloc<15, D3D12_PLACED_SUBRESOURCE_FOOTPRINT> placedFootprints(mipLevelCount);
1485 UINT numRows;
1486 UINT64 rowSizeInBytes;
1487 UINT64 combinedBufferSize;
1488 // We reuse the same top-level buffer area for all levels, hence passing 1 for level count.
1489 fDevice->GetCopyableFootprints(&desc,
1490 /* first resource */ 0,
1491 /* mip level count */ 1,
1492 /* base offset */ 0,
1493 placedFootprints.get(),
1494 &numRows,
1495 &rowSizeInBytes,
1496 &combinedBufferSize);
1497 SkASSERT(combinedBufferSize);
1498
1499 GrStagingBufferManager::Slice slice = fStagingBufferManager.allocateStagingBufferSlice(
1500 combinedBufferSize, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
1501 if (!slice.fBuffer) {
1502 return false;
1503 }
1504
1505 char* bufferData = (char*)slice.fOffsetMapPtr;
1506 SkASSERT(bufferData);
1507 if (!copy_color_data(this->d3dCaps(),
1508 bufferData,
1509 info.fFormat,
1510 backendTexture.dimensions(),
1511 placedFootprints,
1512 color)) {
1513 return false;
1514 }
1515 // Update the offsets in the footprint to be relative to the slice's offset
1516 placedFootprints[0].Offset += slice.fOffset;
1517 // Since we're sharing data for all the levels, set all the upper level footprints to the base.
1518 UINT w = placedFootprints[0].Footprint.Width;
1519 UINT h = placedFootprints[0].Footprint.Height;
1520 for (unsigned int i = 1; i < mipLevelCount; ++i) {
1521 w = std::max(1U, w/2);
1522 h = std::max(1U, h/2);
1523 placedFootprints[i].Offset = placedFootprints[0].Offset;
1524 placedFootprints[i].Footprint.Format = placedFootprints[0].Footprint.Format;
1525 placedFootprints[i].Footprint.Width = w;
1526 placedFootprints[i].Footprint.Height = h;
1527 placedFootprints[i].Footprint.Depth = 1;
1528 placedFootprints[i].Footprint.RowPitch = placedFootprints[0].Footprint.RowPitch;
1529 }
1530
1531 ID3D12Resource* d3dBuffer = static_cast<GrD3DBuffer*>(slice.fBuffer)->d3dResource();
1532 cmdList->copyBufferToTexture(d3dBuffer,
1533 texture.get(),
1534 mipLevelCount,
1535 placedFootprints.get(),
1536 /*left*/ 0,
1537 /*top */ 0);
1538
1539 if (finishedCallback) {
1540 this->addFinishedCallback(std::move(finishedCallback));
1541 }
1542
1543 return true;
1544}
1545
1547 const GrBackendFormat& format,
1548 skgpu::Mipmapped mipmapped,
1549 GrProtected isProtected) {
1550 return this->onCreateBackendTexture(dimensions,
1551 format,
1552 GrRenderable::kNo,
1553 mipmapped,
1554 isProtected,
1555 /*label=*/"D3DGpu_CreateCompressedBackendTexture");
1556}
1557
1559 sk_sp<skgpu::RefCntedCallback> finishedCallback,
1560 const void* data,
1561 size_t size) {
1563 SkAssertResult(backendTexture.getD3DTextureResourceInfo(&info));
1564
1565 sk_sp<GrD3DResourceState> state = backendTexture.getGrD3DResourceState();
1566 SkASSERT(state);
1568 backendTexture.dimensions(),
1571 info,
1572 std::move(state));
1573 if (!texture) {
1574 return false;
1575 }
1576
1577 GrD3DDirectCommandList* cmdList = this->currentCommandList();
1578 if (!cmdList) {
1579 return false;
1580 }
1581
1582 texture->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
1583
1584 ID3D12Resource* d3dResource = texture->d3dResource();
1585 SkASSERT(d3dResource);
1586 D3D12_RESOURCE_DESC desc = d3dResource->GetDesc();
1587 unsigned int mipLevelCount = 1;
1588 if (backendTexture.hasMipmaps()) {
1589 mipLevelCount = SkMipmap::ComputeLevelCount(backendTexture.dimensions().width(),
1590 backendTexture.dimensions().height()) + 1;
1591 }
1592 SkASSERT(mipLevelCount == info.fLevelCount);
1593 AutoTMalloc<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> placedFootprints(mipLevelCount);
1594 UINT64 combinedBufferSize;
1595 AutoTMalloc<UINT> numRows(mipLevelCount);
1596 AutoTMalloc<UINT64> rowSizeInBytes(mipLevelCount);
1597 fDevice->GetCopyableFootprints(&desc,
1598 0,
1599 mipLevelCount,
1600 0,
1601 placedFootprints.get(),
1602 numRows.get(),
1603 rowSizeInBytes.get(),
1604 &combinedBufferSize);
1605 SkASSERT(combinedBufferSize);
1607
1608 GrStagingBufferManager::Slice slice = fStagingBufferManager.allocateStagingBufferSlice(
1609 combinedBufferSize, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
1610 if (!slice.fBuffer) {
1611 return false;
1612 }
1613
1614 char* bufferData = (char*)slice.fOffsetMapPtr;
1615 SkASSERT(bufferData);
1616 copy_compressed_data(bufferData,
1617 info.fFormat,
1618 placedFootprints.get(),
1619 numRows.get(),
1620 rowSizeInBytes.get(),
1621 data,
1622 info.fLevelCount);
1623
1624 // Update the offsets in the footprints to be relative to the slice's offset
1625 for (unsigned int i = 0; i < mipLevelCount; ++i) {
1626 placedFootprints[i].Offset += slice.fOffset;
1627 }
1628
1629 ID3D12Resource* d3dBuffer = static_cast<GrD3DBuffer*>(slice.fBuffer)->d3dResource();
1630 cmdList->copyBufferToTexture(d3dBuffer,
1631 texture.get(),
1632 mipLevelCount,
1633 placedFootprints.get(),
1634 0,
1635 0);
1636
1637 if (finishedCallback) {
1638 this->addFinishedCallback(std::move(finishedCallback));
1639 }
1640
1641 return true;
1642}
1643
1645 SkASSERT(GrBackendApi::kDirect3D == tex.fBackend);
1646 // Nothing to do here, will get cleaned up when the GrBackendTexture object goes away
1647}
1648
1650 return false;
1651}
1652
1653#if defined(GR_TEST_UTILS)
1654bool GrD3DGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
1656
1658 if (!tex.getD3DTextureResourceInfo(&info)) {
1659 return false;
1660 }
1661 ID3D12Resource* textureResource = info.fResource.get();
1662 if (!textureResource) {
1663 return false;
1664 }
1665 return !(textureResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE);
1666}
1667
1668GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
1670 int sampleCnt,
1671 GrProtected isProtected) {
1672 if (dimensions.width() > this->caps()->maxRenderTargetSize() ||
1673 dimensions.height() > this->caps()->maxRenderTargetSize()) {
1674 return {};
1675 }
1676
1677 DXGI_FORMAT dxgiFormat = this->d3dCaps().getFormatFromColorType(colorType);
1678
1680 if (!this->createTextureResourceForBackendSurface(dxgiFormat,
1681 dimensions,
1683 GrRenderable::kYes,
1684 skgpu::Mipmapped::kNo,
1685 sampleCnt,
1686 &info,
1687 isProtected)) {
1688 return {};
1689 }
1690
1691 return GrBackendRenderTarget(dimensions.width(), dimensions.height(), info);
1692}
1693
1694void GrD3DGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
1696
1698 if (rt.getD3DTextureResourceInfo(&info)) {
1700 // Nothing else to do here, will get cleaned up when the GrBackendRenderTarget
1701 // is deleted.
1702 }
1703}
1704
1705void GrD3DGpu::testingOnly_startCapture() {
1706 if (fGraphicsAnalysis) {
1707 fGraphicsAnalysis->BeginCapture();
1708 }
1709}
1710
1711void GrD3DGpu::testingOnly_stopCapture() {
1712 if (fGraphicsAnalysis) {
1713 fGraphicsAnalysis->EndCapture();
1714 }
1715}
1716#endif
1717
1718///////////////////////////////////////////////////////////////////////////////
1719
1721 int numBarriers,
1722 D3D12_RESOURCE_TRANSITION_BARRIER* barriers) const {
1723 SkASSERT(fCurrentDirectCommandList);
1724 SkASSERT(resource);
1725
1726 fCurrentDirectCommandList->resourceBarrier(std::move(resource), numBarriers, barriers);
1727}
1728
1730 int numBarriers,
1731 D3D12_RESOURCE_TRANSITION_BARRIER* barriers) const {
1732 SkASSERT(fCurrentDirectCommandList);
1734
1735 fCurrentDirectCommandList->resourceBarrier(nullptr, numBarriers, barriers);
1736 fCurrentDirectCommandList->addGrBuffer(sk_ref_sp<const GrBuffer>(buffer));
1737}
1738
1742 const skgpu::MutableTextureState* newState) {
1743 // prepare proxies by transitioning to PRESENT renderState
1744 if (!proxies.empty() && access == SkSurfaces::BackendSurfaceAccess::kPresent) {
1745 GrD3DTextureResource* resource;
1746 for (GrSurfaceProxy* proxy : proxies) {
1747 SkASSERT(proxy->isInstantiated());
1748 if (GrTexture* tex = proxy->peekTexture()) {
1749 resource = static_cast<GrD3DTexture*>(tex);
1750 } else {
1751 GrRenderTarget* rt = proxy->peekRenderTarget();
1752 SkASSERT(rt);
1753 resource = static_cast<GrD3DRenderTarget*>(rt);
1754 }
1755 resource->prepareForPresent(this);
1756 }
1757 }
1758}
1759
1761 fCurrentDirectCommandList->addGrBuffer(std::move(buffer));
1762}
1763
1765 if (sync == GrSyncCpu::kYes) {
1766 return this->submitDirectCommandList(SyncQueue::kForce);
1767 } else {
1768 return this->submitDirectCommandList(SyncQueue::kSkip);
1769 }
1770}
1771
1772[[nodiscard]] std::unique_ptr<GrSemaphore> GrD3DGpu::makeSemaphore(bool) {
1773 return GrD3DSemaphore::Make(this);
1774}
1775std::unique_ptr<GrSemaphore> GrD3DGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
1776 GrSemaphoreWrapType /* wrapType */,
1777 GrWrapOwnership /* ownership */) {
1778 SkASSERT(this->caps()->backendSemaphoreSupport());
1779 GrD3DFenceInfo fenceInfo;
1780 if (!semaphore.getD3DFenceInfo(&fenceInfo)) {
1781 return nullptr;
1782 }
1783 return GrD3DSemaphore::MakeWrapped(fenceInfo);
1784}
1785
1787 SkASSERT(semaphore);
1788 GrD3DSemaphore* d3dSem = static_cast<GrD3DSemaphore*>(semaphore);
1789 // TODO: Do we need to track the lifetime of this? How do we know it's done?
1790 fQueue->Signal(d3dSem->fence(), d3dSem->value());
1791}
1792
1794 SkASSERT(semaphore);
1795 GrD3DSemaphore* d3dSem = static_cast<GrD3DSemaphore*>(semaphore);
1796 // TODO: Do we need to track the lifetime of this?
1797 fQueue->Wait(d3dSem->fence(), d3dSem->value());
1798}
1799
1801 this->waitForQueueCompletion();
1802}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
size_t GrBackendFormatBytesPerPixel(const GrBackendFormat &format)
SkTextureCompressionType GrBackendFormatToCompressionType(const GrBackendFormat &format)
static bool is_bgra(DXGI_FORMAT format)
static void copy_compressed_data(char *mapPtr, DXGI_FORMAT dxgiFormat, D3D12_PLACED_SUBRESOURCE_FOOTPRINT *placedFootprints, UINT *numRows, UINT64 *rowSizeInBytes, const void *compressedData, int numMipLevels)
Definition GrD3DGpu.cpp:339
static bool check_resource_info(const GrD3DTextureResourceInfo &info)
Definition GrD3DGpu.cpp:961
static bool check_rt_resource_info(const GrD3DCaps &caps, const GrD3DTextureResourceInfo &info, int sampleCnt)
Definition GrD3DGpu.cpp:979
static const int kDefaultOutstandingAllocCnt
Definition GrD3DGpu.cpp:74
static int get_surface_sample_cnt(GrSurface *surf)
Definition GrD3DGpu.cpp:435
static bool is_odd(int x)
constexpr int kConstantAlignment
Definition GrD3DGpu.cpp:77
static bool check_tex_resource_info(const GrD3DCaps &caps, const GrD3DTextureResourceInfo &info)
Definition GrD3DGpu.cpp:968
static bool copy_color_data(const GrD3DCaps &caps, char *mapPtr, DXGI_FORMAT dxgiFormat, SkISize dimensions, D3D12_PLACED_SUBRESOURCE_FOOTPRINT *placedFootprints, std::array< float, 4 > color)
bool GrDxgiFormatIsCompressed(DXGI_FORMAT format)
Definition GrD3DUtil.cpp:15
static constexpr size_t GrDxgiFormatBytesPerBlock(DXGI_FORMAT format)
Definition GrD3DUtil.h:101
#define GR_D3D_CALL_ERRCHECK(X)
Definition GrD3DUtil.h:16
bool GrClearImage(const GrImageInfo &dstInfo, void *dst, size_t dstRB, std::array< float, 4 > color)
GrWrapCacheable
Definition GrTypesPriv.h:84
static constexpr size_t GrColorTypeBytesPerPixel(GrColorType ct)
GrIOType
@ kRead_GrIOType
@ kRW_GrIOType
GrMipmapStatus
GrWrapOwnership
Definition GrTypesPriv.h:76
GrGpuBufferType
GrTexturable
Definition GrTypesPriv.h:63
GrSemaphoreWrapType
GrColorType
GrAccessPattern
@ kDynamic_GrAccessPattern
GrSurfaceOrigin
Definition GrTypes.h:147
@ kTopLeft_GrSurfaceOrigin
Definition GrTypes.h:148
void * GrGpuFinishedContext
Definition GrTypes.h:178
void(* GrGpuFinishedProc)(GrGpuFinishedContext finishedContext)
Definition GrTypes.h:179
GrSyncCpu
Definition GrTypes.h:239
GrXferBarrierFlags
SkColor4f color
kUnpremul_SkAlphaType
#define SkAssertResult(cond)
Definition SkAssert.h:123
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
#define SkASSERT(cond)
Definition SkAssert.h:116
size_t SkCompressedFormatDataSize(SkTextureCompressionType compressionType, SkISize dimensions, bool mipmapped)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
#define INHERITED(method,...)
static void SkRectMemcpy(void *dst, size_t dstRB, const void *src, size_t srcRB, size_t trimRowBytes, int rowCount)
sk_sp< T > sk_ref_sp(T *obj)
Definition SkRefCnt.h:381
SkFilterMode
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
GrBackendApi backend() const
SkISize dimensions() const
SkISize dimensions() const
bool hasMipmaps() const
GrBackendApi backend() const
bool mipmapSupport() const
Definition GrCaps.h:72
virtual bool isFormatTexturable(const GrBackendFormat &, GrTextureType) const =0
static sk_sp< GrD3DMemoryAllocator > Make(IDXGIAdapter *adapter, ID3D12Device *device)
static sk_sp< GrD3DAttachment > MakeStencil(GrD3DGpu *gpu, SkISize dimensions, int sampleCnt, DXGI_FORMAT format)
ID3D12Resource * d3dResource() const
Definition GrD3DBuffer.h:24
static sk_sp< GrD3DBuffer > Make(GrD3DGpu *, size_t size, GrGpuBufferType, GrAccessPattern)
GrColorType getFormatColorType(DXGI_FORMAT) const
DXGI_FORMAT getFormatFromColorType(GrColorType colorType) const
Definition GrD3DCaps.h:91
bool isFormatRenderable(const GrBackendFormat &format, int sampleCount) const override
DXGI_FORMAT preferredStencilFormat() const
Definition GrD3DCaps.h:62
bool canCopyAsResolve(DXGI_FORMAT dstFormat, int dstSampleCnt, DXGI_FORMAT srcFormat, int srcSamplecnt) const
Definition GrD3DCaps.cpp:83
bool isFormatTexturable(const GrBackendFormat &, GrTextureType) const override
int getRenderTargetSampleCount(int requestedCount, const GrBackendFormat &) const override
void addGrBuffer(sk_sp< const GrBuffer > buffer)
void aliasingBarrier(sk_sp< GrManagedResource > beforeManagedResource, ID3D12Resource *beforeResource, sk_sp< GrManagedResource > afterManagedResource, ID3D12Resource *afterResource)
void copyTextureToTexture(const GrD3DTexture *dst, const GrD3DTexture *src, UINT subresourceIndex=-1)
void uavBarrier(sk_sp< GrManagedResource > managedResource, ID3D12Resource *uavResource)
void copyBufferToTexture(ID3D12Resource *srcBuffer, const GrD3DTextureResource *dstTexture, uint32_t subresourceCount, D3D12_PLACED_SUBRESOURCE_FOOTPRINT *bufferFootprints, int left, int top)
void setComputeRootConstantBufferView(unsigned int rootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS bufferLocation)
void addSampledTextureRef(GrD3DTexture *)
void setComputeRootDescriptorTable(unsigned int rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE bufferLocation)
void setDescriptorHeaps(ID3D12DescriptorHeap *srvDescriptorHeap, ID3D12DescriptorHeap *samplerDescriptorHeap)
void setPipelineState(const sk_sp< GrD3DPipeline > &pipeline)
void dispatch(unsigned int threadGroupCountX, unsigned int threadGroupCountY, unsigned int threadGroupCountZ=1)
void setComputeRootSignature(const sk_sp< GrD3DRootSignature > &rootSignature)
sk_sp< GrTexture > onWrapCompressedBackendTexture(const GrBackendTexture &, GrWrapOwnership, GrWrapCacheable) override
void deleteBackendTexture(const GrBackendTexture &) override
bool onRegenerateMipMapLevels(GrTexture *) override
void addBufferResourceBarriers(GrD3DBuffer *buffer, int numBarriers, D3D12_RESOURCE_TRANSITION_BARRIER *barriers) const
GrD3DDirectCommandList * currentCommandList() const
Definition GrD3DGpu.h:48
void submit(GrOpsRenderPass *renderPass) override
Definition GrD3DGpu.cpp:233
void insertSemaphore(GrSemaphore *semaphore) override
sk_sp< GrGpuBuffer > onCreateBuffer(size_t sizeInBytes, GrGpuBufferType, GrAccessPattern) override
const GrD3DCaps & d3dCaps() const
Definition GrD3DGpu.h:36
bool compile(const GrProgramDesc &, const GrProgramInfo &) override
static std::unique_ptr< GrGpu > Make(const GrD3DBackendContext &backendContext, const GrContextOptions &, GrDirectContext *)
Definition GrD3DGpu.cpp:50
~GrD3DGpu() override
Definition GrD3DGpu.cpp:109
GrOpsRenderPass * onGetOpsRenderPass(GrRenderTarget *, bool useMSAASurface, GrAttachment *, GrSurfaceOrigin, const SkIRect &, const GrOpsRenderPass::LoadAndStoreInfo &, const GrOpsRenderPass::StencilLoadAndStoreInfo &, const skia_private::TArray< GrSurfaceProxy *, true > &sampledProxies, GrXferBarrierFlags renderPassXferBarriers) override
Definition GrD3DGpu.cpp:139
GrBackendTexture onCreateCompressedBackendTexture(SkISize dimensions, const GrBackendFormat &, skgpu::Mipmapped, GrProtected) override
std::unique_ptr< GrSemaphore > wrapBackendSemaphore(const GrBackendSemaphore &, GrSemaphoreWrapType, GrWrapOwnership) override
bool onTransferFromBufferToBuffer(sk_sp< GrGpuBuffer > src, size_t srcOffset, sk_sp< GrGpuBuffer > dst, size_t dstOffset, size_t size) override
Definition GrD3DGpu.cpp:816
void addFinishedProc(GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) override
Definition GrD3DGpu.cpp:245
void prepareSurfacesForBackendAccessAndStateUpdates(SkSpan< GrSurfaceProxy * > proxies, SkSurfaces::BackendSurfaceAccess access, const skgpu::MutableTextureState *newState) override
bool onSubmitToGpu(GrSyncCpu sync) override
void waitSemaphore(GrSemaphore *semaphore) override
bool onTransferPixelsFrom(GrSurface *, SkIRect, GrColorType surfaceColorType, GrColorType bufferColorType, sk_sp< GrGpuBuffer >, size_t offset) override
Definition GrD3DGpu.cpp:908
GrD3DMemoryAllocator * memoryAllocator() const
Definition GrD3DGpu.h:46
bool onReadPixels(GrSurface *, SkIRect, GrColorType surfaceColorType, GrColorType dstColorType, void *, size_t rowBytes) override
Definition GrD3DGpu.cpp:586
void addResourceBarriers(sk_sp< GrManagedResource > resource, int numBarriers, D3D12_RESOURCE_TRANSITION_BARRIER *barriers) const
void takeOwnershipOfBuffer(sk_sp< GrGpuBuffer >) override
GrBackendTexture onCreateBackendTexture(SkISize dimensions, const GrBackendFormat &, GrRenderable, skgpu::Mipmapped, GrProtected, std::string_view label) override
void onResolveRenderTarget(GrRenderTarget *target, const SkIRect &) override
Definition GrD3DGpu.cpp:578
void endRenderPass(GrRenderTarget *target, GrSurfaceOrigin origin, const SkIRect &bounds)
Definition GrD3DGpu.cpp:240
GrD3DResourceProvider & resourceProvider()
Definition GrD3DGpu.h:38
sk_sp< GrThreadSafePipelineBuilder > refPipelineBuilder() override
Definition GrD3DGpu.cpp:45
std::unique_ptr< GrSemaphore > makeSemaphore(bool isOwned) override
GrThreadSafePipelineBuilder * pipelineBuilder() override
Definition GrD3DGpu.cpp:41
bool protectedContext() const
Definition GrD3DGpu.h:55
sk_sp< GrTexture > onCreateCompressedTexture(SkISize dimensions, const GrBackendFormat &, skgpu::Budgeted, skgpu::Mipmapped, GrProtected, const void *data, size_t dataSize) override
Definition GrD3DGpu.cpp:358
bool onUpdateCompressedBackendTexture(const GrBackendTexture &, sk_sp< skgpu::RefCntedCallback > finishedCallback, const void *data, size_t size) override
sk_sp< GrTexture > onWrapRenderableBackendTexture(const GrBackendTexture &, int sampleCnt, GrWrapOwnership, GrWrapCacheable) override
sk_sp< GrTexture > onCreateTexture(SkISize, const GrBackendFormat &, GrRenderable, int renderTargetSampleCnt, skgpu::Budgeted, GrProtected, int mipLevelCount, uint32_t levelClearMask, std::string_view label) override
Definition GrD3DGpu.cpp:309
void finishOutstandingGpuWork() override
bool onTransferPixelsTo(GrTexture *, SkIRect, GrColorType surfaceColorType, GrColorType bufferColorType, sk_sp< GrGpuBuffer >, size_t offset, size_t rowBytes) override
Definition GrD3DGpu.cpp:840
sk_sp< GrRenderTarget > onWrapBackendRenderTarget(const GrBackendRenderTarget &) override
bool onCopySurface(GrSurface *dst, const SkIRect &dstRect, GrSurface *src, const SkIRect &srcRect, GrSamplerState::Filter) override
Definition GrD3DGpu.cpp:442
sk_sp< GrAttachment > makeStencilAttachment(const GrBackendFormat &, SkISize dimensions, int numStencilSamples) override
sk_sp< GrTexture > onWrapBackendTexture(const GrBackendTexture &, GrWrapOwnership, GrWrapCacheable, GrIOType) override
Definition GrD3DGpu.cpp:987
bool onWritePixels(GrSurface *, SkIRect, GrColorType surfaceColorType, GrColorType srcColorType, const GrMipLevel[], int mipLevelCount, bool prepForTexSampling) override
Definition GrD3DGpu.cpp:688
bool onClearBackendTexture(const GrBackendTexture &, sk_sp< skgpu::RefCntedCallback > finishedCallback, std::array< float, 4 > color) override
static sk_sp< GrD3DRenderTarget > MakeWrappedRenderTarget(GrD3DGpu *, SkISize, int sampleCnt, const GrD3DTextureResourceInfo &, sk_sp< GrD3DResourceState >)
const GrD3DTextureResource * msaaTextureResource() const
void recycleDirectCommandList(std::unique_ptr< GrD3DDirectCommandList >)
GrD3DDescriptorHeap::CPUHandle createUnorderedAccessView(ID3D12Resource *resource, unsigned int mipSlice)
void recycleShaderView(const GrD3DDescriptorHeap::CPUHandle &)
GrD3DDescriptorHeap::CPUHandle createShaderResourceView(ID3D12Resource *resource, unsigned int mostDetailedMip=0, unsigned int mipLevels=-1)
D3D12_GPU_VIRTUAL_ADDRESS uploadConstantData(void *data, size_t size)
sk_sp< GrD3DDescriptorTable > findOrCreateShaderViewTable(const std::vector< D3D12_CPU_DESCRIPTOR_HANDLE > &shaderViews)
D3D12_CPU_DESCRIPTOR_HANDLE findOrCreateCompatibleSampler(const GrSamplerState &params)
sk_sp< GrD3DPipeline > findOrCreateMipmapPipeline()
std::unique_ptr< GrD3DDirectCommandList > findOrCreateDirectCommandList()
sk_sp< GrD3DDescriptorTable > findOrCreateSamplerTable(const std::vector< D3D12_CPU_DESCRIPTOR_HANDLE > &samplers)
sk_sp< GrD3DRootSignature > findOrCreateRootSignature(int numTextureSamplers, int numUAVs=0)
static std::unique_ptr< GrD3DSemaphore > Make(GrD3DGpu *gpu)
uint64_t value() const
ID3D12Fence * fence() const
static std::unique_ptr< GrD3DSemaphore > MakeWrapped(const GrD3DFenceInfo &)
static sk_sp< GrD3DTextureRenderTarget > MakeWrappedTextureRenderTarget(GrD3DGpu *, SkISize dimensions, int sampleCnt, GrWrapCacheable, const GrD3DTextureResourceInfo &, sk_sp< GrD3DResourceState >)
static sk_sp< GrD3DTextureRenderTarget > MakeNewTextureRenderTarget(GrD3DGpu *, skgpu::Budgeted, SkISize dimensions, int sampleCnt, const D3D12_RESOURCE_DESC &, GrProtected isProtected, GrMipmapStatus, std::string_view label)
DXGI_FORMAT dxgiFormat() const
void prepareForPresent(GrD3DGpu *gpu)
void setResourceState(const GrD3DGpu *gpu, D3D12_RESOURCE_STATES newResourceState, unsigned int subresource=D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES)
ID3D12Resource * d3dResource() const
static bool InitTextureResourceInfo(GrD3DGpu *gpu, const D3D12_RESOURCE_DESC &desc, D3D12_RESOURCE_STATES initialState, GrProtected, D3D12_CLEAR_VALUE *, GrD3DTextureResourceInfo *)
sk_sp< Resource > resource() const
static sk_sp< GrD3DTexture > MakeNewTexture(GrD3DGpu *, skgpu::Budgeted, SkISize dimensions, const D3D12_RESOURCE_DESC &, GrProtected, GrMipmapStatus, std::string_view label)
static sk_sp< GrD3DTexture > MakeAliasingTexture(GrD3DGpu *, sk_sp< GrD3DTexture >, const D3D12_RESOURCE_DESC &newDesc, D3D12_RESOURCE_STATES)
static sk_sp< GrD3DTexture > MakeWrappedTexture(GrD3DGpu *, SkISize dimensions, GrWrapCacheable, GrIOType, const GrD3DTextureResourceInfo &, sk_sp< GrD3DResourceState >)
GrBackendFormat backendFormat() const override
GrResourceProvider * resourceProvider()
GrDirectContextPriv priv()
void incStencilAttachmentCreates()
Definition GrGpu.h:539
bool submitToGpu(GrSyncCpu sync)
Definition GrGpu.cpp:748
const GrCaps * caps() const
Definition GrGpu.h:73
GrDirectContext * getContext()
Definition GrGpu.h:67
void didWriteToSurface(GrSurface *surface, GrSurfaceOrigin origin, const SkIRect *bounds, uint32_t mipLevels=1) const
Definition GrGpu.cpp:665
Stats fStats
Definition GrGpu.h:703
int numSamples() const
Slice allocateStagingBufferSlice(size_t size, size_t requiredAlignment=1)
SkISize dimensions() const
Definition GrSurface.h:27
bool isProtected() const
Definition GrSurface.h:87
int height() const
Definition GrSurface.h:37
virtual GrRenderTarget * asRenderTarget()
Definition GrSurface.h:65
int width() const
Definition GrSurface.h:32
int maxMipmapLevel() const
Definition GrTexture.h:67
void markMipmapsDirty()
Definition GrTexture.cpp:25
GrTextureType textureType() const
Definition GrTexture.h:55
void * push_back()
Definition SkDeque.cpp:112
const void * front() const
Definition SkDeque.h:42
void pop_front()
Definition SkDeque.cpp:153
bool empty() const
Definition SkDeque.h:38
const void * back() const
Definition SkDeque.h:43
static int ComputeLevelCount(int baseWidth, int baseHeight)
Definition SkMipmap.cpp:134
constexpr bool empty() const
Definition SkSpan_impl.h:96
T * get() const
Definition GrD3DTypes.h:108
T * get() const
Definition SkRefCnt.h:303
static sk_sp< RefCntedCallback > Make(Callback proc, Context ctx)
int size() const
Definition SkTArray.h:416
VkSurfaceKHR surface
Definition main.cc:49
AtkStateType state
static const uint8_t buffer[]
uint32_t uint32_t * format
uint32_t * target
return FALSE
FlTexture * texture
double x
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350
BackendSurfaceAccess
Definition SkSurface.h:44
@ kPresent
back-end surface will be used for presenting to screen
dst
Definition cp.py:12
Budgeted
Definition GpuTypes.h:35
Renderable
Definition GpuTypes.h:69
Mipmapped
Definition GpuTypes.h:53
Protected
Definition GpuTypes.h:61
Definition ref_ptr.h:256
SkScalar w
SkScalar h
int32_t height
int32_t width
Point offset
gr_cp< ID3D12Device > fDevice
sk_sp< GrD3DMemoryAllocator > fMemoryAllocator
gr_cp< IDXGIAdapter1 > fAdapter
D3D12_CPU_DESCRIPTOR_HANDLE fHandle
gr_cp< ID3D12Resource > fResource
Definition GrD3DTypes.h:180
size_t fRowBytes
int32_t fX
x-axis value
int32_t fY
y-axis value
int32_t fBottom
larger y-axis bounds
Definition SkRect.h:36
constexpr SkISize size() const
Definition SkRect.h:172
constexpr int32_t height() const
Definition SkRect.h:165
int32_t fTop
smaller y-axis bounds
Definition SkRect.h:34
static constexpr SkIRect MakeSize(const SkISize &size)
Definition SkRect.h:66
constexpr int32_t width() const
Definition SkRect.h:158
constexpr SkIPoint topLeft() const
Definition SkRect.h:151
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition SkRect.h:104
int32_t fLeft
smaller x-axis bounds
Definition SkRect.h:33
bool contains(int32_t x, int32_t y) const
Definition SkRect.h:463
int32_t fRight
larger x-axis bounds
Definition SkRect.h:35
int32_t fHeight
Definition SkSize.h:18
int32_t fWidth
Definition SkSize.h:17
constexpr int32_t width() const
Definition SkSize.h:36
constexpr int32_t height() const
Definition SkSize.h:37
unsigned int UINT
#define CreateEvent
void * HANDLE
#define FAILED(hr)