blob: 4c80ae7bceea11c66c0f55f6fd8618d498bddf70 [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()) {
Jim Van Verthf43da142020-06-09 16:34:43 -040087 OutstandingCommandList* list = (OutstandingCommandList*)fOutstandingCommandLists.front();
Greg Daniel83ed2132020-03-24 13:15:33 -040088 SkASSERT(list->fFenceValue <= fenceValue);
89 // No reason to recycle the command lists since we are destroying all resources anyways.
90 list->~OutstandingCommandList();
Jim Van Verthf43da142020-06-09 16:34:43 -040091 fOutstandingCommandLists.pop_front();
Greg Daniel83ed2132020-03-24 13:15:33 -040092 }
Jim Van Verthf2788862020-06-03 17:33:12 -040093
94 fResourceProvider.destroyResources();
Greg Daniel83ed2132020-03-24 13:15:33 -040095}
Greg Daniel31a7b072020-02-26 15:31:49 -050096
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050097GrOpsRenderPass* GrD3DGpu::getOpsRenderPass(
Robert Phillips96f22372020-05-20 12:31:18 -040098 GrRenderTarget* rt, GrStencilAttachment*,
99 GrSurfaceOrigin origin, const SkIRect& bounds,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500100 const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
Greg Daniel31a7b072020-02-26 15:31:49 -0500101 const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500102 const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
Greg Daniel31a7b072020-02-26 15:31:49 -0500103 if (!fCachedOpsRenderPass) {
104 fCachedOpsRenderPass.reset(new GrD3DOpsRenderPass(this));
105 }
106
107 if (!fCachedOpsRenderPass->set(rt, origin, bounds, colorInfo, stencilInfo, sampledProxies)) {
108 return nullptr;
109 }
110 return fCachedOpsRenderPass.get();
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500111}
112
Jim Van Verthc632aa62020-04-17 16:58:20 -0400113bool GrD3DGpu::submitDirectCommandList(SyncQueue sync) {
Greg Daniel83ed2132020-03-24 13:15:33 -0400114 SkASSERT(fCurrentDirectCommandList);
115
Jim Van Verth3eadce22020-06-01 11:34:49 -0400116 fResourceProvider.prepForSubmit();
117
Jim Van Verthc632aa62020-04-17 16:58:20 -0400118 GrD3DDirectCommandList::SubmitResult result = fCurrentDirectCommandList->submit(fQueue.get());
119 if (result == GrD3DDirectCommandList::SubmitResult::kFailure) {
120 return false;
121 } else if (result == GrD3DDirectCommandList::SubmitResult::kNoWork) {
122 if (sync == SyncQueue::kForce) {
123 this->waitForQueueCompletion();
Jim Van Verth682a2f42020-05-13 16:54:09 -0400124 this->checkForFinishedCommandLists();
Jim Van Verthc632aa62020-04-17 16:58:20 -0400125 }
126 return true;
127 }
Greg Daniel83ed2132020-03-24 13:15:33 -0400128
129 new (fOutstandingCommandLists.push_back()) OutstandingCommandList(
130 std::move(fCurrentDirectCommandList), ++fCurrentFenceValue);
131
Jim Van Verth9aa9a682020-04-01 10:13:48 -0400132 SkDEBUGCODE(HRESULT hr = ) fQueue->Signal(fFence.get(), fCurrentFenceValue);
Greg Daniel83ed2132020-03-24 13:15:33 -0400133 SkASSERT(SUCCEEDED(hr));
134
Jim Van Verthc632aa62020-04-17 16:58:20 -0400135 if (sync == SyncQueue::kForce) {
136 this->waitForQueueCompletion();
137 }
138
Greg Daniel83ed2132020-03-24 13:15:33 -0400139 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
140
141 // This should be done after we have a new command list in case the freeing of any resources
142 // held by a finished command list causes us send a new command to the gpu (like changing the
143 // resource state.
144 this->checkForFinishedCommandLists();
145
146 SkASSERT(fCurrentDirectCommandList);
Jim Van Verthc632aa62020-04-17 16:58:20 -0400147 return true;
Greg Daniel83ed2132020-03-24 13:15:33 -0400148}
149
150void GrD3DGpu::checkForFinishedCommandLists() {
151 uint64_t currentFenceValue = fFence->GetCompletedValue();
152
153 // Iterate over all the outstanding command lists to see if any have finished. The commands
154 // lists are in order from oldest to newest, so we start at the front to check if their fence
155 // value is less than the last signaled value. If so we pop it off and move onto the next.
156 // Repeat till we find a command list that has not finished yet (and all others afterwards are
157 // also guaranteed to not have finished).
158 SkDeque::F2BIter iter(fOutstandingCommandLists);
159 const OutstandingCommandList* curList = (const OutstandingCommandList*)iter.next();
160 while (curList && curList->fFenceValue <= currentFenceValue) {
161 curList = (const OutstandingCommandList*)iter.next();
162 OutstandingCommandList* front = (OutstandingCommandList*)fOutstandingCommandLists.front();
Greg Daniel7a5f1fa2020-03-24 14:50:19 -0400163 fResourceProvider.recycleDirectCommandList(std::move(front->fCommandList));
Greg Daniel83ed2132020-03-24 13:15:33 -0400164 // Since we used placement new we are responsible for calling the destructor manually.
165 front->~OutstandingCommandList();
166 fOutstandingCommandLists.pop_front();
167 }
168}
169
Jim Van Verthc632aa62020-04-17 16:58:20 -0400170void GrD3DGpu::waitForQueueCompletion() {
171 if (fFence->GetCompletedValue() < fCurrentFenceValue) {
172 HANDLE fenceEvent;
173 fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
174 SkASSERT(fenceEvent);
175 SkDEBUGCODE(HRESULT hr = ) fFence->SetEventOnCompletion(fCurrentFenceValue, fenceEvent);
176 SkASSERT(SUCCEEDED(hr));
177 WaitForSingleObject(fenceEvent, INFINITE);
178 CloseHandle(fenceEvent);
179 }
180}
181
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500182void GrD3DGpu::submit(GrOpsRenderPass* renderPass) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400183 SkASSERT(fCachedOpsRenderPass.get() == renderPass);
184
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500185 // TODO: actually submit something here
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400186 fCachedOpsRenderPass.reset();
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500187}
188
189void GrD3DGpu::querySampleLocations(GrRenderTarget* rt, SkTArray<SkPoint>* sampleLocations) {
190 // TODO
191}
192
193sk_sp<GrTexture> GrD3DGpu::onCreateTexture(SkISize dimensions,
194 const GrBackendFormat& format,
195 GrRenderable renderable,
196 int renderTargetSampleCnt,
197 SkBudgeted budgeted,
198 GrProtected isProtected,
199 int mipLevelCount,
200 uint32_t levelClearMask) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400201 DXGI_FORMAT dxgiFormat;
202 SkAssertResult(format.asDxgiFormat(&dxgiFormat));
203 SkASSERT(!GrDxgiFormatIsCompressed(dxgiFormat));
204
205 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
206
207 if (renderable == GrRenderable::kYes) {
208 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
209 }
210
211 // This desc refers to the texture that will be read by the client. Thus even if msaa is
212 // requested, this describes the resolved texture. Therefore we always have samples set
213 // to 1.
214 SkASSERT(mipLevelCount > 0);
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400215 D3D12_RESOURCE_DESC resourceDesc = {};
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400216 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
217 // TODO: will use 4MB alignment for MSAA textures and 64KB for everything else
218 // might want to manually set alignment to 4KB for smaller textures
219 resourceDesc.Alignment = 0;
220 resourceDesc.Width = dimensions.fWidth;
221 resourceDesc.Height = dimensions.fHeight;
222 resourceDesc.DepthOrArraySize = 1;
223 resourceDesc.MipLevels = mipLevelCount;
224 resourceDesc.Format = dxgiFormat;
225 resourceDesc.SampleDesc.Count = 1;
Greg Danielc9624d52020-04-13 15:36:31 -0400226 // quality levels are only supported for tiled resources so ignore for now
227 resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400228 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400229 resourceDesc.Flags = usageFlags;
230
231 GrMipMapsStatus mipMapsStatus =
232 mipLevelCount > 1 ? GrMipMapsStatus::kDirty : GrMipMapsStatus::kNotAllocated;
233
234 sk_sp<GrD3DTexture> tex;
235 if (renderable == GrRenderable::kYes) {
236 tex = GrD3DTextureRenderTarget::MakeNewTextureRenderTarget(
237 this, budgeted, dimensions, renderTargetSampleCnt, resourceDesc, isProtected,
238 mipMapsStatus);
239 } else {
240 tex = GrD3DTexture::MakeNewTexture(this, budgeted, dimensions, resourceDesc, isProtected,
241 mipMapsStatus);
242 }
243
244 if (!tex) {
245 return nullptr;
246 }
247
248 if (levelClearMask) {
249 // TODO
250 }
251 return std::move(tex);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500252}
253
254sk_sp<GrTexture> GrD3DGpu::onCreateCompressedTexture(SkISize dimensions,
255 const GrBackendFormat& format,
256 SkBudgeted budgeted,
257 GrMipMapped mipMapped,
258 GrProtected isProtected,
259 const void* data, size_t dataSize) {
260 // TODO
261 return nullptr;
262}
263
Jim Van Verth9145f782020-04-28 12:01:12 -0400264static int get_surface_sample_cnt(GrSurface* surf) {
265 if (const GrRenderTarget* rt = surf->asRenderTarget()) {
266 return rt->numSamples();
267 }
268 return 0;
269}
270
271bool GrD3DGpu::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
272 const SkIPoint& dstPoint) {
273
274 if (src->isProtected() && !dst->isProtected()) {
275 SkDebugf("Can't copy from protected memory to non-protected");
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400276 return false;
277 }
Jim Van Verth9145f782020-04-28 12:01:12 -0400278
279 int dstSampleCnt = get_surface_sample_cnt(dst);
280 int srcSampleCnt = get_surface_sample_cnt(src);
281
282 GrD3DTextureResource* dstTexResource;
283 GrD3DTextureResource* srcTexResource;
284 GrRenderTarget* dstRT = dst->asRenderTarget();
285 if (dstRT) {
286 GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(dstRT);
287 dstTexResource = d3dRT->numSamples() > 1 ? d3dRT->msaaTextureResource() : d3dRT;
288 } else {
289 SkASSERT(dst->asTexture());
290 dstTexResource = static_cast<GrD3DTexture*>(dst->asTexture());
291 }
292 GrRenderTarget* srcRT = src->asRenderTarget();
293 if (srcRT) {
294 GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(srcRT);
295 srcTexResource = d3dRT->numSamples() > 1 ? d3dRT->msaaTextureResource() : d3dRT;
296 } else {
297 SkASSERT(src->asTexture());
298 srcTexResource = static_cast<GrD3DTexture*>(src->asTexture());
299 }
300
301 DXGI_FORMAT dstFormat = dstTexResource->dxgiFormat();
302 DXGI_FORMAT srcFormat = srcTexResource->dxgiFormat();
303
304 if (this->d3dCaps().canCopyAsResolve(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt)) {
305 this->copySurfaceAsResolve(dst, src, srcRect, dstPoint);
306 return true;
307 }
308
309 if (this->d3dCaps().canCopyTexture(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt)) {
310 this->copySurfaceAsCopyTexture(dst, src, dstTexResource, srcTexResource, srcRect, dstPoint);
311 return true;
312 }
313
314 return false;
315}
316
317void GrD3DGpu::copySurfaceAsCopyTexture(GrSurface* dst, GrSurface* src,
318 GrD3DTextureResource* dstResource,
319 GrD3DTextureResource* srcResource,
320 const SkIRect& srcRect, const SkIPoint& dstPoint) {
321#ifdef SK_DEBUG
322 int dstSampleCnt = get_surface_sample_cnt(dst);
323 int srcSampleCnt = get_surface_sample_cnt(src);
324 DXGI_FORMAT dstFormat = dstResource->dxgiFormat();
325 DXGI_FORMAT srcFormat;
326 SkAssertResult(dst->backendFormat().asDxgiFormat(&srcFormat));
327 SkASSERT(this->d3dCaps().canCopyTexture(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt));
328#endif
329 if (src->isProtected() && !dst->isProtected()) {
330 SkDebugf("Can't copy from protected memory to non-protected");
331 return;
332 }
333
334 dstResource->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
335 srcResource->setResourceState(this, D3D12_RESOURCE_STATE_COPY_SOURCE);
336
337 D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
338 dstLocation.pResource = dstResource->d3dResource();
339 dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
340 dstLocation.SubresourceIndex = 0;
341
342 D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
343 srcLocation.pResource = srcResource->d3dResource();
344 srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
345 srcLocation.SubresourceIndex = 0;
346
347 D3D12_BOX srcBox = {};
348 srcBox.left = srcRect.fLeft;
349 srcBox.top = srcRect.fTop;
350 srcBox.right = srcRect.fRight;
351 srcBox.bottom = srcRect.fBottom;
352 srcBox.front = 0;
353 srcBox.back = 1;
354 // TODO: use copyResource if copying full resource and sizes match
355 fCurrentDirectCommandList->copyTextureRegion(dstResource->resource(),
356 &dstLocation,
357 dstPoint.fX, dstPoint.fY,
358 srcResource->resource(),
359 &srcLocation,
360 &srcBox);
361
362 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
363 srcRect.width(), srcRect.height());
364 // The rect is already in device space so we pass in kTopLeft so no flip is done.
365 this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
366}
367
368void GrD3DGpu::copySurfaceAsResolve(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
369 const SkIPoint& dstPoint) {
370 // TODO
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400371}
372
Jim Van Verthba7f2292020-04-21 08:56:47 -0400373bool GrD3DGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int height,
374 GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
375 size_t rowBytes) {
376 SkASSERT(surface);
377
378 if (surfaceColorType != dstColorType) {
379 return false;
380 }
381
382 // Set up src location and box
Jim Van Verthc12aad92020-04-24 16:19:01 -0400383 GrD3DTextureResource* texResource = nullptr;
384 GrD3DRenderTarget* rt = static_cast<GrD3DRenderTarget*>(surface->asRenderTarget());
385 if (rt) {
386 texResource = rt;
387 } else {
388 texResource = static_cast<GrD3DTexture*>(surface->asTexture());
389 }
390
391 if (!texResource) {
Jim Van Verthba7f2292020-04-21 08:56:47 -0400392 return false;
393 }
Jim Van Verthc12aad92020-04-24 16:19:01 -0400394
Jim Van Verthba7f2292020-04-21 08:56:47 -0400395 D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
Jim Van Verthc12aad92020-04-24 16:19:01 -0400396 srcLocation.pResource = texResource->d3dResource();
Jim Van Verthba7f2292020-04-21 08:56:47 -0400397 SkASSERT(srcLocation.pResource);
398 srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
399 srcLocation.SubresourceIndex = 0;
400
401 D3D12_BOX srcBox = {};
402 srcBox.left = left;
403 srcBox.top = top;
404 srcBox.right = left + width;
405 srcBox.bottom = top + height;
406 srcBox.front = 0;
407 srcBox.back = 1;
408
409 // Set up dst location and create transfer buffer
410 D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
411 dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
Jim Van Verthba7f2292020-04-21 08:56:47 -0400412 UINT64 transferTotalBytes;
413 const UINT64 baseOffset = 0;
414 D3D12_RESOURCE_DESC desc = srcLocation.pResource->GetDesc();
415 fDevice->GetCopyableFootprints(&desc, 0, 1, baseOffset, &dstLocation.PlacedFootprint,
Jim Van Verthfdd36852020-04-21 16:29:44 -0400416 nullptr, nullptr, &transferTotalBytes);
Jim Van Verthba7f2292020-04-21 08:56:47 -0400417 SkASSERT(transferTotalBytes);
Jim Van Verthfdd36852020-04-21 16:29:44 -0400418 size_t bpp = GrColorTypeBytesPerPixel(dstColorType);
Jim Van Verthc12aad92020-04-24 16:19:01 -0400419 if (this->d3dCaps().bytesPerPixel(texResource->dxgiFormat()) != bpp) {
Jim Van Verthfdd36852020-04-21 16:29:44 -0400420 return false;
421 }
422 size_t tightRowBytes = bpp * width;
Jim Van Verthba7f2292020-04-21 08:56:47 -0400423
424 // TODO: implement some way of reusing buffers instead of making a new one every time.
425 sk_sp<GrGpuBuffer> transferBuffer = this->createBuffer(transferTotalBytes,
426 GrGpuBufferType::kXferGpuToCpu,
427 kDynamic_GrAccessPattern);
428 GrD3DBuffer* d3dBuf = static_cast<GrD3DBuffer*>(transferBuffer.get());
429 dstLocation.pResource = d3dBuf->d3dResource();
430
431 // Need to change the resource state to COPY_SOURCE in order to download from it
Jim Van Verthc12aad92020-04-24 16:19:01 -0400432 texResource->setResourceState(this, D3D12_RESOURCE_STATE_COPY_SOURCE);
Jim Van Verthba7f2292020-04-21 08:56:47 -0400433
434 fCurrentDirectCommandList->copyTextureRegion(d3dBuf->resource(), &dstLocation, 0, 0,
Jim Van Verthc12aad92020-04-24 16:19:01 -0400435 texResource->resource(), &srcLocation, &srcBox);
Jim Van Verthba7f2292020-04-21 08:56:47 -0400436 this->submitDirectCommandList(SyncQueue::kForce);
437
438 const void* mappedMemory = transferBuffer->map();
439
440 SkRectMemcpy(buffer, rowBytes, mappedMemory, dstLocation.PlacedFootprint.Footprint.RowPitch,
Jim Van Verthfdd36852020-04-21 16:29:44 -0400441 tightRowBytes, height);
Jim Van Verthba7f2292020-04-21 08:56:47 -0400442
443 transferBuffer->unmap();
444
445 return true;
446}
447
448bool GrD3DGpu::onWritePixels(GrSurface* surface, int left, int top, int width, int height,
449 GrColorType surfaceColorType, GrColorType srcColorType,
450 const GrMipLevel texels[], int mipLevelCount,
451 bool prepForTexSampling) {
452 GrD3DTexture* d3dTex = static_cast<GrD3DTexture*>(surface->asTexture());
453 if (!d3dTex) {
454 return false;
455 }
456
457 // Make sure we have at least the base level
458 if (!mipLevelCount || !texels[0].fPixels) {
459 return false;
460 }
461
462 SkASSERT(!GrDxgiFormatIsCompressed(d3dTex->dxgiFormat()));
463 bool success = false;
464
465 // Need to change the resource state to COPY_DEST in order to upload to it
466 d3dTex->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
467
468 SkASSERT(mipLevelCount <= d3dTex->texturePriv().maxMipMapLevel() + 1);
469 success = this->uploadToTexture(d3dTex, left, top, width, height, srcColorType, texels,
470 mipLevelCount);
471
472 if (prepForTexSampling) {
473 d3dTex->setResourceState(this, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
474 }
475
476 return success;
477}
478
479bool GrD3DGpu::uploadToTexture(GrD3DTexture* tex, int left, int top, int width, int height,
480 GrColorType colorType, const GrMipLevel* texels, int mipLevelCount) {
481 SkASSERT(this->caps()->isFormatTexturable(tex->backendFormat()));
482 // The assumption is either that we have no mipmaps, or that our rect is the entire texture
483 SkASSERT(1 == mipLevelCount ||
484 (0 == left && 0 == top && width == tex->width() && height == tex->height()));
485
486 // We assume that if the texture has mip levels, we either upload to all the levels or just the
487 // first.
488 SkASSERT(1 == mipLevelCount || mipLevelCount == (tex->texturePriv().maxMipMapLevel() + 1));
489
490 if (width == 0 || height == 0) {
491 return false;
492 }
493
494 SkASSERT(this->d3dCaps().surfaceSupportsWritePixels(tex));
495 SkASSERT(this->d3dCaps().areColorTypeAndFormatCompatible(colorType, tex->backendFormat()));
496
497 ID3D12Resource* d3dResource = tex->d3dResource();
498 SkASSERT(d3dResource);
499 D3D12_RESOURCE_DESC desc = d3dResource->GetDesc();
500 // Either upload only the first miplevel or all miplevels
501 SkASSERT(1 == mipLevelCount || mipLevelCount == (int)desc.MipLevels);
502
503 if (1 == mipLevelCount && !texels[0].fPixels) {
504 return true; // no data to upload
505 }
506
507 for (int i = 0; i < mipLevelCount; ++i) {
508 // We do not allow any gaps in the mip data
509 if (!texels[i].fPixels) {
510 return false;
511 }
512 }
513
514 SkAutoTMalloc<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> placedFootprints(mipLevelCount);
Jim Van Verthba7f2292020-04-21 08:56:47 -0400515 UINT64 combinedBufferSize;
516 // We reset the width and height in the description to match our subrectangle size
517 // so we don't end up allocating more space than we need.
518 desc.Width = width;
519 desc.Height = height;
520 fDevice->GetCopyableFootprints(&desc, 0, mipLevelCount, 0, placedFootprints.get(),
Jim Van Verthfdd36852020-04-21 16:29:44 -0400521 nullptr, nullptr, &combinedBufferSize);
522 size_t bpp = GrColorTypeBytesPerPixel(colorType);
Jim Van Verthba7f2292020-04-21 08:56:47 -0400523 SkASSERT(combinedBufferSize);
524
525 // TODO: do this until we have slices of buttery buffers
526 sk_sp<GrGpuBuffer> transferBuffer = this->createBuffer(combinedBufferSize,
527 GrGpuBufferType::kXferCpuToGpu,
528 kDynamic_GrAccessPattern);
529 if (!transferBuffer) {
530 return false;
531 }
532 char* bufferData = (char*)transferBuffer->map();
533
534 int currentWidth = width;
535 int currentHeight = height;
536 int layerHeight = tex->height();
537
538 for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
539 if (texels[currentMipLevel].fPixels) {
540 SkASSERT(1 == mipLevelCount || currentHeight == layerHeight);
541
Jim Van Verthfdd36852020-04-21 16:29:44 -0400542 const size_t trimRowBytes = currentWidth * bpp;
Jim Van Verthba7f2292020-04-21 08:56:47 -0400543 const size_t srcRowBytes = texels[currentMipLevel].fRowBytes;
544
545 char* dst = bufferData + placedFootprints[currentMipLevel].Offset;
546
547 // copy data into the buffer, skipping any trailing bytes
Jim Van Verthba7f2292020-04-21 08:56:47 -0400548 const char* src = (const char*)texels[currentMipLevel].fPixels;
Jim Van Verthba7f2292020-04-21 08:56:47 -0400549 SkRectMemcpy(dst, placedFootprints[currentMipLevel].Footprint.RowPitch,
550 src, srcRowBytes, trimRowBytes, currentHeight);
551 }
552 currentWidth = std::max(1, currentWidth / 2);
553 currentHeight = std::max(1, currentHeight / 2);
554 layerHeight = currentHeight;
555 }
556
557 transferBuffer->unmap();
558
559 GrD3DBuffer* d3dBuffer = static_cast<GrD3DBuffer*>(transferBuffer.get());
560 fCurrentDirectCommandList->copyBufferToTexture(d3dBuffer, tex, mipLevelCount,
561 placedFootprints.get(), left, top);
562
563 if (mipLevelCount < (int)desc.MipLevels) {
564 tex->texturePriv().markMipMapsDirty();
565 }
566
567 return true;
568}
569
Jim Van Verth9145f782020-04-28 12:01:12 -0400570static bool check_resource_info(const GrD3DTextureResourceInfo& info) {
571 if (!info.fResource.get()) {
572 return false;
573 }
574 return true;
575}
576
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400577static bool check_tex_resource_info(const GrD3DCaps& caps, const GrD3DTextureResourceInfo& info) {
578 if (!caps.isFormatTexturable(info.fFormat)) {
579 return false;
580 }
581 return true;
582}
583
584static bool check_rt_resource_info(const GrD3DCaps& caps, const GrD3DTextureResourceInfo& info,
585 int sampleCnt) {
586 if (!caps.isFormatRenderable(info.fFormat, sampleCnt)) {
587 return false;
588 }
589 return true;
590}
591
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400592sk_sp<GrTexture> GrD3DGpu::onWrapBackendTexture(const GrBackendTexture& tex,
593 GrWrapOwnership,
594 GrWrapCacheable wrapType,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400595 GrIOType ioType) {
596 GrD3DTextureResourceInfo textureInfo;
597 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
598 return nullptr;
599 }
600
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400601 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400602 return nullptr;
603 }
604
605 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
606 return nullptr;
607 }
608
609 // TODO: support protected context
610 if (tex.isProtected()) {
611 return nullptr;
612 }
613
614 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
615 SkASSERT(state);
616 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, ioType, textureInfo,
617 std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500618}
619
620sk_sp<GrTexture> GrD3DGpu::onWrapCompressedBackendTexture(const GrBackendTexture& tex,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400621 GrWrapOwnership,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500622 GrWrapCacheable wrapType) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400623 GrD3DTextureResourceInfo textureInfo;
624 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
625 return nullptr;
626 }
627
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400628 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400629 return nullptr;
630 }
631
632 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
633 return nullptr;
634 }
635
636 // TODO: support protected context
637 if (tex.isProtected()) {
638 return nullptr;
639 }
640
641 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
642 SkASSERT(state);
643 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, kRead_GrIOType,
644 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500645}
646
647sk_sp<GrTexture> GrD3DGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
648 int sampleCnt,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500649 GrWrapOwnership ownership,
650 GrWrapCacheable cacheable) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400651 GrD3DTextureResourceInfo textureInfo;
652 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
653 return nullptr;
654 }
655
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400656 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400657 return nullptr;
658 }
659
660 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
661 return nullptr;
662 }
663 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
664 return nullptr;
665 }
666
667 // TODO: support protected context
668 if (tex.isProtected()) {
669 return nullptr;
670 }
671
672 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
673
674 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
675 SkASSERT(state);
676
677 return GrD3DTextureRenderTarget::MakeWrappedTextureRenderTarget(this, tex.dimensions(),
678 sampleCnt, cacheable,
679 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500680}
681
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400682sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400683 // Currently the Direct3D backend does not support wrapping of msaa render targets directly. In
684 // general this is not an issue since swapchain images in D3D are never multisampled. Thus if
685 // you want a multisampled RT it is best to wrap the swapchain images and then let Skia handle
686 // creating and owning the MSAA images.
687 if (rt.sampleCnt() > 1) {
688 return nullptr;
689 }
690
691 GrD3DTextureResourceInfo info;
692 if (!rt.getD3DTextureResourceInfo(&info)) {
693 return nullptr;
694 }
695
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400696 if (!check_resource_info(info)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400697 return nullptr;
698 }
699
700 if (!check_rt_resource_info(this->d3dCaps(), info, rt.sampleCnt())) {
701 return nullptr;
702 }
703
704 // TODO: support protected context
705 if (rt.isProtected()) {
706 return nullptr;
707 }
708
709 sk_sp<GrD3DResourceState> state = rt.getGrD3DResourceState();
710
711 sk_sp<GrD3DRenderTarget> tgt = GrD3DRenderTarget::MakeWrappedRenderTarget(
712 this, rt.dimensions(), 1, info, std::move(state));
713
714 // We don't allow the client to supply a premade stencil buffer. We always create one if needed.
715 SkASSERT(!rt.stencilBits());
716 if (tgt) {
717 SkASSERT(tgt->canAttemptStencilAttachment());
718 }
719
720 return std::move(tgt);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500721}
722
723sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400724 int sampleCnt) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400725
726 GrD3DTextureResourceInfo textureInfo;
727 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
728 return nullptr;
729 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400730 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400731 return nullptr;
732 }
733
734 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
735 return nullptr;
736 }
737
738 // TODO: support protected context
739 if (tex.isProtected()) {
740 return nullptr;
741 }
742
743 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
744 if (!sampleCnt) {
745 return nullptr;
746 }
747
748 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
749 SkASSERT(state);
750
751 return GrD3DRenderTarget::MakeWrappedRenderTarget(this, tex.dimensions(), sampleCnt,
752 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500753}
754
755sk_sp<GrGpuBuffer> GrD3DGpu::onCreateBuffer(size_t sizeInBytes, GrGpuBufferType type,
Jim Van Verthd6ad4802020-04-03 14:59:20 -0400756 GrAccessPattern accessPattern, const void* data) {
757 sk_sp<GrD3DBuffer> buffer = GrD3DBuffer::Make(this, sizeInBytes, type, accessPattern);
758 if (data && buffer) {
759 buffer->updateData(data, sizeInBytes);
760 }
761
762 return std::move(buffer);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500763}
764
765GrStencilAttachment* GrD3DGpu::createStencilAttachmentForRenderTarget(
766 const GrRenderTarget* rt, int width, int height, int numStencilSamples) {
Jim Van Verth4f51f472020-04-13 11:02:21 -0400767 SkASSERT(numStencilSamples == rt->numSamples() || this->caps()->mixedSamplesSupport());
768 SkASSERT(width >= rt->width());
769 SkASSERT(height >= rt->height());
770
771 const GrD3DCaps::StencilFormat& sFmt = this->d3dCaps().preferredStencilFormat();
772
773 GrD3DStencilAttachment* stencil(GrD3DStencilAttachment::Make(this,
774 width,
775 height,
776 numStencilSamples,
777 sFmt));
778 fStats.incStencilAttachmentCreates();
779 return stencil;
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500780}
781
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400782bool GrD3DGpu::createTextureResourceForBackendSurface(DXGI_FORMAT dxgiFormat,
783 SkISize dimensions,
784 GrTexturable texturable,
785 GrRenderable renderable,
786 GrMipMapped mipMapped,
787 GrD3DTextureResourceInfo* info,
Greg Daniel16032b32020-05-06 15:31:10 -0400788 GrProtected isProtected) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400789 SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400790
791 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
792 return false;
793 }
794
795 if (texturable == GrTexturable::kYes && !this->d3dCaps().isFormatTexturable(dxgiFormat)) {
796 return false;
797 }
798
799 if (renderable == GrRenderable::kYes && !this->d3dCaps().isFormatRenderable(dxgiFormat, 1)) {
800 return false;
801 }
802
803 int numMipLevels = 1;
804 if (mipMapped == GrMipMapped::kYes) {
805 numMipLevels = SkMipMap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
806 }
807
808 // create the texture
809 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
810 if (renderable == GrRenderable::kYes) {
811 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
812 }
813
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400814 D3D12_RESOURCE_DESC resourceDesc = {};
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400815 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
Greg Daniel16032b32020-05-06 15:31:10 -0400816 resourceDesc.Alignment = 0; // use default alignment
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400817 resourceDesc.Width = dimensions.fWidth;
818 resourceDesc.Height = dimensions.fHeight;
819 resourceDesc.DepthOrArraySize = 1;
820 resourceDesc.MipLevels = numMipLevels;
821 resourceDesc.Format = dxgiFormat;
822 resourceDesc.SampleDesc.Count = 1;
Greg Danielc9624d52020-04-13 15:36:31 -0400823 // quality levels are only supported for tiled resources so ignore for now
824 resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
Greg Daniel16032b32020-05-06 15:31:10 -0400825 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400826 resourceDesc.Flags = usageFlags;
827
Jim Van Verth280d4f72020-05-04 10:04:24 -0400828 D3D12_CLEAR_VALUE* clearValuePtr = nullptr;
829 D3D12_CLEAR_VALUE clearValue = {};
830 if (renderable == GrRenderable::kYes) {
831 clearValue.Format = dxgiFormat;
832 // Assume transparent black
833 clearValue.Color[0] = 0;
834 clearValue.Color[1] = 0;
835 clearValue.Color[2] = 0;
836 clearValue.Color[3] = 0;
837 clearValuePtr = &clearValue;
838 }
839
Greg Daniel16032b32020-05-06 15:31:10 -0400840 D3D12_RESOURCE_STATES initialState = (renderable == GrRenderable::kYes)
841 ? D3D12_RESOURCE_STATE_RENDER_TARGET
842 : D3D12_RESOURCE_STATE_COPY_DEST;
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400843 if (!GrD3DTextureResource::InitTextureResourceInfo(this, resourceDesc, initialState,
Jim Van Verth280d4f72020-05-04 10:04:24 -0400844 isProtected, clearValuePtr, info)) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400845 SkDebugf("Failed to init texture resource info\n");
846 return false;
847 }
848
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400849 return true;
850}
851
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500852GrBackendTexture GrD3DGpu::onCreateBackendTexture(SkISize dimensions,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400853 const GrBackendFormat& format,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400854 GrRenderable renderable,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400855 GrMipMapped mipMapped,
Greg Daniel16032b32020-05-06 15:31:10 -0400856 GrProtected isProtected) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400857 this->handleDirtyContext();
858
859 const GrD3DCaps& caps = this->d3dCaps();
860
861 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
862 return {};
863 }
864
865 DXGI_FORMAT dxgiFormat;
866 if (!format.asDxgiFormat(&dxgiFormat)) {
867 return {};
868 }
869
870 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
871 if (!caps.isFormatTexturable(dxgiFormat)) {
872 return {};
873 }
874
875 GrD3DTextureResourceInfo info;
876 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
877 renderable, mipMapped,
Greg Daniel16032b32020-05-06 15:31:10 -0400878 &info, isProtected)) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400879 return {};
880 }
881
882 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500883}
884
Greg Daniel16032b32020-05-06 15:31:10 -0400885bool GrD3DGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
886 sk_sp<GrRefCntedCallback> finishedCallback,
887 const BackendTextureData* data) {
888 // TODO: handle finishedCallback and data upload
889 return true;
890}
891
Greg Danielc1ad77c2020-05-06 11:40:03 -0400892GrBackendTexture GrD3DGpu::onCreateCompressedBackendTexture(
893 SkISize dimensions, const GrBackendFormat& format, GrMipMapped mipMapped,
894 GrProtected isProtected, sk_sp<GrRefCntedCallback> finishedCallback,
895 const BackendTextureData* data) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400896 this->handleDirtyContext();
897
898 const GrD3DCaps& caps = this->d3dCaps();
899
900 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
901 return {};
902 }
903
904 DXGI_FORMAT dxgiFormat;
905 if (!format.asDxgiFormat(&dxgiFormat)) {
906 return {};
907 }
908
909 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
910 if (!caps.isFormatTexturable(dxgiFormat)) {
911 return {};
912 }
913
914 GrD3DTextureResourceInfo info;
915 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
916 GrRenderable::kNo, mipMapped,
Greg Daniel16032b32020-05-06 15:31:10 -0400917 &info, isProtected)) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400918 return {};
919 }
920
921 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500922}
923
924void GrD3DGpu::deleteBackendTexture(const GrBackendTexture& tex) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400925 SkASSERT(GrBackendApi::kDirect3D == tex.fBackend);
926 // Nothing to do here, will get cleaned up when the GrBackendTexture object goes away
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500927}
928
Robert Phillips979b2232020-02-20 10:47:29 -0500929bool GrD3DGpu::compile(const GrProgramDesc&, const GrProgramInfo&) {
930 return false;
931}
932
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500933#if GR_TEST_UTILS
934bool GrD3DGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400935 SkASSERT(GrBackendApi::kDirect3D == tex.backend());
936
937 GrD3DTextureResourceInfo info;
938 if (!tex.getD3DTextureResourceInfo(&info)) {
939 return false;
940 }
941 ID3D12Resource* textureResource = info.fResource.get();
942 if (!textureResource) {
943 return false;
944 }
945 return !(textureResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500946}
947
948GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(int w, int h,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400949 GrColorType colorType) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400950 this->handleDirtyContext();
951
952 if (w > this->caps()->maxRenderTargetSize() || h > this->caps()->maxRenderTargetSize()) {
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400953 return {};
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400954 }
955
956 DXGI_FORMAT dxgiFormat = this->d3dCaps().getFormatFromColorType(colorType);
957
958 GrD3DTextureResourceInfo info;
959 if (!this->createTextureResourceForBackendSurface(dxgiFormat, { w, h }, GrTexturable::kNo,
960 GrRenderable::kYes, GrMipMapped::kNo,
Greg Daniel16032b32020-05-06 15:31:10 -0400961 &info, GrProtected::kNo)) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400962 return {};
963 }
964
965 return GrBackendRenderTarget(w, h, 1, info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500966}
967
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400968void GrD3DGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
969 SkASSERT(GrBackendApi::kDirect3D == rt.backend());
970
971 GrD3DTextureResourceInfo info;
972 if (rt.getD3DTextureResourceInfo(&info)) {
973 this->testingOnly_flushGpuAndSync();
974 // Nothing else to do here, will get cleaned up when the GrBackendRenderTarget
975 // is deleted.
976 }
977}
978
979void GrD3DGpu::testingOnly_flushGpuAndSync() {
Jim Van Verthc632aa62020-04-17 16:58:20 -0400980 SkAssertResult(this->submitDirectCommandList(SyncQueue::kForce));
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400981}
Jim Van Verthc632aa62020-04-17 16:58:20 -0400982
Jim Van Verth9b5e16c2020-04-20 10:45:52 -0400983void GrD3DGpu::testingOnly_startCapture() {
984 if (fGraphicsAnalysis) {
985 fGraphicsAnalysis->BeginCapture();
986 }
987}
988
989void GrD3DGpu::testingOnly_endCapture() {
990 if (fGraphicsAnalysis) {
991 fGraphicsAnalysis->EndCapture();
992 }
993}
994#endif
995
Jim Van Verthc632aa62020-04-17 16:58:20 -0400996///////////////////////////////////////////////////////////////////////////////
997
Greg Daniela5a6b322020-04-23 12:52:27 -0400998void GrD3DGpu::addResourceBarriers(sk_sp<GrManagedResource> resource,
Jim Van Verthc632aa62020-04-17 16:58:20 -0400999 int numBarriers,
1000 D3D12_RESOURCE_TRANSITION_BARRIER* barriers) const {
1001 SkASSERT(fCurrentDirectCommandList);
1002 SkASSERT(resource);
1003
Greg Daniela5a6b322020-04-23 12:52:27 -04001004 fCurrentDirectCommandList->resourceBarrier(std::move(resource), numBarriers, barriers);
Jim Van Verthc632aa62020-04-17 16:58:20 -04001005}
1006
Greg Daniel9efe3862020-06-11 11:51:06 -04001007void GrD3DGpu::prepareSurfacesForBackendAccessAndStateUpdates(
1008 GrSurfaceProxy* proxies[],
1009 int numProxies,
1010 SkSurface::BackendSurfaceAccess access,
1011 const GrBackendSurfaceMutableState* newState) {
Jim Van Verth682a2f42020-05-13 16:54:09 -04001012 SkASSERT(numProxies >= 0);
1013 SkASSERT(!numProxies || proxies);
1014
1015 // prepare proxies by transitioning to PRESENT renderState
1016 if (numProxies && access == SkSurface::BackendSurfaceAccess::kPresent) {
1017 GrD3DTextureResource* resource;
1018 for (int i = 0; i < numProxies; ++i) {
1019 SkASSERT(proxies[i]->isInstantiated());
1020 if (GrTexture* tex = proxies[i]->peekTexture()) {
1021 resource = static_cast<GrD3DTexture*>(tex);
1022 } else {
1023 GrRenderTarget* rt = proxies[i]->peekRenderTarget();
1024 SkASSERT(rt);
1025 resource = static_cast<GrD3DRenderTarget*>(rt);
1026 }
1027 resource->prepareForPresent(this);
1028 }
1029 }
1030}
1031
Jim Van Verthc632aa62020-04-17 16:58:20 -04001032bool GrD3DGpu::onSubmitToGpu(bool syncCpu) {
1033 if (syncCpu) {
1034 return this->submitDirectCommandList(SyncQueue::kForce);
1035 } else {
1036 return this->submitDirectCommandList(SyncQueue::kSkip);
1037 }
1038}