blob: 2427d0542be6cbaf95056d4a1b85a2efd0e96d68 [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 Verth9b5e16c2020-04-20 10:45:52 -040024#if GR_TEST_UTILS
25#include <DXProgrammableCapture.h>
26#endif
27
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050028sk_sp<GrGpu> GrD3DGpu::Make(const GrD3DBackendContext& backendContext,
29 const GrContextOptions& contextOptions, GrContext* context) {
30 return sk_sp<GrGpu>(new GrD3DGpu(context, contextOptions, backendContext));
31}
32
Greg Daniel83ed2132020-03-24 13:15:33 -040033// This constant determines how many OutstandingCommandLists are allocated together as a block in
34// the deque. As such it needs to balance allocating too much memory vs. incurring
35// allocation/deallocation thrashing. It should roughly correspond to the max number of outstanding
36// command lists we expect to see.
37static const int kDefaultOutstandingAllocCnt = 8;
38
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050039GrD3DGpu::GrD3DGpu(GrContext* context, const GrContextOptions& contextOptions,
40 const GrD3DBackendContext& backendContext)
Jim Van Verth03b8ab22020-02-24 11:36:15 -050041 : INHERITED(context)
42 , fDevice(backendContext.fDevice)
Greg Daniel02c45902020-03-09 10:58:09 -040043
44 , fQueue(backendContext.fQueue)
Greg Daniel83ed2132020-03-24 13:15:33 -040045 , fResourceProvider(this)
46 , fOutstandingCommandLists(sizeof(OutstandingCommandList), kDefaultOutstandingAllocCnt) {
Jim Van Verth8ec13302020-02-26 12:59:56 -050047 fCaps.reset(new GrD3DCaps(contextOptions,
Jim Van Verth9aa9a682020-04-01 10:13:48 -040048 backendContext.fAdapter.get(),
49 backendContext.fDevice.get()));
Greg Daniel85da3362020-03-09 15:18:35 -040050
51 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
Greg Daniele52c9782020-03-23 14:18:37 -040052 SkASSERT(fCurrentDirectCommandList);
Greg Daniel83ed2132020-03-24 13:15:33 -040053
54 SkASSERT(fCurrentFenceValue == 0);
55 SkDEBUGCODE(HRESULT hr = ) fDevice->CreateFence(fCurrentFenceValue, D3D12_FENCE_FLAG_NONE,
56 IID_PPV_ARGS(&fFence));
57 SkASSERT(SUCCEEDED(hr));
Jim Van Verth9b5e16c2020-04-20 10:45:52 -040058
59#if GR_TEST_UTILS
60 HRESULT getAnalysis = DXGIGetDebugInterface1(0, IID_PPV_ARGS(&fGraphicsAnalysis));
61 if (FAILED(getAnalysis)) {
62 fGraphicsAnalysis = nullptr;
63 }
64#endif
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050065}
66
Greg Daniel83ed2132020-03-24 13:15:33 -040067GrD3DGpu::~GrD3DGpu() {
68 this->destroyResources();
69}
70
71void GrD3DGpu::destroyResources() {
72 if (fCurrentDirectCommandList) {
73 fCurrentDirectCommandList->close();
74 fCurrentDirectCommandList.reset();
75 }
76
77 // We need to make sure everything has finished on the queue.
Jim Van Verthc632aa62020-04-17 16:58:20 -040078 this->waitForQueueCompletion();
Greg Daniel83ed2132020-03-24 13:15:33 -040079
80 SkDEBUGCODE(uint64_t fenceValue = fFence->GetCompletedValue();)
81
82 // We used a placement new for each object in fOutstandingCommandLists, so we're responsible
83 // for calling the destructor on each of them as well.
84 while (!fOutstandingCommandLists.empty()) {
85 OutstandingCommandList* list = (OutstandingCommandList*)fOutstandingCommandLists.back();
86 SkASSERT(list->fFenceValue <= fenceValue);
87 // No reason to recycle the command lists since we are destroying all resources anyways.
88 list->~OutstandingCommandList();
89 fOutstandingCommandLists.pop_back();
90 }
91}
Greg Daniel31a7b072020-02-26 15:31:49 -050092
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050093GrOpsRenderPass* GrD3DGpu::getOpsRenderPass(
94 GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
95 const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
Greg Daniel31a7b072020-02-26 15:31:49 -050096 const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050097 const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
Greg Daniel31a7b072020-02-26 15:31:49 -050098 if (!fCachedOpsRenderPass) {
99 fCachedOpsRenderPass.reset(new GrD3DOpsRenderPass(this));
100 }
101
102 if (!fCachedOpsRenderPass->set(rt, origin, bounds, colorInfo, stencilInfo, sampledProxies)) {
103 return nullptr;
104 }
105 return fCachedOpsRenderPass.get();
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500106}
107
Jim Van Verthc632aa62020-04-17 16:58:20 -0400108bool GrD3DGpu::submitDirectCommandList(SyncQueue sync) {
Greg Daniel83ed2132020-03-24 13:15:33 -0400109 SkASSERT(fCurrentDirectCommandList);
110
Jim Van Verthc632aa62020-04-17 16:58:20 -0400111 GrD3DDirectCommandList::SubmitResult result = fCurrentDirectCommandList->submit(fQueue.get());
112 if (result == GrD3DDirectCommandList::SubmitResult::kFailure) {
113 return false;
114 } else if (result == GrD3DDirectCommandList::SubmitResult::kNoWork) {
115 if (sync == SyncQueue::kForce) {
116 this->waitForQueueCompletion();
117 }
118 return true;
119 }
Greg Daniel83ed2132020-03-24 13:15:33 -0400120
121 new (fOutstandingCommandLists.push_back()) OutstandingCommandList(
122 std::move(fCurrentDirectCommandList), ++fCurrentFenceValue);
123
Jim Van Verth9aa9a682020-04-01 10:13:48 -0400124 SkDEBUGCODE(HRESULT hr = ) fQueue->Signal(fFence.get(), fCurrentFenceValue);
Greg Daniel83ed2132020-03-24 13:15:33 -0400125 SkASSERT(SUCCEEDED(hr));
126
Jim Van Verthc632aa62020-04-17 16:58:20 -0400127 if (sync == SyncQueue::kForce) {
128 this->waitForQueueCompletion();
129 }
130
Greg Daniel83ed2132020-03-24 13:15:33 -0400131 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
132
133 // This should be done after we have a new command list in case the freeing of any resources
134 // held by a finished command list causes us send a new command to the gpu (like changing the
135 // resource state.
136 this->checkForFinishedCommandLists();
137
138 SkASSERT(fCurrentDirectCommandList);
Jim Van Verthc632aa62020-04-17 16:58:20 -0400139 return true;
Greg Daniel83ed2132020-03-24 13:15:33 -0400140}
141
142void GrD3DGpu::checkForFinishedCommandLists() {
143 uint64_t currentFenceValue = fFence->GetCompletedValue();
144
145 // Iterate over all the outstanding command lists to see if any have finished. The commands
146 // lists are in order from oldest to newest, so we start at the front to check if their fence
147 // value is less than the last signaled value. If so we pop it off and move onto the next.
148 // Repeat till we find a command list that has not finished yet (and all others afterwards are
149 // also guaranteed to not have finished).
150 SkDeque::F2BIter iter(fOutstandingCommandLists);
151 const OutstandingCommandList* curList = (const OutstandingCommandList*)iter.next();
152 while (curList && curList->fFenceValue <= currentFenceValue) {
153 curList = (const OutstandingCommandList*)iter.next();
154 OutstandingCommandList* front = (OutstandingCommandList*)fOutstandingCommandLists.front();
Greg Daniel7a5f1fa2020-03-24 14:50:19 -0400155 fResourceProvider.recycleDirectCommandList(std::move(front->fCommandList));
Greg Daniel83ed2132020-03-24 13:15:33 -0400156 // Since we used placement new we are responsible for calling the destructor manually.
157 front->~OutstandingCommandList();
158 fOutstandingCommandLists.pop_front();
159 }
160}
161
Jim Van Verthc632aa62020-04-17 16:58:20 -0400162void GrD3DGpu::waitForQueueCompletion() {
163 if (fFence->GetCompletedValue() < fCurrentFenceValue) {
164 HANDLE fenceEvent;
165 fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
166 SkASSERT(fenceEvent);
167 SkDEBUGCODE(HRESULT hr = ) fFence->SetEventOnCompletion(fCurrentFenceValue, fenceEvent);
168 SkASSERT(SUCCEEDED(hr));
169 WaitForSingleObject(fenceEvent, INFINITE);
170 CloseHandle(fenceEvent);
171 }
172}
173
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500174void GrD3DGpu::submit(GrOpsRenderPass* renderPass) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400175 SkASSERT(fCachedOpsRenderPass.get() == renderPass);
176
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500177 // TODO: actually submit something here
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400178 fCachedOpsRenderPass.reset();
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500179}
180
181void GrD3DGpu::querySampleLocations(GrRenderTarget* rt, SkTArray<SkPoint>* sampleLocations) {
182 // TODO
183}
184
185sk_sp<GrTexture> GrD3DGpu::onCreateTexture(SkISize dimensions,
186 const GrBackendFormat& format,
187 GrRenderable renderable,
188 int renderTargetSampleCnt,
189 SkBudgeted budgeted,
190 GrProtected isProtected,
191 int mipLevelCount,
192 uint32_t levelClearMask) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400193 DXGI_FORMAT dxgiFormat;
194 SkAssertResult(format.asDxgiFormat(&dxgiFormat));
195 SkASSERT(!GrDxgiFormatIsCompressed(dxgiFormat));
196
197 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
198
199 if (renderable == GrRenderable::kYes) {
200 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
201 }
202
203 // This desc refers to the texture that will be read by the client. Thus even if msaa is
204 // requested, this describes the resolved texture. Therefore we always have samples set
205 // to 1.
206 SkASSERT(mipLevelCount > 0);
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400207 D3D12_RESOURCE_DESC resourceDesc = {};
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400208 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
209 // TODO: will use 4MB alignment for MSAA textures and 64KB for everything else
210 // might want to manually set alignment to 4KB for smaller textures
211 resourceDesc.Alignment = 0;
212 resourceDesc.Width = dimensions.fWidth;
213 resourceDesc.Height = dimensions.fHeight;
214 resourceDesc.DepthOrArraySize = 1;
215 resourceDesc.MipLevels = mipLevelCount;
216 resourceDesc.Format = dxgiFormat;
217 resourceDesc.SampleDesc.Count = 1;
Greg Danielc9624d52020-04-13 15:36:31 -0400218 // quality levels are only supported for tiled resources so ignore for now
219 resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400220 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400221 resourceDesc.Flags = usageFlags;
222
223 GrMipMapsStatus mipMapsStatus =
224 mipLevelCount > 1 ? GrMipMapsStatus::kDirty : GrMipMapsStatus::kNotAllocated;
225
226 sk_sp<GrD3DTexture> tex;
227 if (renderable == GrRenderable::kYes) {
228 tex = GrD3DTextureRenderTarget::MakeNewTextureRenderTarget(
229 this, budgeted, dimensions, renderTargetSampleCnt, resourceDesc, isProtected,
230 mipMapsStatus);
231 } else {
232 tex = GrD3DTexture::MakeNewTexture(this, budgeted, dimensions, resourceDesc, isProtected,
233 mipMapsStatus);
234 }
235
236 if (!tex) {
237 return nullptr;
238 }
239
240 if (levelClearMask) {
241 // TODO
242 }
243 return std::move(tex);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500244}
245
246sk_sp<GrTexture> GrD3DGpu::onCreateCompressedTexture(SkISize dimensions,
247 const GrBackendFormat& format,
248 SkBudgeted budgeted,
249 GrMipMapped mipMapped,
250 GrProtected isProtected,
251 const void* data, size_t dataSize) {
252 // TODO
253 return nullptr;
254}
255
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400256static bool check_resource_info(const GrD3DTextureResourceInfo& info) {
Jim Van Verth9aa9a682020-04-01 10:13:48 -0400257 if (!info.fResource.get()) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400258 return false;
259 }
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400260 return true;
261}
262
263static bool check_tex_resource_info(const GrD3DCaps& caps, const GrD3DTextureResourceInfo& info) {
264 if (!caps.isFormatTexturable(info.fFormat)) {
265 return false;
266 }
267 return true;
268}
269
270static bool check_rt_resource_info(const GrD3DCaps& caps, const GrD3DTextureResourceInfo& info,
271 int sampleCnt) {
272 if (!caps.isFormatRenderable(info.fFormat, sampleCnt)) {
273 return false;
274 }
275 return true;
276}
277
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400278sk_sp<GrTexture> GrD3DGpu::onWrapBackendTexture(const GrBackendTexture& tex,
279 GrWrapOwnership,
280 GrWrapCacheable wrapType,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400281 GrIOType ioType) {
282 GrD3DTextureResourceInfo textureInfo;
283 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
284 return nullptr;
285 }
286
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400287 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400288 return nullptr;
289 }
290
291 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
292 return nullptr;
293 }
294
295 // TODO: support protected context
296 if (tex.isProtected()) {
297 return nullptr;
298 }
299
300 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
301 SkASSERT(state);
302 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, ioType, textureInfo,
303 std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500304}
305
306sk_sp<GrTexture> GrD3DGpu::onWrapCompressedBackendTexture(const GrBackendTexture& tex,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400307 GrWrapOwnership,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500308 GrWrapCacheable wrapType) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400309 GrD3DTextureResourceInfo textureInfo;
310 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
311 return nullptr;
312 }
313
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400314 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400315 return nullptr;
316 }
317
318 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
319 return nullptr;
320 }
321
322 // TODO: support protected context
323 if (tex.isProtected()) {
324 return nullptr;
325 }
326
327 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
328 SkASSERT(state);
329 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, kRead_GrIOType,
330 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500331}
332
333sk_sp<GrTexture> GrD3DGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
334 int sampleCnt,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500335 GrWrapOwnership ownership,
336 GrWrapCacheable cacheable) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400337 GrD3DTextureResourceInfo textureInfo;
338 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
339 return nullptr;
340 }
341
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400342 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400343 return nullptr;
344 }
345
346 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
347 return nullptr;
348 }
349 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
350 return nullptr;
351 }
352
353 // TODO: support protected context
354 if (tex.isProtected()) {
355 return nullptr;
356 }
357
358 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
359
360 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
361 SkASSERT(state);
362
363 return GrD3DTextureRenderTarget::MakeWrappedTextureRenderTarget(this, tex.dimensions(),
364 sampleCnt, cacheable,
365 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500366}
367
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400368sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400369 // Currently the Direct3D backend does not support wrapping of msaa render targets directly. In
370 // general this is not an issue since swapchain images in D3D are never multisampled. Thus if
371 // you want a multisampled RT it is best to wrap the swapchain images and then let Skia handle
372 // creating and owning the MSAA images.
373 if (rt.sampleCnt() > 1) {
374 return nullptr;
375 }
376
377 GrD3DTextureResourceInfo info;
378 if (!rt.getD3DTextureResourceInfo(&info)) {
379 return nullptr;
380 }
381
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400382 if (!check_resource_info(info)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400383 return nullptr;
384 }
385
386 if (!check_rt_resource_info(this->d3dCaps(), info, rt.sampleCnt())) {
387 return nullptr;
388 }
389
390 // TODO: support protected context
391 if (rt.isProtected()) {
392 return nullptr;
393 }
394
395 sk_sp<GrD3DResourceState> state = rt.getGrD3DResourceState();
396
397 sk_sp<GrD3DRenderTarget> tgt = GrD3DRenderTarget::MakeWrappedRenderTarget(
398 this, rt.dimensions(), 1, info, std::move(state));
399
400 // We don't allow the client to supply a premade stencil buffer. We always create one if needed.
401 SkASSERT(!rt.stencilBits());
402 if (tgt) {
403 SkASSERT(tgt->canAttemptStencilAttachment());
404 }
405
406 return std::move(tgt);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500407}
408
409sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400410 int sampleCnt) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400411
412 GrD3DTextureResourceInfo textureInfo;
413 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
414 return nullptr;
415 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400416 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400417 return nullptr;
418 }
419
420 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
421 return nullptr;
422 }
423
424 // TODO: support protected context
425 if (tex.isProtected()) {
426 return nullptr;
427 }
428
429 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
430 if (!sampleCnt) {
431 return nullptr;
432 }
433
434 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
435 SkASSERT(state);
436
437 return GrD3DRenderTarget::MakeWrappedRenderTarget(this, tex.dimensions(), sampleCnt,
438 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500439}
440
441sk_sp<GrGpuBuffer> GrD3DGpu::onCreateBuffer(size_t sizeInBytes, GrGpuBufferType type,
Jim Van Verthd6ad4802020-04-03 14:59:20 -0400442 GrAccessPattern accessPattern, const void* data) {
443 sk_sp<GrD3DBuffer> buffer = GrD3DBuffer::Make(this, sizeInBytes, type, accessPattern);
444 if (data && buffer) {
445 buffer->updateData(data, sizeInBytes);
446 }
447
448 return std::move(buffer);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500449}
450
451GrStencilAttachment* GrD3DGpu::createStencilAttachmentForRenderTarget(
452 const GrRenderTarget* rt, int width, int height, int numStencilSamples) {
Jim Van Verth4f51f472020-04-13 11:02:21 -0400453 SkASSERT(numStencilSamples == rt->numSamples() || this->caps()->mixedSamplesSupport());
454 SkASSERT(width >= rt->width());
455 SkASSERT(height >= rt->height());
456
457 const GrD3DCaps::StencilFormat& sFmt = this->d3dCaps().preferredStencilFormat();
458
459 GrD3DStencilAttachment* stencil(GrD3DStencilAttachment::Make(this,
460 width,
461 height,
462 numStencilSamples,
463 sFmt));
464 fStats.incStencilAttachmentCreates();
465 return stencil;
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500466}
467
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400468bool GrD3DGpu::createTextureResourceForBackendSurface(DXGI_FORMAT dxgiFormat,
469 SkISize dimensions,
470 GrTexturable texturable,
471 GrRenderable renderable,
472 GrMipMapped mipMapped,
473 GrD3DTextureResourceInfo* info,
474 GrProtected isProtected,
475 const BackendTextureData* data) {
476 SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
477 if (texturable == GrTexturable::kNo) {
478 SkASSERT(!data && mipMapped == GrMipMapped::kNo);
479 }
480
481 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
482 return false;
483 }
484
485 if (texturable == GrTexturable::kYes && !this->d3dCaps().isFormatTexturable(dxgiFormat)) {
486 return false;
487 }
488
489 if (renderable == GrRenderable::kYes && !this->d3dCaps().isFormatRenderable(dxgiFormat, 1)) {
490 return false;
491 }
492
493 int numMipLevels = 1;
494 if (mipMapped == GrMipMapped::kYes) {
495 numMipLevels = SkMipMap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
496 }
497
498 // create the texture
499 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
500 if (renderable == GrRenderable::kYes) {
501 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
502 }
503
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400504 D3D12_RESOURCE_DESC resourceDesc = {};
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400505 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
506 resourceDesc.Alignment = 0; // use default alignment
507 resourceDesc.Width = dimensions.fWidth;
508 resourceDesc.Height = dimensions.fHeight;
509 resourceDesc.DepthOrArraySize = 1;
510 resourceDesc.MipLevels = numMipLevels;
511 resourceDesc.Format = dxgiFormat;
512 resourceDesc.SampleDesc.Count = 1;
Greg Danielc9624d52020-04-13 15:36:31 -0400513 // quality levels are only supported for tiled resources so ignore for now
514 resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400515 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
516 resourceDesc.Flags = usageFlags;
517
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400518 D3D12_RESOURCE_STATES initialState =
519 (renderable == GrRenderable::kYes) && !data ? D3D12_RESOURCE_STATE_RENDER_TARGET :
520 D3D12_RESOURCE_STATE_COPY_DEST;
521 if (!GrD3DTextureResource::InitTextureResourceInfo(this, resourceDesc, initialState,
522 isProtected, info)) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400523 SkDebugf("Failed to init texture resource info\n");
524 return false;
525 }
526
527 if (!data) {
528 return true;
529 }
530
531 // TODO: upload the data
532
533 return true;
534}
535
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500536GrBackendTexture GrD3DGpu::onCreateBackendTexture(SkISize dimensions,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400537 const GrBackendFormat& format,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400538 GrRenderable renderable,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400539 GrMipMapped mipMapped,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400540 GrProtected isProtected,
541 const BackendTextureData* data) {
542 this->handleDirtyContext();
543
544 const GrD3DCaps& caps = this->d3dCaps();
545
546 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
547 return {};
548 }
549
550 DXGI_FORMAT dxgiFormat;
551 if (!format.asDxgiFormat(&dxgiFormat)) {
552 return {};
553 }
554
555 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
556 if (!caps.isFormatTexturable(dxgiFormat)) {
557 return {};
558 }
559
560 GrD3DTextureResourceInfo info;
561 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
562 renderable, mipMapped,
563 &info, isProtected, data)) {
564 return {};
565 }
566
567 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500568}
569
570GrBackendTexture GrD3DGpu::onCreateCompressedBackendTexture(SkISize dimensions,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400571 const GrBackendFormat& format,
572 GrMipMapped mipMapped,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400573 GrProtected isProtected,
574 const BackendTextureData* data) {
575 this->handleDirtyContext();
576
577 const GrD3DCaps& caps = this->d3dCaps();
578
579 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
580 return {};
581 }
582
583 DXGI_FORMAT dxgiFormat;
584 if (!format.asDxgiFormat(&dxgiFormat)) {
585 return {};
586 }
587
588 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
589 if (!caps.isFormatTexturable(dxgiFormat)) {
590 return {};
591 }
592
593 GrD3DTextureResourceInfo info;
594 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
595 GrRenderable::kNo, mipMapped,
596 &info, isProtected, data)) {
597 return {};
598 }
599
600 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500601}
602
603void GrD3DGpu::deleteBackendTexture(const GrBackendTexture& tex) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400604 SkASSERT(GrBackendApi::kDirect3D == tex.fBackend);
605 // Nothing to do here, will get cleaned up when the GrBackendTexture object goes away
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500606}
607
Robert Phillips979b2232020-02-20 10:47:29 -0500608bool GrD3DGpu::compile(const GrProgramDesc&, const GrProgramInfo&) {
609 return false;
610}
611
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500612#if GR_TEST_UTILS
613bool GrD3DGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400614 SkASSERT(GrBackendApi::kDirect3D == tex.backend());
615
616 GrD3DTextureResourceInfo info;
617 if (!tex.getD3DTextureResourceInfo(&info)) {
618 return false;
619 }
620 ID3D12Resource* textureResource = info.fResource.get();
621 if (!textureResource) {
622 return false;
623 }
624 return !(textureResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500625}
626
627GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(int w, int h,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400628 GrColorType colorType) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400629 this->handleDirtyContext();
630
631 if (w > this->caps()->maxRenderTargetSize() || h > this->caps()->maxRenderTargetSize()) {
Jim Van Verth2b9f53e2020-04-14 11:47:34 -0400632 return {};
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400633 }
634
635 DXGI_FORMAT dxgiFormat = this->d3dCaps().getFormatFromColorType(colorType);
636
637 GrD3DTextureResourceInfo info;
638 if (!this->createTextureResourceForBackendSurface(dxgiFormat, { w, h }, GrTexturable::kNo,
639 GrRenderable::kYes, GrMipMapped::kNo,
640 &info, GrProtected::kNo, nullptr)) {
641 return {};
642 }
643
644 return GrBackendRenderTarget(w, h, 1, info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500645}
646
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400647void GrD3DGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
648 SkASSERT(GrBackendApi::kDirect3D == rt.backend());
649
650 GrD3DTextureResourceInfo info;
651 if (rt.getD3DTextureResourceInfo(&info)) {
652 this->testingOnly_flushGpuAndSync();
653 // Nothing else to do here, will get cleaned up when the GrBackendRenderTarget
654 // is deleted.
655 }
656}
657
658void GrD3DGpu::testingOnly_flushGpuAndSync() {
Jim Van Verthc632aa62020-04-17 16:58:20 -0400659 SkAssertResult(this->submitDirectCommandList(SyncQueue::kForce));
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400660}
Jim Van Verthc632aa62020-04-17 16:58:20 -0400661
Jim Van Verth9b5e16c2020-04-20 10:45:52 -0400662void GrD3DGpu::testingOnly_startCapture() {
663 if (fGraphicsAnalysis) {
664 fGraphicsAnalysis->BeginCapture();
665 }
666}
667
668void GrD3DGpu::testingOnly_endCapture() {
669 if (fGraphicsAnalysis) {
670 fGraphicsAnalysis->EndCapture();
671 }
672}
673#endif
674
Jim Van Verthc632aa62020-04-17 16:58:20 -0400675///////////////////////////////////////////////////////////////////////////////
676
677void GrD3DGpu::addResourceBarriers(const GrManagedResource* resource,
678 int numBarriers,
679 D3D12_RESOURCE_TRANSITION_BARRIER* barriers) const {
680 SkASSERT(fCurrentDirectCommandList);
681 SkASSERT(resource);
682
683 fCurrentDirectCommandList->resourceBarrier(resource, numBarriers, barriers);
684}
685
686bool GrD3DGpu::onSubmitToGpu(bool syncCpu) {
687 if (syncCpu) {
688 return this->submitDirectCommandList(SyncQueue::kForce);
689 } else {
690 return this->submitDirectCommandList(SyncQueue::kSkip);
691 }
692}