blob: 3e3951a178072f937452cb2bcca1e1461930960f [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 Verth96bfeff2020-04-09 14:36:12 -040012#include "src/core/SkMipMap.h"
Jim Van Verthd6ad4802020-04-03 14:59:20 -040013#include "src/gpu/d3d/GrD3DBuffer.h"
Greg Daniel31a7b072020-02-26 15:31:49 -050014#include "src/gpu/d3d/GrD3DCaps.h"
15#include "src/gpu/d3d/GrD3DOpsRenderPass.h"
Jim Van Verthaa90dad2020-03-30 15:00:39 -040016#include "src/gpu/d3d/GrD3DTexture.h"
17#include "src/gpu/d3d/GrD3DTextureRenderTarget.h"
18#include "src/gpu/d3d/GrD3DUtil.h"
Greg Daniel31a7b072020-02-26 15:31:49 -050019
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050020sk_sp<GrGpu> GrD3DGpu::Make(const GrD3DBackendContext& backendContext,
21 const GrContextOptions& contextOptions, GrContext* context) {
22 return sk_sp<GrGpu>(new GrD3DGpu(context, contextOptions, backendContext));
23}
24
Greg Daniel83ed2132020-03-24 13:15:33 -040025// This constant determines how many OutstandingCommandLists are allocated together as a block in
26// the deque. As such it needs to balance allocating too much memory vs. incurring
27// allocation/deallocation thrashing. It should roughly correspond to the max number of outstanding
28// command lists we expect to see.
29static const int kDefaultOutstandingAllocCnt = 8;
30
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050031GrD3DGpu::GrD3DGpu(GrContext* context, const GrContextOptions& contextOptions,
32 const GrD3DBackendContext& backendContext)
Jim Van Verth03b8ab22020-02-24 11:36:15 -050033 : INHERITED(context)
34 , fDevice(backendContext.fDevice)
Greg Daniel02c45902020-03-09 10:58:09 -040035
36 , fQueue(backendContext.fQueue)
Greg Daniel83ed2132020-03-24 13:15:33 -040037 , fResourceProvider(this)
38 , fOutstandingCommandLists(sizeof(OutstandingCommandList), kDefaultOutstandingAllocCnt) {
Jim Van Verth8ec13302020-02-26 12:59:56 -050039 fCaps.reset(new GrD3DCaps(contextOptions,
Jim Van Verth9aa9a682020-04-01 10:13:48 -040040 backendContext.fAdapter.get(),
41 backendContext.fDevice.get()));
Greg Daniel85da3362020-03-09 15:18:35 -040042
43 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
Greg Daniele52c9782020-03-23 14:18:37 -040044 SkASSERT(fCurrentDirectCommandList);
Greg Daniel83ed2132020-03-24 13:15:33 -040045
46 SkASSERT(fCurrentFenceValue == 0);
47 SkDEBUGCODE(HRESULT hr = ) fDevice->CreateFence(fCurrentFenceValue, D3D12_FENCE_FLAG_NONE,
48 IID_PPV_ARGS(&fFence));
49 SkASSERT(SUCCEEDED(hr));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050050}
51
Greg Daniel83ed2132020-03-24 13:15:33 -040052GrD3DGpu::~GrD3DGpu() {
53 this->destroyResources();
54}
55
56void GrD3DGpu::destroyResources() {
57 if (fCurrentDirectCommandList) {
58 fCurrentDirectCommandList->close();
59 fCurrentDirectCommandList.reset();
60 }
61
62 // We need to make sure everything has finished on the queue.
63 if (fFence->GetCompletedValue() < fCurrentFenceValue) {
64 HANDLE fenceEvent;
65 fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
66 SkASSERT(fenceEvent);
67 SkDEBUGCODE(HRESULT hr = ) fFence->SetEventOnCompletion(fCurrentFenceValue, fenceEvent);
68 SkASSERT(SUCCEEDED(hr));
69 WaitForSingleObject(fenceEvent, INFINITE);
70 CloseHandle(fenceEvent);
71 }
72
73 SkDEBUGCODE(uint64_t fenceValue = fFence->GetCompletedValue();)
74
75 // We used a placement new for each object in fOutstandingCommandLists, so we're responsible
76 // for calling the destructor on each of them as well.
77 while (!fOutstandingCommandLists.empty()) {
78 OutstandingCommandList* list = (OutstandingCommandList*)fOutstandingCommandLists.back();
79 SkASSERT(list->fFenceValue <= fenceValue);
80 // No reason to recycle the command lists since we are destroying all resources anyways.
81 list->~OutstandingCommandList();
82 fOutstandingCommandLists.pop_back();
83 }
84}
Greg Daniel31a7b072020-02-26 15:31:49 -050085
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050086GrOpsRenderPass* GrD3DGpu::getOpsRenderPass(
87 GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
88 const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
Greg Daniel31a7b072020-02-26 15:31:49 -050089 const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050090 const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
Greg Daniel31a7b072020-02-26 15:31:49 -050091 if (!fCachedOpsRenderPass) {
92 fCachedOpsRenderPass.reset(new GrD3DOpsRenderPass(this));
93 }
94
95 if (!fCachedOpsRenderPass->set(rt, origin, bounds, colorInfo, stencilInfo, sampledProxies)) {
96 return nullptr;
97 }
98 return fCachedOpsRenderPass.get();
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050099}
100
Greg Daniel83ed2132020-03-24 13:15:33 -0400101void GrD3DGpu::submitDirectCommandList() {
102 SkASSERT(fCurrentDirectCommandList);
103
Jim Van Verth9aa9a682020-04-01 10:13:48 -0400104 fCurrentDirectCommandList->submit(fQueue.get());
Greg Daniel83ed2132020-03-24 13:15:33 -0400105
106 new (fOutstandingCommandLists.push_back()) OutstandingCommandList(
107 std::move(fCurrentDirectCommandList), ++fCurrentFenceValue);
108
Jim Van Verth9aa9a682020-04-01 10:13:48 -0400109 SkDEBUGCODE(HRESULT hr = ) fQueue->Signal(fFence.get(), fCurrentFenceValue);
Greg Daniel83ed2132020-03-24 13:15:33 -0400110 SkASSERT(SUCCEEDED(hr));
111
112 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
113
114 // This should be done after we have a new command list in case the freeing of any resources
115 // held by a finished command list causes us send a new command to the gpu (like changing the
116 // resource state.
117 this->checkForFinishedCommandLists();
118
119 SkASSERT(fCurrentDirectCommandList);
120}
121
122void GrD3DGpu::checkForFinishedCommandLists() {
123 uint64_t currentFenceValue = fFence->GetCompletedValue();
124
125 // Iterate over all the outstanding command lists to see if any have finished. The commands
126 // lists are in order from oldest to newest, so we start at the front to check if their fence
127 // value is less than the last signaled value. If so we pop it off and move onto the next.
128 // Repeat till we find a command list that has not finished yet (and all others afterwards are
129 // also guaranteed to not have finished).
130 SkDeque::F2BIter iter(fOutstandingCommandLists);
131 const OutstandingCommandList* curList = (const OutstandingCommandList*)iter.next();
132 while (curList && curList->fFenceValue <= currentFenceValue) {
133 curList = (const OutstandingCommandList*)iter.next();
134 OutstandingCommandList* front = (OutstandingCommandList*)fOutstandingCommandLists.front();
Greg Daniel7a5f1fa2020-03-24 14:50:19 -0400135 fResourceProvider.recycleDirectCommandList(std::move(front->fCommandList));
Greg Daniel83ed2132020-03-24 13:15:33 -0400136 // Since we used placement new we are responsible for calling the destructor manually.
137 front->~OutstandingCommandList();
138 fOutstandingCommandLists.pop_front();
139 }
140}
141
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500142void GrD3DGpu::submit(GrOpsRenderPass* renderPass) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400143 SkASSERT(fCachedOpsRenderPass.get() == renderPass);
144
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500145 // TODO: actually submit something here
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400146 fCachedOpsRenderPass.reset();
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500147}
148
149void GrD3DGpu::querySampleLocations(GrRenderTarget* rt, SkTArray<SkPoint>* sampleLocations) {
150 // TODO
151}
152
153sk_sp<GrTexture> GrD3DGpu::onCreateTexture(SkISize dimensions,
154 const GrBackendFormat& format,
155 GrRenderable renderable,
156 int renderTargetSampleCnt,
157 SkBudgeted budgeted,
158 GrProtected isProtected,
159 int mipLevelCount,
160 uint32_t levelClearMask) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400161 DXGI_FORMAT dxgiFormat;
162 SkAssertResult(format.asDxgiFormat(&dxgiFormat));
163 SkASSERT(!GrDxgiFormatIsCompressed(dxgiFormat));
164
165 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
166
167 if (renderable == GrRenderable::kYes) {
168 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
169 }
170
171 // This desc refers to the texture that will be read by the client. Thus even if msaa is
172 // requested, this describes the resolved texture. Therefore we always have samples set
173 // to 1.
174 SkASSERT(mipLevelCount > 0);
175 D3D12_RESOURCE_DESC resourceDesc;
176 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
177 // TODO: will use 4MB alignment for MSAA textures and 64KB for everything else
178 // might want to manually set alignment to 4KB for smaller textures
179 resourceDesc.Alignment = 0;
180 resourceDesc.Width = dimensions.fWidth;
181 resourceDesc.Height = dimensions.fHeight;
182 resourceDesc.DepthOrArraySize = 1;
183 resourceDesc.MipLevels = mipLevelCount;
184 resourceDesc.Format = dxgiFormat;
185 resourceDesc.SampleDesc.Count = 1;
186 resourceDesc.SampleDesc.Quality = 0; // quality levels are only supported for tiled resources
187 // so ignore for now
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400188 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400189 resourceDesc.Flags = usageFlags;
190
191 GrMipMapsStatus mipMapsStatus =
192 mipLevelCount > 1 ? GrMipMapsStatus::kDirty : GrMipMapsStatus::kNotAllocated;
193
194 sk_sp<GrD3DTexture> tex;
195 if (renderable == GrRenderable::kYes) {
196 tex = GrD3DTextureRenderTarget::MakeNewTextureRenderTarget(
197 this, budgeted, dimensions, renderTargetSampleCnt, resourceDesc, isProtected,
198 mipMapsStatus);
199 } else {
200 tex = GrD3DTexture::MakeNewTexture(this, budgeted, dimensions, resourceDesc, isProtected,
201 mipMapsStatus);
202 }
203
204 if (!tex) {
205 return nullptr;
206 }
207
208 if (levelClearMask) {
209 // TODO
210 }
211 return std::move(tex);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500212}
213
214sk_sp<GrTexture> GrD3DGpu::onCreateCompressedTexture(SkISize dimensions,
215 const GrBackendFormat& format,
216 SkBudgeted budgeted,
217 GrMipMapped mipMapped,
218 GrProtected isProtected,
219 const void* data, size_t dataSize) {
220 // TODO
221 return nullptr;
222}
223
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400224static bool check_resource_info(const GrD3DTextureResourceInfo& info) {
Jim Van Verth9aa9a682020-04-01 10:13:48 -0400225 if (!info.fResource.get()) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400226 return false;
227 }
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400228 return true;
229}
230
231static bool check_tex_resource_info(const GrD3DCaps& caps, const GrD3DTextureResourceInfo& info) {
232 if (!caps.isFormatTexturable(info.fFormat)) {
233 return false;
234 }
235 return true;
236}
237
238static bool check_rt_resource_info(const GrD3DCaps& caps, const GrD3DTextureResourceInfo& info,
239 int sampleCnt) {
240 if (!caps.isFormatRenderable(info.fFormat, sampleCnt)) {
241 return false;
242 }
243 return true;
244}
245
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400246sk_sp<GrTexture> GrD3DGpu::onWrapBackendTexture(const GrBackendTexture& tex,
247 GrWrapOwnership,
248 GrWrapCacheable wrapType,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400249 GrIOType ioType) {
250 GrD3DTextureResourceInfo textureInfo;
251 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
252 return nullptr;
253 }
254
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400255 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400256 return nullptr;
257 }
258
259 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
260 return nullptr;
261 }
262
263 // TODO: support protected context
264 if (tex.isProtected()) {
265 return nullptr;
266 }
267
268 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
269 SkASSERT(state);
270 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, ioType, textureInfo,
271 std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500272}
273
274sk_sp<GrTexture> GrD3DGpu::onWrapCompressedBackendTexture(const GrBackendTexture& tex,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400275 GrWrapOwnership,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500276 GrWrapCacheable wrapType) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400277 GrD3DTextureResourceInfo textureInfo;
278 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
279 return nullptr;
280 }
281
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400282 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400283 return nullptr;
284 }
285
286 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
287 return nullptr;
288 }
289
290 // TODO: support protected context
291 if (tex.isProtected()) {
292 return nullptr;
293 }
294
295 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
296 SkASSERT(state);
297 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, kRead_GrIOType,
298 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500299}
300
301sk_sp<GrTexture> GrD3DGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
302 int sampleCnt,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500303 GrWrapOwnership ownership,
304 GrWrapCacheable cacheable) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400305 GrD3DTextureResourceInfo textureInfo;
306 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
307 return nullptr;
308 }
309
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400310 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400311 return nullptr;
312 }
313
314 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
315 return nullptr;
316 }
317 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
318 return nullptr;
319 }
320
321 // TODO: support protected context
322 if (tex.isProtected()) {
323 return nullptr;
324 }
325
326 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
327
328 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
329 SkASSERT(state);
330
331 return GrD3DTextureRenderTarget::MakeWrappedTextureRenderTarget(this, tex.dimensions(),
332 sampleCnt, cacheable,
333 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500334}
335
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400336sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400337 // Currently the Direct3D backend does not support wrapping of msaa render targets directly. In
338 // general this is not an issue since swapchain images in D3D are never multisampled. Thus if
339 // you want a multisampled RT it is best to wrap the swapchain images and then let Skia handle
340 // creating and owning the MSAA images.
341 if (rt.sampleCnt() > 1) {
342 return nullptr;
343 }
344
345 GrD3DTextureResourceInfo info;
346 if (!rt.getD3DTextureResourceInfo(&info)) {
347 return nullptr;
348 }
349
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400350 if (!check_resource_info(info)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400351 return nullptr;
352 }
353
354 if (!check_rt_resource_info(this->d3dCaps(), info, rt.sampleCnt())) {
355 return nullptr;
356 }
357
358 // TODO: support protected context
359 if (rt.isProtected()) {
360 return nullptr;
361 }
362
363 sk_sp<GrD3DResourceState> state = rt.getGrD3DResourceState();
364
365 sk_sp<GrD3DRenderTarget> tgt = GrD3DRenderTarget::MakeWrappedRenderTarget(
366 this, rt.dimensions(), 1, info, std::move(state));
367
368 // We don't allow the client to supply a premade stencil buffer. We always create one if needed.
369 SkASSERT(!rt.stencilBits());
370 if (tgt) {
371 SkASSERT(tgt->canAttemptStencilAttachment());
372 }
373
374 return std::move(tgt);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500375}
376
377sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400378 int sampleCnt) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400379
380 GrD3DTextureResourceInfo textureInfo;
381 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
382 return nullptr;
383 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400384 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400385 return nullptr;
386 }
387
388 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
389 return nullptr;
390 }
391
392 // TODO: support protected context
393 if (tex.isProtected()) {
394 return nullptr;
395 }
396
397 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
398 if (!sampleCnt) {
399 return nullptr;
400 }
401
402 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
403 SkASSERT(state);
404
405 return GrD3DRenderTarget::MakeWrappedRenderTarget(this, tex.dimensions(), sampleCnt,
406 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500407}
408
409sk_sp<GrGpuBuffer> GrD3DGpu::onCreateBuffer(size_t sizeInBytes, GrGpuBufferType type,
Jim Van Verthd6ad4802020-04-03 14:59:20 -0400410 GrAccessPattern accessPattern, const void* data) {
411 sk_sp<GrD3DBuffer> buffer = GrD3DBuffer::Make(this, sizeInBytes, type, accessPattern);
412 if (data && buffer) {
413 buffer->updateData(data, sizeInBytes);
414 }
415
416 return std::move(buffer);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500417}
418
419GrStencilAttachment* GrD3DGpu::createStencilAttachmentForRenderTarget(
420 const GrRenderTarget* rt, int width, int height, int numStencilSamples) {
421 // TODO
422 return nullptr;
423}
424
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400425bool GrD3DGpu::createTextureResourceForBackendSurface(DXGI_FORMAT dxgiFormat,
426 SkISize dimensions,
427 GrTexturable texturable,
428 GrRenderable renderable,
429 GrMipMapped mipMapped,
430 GrD3DTextureResourceInfo* info,
431 GrProtected isProtected,
432 const BackendTextureData* data) {
433 SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
434 if (texturable == GrTexturable::kNo) {
435 SkASSERT(!data && mipMapped == GrMipMapped::kNo);
436 }
437
438 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
439 return false;
440 }
441
442 if (texturable == GrTexturable::kYes && !this->d3dCaps().isFormatTexturable(dxgiFormat)) {
443 return false;
444 }
445
446 if (renderable == GrRenderable::kYes && !this->d3dCaps().isFormatRenderable(dxgiFormat, 1)) {
447 return false;
448 }
449
450 int numMipLevels = 1;
451 if (mipMapped == GrMipMapped::kYes) {
452 numMipLevels = SkMipMap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
453 }
454
455 // create the texture
456 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
457 if (renderable == GrRenderable::kYes) {
458 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
459 }
460
461 D3D12_RESOURCE_DESC resourceDesc;
462 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
463 resourceDesc.Alignment = 0; // use default alignment
464 resourceDesc.Width = dimensions.fWidth;
465 resourceDesc.Height = dimensions.fHeight;
466 resourceDesc.DepthOrArraySize = 1;
467 resourceDesc.MipLevels = numMipLevels;
468 resourceDesc.Format = dxgiFormat;
469 resourceDesc.SampleDesc.Count = 1;
470 resourceDesc.SampleDesc.Quality = 0; // quality levels are only supported for tiled resources
471 // so ignore for now
472 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
473 resourceDesc.Flags = usageFlags;
474
475 if (!GrD3DTextureResource::InitTextureResourceInfo(this, resourceDesc, isProtected, info)) {
476 SkDebugf("Failed to init texture resource info\n");
477 return false;
478 }
479
480 if (!data) {
481 return true;
482 }
483
484 // TODO: upload the data
485
486 return true;
487}
488
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500489GrBackendTexture GrD3DGpu::onCreateBackendTexture(SkISize dimensions,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400490 const GrBackendFormat& format,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400491 GrRenderable renderable,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400492 GrMipMapped mipMapped,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400493 GrProtected isProtected,
494 const BackendTextureData* data) {
495 this->handleDirtyContext();
496
497 const GrD3DCaps& caps = this->d3dCaps();
498
499 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
500 return {};
501 }
502
503 DXGI_FORMAT dxgiFormat;
504 if (!format.asDxgiFormat(&dxgiFormat)) {
505 return {};
506 }
507
508 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
509 if (!caps.isFormatTexturable(dxgiFormat)) {
510 return {};
511 }
512
513 GrD3DTextureResourceInfo info;
514 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
515 renderable, mipMapped,
516 &info, isProtected, data)) {
517 return {};
518 }
519
520 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500521}
522
523GrBackendTexture GrD3DGpu::onCreateCompressedBackendTexture(SkISize dimensions,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400524 const GrBackendFormat& format,
525 GrMipMapped mipMapped,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400526 GrProtected isProtected,
527 const BackendTextureData* data) {
528 this->handleDirtyContext();
529
530 const GrD3DCaps& caps = this->d3dCaps();
531
532 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
533 return {};
534 }
535
536 DXGI_FORMAT dxgiFormat;
537 if (!format.asDxgiFormat(&dxgiFormat)) {
538 return {};
539 }
540
541 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
542 if (!caps.isFormatTexturable(dxgiFormat)) {
543 return {};
544 }
545
546 GrD3DTextureResourceInfo info;
547 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
548 GrRenderable::kNo, mipMapped,
549 &info, isProtected, data)) {
550 return {};
551 }
552
553 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500554}
555
556void GrD3DGpu::deleteBackendTexture(const GrBackendTexture& tex) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400557 SkASSERT(GrBackendApi::kDirect3D == tex.fBackend);
558 // Nothing to do here, will get cleaned up when the GrBackendTexture object goes away
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500559}
560
Robert Phillips979b2232020-02-20 10:47:29 -0500561bool GrD3DGpu::compile(const GrProgramDesc&, const GrProgramInfo&) {
562 return false;
563}
564
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500565#if GR_TEST_UTILS
566bool GrD3DGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400567 SkASSERT(GrBackendApi::kDirect3D == tex.backend());
568
569 GrD3DTextureResourceInfo info;
570 if (!tex.getD3DTextureResourceInfo(&info)) {
571 return false;
572 }
573 ID3D12Resource* textureResource = info.fResource.get();
574 if (!textureResource) {
575 return false;
576 }
577 return !(textureResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500578}
579
580GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(int w, int h,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400581 GrColorType colorType) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400582 this->handleDirtyContext();
583
584 if (w > this->caps()->maxRenderTargetSize() || h > this->caps()->maxRenderTargetSize()) {
585 return GrBackendRenderTarget();
586 }
587
588 DXGI_FORMAT dxgiFormat = this->d3dCaps().getFormatFromColorType(colorType);
589
590 GrD3DTextureResourceInfo info;
591 if (!this->createTextureResourceForBackendSurface(dxgiFormat, { w, h }, GrTexturable::kNo,
592 GrRenderable::kYes, GrMipMapped::kNo,
593 &info, GrProtected::kNo, nullptr)) {
594 return {};
595 }
596
597 return GrBackendRenderTarget(w, h, 1, info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500598}
599
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400600void GrD3DGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
601 SkASSERT(GrBackendApi::kDirect3D == rt.backend());
602
603 GrD3DTextureResourceInfo info;
604 if (rt.getD3DTextureResourceInfo(&info)) {
605 this->testingOnly_flushGpuAndSync();
606 // Nothing else to do here, will get cleaned up when the GrBackendRenderTarget
607 // is deleted.
608 }
609}
610
611void GrD3DGpu::testingOnly_flushGpuAndSync() {
612 // TODO
613}
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500614#endif