blob: 3fc5446e4da8ebeb27bfc1faec4c770ed5775450 [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 Daniel31a7b072020-02-26 15:31:49 -050023
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050024sk_sp<GrGpu> GrD3DGpu::Make(const GrD3DBackendContext& backendContext,
25 const GrContextOptions& contextOptions, GrContext* context) {
26 return sk_sp<GrGpu>(new GrD3DGpu(context, contextOptions, backendContext));
27}
28
Greg Daniel83ed2132020-03-24 13:15:33 -040029// This constant determines how many OutstandingCommandLists are allocated together as a block in
30// the deque. As such it needs to balance allocating too much memory vs. incurring
31// allocation/deallocation thrashing. It should roughly correspond to the max number of outstanding
32// command lists we expect to see.
33static const int kDefaultOutstandingAllocCnt = 8;
34
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050035GrD3DGpu::GrD3DGpu(GrContext* context, const GrContextOptions& contextOptions,
36 const GrD3DBackendContext& backendContext)
Jim Van Verth03b8ab22020-02-24 11:36:15 -050037 : INHERITED(context)
38 , fDevice(backendContext.fDevice)
Greg Daniel02c45902020-03-09 10:58:09 -040039
40 , fQueue(backendContext.fQueue)
Greg Daniel83ed2132020-03-24 13:15:33 -040041 , fResourceProvider(this)
42 , fOutstandingCommandLists(sizeof(OutstandingCommandList), kDefaultOutstandingAllocCnt) {
Jim Van Verth8ec13302020-02-26 12:59:56 -050043 fCaps.reset(new GrD3DCaps(contextOptions,
Jim Van Verth9aa9a682020-04-01 10:13:48 -040044 backendContext.fAdapter.get(),
45 backendContext.fDevice.get()));
Greg Daniel85da3362020-03-09 15:18:35 -040046
47 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
Greg Daniele52c9782020-03-23 14:18:37 -040048 SkASSERT(fCurrentDirectCommandList);
Greg Daniel83ed2132020-03-24 13:15:33 -040049
50 SkASSERT(fCurrentFenceValue == 0);
51 SkDEBUGCODE(HRESULT hr = ) fDevice->CreateFence(fCurrentFenceValue, D3D12_FENCE_FLAG_NONE,
52 IID_PPV_ARGS(&fFence));
53 SkASSERT(SUCCEEDED(hr));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050054}
55
Greg Daniel83ed2132020-03-24 13:15:33 -040056GrD3DGpu::~GrD3DGpu() {
57 this->destroyResources();
58}
59
60void GrD3DGpu::destroyResources() {
61 if (fCurrentDirectCommandList) {
62 fCurrentDirectCommandList->close();
63 fCurrentDirectCommandList.reset();
64 }
65
66 // We need to make sure everything has finished on the queue.
Jim Van Verthc632aa62020-04-17 16:58:20 -040067 this->waitForQueueCompletion();
Greg Daniel83ed2132020-03-24 13:15:33 -040068
69 SkDEBUGCODE(uint64_t fenceValue = fFence->GetCompletedValue();)
70
71 // We used a placement new for each object in fOutstandingCommandLists, so we're responsible
72 // for calling the destructor on each of them as well.
73 while (!fOutstandingCommandLists.empty()) {
74 OutstandingCommandList* list = (OutstandingCommandList*)fOutstandingCommandLists.back();
75 SkASSERT(list->fFenceValue <= fenceValue);
76 // No reason to recycle the command lists since we are destroying all resources anyways.
77 list->~OutstandingCommandList();
78 fOutstandingCommandLists.pop_back();
79 }
80}
Greg Daniel31a7b072020-02-26 15:31:49 -050081
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050082GrOpsRenderPass* GrD3DGpu::getOpsRenderPass(
83 GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
84 const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
Greg Daniel31a7b072020-02-26 15:31:49 -050085 const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050086 const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
Greg Daniel31a7b072020-02-26 15:31:49 -050087 if (!fCachedOpsRenderPass) {
88 fCachedOpsRenderPass.reset(new GrD3DOpsRenderPass(this));
89 }
90
91 if (!fCachedOpsRenderPass->set(rt, origin, bounds, colorInfo, stencilInfo, sampledProxies)) {
92 return nullptr;
93 }
94 return fCachedOpsRenderPass.get();
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050095}
96
Jim Van Verthc632aa62020-04-17 16:58:20 -040097bool GrD3DGpu::submitDirectCommandList(SyncQueue sync) {
Greg Daniel83ed2132020-03-24 13:15:33 -040098 SkASSERT(fCurrentDirectCommandList);
99
Jim Van Verthc632aa62020-04-17 16:58:20 -0400100 GrD3DDirectCommandList::SubmitResult result = fCurrentDirectCommandList->submit(fQueue.get());
101 if (result == GrD3DDirectCommandList::SubmitResult::kFailure) {
102 return false;
103 } else if (result == GrD3DDirectCommandList::SubmitResult::kNoWork) {
104 if (sync == SyncQueue::kForce) {
105 this->waitForQueueCompletion();
106 }
107 return true;
108 }
Greg Daniel83ed2132020-03-24 13:15:33 -0400109
110 new (fOutstandingCommandLists.push_back()) OutstandingCommandList(
111 std::move(fCurrentDirectCommandList), ++fCurrentFenceValue);
112
Jim Van Verth9aa9a682020-04-01 10:13:48 -0400113 SkDEBUGCODE(HRESULT hr = ) fQueue->Signal(fFence.get(), fCurrentFenceValue);
Greg Daniel83ed2132020-03-24 13:15:33 -0400114 SkASSERT(SUCCEEDED(hr));
115
Jim Van Verthc632aa62020-04-17 16:58:20 -0400116 if (sync == SyncQueue::kForce) {
117 this->waitForQueueCompletion();
118 }
119
Greg Daniel83ed2132020-03-24 13:15:33 -0400120 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
121
122 // This should be done after we have a new command list in case the freeing of any resources
123 // held by a finished command list causes us send a new command to the gpu (like changing the
124 // resource state.
125 this->checkForFinishedCommandLists();
126
127 SkASSERT(fCurrentDirectCommandList);
Jim Van Verthc632aa62020-04-17 16:58:20 -0400128 return true;
Greg Daniel83ed2132020-03-24 13:15:33 -0400129}
130
131void GrD3DGpu::checkForFinishedCommandLists() {
132 uint64_t currentFenceValue = fFence->GetCompletedValue();
133
134 // Iterate over all the outstanding command lists to see if any have finished. The commands
135 // lists are in order from oldest to newest, so we start at the front to check if their fence
136 // value is less than the last signaled value. If so we pop it off and move onto the next.
137 // Repeat till we find a command list that has not finished yet (and all others afterwards are
138 // also guaranteed to not have finished).
139 SkDeque::F2BIter iter(fOutstandingCommandLists);
140 const OutstandingCommandList* curList = (const OutstandingCommandList*)iter.next();
141 while (curList && curList->fFenceValue <= currentFenceValue) {
142 curList = (const OutstandingCommandList*)iter.next();
143 OutstandingCommandList* front = (OutstandingCommandList*)fOutstandingCommandLists.front();
Greg Daniel7a5f1fa2020-03-24 14:50:19 -0400144 fResourceProvider.recycleDirectCommandList(std::move(front->fCommandList));
Greg Daniel83ed2132020-03-24 13:15:33 -0400145 // Since we used placement new we are responsible for calling the destructor manually.
146 front->~OutstandingCommandList();
147 fOutstandingCommandLists.pop_front();
148 }
149}
150
Jim Van Verthc632aa62020-04-17 16:58:20 -0400151void GrD3DGpu::waitForQueueCompletion() {
152 if (fFence->GetCompletedValue() < fCurrentFenceValue) {
153 HANDLE fenceEvent;
154 fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
155 SkASSERT(fenceEvent);
156 SkDEBUGCODE(HRESULT hr = ) fFence->SetEventOnCompletion(fCurrentFenceValue, fenceEvent);
157 SkASSERT(SUCCEEDED(hr));
158 WaitForSingleObject(fenceEvent, INFINITE);
159 CloseHandle(fenceEvent);
160 }
161}
162
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500163void GrD3DGpu::submit(GrOpsRenderPass* renderPass) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400164 SkASSERT(fCachedOpsRenderPass.get() == renderPass);
165
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500166 // TODO: actually submit something here
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400167 fCachedOpsRenderPass.reset();
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500168}
169
170void GrD3DGpu::querySampleLocations(GrRenderTarget* rt, SkTArray<SkPoint>* sampleLocations) {
171 // TODO
172}
173
174sk_sp<GrTexture> GrD3DGpu::onCreateTexture(SkISize dimensions,
175 const GrBackendFormat& format,
176 GrRenderable renderable,
177 int renderTargetSampleCnt,
178 SkBudgeted budgeted,
179 GrProtected isProtected,
180 int mipLevelCount,
181 uint32_t levelClearMask) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400182 DXGI_FORMAT dxgiFormat;
183 SkAssertResult(format.asDxgiFormat(&dxgiFormat));
184 SkASSERT(!GrDxgiFormatIsCompressed(dxgiFormat));
185
186 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
187
188 if (renderable == GrRenderable::kYes) {
189 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
190 }
191
192 // This desc refers to the texture that will be read by the client. Thus even if msaa is
193 // requested, this describes the resolved texture. Therefore we always have samples set
194 // to 1.
195 SkASSERT(mipLevelCount > 0);
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400196 D3D12_RESOURCE_DESC resourceDesc = {};
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400197 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
198 // TODO: will use 4MB alignment for MSAA textures and 64KB for everything else
199 // might want to manually set alignment to 4KB for smaller textures
200 resourceDesc.Alignment = 0;
201 resourceDesc.Width = dimensions.fWidth;
202 resourceDesc.Height = dimensions.fHeight;
203 resourceDesc.DepthOrArraySize = 1;
204 resourceDesc.MipLevels = mipLevelCount;
205 resourceDesc.Format = dxgiFormat;
206 resourceDesc.SampleDesc.Count = 1;
Greg Danielc9624d52020-04-13 15:36:31 -0400207 // quality levels are only supported for tiled resources so ignore for now
208 resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400209 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400210 resourceDesc.Flags = usageFlags;
211
212 GrMipMapsStatus mipMapsStatus =
213 mipLevelCount > 1 ? GrMipMapsStatus::kDirty : GrMipMapsStatus::kNotAllocated;
214
215 sk_sp<GrD3DTexture> tex;
216 if (renderable == GrRenderable::kYes) {
217 tex = GrD3DTextureRenderTarget::MakeNewTextureRenderTarget(
218 this, budgeted, dimensions, renderTargetSampleCnt, resourceDesc, isProtected,
219 mipMapsStatus);
220 } else {
221 tex = GrD3DTexture::MakeNewTexture(this, budgeted, dimensions, resourceDesc, isProtected,
222 mipMapsStatus);
223 }
224
225 if (!tex) {
226 return nullptr;
227 }
228
229 if (levelClearMask) {
230 // TODO
231 }
232 return std::move(tex);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500233}
234
235sk_sp<GrTexture> GrD3DGpu::onCreateCompressedTexture(SkISize dimensions,
236 const GrBackendFormat& format,
237 SkBudgeted budgeted,
238 GrMipMapped mipMapped,
239 GrProtected isProtected,
240 const void* data, size_t dataSize) {
241 // TODO
242 return nullptr;
243}
244
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400245static bool check_resource_info(const GrD3DTextureResourceInfo& info) {
Jim Van Verth9aa9a682020-04-01 10:13:48 -0400246 if (!info.fResource.get()) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400247 return false;
248 }
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400249 return true;
250}
251
252static bool check_tex_resource_info(const GrD3DCaps& caps, const GrD3DTextureResourceInfo& info) {
253 if (!caps.isFormatTexturable(info.fFormat)) {
254 return false;
255 }
256 return true;
257}
258
259static bool check_rt_resource_info(const GrD3DCaps& caps, const GrD3DTextureResourceInfo& info,
260 int sampleCnt) {
261 if (!caps.isFormatRenderable(info.fFormat, sampleCnt)) {
262 return false;
263 }
264 return true;
265}
266
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400267sk_sp<GrTexture> GrD3DGpu::onWrapBackendTexture(const GrBackendTexture& tex,
268 GrWrapOwnership,
269 GrWrapCacheable wrapType,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400270 GrIOType ioType) {
271 GrD3DTextureResourceInfo textureInfo;
272 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
273 return nullptr;
274 }
275
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400276 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400277 return nullptr;
278 }
279
280 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
281 return nullptr;
282 }
283
284 // TODO: support protected context
285 if (tex.isProtected()) {
286 return nullptr;
287 }
288
289 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
290 SkASSERT(state);
291 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, ioType, textureInfo,
292 std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500293}
294
295sk_sp<GrTexture> GrD3DGpu::onWrapCompressedBackendTexture(const GrBackendTexture& tex,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400296 GrWrapOwnership,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500297 GrWrapCacheable wrapType) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400298 GrD3DTextureResourceInfo textureInfo;
299 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
300 return nullptr;
301 }
302
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400303 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400304 return nullptr;
305 }
306
307 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
308 return nullptr;
309 }
310
311 // TODO: support protected context
312 if (tex.isProtected()) {
313 return nullptr;
314 }
315
316 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
317 SkASSERT(state);
318 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, kRead_GrIOType,
319 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500320}
321
322sk_sp<GrTexture> GrD3DGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
323 int sampleCnt,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500324 GrWrapOwnership ownership,
325 GrWrapCacheable cacheable) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400326 GrD3DTextureResourceInfo textureInfo;
327 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
328 return nullptr;
329 }
330
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400331 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400332 return nullptr;
333 }
334
335 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
336 return nullptr;
337 }
338 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
339 return nullptr;
340 }
341
342 // TODO: support protected context
343 if (tex.isProtected()) {
344 return nullptr;
345 }
346
347 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
348
349 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
350 SkASSERT(state);
351
352 return GrD3DTextureRenderTarget::MakeWrappedTextureRenderTarget(this, tex.dimensions(),
353 sampleCnt, cacheable,
354 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500355}
356
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400357sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400358 // Currently the Direct3D backend does not support wrapping of msaa render targets directly. In
359 // general this is not an issue since swapchain images in D3D are never multisampled. Thus if
360 // you want a multisampled RT it is best to wrap the swapchain images and then let Skia handle
361 // creating and owning the MSAA images.
362 if (rt.sampleCnt() > 1) {
363 return nullptr;
364 }
365
366 GrD3DTextureResourceInfo info;
367 if (!rt.getD3DTextureResourceInfo(&info)) {
368 return nullptr;
369 }
370
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400371 if (!check_resource_info(info)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400372 return nullptr;
373 }
374
375 if (!check_rt_resource_info(this->d3dCaps(), info, rt.sampleCnt())) {
376 return nullptr;
377 }
378
379 // TODO: support protected context
380 if (rt.isProtected()) {
381 return nullptr;
382 }
383
384 sk_sp<GrD3DResourceState> state = rt.getGrD3DResourceState();
385
386 sk_sp<GrD3DRenderTarget> tgt = GrD3DRenderTarget::MakeWrappedRenderTarget(
387 this, rt.dimensions(), 1, info, std::move(state));
388
389 // We don't allow the client to supply a premade stencil buffer. We always create one if needed.
390 SkASSERT(!rt.stencilBits());
391 if (tgt) {
392 SkASSERT(tgt->canAttemptStencilAttachment());
393 }
394
395 return std::move(tgt);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500396}
397
398sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400399 int sampleCnt) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400400
401 GrD3DTextureResourceInfo textureInfo;
402 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
403 return nullptr;
404 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400405 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400406 return nullptr;
407 }
408
409 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
410 return nullptr;
411 }
412
413 // TODO: support protected context
414 if (tex.isProtected()) {
415 return nullptr;
416 }
417
418 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
419 if (!sampleCnt) {
420 return nullptr;
421 }
422
423 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
424 SkASSERT(state);
425
426 return GrD3DRenderTarget::MakeWrappedRenderTarget(this, tex.dimensions(), sampleCnt,
427 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500428}
429
430sk_sp<GrGpuBuffer> GrD3DGpu::onCreateBuffer(size_t sizeInBytes, GrGpuBufferType type,
Jim Van Verthd6ad4802020-04-03 14:59:20 -0400431 GrAccessPattern accessPattern, const void* data) {
432 sk_sp<GrD3DBuffer> buffer = GrD3DBuffer::Make(this, sizeInBytes, type, accessPattern);
433 if (data && buffer) {
434 buffer->updateData(data, sizeInBytes);
435 }
436
437 return std::move(buffer);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500438}
439
440GrStencilAttachment* GrD3DGpu::createStencilAttachmentForRenderTarget(
441 const GrRenderTarget* rt, int width, int height, int numStencilSamples) {
Jim Van Verth4f51f472020-04-13 11:02:21 -0400442 SkASSERT(numStencilSamples == rt->numSamples() || this->caps()->mixedSamplesSupport());
443 SkASSERT(width >= rt->width());
444 SkASSERT(height >= rt->height());
445
446 const GrD3DCaps::StencilFormat& sFmt = this->d3dCaps().preferredStencilFormat();
447
448 GrD3DStencilAttachment* stencil(GrD3DStencilAttachment::Make(this,
449 width,
450 height,
451 numStencilSamples,
452 sFmt));
453 fStats.incStencilAttachmentCreates();
454 return stencil;
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500455}
456
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400457bool GrD3DGpu::createTextureResourceForBackendSurface(DXGI_FORMAT dxgiFormat,
458 SkISize dimensions,
459 GrTexturable texturable,
460 GrRenderable renderable,
461 GrMipMapped mipMapped,
462 GrD3DTextureResourceInfo* info,
463 GrProtected isProtected,
464 const BackendTextureData* data) {
465 SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
466 if (texturable == GrTexturable::kNo) {
467 SkASSERT(!data && mipMapped == GrMipMapped::kNo);
468 }
469
470 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
471 return false;
472 }
473
474 if (texturable == GrTexturable::kYes && !this->d3dCaps().isFormatTexturable(dxgiFormat)) {
475 return false;
476 }
477
478 if (renderable == GrRenderable::kYes && !this->d3dCaps().isFormatRenderable(dxgiFormat, 1)) {
479 return false;
480 }
481
482 int numMipLevels = 1;
483 if (mipMapped == GrMipMapped::kYes) {
484 numMipLevels = SkMipMap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
485 }
486
487 // create the texture
488 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
489 if (renderable == GrRenderable::kYes) {
490 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
491 }
492
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400493 D3D12_RESOURCE_DESC resourceDesc = {};
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400494 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
495 resourceDesc.Alignment = 0; // use default alignment
496 resourceDesc.Width = dimensions.fWidth;
497 resourceDesc.Height = dimensions.fHeight;
498 resourceDesc.DepthOrArraySize = 1;
499 resourceDesc.MipLevels = numMipLevels;
500 resourceDesc.Format = dxgiFormat;
501 resourceDesc.SampleDesc.Count = 1;
Greg Danielc9624d52020-04-13 15:36:31 -0400502 // quality levels are only supported for tiled resources so ignore for now
503 resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400504 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
505 resourceDesc.Flags = usageFlags;
506
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400507 D3D12_RESOURCE_STATES initialState =
508 (renderable == GrRenderable::kYes) && !data ? D3D12_RESOURCE_STATE_RENDER_TARGET :
509 D3D12_RESOURCE_STATE_COPY_DEST;
510 if (!GrD3DTextureResource::InitTextureResourceInfo(this, resourceDesc, initialState,
511 isProtected, info)) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400512 SkDebugf("Failed to init texture resource info\n");
513 return false;
514 }
515
516 if (!data) {
517 return true;
518 }
519
520 // TODO: upload the data
521
522 return true;
523}
524
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500525GrBackendTexture GrD3DGpu::onCreateBackendTexture(SkISize dimensions,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400526 const GrBackendFormat& format,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400527 GrRenderable renderable,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400528 GrMipMapped mipMapped,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400529 GrProtected isProtected,
530 const BackendTextureData* data) {
531 this->handleDirtyContext();
532
533 const GrD3DCaps& caps = this->d3dCaps();
534
535 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
536 return {};
537 }
538
539 DXGI_FORMAT dxgiFormat;
540 if (!format.asDxgiFormat(&dxgiFormat)) {
541 return {};
542 }
543
544 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
545 if (!caps.isFormatTexturable(dxgiFormat)) {
546 return {};
547 }
548
549 GrD3DTextureResourceInfo info;
550 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
551 renderable, mipMapped,
552 &info, isProtected, data)) {
553 return {};
554 }
555
556 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500557}
558
559GrBackendTexture GrD3DGpu::onCreateCompressedBackendTexture(SkISize dimensions,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400560 const GrBackendFormat& format,
561 GrMipMapped mipMapped,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400562 GrProtected isProtected,
563 const BackendTextureData* data) {
564 this->handleDirtyContext();
565
566 const GrD3DCaps& caps = this->d3dCaps();
567
568 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
569 return {};
570 }
571
572 DXGI_FORMAT dxgiFormat;
573 if (!format.asDxgiFormat(&dxgiFormat)) {
574 return {};
575 }
576
577 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
578 if (!caps.isFormatTexturable(dxgiFormat)) {
579 return {};
580 }
581
582 GrD3DTextureResourceInfo info;
583 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
584 GrRenderable::kNo, mipMapped,
585 &info, isProtected, data)) {
586 return {};
587 }
588
589 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500590}
591
592void GrD3DGpu::deleteBackendTexture(const GrBackendTexture& tex) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400593 SkASSERT(GrBackendApi::kDirect3D == tex.fBackend);
594 // Nothing to do here, will get cleaned up when the GrBackendTexture object goes away
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500595}
596
Robert Phillips979b2232020-02-20 10:47:29 -0500597bool GrD3DGpu::compile(const GrProgramDesc&, const GrProgramInfo&) {
598 return false;
599}
600
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500601#if GR_TEST_UTILS
602bool GrD3DGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400603 SkASSERT(GrBackendApi::kDirect3D == tex.backend());
604
605 GrD3DTextureResourceInfo info;
606 if (!tex.getD3DTextureResourceInfo(&info)) {
607 return false;
608 }
609 ID3D12Resource* textureResource = info.fResource.get();
610 if (!textureResource) {
611 return false;
612 }
613 return !(textureResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500614}
615
616GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(int w, int h,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400617 GrColorType colorType) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400618 this->handleDirtyContext();
619
620 if (w > this->caps()->maxRenderTargetSize() || h > this->caps()->maxRenderTargetSize()) {
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400621 return {};
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400622 }
623
624 DXGI_FORMAT dxgiFormat = this->d3dCaps().getFormatFromColorType(colorType);
625
626 GrD3DTextureResourceInfo info;
627 if (!this->createTextureResourceForBackendSurface(dxgiFormat, { w, h }, GrTexturable::kNo,
628 GrRenderable::kYes, GrMipMapped::kNo,
629 &info, GrProtected::kNo, nullptr)) {
630 return {};
631 }
632
633 return GrBackendRenderTarget(w, h, 1, info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500634}
635
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400636void GrD3DGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
637 SkASSERT(GrBackendApi::kDirect3D == rt.backend());
638
639 GrD3DTextureResourceInfo info;
640 if (rt.getD3DTextureResourceInfo(&info)) {
641 this->testingOnly_flushGpuAndSync();
642 // Nothing else to do here, will get cleaned up when the GrBackendRenderTarget
643 // is deleted.
644 }
645}
646
647void GrD3DGpu::testingOnly_flushGpuAndSync() {
Jim Van Verthc632aa62020-04-17 16:58:20 -0400648 SkAssertResult(this->submitDirectCommandList(SyncQueue::kForce));
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400649}
Jim Van Verthc632aa62020-04-17 16:58:20 -0400650
651///////////////////////////////////////////////////////////////////////////////
652
653void GrD3DGpu::addResourceBarriers(const GrManagedResource* resource,
654 int numBarriers,
655 D3D12_RESOURCE_TRANSITION_BARRIER* barriers) const {
656 SkASSERT(fCurrentDirectCommandList);
657 SkASSERT(resource);
658
659 fCurrentDirectCommandList->resourceBarrier(resource, numBarriers, barriers);
660}
661
662bool GrD3DGpu::onSubmitToGpu(bool syncCpu) {
663 if (syncCpu) {
664 return this->submitDirectCommandList(SyncQueue::kForce);
665 } else {
666 return this->submitDirectCommandList(SyncQueue::kSkip);
667 }
668}
669
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500670#endif