Flutter Engine
The Flutter Engine
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
42 return nullptr;
43}
44
46 return nullptr;
47}
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
139GrOpsRenderPass* GrD3DGpu::onGetOpsRenderPass(
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
245void GrD3DGpu::addFinishedProc(GrGpuFinishedProc finishedProc,
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
309sk_sp<GrTexture> GrD3DGpu::onCreateTexture(SkISize dimensions,
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
358sk_sp<GrTexture> GrD3DGpu::onCreateCompressedTexture(SkISize dimensions,
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,
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
578void GrD3DGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect) {
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
586bool GrD3DGpu::onReadPixels(GrSurface* surface,
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,
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
688bool GrD3DGpu::onWritePixels(GrSurface* surface,
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,
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
816bool GrD3DGpu::onTransferFromBufferToBuffer(sk_sp<GrGpuBuffer> src,
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
840bool GrD3DGpu::onTransferPixelsTo(GrTexture* texture,
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
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
908bool GrD3DGpu::onTransferPixelsFrom(GrSurface* surface,
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
987sk_sp<GrTexture> GrD3DGpu::onWrapBackendTexture(const GrBackendTexture& tex,
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
1015sk_sp<GrTexture> GrD3DGpu::onWrapCompressedBackendTexture(const GrBackendTexture& tex,
1016 GrWrapOwnership ownership,
1017 GrWrapCacheable wrapType) {
1018 return this->onWrapBackendTexture(tex, ownership, wrapType, kRead_GrIOType);
1019}
1020
1021sk_sp<GrTexture> GrD3DGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
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
1056sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt) {
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
1104bool GrD3DGpu::onRegenerateMipMapLevels(GrTexture * tex) {
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
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
1318sk_sp<GrGpuBuffer> GrD3DGpu::onCreateBuffer(size_t sizeInBytes,
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
1402GrBackendTexture GrD3DGpu::onCreateBackendTexture(SkISize dimensions,
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
1452bool GrD3DGpu::onClearBackendTexture(const GrBackendTexture& backendTexture,
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
1546GrBackendTexture GrD3DGpu::onCreateCompressedBackendTexture(SkISize dimensions,
1547 const GrBackendFormat& format,
1548 skgpu::Mipmapped mipmapped,
1549 GrProtected isProtected) {
1550 return this->onCreateBackendTexture(dimensions,
1551 format,
1553 mipmapped,
1554 isProtected,
1555 /*label=*/"D3DGpu_CreateCompressedBackendTexture");
1556}
1557
1558bool GrD3DGpu::onUpdateCompressedBackendTexture(const GrBackendTexture& backendTexture,
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,
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);
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
1739void GrD3DGpu::prepareSurfacesForBackendAccessAndStateUpdates(
1742 const skgpu::MutableTextureState* newState) {
1743 // prepare proxies by transitioning to PRESENT renderState
1744 if (!proxies.empty() && access == SkSurfaces::BackendSurfaceAccess::kPresent) {
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
1764bool GrD3DGpu::onSubmitToGpu(GrSyncCpu sync) {
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
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
size_t GrBackendFormatBytesPerPixel(const GrBackendFormat &format)
SkTextureCompressionType GrBackendFormatToCompressionType(const GrBackendFormat &format)
static bool is_bgra(DXGI_FORMAT format)
Definition: GrD3DGpu.cpp:1099
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)
Definition: GrD3DGpu.cpp:1089
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)
Definition: GrD3DGpu.cpp:1434
bool GrDxgiFormatIsCompressed(DXGI_FORMAT format)
Definition: GrD3DUtil.cpp:15
static constexpr size_t GrDxgiFormatBytesPerBlock(DXGI_FORMAT format)
Definition: GrD3DUtil.h:103
#define GR_D3D_CALL_ERRCHECK(X)
Definition: GrD3DUtil.h:18
bool GrClearImage(const GrImageInfo &dstInfo, void *dst, size_t dstRB, std::array< float, 4 > color)
GrWrapCacheable
Definition: GrTypesPriv.h:85
static constexpr size_t GrColorTypeBytesPerPixel(GrColorType ct)
Definition: GrTypesPriv.h:896
GrIOType
Definition: GrTypesPriv.h:402
@ kRead_GrIOType
Definition: GrTypesPriv.h:403
@ kRW_GrIOType
Definition: GrTypesPriv.h:405
GrMipmapStatus
Definition: GrTypesPriv.h:523
GrWrapOwnership
Definition: GrTypesPriv.h:77
GrGpuBufferType
Definition: GrTypesPriv.h:411
GrTexturable
Definition: GrTypesPriv.h:64
GrSemaphoreWrapType
Definition: GrTypesPriv.h:146
GrColorType
Definition: GrTypesPriv.h:540
GrAccessPattern
Definition: GrTypesPriv.h:424
@ kDynamic_GrAccessPattern
Definition: GrTypesPriv.h:426
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
kUnpremul_SkAlphaType
#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
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static SkString resource(SkPDFResourceType type, int index)
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
static void SkRectMemcpy(void *dst, size_t dstRB, const void *src, size_t srcRB, size_t trimRowBytes, int rowCount)
Definition: SkRectMemcpy.h:16
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
SkFilterMode
SkTextureCompressionType
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
GLenum type
GrBackendApi backend() const
SkISize dimensions() const
SkISize dimensions() const
bool hasMipmaps() const
bool isProtected() 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)
Definition: GrD3DBuffer.cpp:64
GrColorType getFormatColorType(DXGI_FORMAT) const
Definition: GrD3DCaps.cpp:899
DXGI_FORMAT getFormatFromColorType(GrColorType colorType) const
Definition: GrD3DCaps.h:91
bool isFormatRenderable(const GrBackendFormat &format, int sampleCount) const override
Definition: GrD3DCaps.cpp:830
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
Definition: GrD3DCaps.cpp:800
int getRenderTargetSampleCount(int requestedCount, const GrBackendFormat &) const override
Definition: GrD3DCaps.cpp:847
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)
void deleteBackendTexture(const GrBackendTexture &) override
Definition: GrD3DGpu.cpp:1644
void addBufferResourceBarriers(GrD3DBuffer *buffer, int numBarriers, D3D12_RESOURCE_TRANSITION_BARRIER *barriers) const
Definition: GrD3DGpu.cpp:1729
GrD3DDirectCommandList * currentCommandList() const
Definition: GrD3DGpu.h:48
void submit(GrOpsRenderPass *renderPass) override
Definition: GrD3DGpu.cpp:233
void insertSemaphore(GrSemaphore *semaphore) override
Definition: GrD3DGpu.cpp:1786
const GrD3DCaps & d3dCaps() const
Definition: GrD3DGpu.h:36
bool compile(const GrProgramDesc &, const GrProgramInfo &) override
Definition: GrD3DGpu.cpp:1649
static std::unique_ptr< GrGpu > Make(const GrD3DBackendContext &backendContext, const GrContextOptions &, GrDirectContext *)
Definition: GrD3DGpu.cpp:50
~GrD3DGpu() override
Definition: GrD3DGpu.cpp:109
std::unique_ptr< GrSemaphore > wrapBackendSemaphore(const GrBackendSemaphore &, GrSemaphoreWrapType, GrWrapOwnership) override
Definition: GrD3DGpu.cpp:1775
void waitSemaphore(GrSemaphore *semaphore) override
Definition: GrD3DGpu.cpp:1793
GrD3DMemoryAllocator * memoryAllocator() const
Definition: GrD3DGpu.h:46
void addResourceBarriers(sk_sp< GrManagedResource > resource, int numBarriers, D3D12_RESOURCE_TRANSITION_BARRIER *barriers) const
Definition: GrD3DGpu.cpp:1720
void takeOwnershipOfBuffer(sk_sp< GrGpuBuffer >) override
Definition: GrD3DGpu.cpp:1760
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
Definition: GrD3DGpu.cpp:1772
GrThreadSafePipelineBuilder * pipelineBuilder() override
Definition: GrD3DGpu.cpp:41
bool protectedContext() const
Definition: GrD3DGpu.h:55
void finishOutstandingGpuWork() override
Definition: GrD3DGpu.cpp:1800
sk_sp< GrAttachment > makeStencilAttachment(const GrBackendFormat &, SkISize dimensions, int numStencilSamples) override
Definition: GrD3DGpu.cpp:1324
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
uint32_t mipLevels() const
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
Definition: GrD3DTexture.h:44
GrResourceProvider * resourceProvider()
GrDirectContextPriv priv()
void * map()
Definition: GrGpuBuffer.cpp:28
void unmap()
Definition: GrGpuBuffer.cpp:38
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
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:421
DlColor color
VkSurfaceKHR surface
Definition: main.cc:49
EMSCRIPTEN_KEEPALIVE void empty()
AtkStateType state
uint32_t uint32_t * format
uint32_t * target
static float max(float r, float g, float b)
Definition: hsl.cpp:49
return FALSE
FlTexture * texture
double x
Optional< SkRect > bounds
Definition: SkRecords.h:189
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
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
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
SeparatedVector2 offset
gr_cp< ID3D12Device > fDevice
sk_sp< GrD3DMemoryAllocator > fMemoryAllocator
gr_cp< IDXGIAdapter1 > fAdapter
D3D12_CPU_DESCRIPTOR_HANDLE fHandle
size_t fRowBytes
Definition: GrTypesPriv.h:136
int32_t fX
x-axis value
Definition: SkPoint_impl.h:29
int32_t fY
y-axis value
Definition: SkPoint_impl.h:30
Definition: SkRect.h:32
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
Definition: SkSize.h:16
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
Definition: SkSize.h:52
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
unsigned int UINT
Definition: windows_types.h:32
#define CreateEvent
void * HANDLE
Definition: windows_types.h:36
#define FAILED(hr)