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