blob: c41ae081e01fcd236f38e7c29206690a14a24bfe [file] [log] [blame]
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -05001/*
Jim Van Verth03b8ab22020-02-24 11:36:15 -05002 * Copyright 2020 Google LLC
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -05003 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -05008#include "src/gpu/d3d/GrD3DGpu.h"
9
Jim Van Verth96bfeff2020-04-09 14:36:12 -040010#include "include/gpu/GrBackendSurface.h"
Jim Van Verth9aa9a682020-04-01 10:13:48 -040011#include "include/gpu/d3d/GrD3DBackendContext.h"
Jim Van Verthc632aa62020-04-17 16:58:20 -040012#include "src/core/SkConvertPixels.h"
Jim Van Verth96bfeff2020-04-09 14:36:12 -040013#include "src/core/SkMipMap.h"
Jim Van Verthc632aa62020-04-17 16:58:20 -040014#include "src/gpu/GrDataUtils.h"
15#include "src/gpu/GrTexturePriv.h"
Jim Van Verthd6ad4802020-04-03 14:59:20 -040016#include "src/gpu/d3d/GrD3DBuffer.h"
Greg Daniel31a7b072020-02-26 15:31:49 -050017#include "src/gpu/d3d/GrD3DCaps.h"
18#include "src/gpu/d3d/GrD3DOpsRenderPass.h"
Jim Van Verth4f51f472020-04-13 11:02:21 -040019#include "src/gpu/d3d/GrD3DStencilAttachment.h"
Jim Van Verthaa90dad2020-03-30 15:00:39 -040020#include "src/gpu/d3d/GrD3DTexture.h"
21#include "src/gpu/d3d/GrD3DTextureRenderTarget.h"
22#include "src/gpu/d3d/GrD3DUtil.h"
Greg Daniel5fc5c812020-04-23 10:30:23 -040023#include "src/sksl/SkSLCompiler.h"
Greg Daniel31a7b072020-02-26 15:31:49 -050024
Jim Van Verth9b5e16c2020-04-20 10:45:52 -040025#if GR_TEST_UTILS
26#include <DXProgrammableCapture.h>
27#endif
28
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050029sk_sp<GrGpu> GrD3DGpu::Make(const GrD3DBackendContext& backendContext,
30 const GrContextOptions& contextOptions, GrContext* context) {
31 return sk_sp<GrGpu>(new GrD3DGpu(context, contextOptions, backendContext));
32}
33
Greg Daniel83ed2132020-03-24 13:15:33 -040034// This constant determines how many OutstandingCommandLists are allocated together as a block in
35// the deque. As such it needs to balance allocating too much memory vs. incurring
36// allocation/deallocation thrashing. It should roughly correspond to the max number of outstanding
37// command lists we expect to see.
38static const int kDefaultOutstandingAllocCnt = 8;
39
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050040GrD3DGpu::GrD3DGpu(GrContext* context, const GrContextOptions& contextOptions,
41 const GrD3DBackendContext& backendContext)
Jim Van Verth03b8ab22020-02-24 11:36:15 -050042 : INHERITED(context)
43 , fDevice(backendContext.fDevice)
Greg Daniel02c45902020-03-09 10:58:09 -040044
45 , fQueue(backendContext.fQueue)
Greg Daniel83ed2132020-03-24 13:15:33 -040046 , fResourceProvider(this)
Greg Daniel5fc5c812020-04-23 10:30:23 -040047 , fOutstandingCommandLists(sizeof(OutstandingCommandList), kDefaultOutstandingAllocCnt)
48 , fCompiler(new SkSL::Compiler()) {
Jim Van Verth8ec13302020-02-26 12:59:56 -050049 fCaps.reset(new GrD3DCaps(contextOptions,
Jim Van Verth9aa9a682020-04-01 10:13:48 -040050 backendContext.fAdapter.get(),
51 backendContext.fDevice.get()));
Greg Daniel85da3362020-03-09 15:18:35 -040052
53 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
Greg Daniele52c9782020-03-23 14:18:37 -040054 SkASSERT(fCurrentDirectCommandList);
Greg Daniel83ed2132020-03-24 13:15:33 -040055
56 SkASSERT(fCurrentFenceValue == 0);
57 SkDEBUGCODE(HRESULT hr = ) fDevice->CreateFence(fCurrentFenceValue, D3D12_FENCE_FLAG_NONE,
58 IID_PPV_ARGS(&fFence));
59 SkASSERT(SUCCEEDED(hr));
Jim Van Verth9b5e16c2020-04-20 10:45:52 -040060
61#if GR_TEST_UTILS
62 HRESULT getAnalysis = DXGIGetDebugInterface1(0, IID_PPV_ARGS(&fGraphicsAnalysis));
63 if (FAILED(getAnalysis)) {
64 fGraphicsAnalysis = nullptr;
65 }
66#endif
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050067}
68
Greg Daniel83ed2132020-03-24 13:15:33 -040069GrD3DGpu::~GrD3DGpu() {
70 this->destroyResources();
71}
72
73void GrD3DGpu::destroyResources() {
74 if (fCurrentDirectCommandList) {
75 fCurrentDirectCommandList->close();
Jim Van Verthba7f2292020-04-21 08:56:47 -040076 fCurrentDirectCommandList->reset();
Greg Daniel83ed2132020-03-24 13:15:33 -040077 }
78
79 // We need to make sure everything has finished on the queue.
Jim Van Verthc632aa62020-04-17 16:58:20 -040080 this->waitForQueueCompletion();
Greg Daniel83ed2132020-03-24 13:15:33 -040081
82 SkDEBUGCODE(uint64_t fenceValue = fFence->GetCompletedValue();)
83
84 // We used a placement new for each object in fOutstandingCommandLists, so we're responsible
85 // for calling the destructor on each of them as well.
86 while (!fOutstandingCommandLists.empty()) {
87 OutstandingCommandList* list = (OutstandingCommandList*)fOutstandingCommandLists.back();
88 SkASSERT(list->fFenceValue <= fenceValue);
89 // No reason to recycle the command lists since we are destroying all resources anyways.
90 list->~OutstandingCommandList();
91 fOutstandingCommandLists.pop_back();
92 }
93}
Greg Daniel31a7b072020-02-26 15:31:49 -050094
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050095GrOpsRenderPass* GrD3DGpu::getOpsRenderPass(
Robert Phillips96f22372020-05-20 12:31:18 -040096 GrRenderTarget* rt, GrStencilAttachment*,
97 GrSurfaceOrigin origin, const SkIRect& bounds,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050098 const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
Greg Daniel31a7b072020-02-26 15:31:49 -050099 const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500100 const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
Greg Daniel31a7b072020-02-26 15:31:49 -0500101 if (!fCachedOpsRenderPass) {
102 fCachedOpsRenderPass.reset(new GrD3DOpsRenderPass(this));
103 }
104
105 if (!fCachedOpsRenderPass->set(rt, origin, bounds, colorInfo, stencilInfo, sampledProxies)) {
106 return nullptr;
107 }
108 return fCachedOpsRenderPass.get();
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500109}
110
Jim Van Verthc632aa62020-04-17 16:58:20 -0400111bool GrD3DGpu::submitDirectCommandList(SyncQueue sync) {
Greg Daniel83ed2132020-03-24 13:15:33 -0400112 SkASSERT(fCurrentDirectCommandList);
113
Jim Van Verthc632aa62020-04-17 16:58:20 -0400114 GrD3DDirectCommandList::SubmitResult result = fCurrentDirectCommandList->submit(fQueue.get());
115 if (result == GrD3DDirectCommandList::SubmitResult::kFailure) {
116 return false;
117 } else if (result == GrD3DDirectCommandList::SubmitResult::kNoWork) {
118 if (sync == SyncQueue::kForce) {
119 this->waitForQueueCompletion();
Jim Van Verth682a2f42020-05-13 16:54:09 -0400120 this->checkForFinishedCommandLists();
Jim Van Verthc632aa62020-04-17 16:58:20 -0400121 }
122 return true;
123 }
Greg Daniel83ed2132020-03-24 13:15:33 -0400124
125 new (fOutstandingCommandLists.push_back()) OutstandingCommandList(
126 std::move(fCurrentDirectCommandList), ++fCurrentFenceValue);
127
Jim Van Verth9aa9a682020-04-01 10:13:48 -0400128 SkDEBUGCODE(HRESULT hr = ) fQueue->Signal(fFence.get(), fCurrentFenceValue);
Greg Daniel83ed2132020-03-24 13:15:33 -0400129 SkASSERT(SUCCEEDED(hr));
130
Jim Van Verthc632aa62020-04-17 16:58:20 -0400131 if (sync == SyncQueue::kForce) {
132 this->waitForQueueCompletion();
133 }
134
Greg Daniel83ed2132020-03-24 13:15:33 -0400135 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
136
137 // This should be done after we have a new command list in case the freeing of any resources
138 // held by a finished command list causes us send a new command to the gpu (like changing the
139 // resource state.
140 this->checkForFinishedCommandLists();
141
142 SkASSERT(fCurrentDirectCommandList);
Jim Van Verthc632aa62020-04-17 16:58:20 -0400143 return true;
Greg Daniel83ed2132020-03-24 13:15:33 -0400144}
145
146void GrD3DGpu::checkForFinishedCommandLists() {
147 uint64_t currentFenceValue = fFence->GetCompletedValue();
148
149 // Iterate over all the outstanding command lists to see if any have finished. The commands
150 // lists are in order from oldest to newest, so we start at the front to check if their fence
151 // value is less than the last signaled value. If so we pop it off and move onto the next.
152 // Repeat till we find a command list that has not finished yet (and all others afterwards are
153 // also guaranteed to not have finished).
154 SkDeque::F2BIter iter(fOutstandingCommandLists);
155 const OutstandingCommandList* curList = (const OutstandingCommandList*)iter.next();
156 while (curList && curList->fFenceValue <= currentFenceValue) {
157 curList = (const OutstandingCommandList*)iter.next();
158 OutstandingCommandList* front = (OutstandingCommandList*)fOutstandingCommandLists.front();
Greg Daniel7a5f1fa2020-03-24 14:50:19 -0400159 fResourceProvider.recycleDirectCommandList(std::move(front->fCommandList));
Greg Daniel83ed2132020-03-24 13:15:33 -0400160 // Since we used placement new we are responsible for calling the destructor manually.
161 front->~OutstandingCommandList();
162 fOutstandingCommandLists.pop_front();
163 }
164}
165
Jim Van Verthc632aa62020-04-17 16:58:20 -0400166void GrD3DGpu::waitForQueueCompletion() {
167 if (fFence->GetCompletedValue() < fCurrentFenceValue) {
168 HANDLE fenceEvent;
169 fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
170 SkASSERT(fenceEvent);
171 SkDEBUGCODE(HRESULT hr = ) fFence->SetEventOnCompletion(fCurrentFenceValue, fenceEvent);
172 SkASSERT(SUCCEEDED(hr));
173 WaitForSingleObject(fenceEvent, INFINITE);
174 CloseHandle(fenceEvent);
175 }
176}
177
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500178void GrD3DGpu::submit(GrOpsRenderPass* renderPass) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400179 SkASSERT(fCachedOpsRenderPass.get() == renderPass);
180
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500181 // TODO: actually submit something here
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400182 fCachedOpsRenderPass.reset();
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500183}
184
185void GrD3DGpu::querySampleLocations(GrRenderTarget* rt, SkTArray<SkPoint>* sampleLocations) {
186 // TODO
187}
188
189sk_sp<GrTexture> GrD3DGpu::onCreateTexture(SkISize dimensions,
190 const GrBackendFormat& format,
191 GrRenderable renderable,
192 int renderTargetSampleCnt,
193 SkBudgeted budgeted,
194 GrProtected isProtected,
195 int mipLevelCount,
196 uint32_t levelClearMask) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400197 DXGI_FORMAT dxgiFormat;
198 SkAssertResult(format.asDxgiFormat(&dxgiFormat));
199 SkASSERT(!GrDxgiFormatIsCompressed(dxgiFormat));
200
201 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
202
203 if (renderable == GrRenderable::kYes) {
204 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
205 }
206
207 // This desc refers to the texture that will be read by the client. Thus even if msaa is
208 // requested, this describes the resolved texture. Therefore we always have samples set
209 // to 1.
210 SkASSERT(mipLevelCount > 0);
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400211 D3D12_RESOURCE_DESC resourceDesc = {};
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400212 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
213 // TODO: will use 4MB alignment for MSAA textures and 64KB for everything else
214 // might want to manually set alignment to 4KB for smaller textures
215 resourceDesc.Alignment = 0;
216 resourceDesc.Width = dimensions.fWidth;
217 resourceDesc.Height = dimensions.fHeight;
218 resourceDesc.DepthOrArraySize = 1;
219 resourceDesc.MipLevels = mipLevelCount;
220 resourceDesc.Format = dxgiFormat;
221 resourceDesc.SampleDesc.Count = 1;
Greg Danielc9624d52020-04-13 15:36:31 -0400222 // quality levels are only supported for tiled resources so ignore for now
223 resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400224 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400225 resourceDesc.Flags = usageFlags;
226
227 GrMipMapsStatus mipMapsStatus =
228 mipLevelCount > 1 ? GrMipMapsStatus::kDirty : GrMipMapsStatus::kNotAllocated;
229
230 sk_sp<GrD3DTexture> tex;
231 if (renderable == GrRenderable::kYes) {
232 tex = GrD3DTextureRenderTarget::MakeNewTextureRenderTarget(
233 this, budgeted, dimensions, renderTargetSampleCnt, resourceDesc, isProtected,
234 mipMapsStatus);
235 } else {
236 tex = GrD3DTexture::MakeNewTexture(this, budgeted, dimensions, resourceDesc, isProtected,
237 mipMapsStatus);
238 }
239
240 if (!tex) {
241 return nullptr;
242 }
243
244 if (levelClearMask) {
245 // TODO
246 }
247 return std::move(tex);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500248}
249
250sk_sp<GrTexture> GrD3DGpu::onCreateCompressedTexture(SkISize dimensions,
251 const GrBackendFormat& format,
252 SkBudgeted budgeted,
253 GrMipMapped mipMapped,
254 GrProtected isProtected,
255 const void* data, size_t dataSize) {
256 // TODO
257 return nullptr;
258}
259
Jim Van Verth9145f782020-04-28 12:01:12 -0400260static int get_surface_sample_cnt(GrSurface* surf) {
261 if (const GrRenderTarget* rt = surf->asRenderTarget()) {
262 return rt->numSamples();
263 }
264 return 0;
265}
266
267bool GrD3DGpu::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
268 const SkIPoint& dstPoint) {
269
270 if (src->isProtected() && !dst->isProtected()) {
271 SkDebugf("Can't copy from protected memory to non-protected");
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400272 return false;
273 }
Jim Van Verth9145f782020-04-28 12:01:12 -0400274
275 int dstSampleCnt = get_surface_sample_cnt(dst);
276 int srcSampleCnt = get_surface_sample_cnt(src);
277
278 GrD3DTextureResource* dstTexResource;
279 GrD3DTextureResource* srcTexResource;
280 GrRenderTarget* dstRT = dst->asRenderTarget();
281 if (dstRT) {
282 GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(dstRT);
283 dstTexResource = d3dRT->numSamples() > 1 ? d3dRT->msaaTextureResource() : d3dRT;
284 } else {
285 SkASSERT(dst->asTexture());
286 dstTexResource = static_cast<GrD3DTexture*>(dst->asTexture());
287 }
288 GrRenderTarget* srcRT = src->asRenderTarget();
289 if (srcRT) {
290 GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(srcRT);
291 srcTexResource = d3dRT->numSamples() > 1 ? d3dRT->msaaTextureResource() : d3dRT;
292 } else {
293 SkASSERT(src->asTexture());
294 srcTexResource = static_cast<GrD3DTexture*>(src->asTexture());
295 }
296
297 DXGI_FORMAT dstFormat = dstTexResource->dxgiFormat();
298 DXGI_FORMAT srcFormat = srcTexResource->dxgiFormat();
299
300 if (this->d3dCaps().canCopyAsResolve(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt)) {
301 this->copySurfaceAsResolve(dst, src, srcRect, dstPoint);
302 return true;
303 }
304
305 if (this->d3dCaps().canCopyTexture(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt)) {
306 this->copySurfaceAsCopyTexture(dst, src, dstTexResource, srcTexResource, srcRect, dstPoint);
307 return true;
308 }
309
310 return false;
311}
312
313void GrD3DGpu::copySurfaceAsCopyTexture(GrSurface* dst, GrSurface* src,
314 GrD3DTextureResource* dstResource,
315 GrD3DTextureResource* srcResource,
316 const SkIRect& srcRect, const SkIPoint& dstPoint) {
317#ifdef SK_DEBUG
318 int dstSampleCnt = get_surface_sample_cnt(dst);
319 int srcSampleCnt = get_surface_sample_cnt(src);
320 DXGI_FORMAT dstFormat = dstResource->dxgiFormat();
321 DXGI_FORMAT srcFormat;
322 SkAssertResult(dst->backendFormat().asDxgiFormat(&srcFormat));
323 SkASSERT(this->d3dCaps().canCopyTexture(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt));
324#endif
325 if (src->isProtected() && !dst->isProtected()) {
326 SkDebugf("Can't copy from protected memory to non-protected");
327 return;
328 }
329
330 dstResource->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
331 srcResource->setResourceState(this, D3D12_RESOURCE_STATE_COPY_SOURCE);
332
333 D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
334 dstLocation.pResource = dstResource->d3dResource();
335 dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
336 dstLocation.SubresourceIndex = 0;
337
338 D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
339 srcLocation.pResource = srcResource->d3dResource();
340 srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
341 srcLocation.SubresourceIndex = 0;
342
343 D3D12_BOX srcBox = {};
344 srcBox.left = srcRect.fLeft;
345 srcBox.top = srcRect.fTop;
346 srcBox.right = srcRect.fRight;
347 srcBox.bottom = srcRect.fBottom;
348 srcBox.front = 0;
349 srcBox.back = 1;
350 // TODO: use copyResource if copying full resource and sizes match
351 fCurrentDirectCommandList->copyTextureRegion(dstResource->resource(),
352 &dstLocation,
353 dstPoint.fX, dstPoint.fY,
354 srcResource->resource(),
355 &srcLocation,
356 &srcBox);
357
358 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
359 srcRect.width(), srcRect.height());
360 // The rect is already in device space so we pass in kTopLeft so no flip is done.
361 this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
362}
363
364void GrD3DGpu::copySurfaceAsResolve(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
365 const SkIPoint& dstPoint) {
366 // TODO
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400367}
368
Jim Van Verthba7f2292020-04-21 08:56:47 -0400369bool GrD3DGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int height,
370 GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
371 size_t rowBytes) {
372 SkASSERT(surface);
373
374 if (surfaceColorType != dstColorType) {
375 return false;
376 }
377
378 // Set up src location and box
Jim Van Verthc12aad92020-04-24 16:19:01 -0400379 GrD3DTextureResource* texResource = nullptr;
380 GrD3DRenderTarget* rt = static_cast<GrD3DRenderTarget*>(surface->asRenderTarget());
381 if (rt) {
382 texResource = rt;
383 } else {
384 texResource = static_cast<GrD3DTexture*>(surface->asTexture());
385 }
386
387 if (!texResource) {
Jim Van Verthba7f2292020-04-21 08:56:47 -0400388 return false;
389 }
Jim Van Verthc12aad92020-04-24 16:19:01 -0400390
Jim Van Verthba7f2292020-04-21 08:56:47 -0400391 D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
Jim Van Verthc12aad92020-04-24 16:19:01 -0400392 srcLocation.pResource = texResource->d3dResource();
Jim Van Verthba7f2292020-04-21 08:56:47 -0400393 SkASSERT(srcLocation.pResource);
394 srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
395 srcLocation.SubresourceIndex = 0;
396
397 D3D12_BOX srcBox = {};
398 srcBox.left = left;
399 srcBox.top = top;
400 srcBox.right = left + width;
401 srcBox.bottom = top + height;
402 srcBox.front = 0;
403 srcBox.back = 1;
404
405 // Set up dst location and create transfer buffer
406 D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
407 dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
Jim Van Verthba7f2292020-04-21 08:56:47 -0400408 UINT64 transferTotalBytes;
409 const UINT64 baseOffset = 0;
410 D3D12_RESOURCE_DESC desc = srcLocation.pResource->GetDesc();
411 fDevice->GetCopyableFootprints(&desc, 0, 1, baseOffset, &dstLocation.PlacedFootprint,
Jim Van Verthfdd36852020-04-21 16:29:44 -0400412 nullptr, nullptr, &transferTotalBytes);
Jim Van Verthba7f2292020-04-21 08:56:47 -0400413 SkASSERT(transferTotalBytes);
Jim Van Verthfdd36852020-04-21 16:29:44 -0400414 size_t bpp = GrColorTypeBytesPerPixel(dstColorType);
Jim Van Verthc12aad92020-04-24 16:19:01 -0400415 if (this->d3dCaps().bytesPerPixel(texResource->dxgiFormat()) != bpp) {
Jim Van Verthfdd36852020-04-21 16:29:44 -0400416 return false;
417 }
418 size_t tightRowBytes = bpp * width;
Jim Van Verthba7f2292020-04-21 08:56:47 -0400419
420 // TODO: implement some way of reusing buffers instead of making a new one every time.
421 sk_sp<GrGpuBuffer> transferBuffer = this->createBuffer(transferTotalBytes,
422 GrGpuBufferType::kXferGpuToCpu,
423 kDynamic_GrAccessPattern);
424 GrD3DBuffer* d3dBuf = static_cast<GrD3DBuffer*>(transferBuffer.get());
425 dstLocation.pResource = d3dBuf->d3dResource();
426
427 // Need to change the resource state to COPY_SOURCE in order to download from it
Jim Van Verthc12aad92020-04-24 16:19:01 -0400428 texResource->setResourceState(this, D3D12_RESOURCE_STATE_COPY_SOURCE);
Jim Van Verthba7f2292020-04-21 08:56:47 -0400429
430 fCurrentDirectCommandList->copyTextureRegion(d3dBuf->resource(), &dstLocation, 0, 0,
Jim Van Verthc12aad92020-04-24 16:19:01 -0400431 texResource->resource(), &srcLocation, &srcBox);
Jim Van Verthba7f2292020-04-21 08:56:47 -0400432 this->submitDirectCommandList(SyncQueue::kForce);
433
434 const void* mappedMemory = transferBuffer->map();
435
436 SkRectMemcpy(buffer, rowBytes, mappedMemory, dstLocation.PlacedFootprint.Footprint.RowPitch,
Jim Van Verthfdd36852020-04-21 16:29:44 -0400437 tightRowBytes, height);
Jim Van Verthba7f2292020-04-21 08:56:47 -0400438
439 transferBuffer->unmap();
440
441 return true;
442}
443
444bool GrD3DGpu::onWritePixels(GrSurface* surface, int left, int top, int width, int height,
445 GrColorType surfaceColorType, GrColorType srcColorType,
446 const GrMipLevel texels[], int mipLevelCount,
447 bool prepForTexSampling) {
448 GrD3DTexture* d3dTex = static_cast<GrD3DTexture*>(surface->asTexture());
449 if (!d3dTex) {
450 return false;
451 }
452
453 // Make sure we have at least the base level
454 if (!mipLevelCount || !texels[0].fPixels) {
455 return false;
456 }
457
458 SkASSERT(!GrDxgiFormatIsCompressed(d3dTex->dxgiFormat()));
459 bool success = false;
460
461 // Need to change the resource state to COPY_DEST in order to upload to it
462 d3dTex->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
463
464 SkASSERT(mipLevelCount <= d3dTex->texturePriv().maxMipMapLevel() + 1);
465 success = this->uploadToTexture(d3dTex, left, top, width, height, srcColorType, texels,
466 mipLevelCount);
467
468 if (prepForTexSampling) {
469 d3dTex->setResourceState(this, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
470 }
471
472 return success;
473}
474
475bool GrD3DGpu::uploadToTexture(GrD3DTexture* tex, int left, int top, int width, int height,
476 GrColorType colorType, const GrMipLevel* texels, int mipLevelCount) {
477 SkASSERT(this->caps()->isFormatTexturable(tex->backendFormat()));
478 // The assumption is either that we have no mipmaps, or that our rect is the entire texture
479 SkASSERT(1 == mipLevelCount ||
480 (0 == left && 0 == top && width == tex->width() && height == tex->height()));
481
482 // We assume that if the texture has mip levels, we either upload to all the levels or just the
483 // first.
484 SkASSERT(1 == mipLevelCount || mipLevelCount == (tex->texturePriv().maxMipMapLevel() + 1));
485
486 if (width == 0 || height == 0) {
487 return false;
488 }
489
490 SkASSERT(this->d3dCaps().surfaceSupportsWritePixels(tex));
491 SkASSERT(this->d3dCaps().areColorTypeAndFormatCompatible(colorType, tex->backendFormat()));
492
493 ID3D12Resource* d3dResource = tex->d3dResource();
494 SkASSERT(d3dResource);
495 D3D12_RESOURCE_DESC desc = d3dResource->GetDesc();
496 // Either upload only the first miplevel or all miplevels
497 SkASSERT(1 == mipLevelCount || mipLevelCount == (int)desc.MipLevels);
498
499 if (1 == mipLevelCount && !texels[0].fPixels) {
500 return true; // no data to upload
501 }
502
503 for (int i = 0; i < mipLevelCount; ++i) {
504 // We do not allow any gaps in the mip data
505 if (!texels[i].fPixels) {
506 return false;
507 }
508 }
509
510 SkAutoTMalloc<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> placedFootprints(mipLevelCount);
Jim Van Verthba7f2292020-04-21 08:56:47 -0400511 UINT64 combinedBufferSize;
512 // We reset the width and height in the description to match our subrectangle size
513 // so we don't end up allocating more space than we need.
514 desc.Width = width;
515 desc.Height = height;
516 fDevice->GetCopyableFootprints(&desc, 0, mipLevelCount, 0, placedFootprints.get(),
Jim Van Verthfdd36852020-04-21 16:29:44 -0400517 nullptr, nullptr, &combinedBufferSize);
518 size_t bpp = GrColorTypeBytesPerPixel(colorType);
Jim Van Verthba7f2292020-04-21 08:56:47 -0400519 SkASSERT(combinedBufferSize);
520
521 // TODO: do this until we have slices of buttery buffers
522 sk_sp<GrGpuBuffer> transferBuffer = this->createBuffer(combinedBufferSize,
523 GrGpuBufferType::kXferCpuToGpu,
524 kDynamic_GrAccessPattern);
525 if (!transferBuffer) {
526 return false;
527 }
528 char* bufferData = (char*)transferBuffer->map();
529
530 int currentWidth = width;
531 int currentHeight = height;
532 int layerHeight = tex->height();
533
534 for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
535 if (texels[currentMipLevel].fPixels) {
536 SkASSERT(1 == mipLevelCount || currentHeight == layerHeight);
537
Jim Van Verthfdd36852020-04-21 16:29:44 -0400538 const size_t trimRowBytes = currentWidth * bpp;
Jim Van Verthba7f2292020-04-21 08:56:47 -0400539 const size_t srcRowBytes = texels[currentMipLevel].fRowBytes;
540
541 char* dst = bufferData + placedFootprints[currentMipLevel].Offset;
542
543 // copy data into the buffer, skipping any trailing bytes
Jim Van Verthba7f2292020-04-21 08:56:47 -0400544 const char* src = (const char*)texels[currentMipLevel].fPixels;
Jim Van Verthba7f2292020-04-21 08:56:47 -0400545 SkRectMemcpy(dst, placedFootprints[currentMipLevel].Footprint.RowPitch,
546 src, srcRowBytes, trimRowBytes, currentHeight);
547 }
548 currentWidth = std::max(1, currentWidth / 2);
549 currentHeight = std::max(1, currentHeight / 2);
550 layerHeight = currentHeight;
551 }
552
553 transferBuffer->unmap();
554
555 GrD3DBuffer* d3dBuffer = static_cast<GrD3DBuffer*>(transferBuffer.get());
556 fCurrentDirectCommandList->copyBufferToTexture(d3dBuffer, tex, mipLevelCount,
557 placedFootprints.get(), left, top);
558
559 if (mipLevelCount < (int)desc.MipLevels) {
560 tex->texturePriv().markMipMapsDirty();
561 }
562
563 return true;
564}
565
Michael Ludwig1e632792020-05-21 12:45:31 -0400566void GrD3DGpu::clear(const GrScissorState& scissor, const SkPMColor4f& color, GrRenderTarget* rt) {
Jim Van Verth280d4f72020-05-04 10:04:24 -0400567 GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(rt);
568
569 d3dRT->setResourceState(this, D3D12_RESOURCE_STATE_RENDER_TARGET);
570
Michael Ludwig1e632792020-05-21 12:45:31 -0400571 fCurrentDirectCommandList->clearRenderTargetView(d3dRT, color, scissor);
Jim Van Verth280d4f72020-05-04 10:04:24 -0400572}
573
Jim Van Verth9145f782020-04-28 12:01:12 -0400574static bool check_resource_info(const GrD3DTextureResourceInfo& info) {
575 if (!info.fResource.get()) {
576 return false;
577 }
578 return true;
579}
580
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400581static bool check_tex_resource_info(const GrD3DCaps& caps, const GrD3DTextureResourceInfo& info) {
582 if (!caps.isFormatTexturable(info.fFormat)) {
583 return false;
584 }
585 return true;
586}
587
588static bool check_rt_resource_info(const GrD3DCaps& caps, const GrD3DTextureResourceInfo& info,
589 int sampleCnt) {
590 if (!caps.isFormatRenderable(info.fFormat, sampleCnt)) {
591 return false;
592 }
593 return true;
594}
595
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400596sk_sp<GrTexture> GrD3DGpu::onWrapBackendTexture(const GrBackendTexture& tex,
597 GrWrapOwnership,
598 GrWrapCacheable wrapType,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400599 GrIOType ioType) {
600 GrD3DTextureResourceInfo textureInfo;
601 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
602 return nullptr;
603 }
604
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400605 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400606 return nullptr;
607 }
608
609 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
610 return nullptr;
611 }
612
613 // TODO: support protected context
614 if (tex.isProtected()) {
615 return nullptr;
616 }
617
618 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
619 SkASSERT(state);
620 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, ioType, textureInfo,
621 std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500622}
623
624sk_sp<GrTexture> GrD3DGpu::onWrapCompressedBackendTexture(const GrBackendTexture& tex,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400625 GrWrapOwnership,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500626 GrWrapCacheable wrapType) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400627 GrD3DTextureResourceInfo textureInfo;
628 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
629 return nullptr;
630 }
631
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400632 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400633 return nullptr;
634 }
635
636 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
637 return nullptr;
638 }
639
640 // TODO: support protected context
641 if (tex.isProtected()) {
642 return nullptr;
643 }
644
645 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
646 SkASSERT(state);
647 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, kRead_GrIOType,
648 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500649}
650
651sk_sp<GrTexture> GrD3DGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
652 int sampleCnt,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500653 GrWrapOwnership ownership,
654 GrWrapCacheable cacheable) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400655 GrD3DTextureResourceInfo textureInfo;
656 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
657 return nullptr;
658 }
659
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400660 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400661 return nullptr;
662 }
663
664 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
665 return nullptr;
666 }
667 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
668 return nullptr;
669 }
670
671 // TODO: support protected context
672 if (tex.isProtected()) {
673 return nullptr;
674 }
675
676 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
677
678 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
679 SkASSERT(state);
680
681 return GrD3DTextureRenderTarget::MakeWrappedTextureRenderTarget(this, tex.dimensions(),
682 sampleCnt, cacheable,
683 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500684}
685
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400686sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400687 // Currently the Direct3D backend does not support wrapping of msaa render targets directly. In
688 // general this is not an issue since swapchain images in D3D are never multisampled. Thus if
689 // you want a multisampled RT it is best to wrap the swapchain images and then let Skia handle
690 // creating and owning the MSAA images.
691 if (rt.sampleCnt() > 1) {
692 return nullptr;
693 }
694
695 GrD3DTextureResourceInfo info;
696 if (!rt.getD3DTextureResourceInfo(&info)) {
697 return nullptr;
698 }
699
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400700 if (!check_resource_info(info)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400701 return nullptr;
702 }
703
704 if (!check_rt_resource_info(this->d3dCaps(), info, rt.sampleCnt())) {
705 return nullptr;
706 }
707
708 // TODO: support protected context
709 if (rt.isProtected()) {
710 return nullptr;
711 }
712
713 sk_sp<GrD3DResourceState> state = rt.getGrD3DResourceState();
714
715 sk_sp<GrD3DRenderTarget> tgt = GrD3DRenderTarget::MakeWrappedRenderTarget(
716 this, rt.dimensions(), 1, info, std::move(state));
717
718 // We don't allow the client to supply a premade stencil buffer. We always create one if needed.
719 SkASSERT(!rt.stencilBits());
720 if (tgt) {
721 SkASSERT(tgt->canAttemptStencilAttachment());
722 }
723
724 return std::move(tgt);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500725}
726
727sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400728 int sampleCnt) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400729
730 GrD3DTextureResourceInfo textureInfo;
731 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
732 return nullptr;
733 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400734 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400735 return nullptr;
736 }
737
738 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
739 return nullptr;
740 }
741
742 // TODO: support protected context
743 if (tex.isProtected()) {
744 return nullptr;
745 }
746
747 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
748 if (!sampleCnt) {
749 return nullptr;
750 }
751
752 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
753 SkASSERT(state);
754
755 return GrD3DRenderTarget::MakeWrappedRenderTarget(this, tex.dimensions(), sampleCnt,
756 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500757}
758
759sk_sp<GrGpuBuffer> GrD3DGpu::onCreateBuffer(size_t sizeInBytes, GrGpuBufferType type,
Jim Van Verthd6ad4802020-04-03 14:59:20 -0400760 GrAccessPattern accessPattern, const void* data) {
761 sk_sp<GrD3DBuffer> buffer = GrD3DBuffer::Make(this, sizeInBytes, type, accessPattern);
762 if (data && buffer) {
763 buffer->updateData(data, sizeInBytes);
764 }
765
766 return std::move(buffer);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500767}
768
769GrStencilAttachment* GrD3DGpu::createStencilAttachmentForRenderTarget(
770 const GrRenderTarget* rt, int width, int height, int numStencilSamples) {
Jim Van Verth4f51f472020-04-13 11:02:21 -0400771 SkASSERT(numStencilSamples == rt->numSamples() || this->caps()->mixedSamplesSupport());
772 SkASSERT(width >= rt->width());
773 SkASSERT(height >= rt->height());
774
775 const GrD3DCaps::StencilFormat& sFmt = this->d3dCaps().preferredStencilFormat();
776
777 GrD3DStencilAttachment* stencil(GrD3DStencilAttachment::Make(this,
778 width,
779 height,
780 numStencilSamples,
781 sFmt));
782 fStats.incStencilAttachmentCreates();
783 return stencil;
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500784}
785
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400786bool GrD3DGpu::createTextureResourceForBackendSurface(DXGI_FORMAT dxgiFormat,
787 SkISize dimensions,
788 GrTexturable texturable,
789 GrRenderable renderable,
790 GrMipMapped mipMapped,
791 GrD3DTextureResourceInfo* info,
Greg Daniel16032b32020-05-06 15:31:10 -0400792 GrProtected isProtected) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400793 SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400794
795 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
796 return false;
797 }
798
799 if (texturable == GrTexturable::kYes && !this->d3dCaps().isFormatTexturable(dxgiFormat)) {
800 return false;
801 }
802
803 if (renderable == GrRenderable::kYes && !this->d3dCaps().isFormatRenderable(dxgiFormat, 1)) {
804 return false;
805 }
806
807 int numMipLevels = 1;
808 if (mipMapped == GrMipMapped::kYes) {
809 numMipLevels = SkMipMap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
810 }
811
812 // create the texture
813 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
814 if (renderable == GrRenderable::kYes) {
815 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
816 }
817
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400818 D3D12_RESOURCE_DESC resourceDesc = {};
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400819 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
Greg Daniel16032b32020-05-06 15:31:10 -0400820 resourceDesc.Alignment = 0; // use default alignment
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400821 resourceDesc.Width = dimensions.fWidth;
822 resourceDesc.Height = dimensions.fHeight;
823 resourceDesc.DepthOrArraySize = 1;
824 resourceDesc.MipLevels = numMipLevels;
825 resourceDesc.Format = dxgiFormat;
826 resourceDesc.SampleDesc.Count = 1;
Greg Danielc9624d52020-04-13 15:36:31 -0400827 // quality levels are only supported for tiled resources so ignore for now
828 resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
Greg Daniel16032b32020-05-06 15:31:10 -0400829 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400830 resourceDesc.Flags = usageFlags;
831
Jim Van Verth280d4f72020-05-04 10:04:24 -0400832 D3D12_CLEAR_VALUE* clearValuePtr = nullptr;
833 D3D12_CLEAR_VALUE clearValue = {};
834 if (renderable == GrRenderable::kYes) {
835 clearValue.Format = dxgiFormat;
836 // Assume transparent black
837 clearValue.Color[0] = 0;
838 clearValue.Color[1] = 0;
839 clearValue.Color[2] = 0;
840 clearValue.Color[3] = 0;
841 clearValuePtr = &clearValue;
842 }
843
Greg Daniel16032b32020-05-06 15:31:10 -0400844 D3D12_RESOURCE_STATES initialState = (renderable == GrRenderable::kYes)
845 ? D3D12_RESOURCE_STATE_RENDER_TARGET
846 : D3D12_RESOURCE_STATE_COPY_DEST;
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400847 if (!GrD3DTextureResource::InitTextureResourceInfo(this, resourceDesc, initialState,
Jim Van Verth280d4f72020-05-04 10:04:24 -0400848 isProtected, clearValuePtr, info)) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400849 SkDebugf("Failed to init texture resource info\n");
850 return false;
851 }
852
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400853 return true;
854}
855
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500856GrBackendTexture GrD3DGpu::onCreateBackendTexture(SkISize dimensions,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400857 const GrBackendFormat& format,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400858 GrRenderable renderable,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400859 GrMipMapped mipMapped,
Greg Daniel16032b32020-05-06 15:31:10 -0400860 GrProtected isProtected) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400861 this->handleDirtyContext();
862
863 const GrD3DCaps& caps = this->d3dCaps();
864
865 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
866 return {};
867 }
868
869 DXGI_FORMAT dxgiFormat;
870 if (!format.asDxgiFormat(&dxgiFormat)) {
871 return {};
872 }
873
874 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
875 if (!caps.isFormatTexturable(dxgiFormat)) {
876 return {};
877 }
878
879 GrD3DTextureResourceInfo info;
880 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
881 renderable, mipMapped,
Greg Daniel16032b32020-05-06 15:31:10 -0400882 &info, isProtected)) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400883 return {};
884 }
885
886 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500887}
888
Greg Daniel16032b32020-05-06 15:31:10 -0400889bool GrD3DGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
890 sk_sp<GrRefCntedCallback> finishedCallback,
891 const BackendTextureData* data) {
892 // TODO: handle finishedCallback and data upload
893 return true;
894}
895
Greg Danielc1ad77c2020-05-06 11:40:03 -0400896GrBackendTexture GrD3DGpu::onCreateCompressedBackendTexture(
897 SkISize dimensions, const GrBackendFormat& format, GrMipMapped mipMapped,
898 GrProtected isProtected, sk_sp<GrRefCntedCallback> finishedCallback,
899 const BackendTextureData* data) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400900 this->handleDirtyContext();
901
902 const GrD3DCaps& caps = this->d3dCaps();
903
904 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
905 return {};
906 }
907
908 DXGI_FORMAT dxgiFormat;
909 if (!format.asDxgiFormat(&dxgiFormat)) {
910 return {};
911 }
912
913 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
914 if (!caps.isFormatTexturable(dxgiFormat)) {
915 return {};
916 }
917
918 GrD3DTextureResourceInfo info;
919 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
920 GrRenderable::kNo, mipMapped,
Greg Daniel16032b32020-05-06 15:31:10 -0400921 &info, isProtected)) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400922 return {};
923 }
924
925 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500926}
927
928void GrD3DGpu::deleteBackendTexture(const GrBackendTexture& tex) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400929 SkASSERT(GrBackendApi::kDirect3D == tex.fBackend);
930 // Nothing to do here, will get cleaned up when the GrBackendTexture object goes away
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500931}
932
Robert Phillips979b2232020-02-20 10:47:29 -0500933bool GrD3DGpu::compile(const GrProgramDesc&, const GrProgramInfo&) {
934 return false;
935}
936
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500937#if GR_TEST_UTILS
938bool GrD3DGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400939 SkASSERT(GrBackendApi::kDirect3D == tex.backend());
940
941 GrD3DTextureResourceInfo info;
942 if (!tex.getD3DTextureResourceInfo(&info)) {
943 return false;
944 }
945 ID3D12Resource* textureResource = info.fResource.get();
946 if (!textureResource) {
947 return false;
948 }
949 return !(textureResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500950}
951
952GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(int w, int h,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400953 GrColorType colorType) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400954 this->handleDirtyContext();
955
956 if (w > this->caps()->maxRenderTargetSize() || h > this->caps()->maxRenderTargetSize()) {
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400957 return {};
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400958 }
959
960 DXGI_FORMAT dxgiFormat = this->d3dCaps().getFormatFromColorType(colorType);
961
962 GrD3DTextureResourceInfo info;
963 if (!this->createTextureResourceForBackendSurface(dxgiFormat, { w, h }, GrTexturable::kNo,
964 GrRenderable::kYes, GrMipMapped::kNo,
Greg Daniel16032b32020-05-06 15:31:10 -0400965 &info, GrProtected::kNo)) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400966 return {};
967 }
968
969 return GrBackendRenderTarget(w, h, 1, info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500970}
971
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400972void GrD3DGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
973 SkASSERT(GrBackendApi::kDirect3D == rt.backend());
974
975 GrD3DTextureResourceInfo info;
976 if (rt.getD3DTextureResourceInfo(&info)) {
977 this->testingOnly_flushGpuAndSync();
978 // Nothing else to do here, will get cleaned up when the GrBackendRenderTarget
979 // is deleted.
980 }
981}
982
983void GrD3DGpu::testingOnly_flushGpuAndSync() {
Jim Van Verthc632aa62020-04-17 16:58:20 -0400984 SkAssertResult(this->submitDirectCommandList(SyncQueue::kForce));
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400985}
Jim Van Verthc632aa62020-04-17 16:58:20 -0400986
Jim Van Verth9b5e16c2020-04-20 10:45:52 -0400987void GrD3DGpu::testingOnly_startCapture() {
988 if (fGraphicsAnalysis) {
989 fGraphicsAnalysis->BeginCapture();
990 }
991}
992
993void GrD3DGpu::testingOnly_endCapture() {
994 if (fGraphicsAnalysis) {
995 fGraphicsAnalysis->EndCapture();
996 }
997}
998#endif
999
Jim Van Verthc632aa62020-04-17 16:58:20 -04001000///////////////////////////////////////////////////////////////////////////////
1001
Greg Daniela5a6b322020-04-23 12:52:27 -04001002void GrD3DGpu::addResourceBarriers(sk_sp<GrManagedResource> resource,
Jim Van Verthc632aa62020-04-17 16:58:20 -04001003 int numBarriers,
1004 D3D12_RESOURCE_TRANSITION_BARRIER* barriers) const {
1005 SkASSERT(fCurrentDirectCommandList);
1006 SkASSERT(resource);
1007
Greg Daniela5a6b322020-04-23 12:52:27 -04001008 fCurrentDirectCommandList->resourceBarrier(std::move(resource), numBarriers, barriers);
Jim Van Verthc632aa62020-04-17 16:58:20 -04001009}
1010
Jim Van Verth682a2f42020-05-13 16:54:09 -04001011void GrD3DGpu::prepareSurfacesForBackendAccessAndExternalIO(
1012 GrSurfaceProxy* proxies[], int numProxies, SkSurface::BackendSurfaceAccess access,
1013 const GrPrepareForExternalIORequests& externalRequests) {
1014 SkASSERT(numProxies >= 0);
1015 SkASSERT(!numProxies || proxies);
1016
1017 // prepare proxies by transitioning to PRESENT renderState
1018 if (numProxies && access == SkSurface::BackendSurfaceAccess::kPresent) {
1019 GrD3DTextureResource* resource;
1020 for (int i = 0; i < numProxies; ++i) {
1021 SkASSERT(proxies[i]->isInstantiated());
1022 if (GrTexture* tex = proxies[i]->peekTexture()) {
1023 resource = static_cast<GrD3DTexture*>(tex);
1024 } else {
1025 GrRenderTarget* rt = proxies[i]->peekRenderTarget();
1026 SkASSERT(rt);
1027 resource = static_cast<GrD3DRenderTarget*>(rt);
1028 }
1029 resource->prepareForPresent(this);
1030 }
1031 }
1032}
1033
Jim Van Verthc632aa62020-04-17 16:58:20 -04001034bool GrD3DGpu::onSubmitToGpu(bool syncCpu) {
1035 if (syncCpu) {
1036 return this->submitDirectCommandList(SyncQueue::kForce);
1037 } else {
1038 return this->submitDirectCommandList(SyncQueue::kSkip);
1039 }
1040}