blob: 5186ff79ed0a6e8ceddc19bc0a014d976eb6d79b [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 Verth4f51f472020-04-13 11:02:21 -040016#include "src/gpu/d3d/GrD3DStencilAttachment.h"
Jim Van Verthaa90dad2020-03-30 15:00:39 -040017#include "src/gpu/d3d/GrD3DTexture.h"
18#include "src/gpu/d3d/GrD3DTextureRenderTarget.h"
19#include "src/gpu/d3d/GrD3DUtil.h"
Greg Daniel31a7b072020-02-26 15:31:49 -050020
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050021sk_sp<GrGpu> GrD3DGpu::Make(const GrD3DBackendContext& backendContext,
22 const GrContextOptions& contextOptions, GrContext* context) {
23 return sk_sp<GrGpu>(new GrD3DGpu(context, contextOptions, backendContext));
24}
25
Greg Daniel83ed2132020-03-24 13:15:33 -040026// This constant determines how many OutstandingCommandLists are allocated together as a block in
27// the deque. As such it needs to balance allocating too much memory vs. incurring
28// allocation/deallocation thrashing. It should roughly correspond to the max number of outstanding
29// command lists we expect to see.
30static const int kDefaultOutstandingAllocCnt = 8;
31
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050032GrD3DGpu::GrD3DGpu(GrContext* context, const GrContextOptions& contextOptions,
33 const GrD3DBackendContext& backendContext)
Jim Van Verth03b8ab22020-02-24 11:36:15 -050034 : INHERITED(context)
35 , fDevice(backendContext.fDevice)
Greg Daniel02c45902020-03-09 10:58:09 -040036
37 , fQueue(backendContext.fQueue)
Greg Daniel83ed2132020-03-24 13:15:33 -040038 , fResourceProvider(this)
39 , fOutstandingCommandLists(sizeof(OutstandingCommandList), kDefaultOutstandingAllocCnt) {
Jim Van Verth8ec13302020-02-26 12:59:56 -050040 fCaps.reset(new GrD3DCaps(contextOptions,
Jim Van Verth9aa9a682020-04-01 10:13:48 -040041 backendContext.fAdapter.get(),
42 backendContext.fDevice.get()));
Greg Daniel85da3362020-03-09 15:18:35 -040043
44 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
Greg Daniele52c9782020-03-23 14:18:37 -040045 SkASSERT(fCurrentDirectCommandList);
Greg Daniel83ed2132020-03-24 13:15:33 -040046
47 SkASSERT(fCurrentFenceValue == 0);
48 SkDEBUGCODE(HRESULT hr = ) fDevice->CreateFence(fCurrentFenceValue, D3D12_FENCE_FLAG_NONE,
49 IID_PPV_ARGS(&fFence));
50 SkASSERT(SUCCEEDED(hr));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050051}
52
Greg Daniel83ed2132020-03-24 13:15:33 -040053GrD3DGpu::~GrD3DGpu() {
54 this->destroyResources();
55}
56
57void GrD3DGpu::destroyResources() {
58 if (fCurrentDirectCommandList) {
59 fCurrentDirectCommandList->close();
60 fCurrentDirectCommandList.reset();
61 }
62
63 // We need to make sure everything has finished on the queue.
64 if (fFence->GetCompletedValue() < fCurrentFenceValue) {
65 HANDLE fenceEvent;
66 fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
67 SkASSERT(fenceEvent);
68 SkDEBUGCODE(HRESULT hr = ) fFence->SetEventOnCompletion(fCurrentFenceValue, fenceEvent);
69 SkASSERT(SUCCEEDED(hr));
70 WaitForSingleObject(fenceEvent, INFINITE);
71 CloseHandle(fenceEvent);
72 }
73
74 SkDEBUGCODE(uint64_t fenceValue = fFence->GetCompletedValue();)
75
76 // We used a placement new for each object in fOutstandingCommandLists, so we're responsible
77 // for calling the destructor on each of them as well.
78 while (!fOutstandingCommandLists.empty()) {
79 OutstandingCommandList* list = (OutstandingCommandList*)fOutstandingCommandLists.back();
80 SkASSERT(list->fFenceValue <= fenceValue);
81 // No reason to recycle the command lists since we are destroying all resources anyways.
82 list->~OutstandingCommandList();
83 fOutstandingCommandLists.pop_back();
84 }
85}
Greg Daniel31a7b072020-02-26 15:31:49 -050086
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050087GrOpsRenderPass* GrD3DGpu::getOpsRenderPass(
88 GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
89 const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
Greg Daniel31a7b072020-02-26 15:31:49 -050090 const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -050091 const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
Greg Daniel31a7b072020-02-26 15:31:49 -050092 if (!fCachedOpsRenderPass) {
93 fCachedOpsRenderPass.reset(new GrD3DOpsRenderPass(this));
94 }
95
96 if (!fCachedOpsRenderPass->set(rt, origin, bounds, colorInfo, stencilInfo, sampledProxies)) {
97 return nullptr;
98 }
99 return fCachedOpsRenderPass.get();
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500100}
101
Greg Daniel83ed2132020-03-24 13:15:33 -0400102void GrD3DGpu::submitDirectCommandList() {
103 SkASSERT(fCurrentDirectCommandList);
104
Jim Van Verth9aa9a682020-04-01 10:13:48 -0400105 fCurrentDirectCommandList->submit(fQueue.get());
Greg Daniel83ed2132020-03-24 13:15:33 -0400106
107 new (fOutstandingCommandLists.push_back()) OutstandingCommandList(
108 std::move(fCurrentDirectCommandList), ++fCurrentFenceValue);
109
Jim Van Verth9aa9a682020-04-01 10:13:48 -0400110 SkDEBUGCODE(HRESULT hr = ) fQueue->Signal(fFence.get(), fCurrentFenceValue);
Greg Daniel83ed2132020-03-24 13:15:33 -0400111 SkASSERT(SUCCEEDED(hr));
112
113 fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
114
115 // This should be done after we have a new command list in case the freeing of any resources
116 // held by a finished command list causes us send a new command to the gpu (like changing the
117 // resource state.
118 this->checkForFinishedCommandLists();
119
120 SkASSERT(fCurrentDirectCommandList);
121}
122
123void GrD3DGpu::checkForFinishedCommandLists() {
124 uint64_t currentFenceValue = fFence->GetCompletedValue();
125
126 // Iterate over all the outstanding command lists to see if any have finished. The commands
127 // lists are in order from oldest to newest, so we start at the front to check if their fence
128 // value is less than the last signaled value. If so we pop it off and move onto the next.
129 // Repeat till we find a command list that has not finished yet (and all others afterwards are
130 // also guaranteed to not have finished).
131 SkDeque::F2BIter iter(fOutstandingCommandLists);
132 const OutstandingCommandList* curList = (const OutstandingCommandList*)iter.next();
133 while (curList && curList->fFenceValue <= currentFenceValue) {
134 curList = (const OutstandingCommandList*)iter.next();
135 OutstandingCommandList* front = (OutstandingCommandList*)fOutstandingCommandLists.front();
Greg Daniel7a5f1fa2020-03-24 14:50:19 -0400136 fResourceProvider.recycleDirectCommandList(std::move(front->fCommandList));
Greg Daniel83ed2132020-03-24 13:15:33 -0400137 // Since we used placement new we are responsible for calling the destructor manually.
138 front->~OutstandingCommandList();
139 fOutstandingCommandLists.pop_front();
140 }
141}
142
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500143void GrD3DGpu::submit(GrOpsRenderPass* renderPass) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400144 SkASSERT(fCachedOpsRenderPass.get() == renderPass);
145
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500146 // TODO: actually submit something here
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400147 fCachedOpsRenderPass.reset();
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500148}
149
150void GrD3DGpu::querySampleLocations(GrRenderTarget* rt, SkTArray<SkPoint>* sampleLocations) {
151 // TODO
152}
153
154sk_sp<GrTexture> GrD3DGpu::onCreateTexture(SkISize dimensions,
155 const GrBackendFormat& format,
156 GrRenderable renderable,
157 int renderTargetSampleCnt,
158 SkBudgeted budgeted,
159 GrProtected isProtected,
160 int mipLevelCount,
161 uint32_t levelClearMask) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400162 DXGI_FORMAT dxgiFormat;
163 SkAssertResult(format.asDxgiFormat(&dxgiFormat));
164 SkASSERT(!GrDxgiFormatIsCompressed(dxgiFormat));
165
166 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
167
168 if (renderable == GrRenderable::kYes) {
169 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
170 }
171
172 // This desc refers to the texture that will be read by the client. Thus even if msaa is
173 // requested, this describes the resolved texture. Therefore we always have samples set
174 // to 1.
175 SkASSERT(mipLevelCount > 0);
176 D3D12_RESOURCE_DESC resourceDesc;
177 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
178 // TODO: will use 4MB alignment for MSAA textures and 64KB for everything else
179 // might want to manually set alignment to 4KB for smaller textures
180 resourceDesc.Alignment = 0;
181 resourceDesc.Width = dimensions.fWidth;
182 resourceDesc.Height = dimensions.fHeight;
183 resourceDesc.DepthOrArraySize = 1;
184 resourceDesc.MipLevels = mipLevelCount;
185 resourceDesc.Format = dxgiFormat;
186 resourceDesc.SampleDesc.Count = 1;
Greg Danielc9624d52020-04-13 15:36:31 -0400187 // quality levels are only supported for tiled resources so ignore for now
188 resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400189 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400190 resourceDesc.Flags = usageFlags;
191
192 GrMipMapsStatus mipMapsStatus =
193 mipLevelCount > 1 ? GrMipMapsStatus::kDirty : GrMipMapsStatus::kNotAllocated;
194
195 sk_sp<GrD3DTexture> tex;
196 if (renderable == GrRenderable::kYes) {
197 tex = GrD3DTextureRenderTarget::MakeNewTextureRenderTarget(
198 this, budgeted, dimensions, renderTargetSampleCnt, resourceDesc, isProtected,
199 mipMapsStatus);
200 } else {
201 tex = GrD3DTexture::MakeNewTexture(this, budgeted, dimensions, resourceDesc, isProtected,
202 mipMapsStatus);
203 }
204
205 if (!tex) {
206 return nullptr;
207 }
208
209 if (levelClearMask) {
210 // TODO
211 }
212 return std::move(tex);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500213}
214
215sk_sp<GrTexture> GrD3DGpu::onCreateCompressedTexture(SkISize dimensions,
216 const GrBackendFormat& format,
217 SkBudgeted budgeted,
218 GrMipMapped mipMapped,
219 GrProtected isProtected,
220 const void* data, size_t dataSize) {
221 // TODO
222 return nullptr;
223}
224
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400225static bool check_resource_info(const GrD3DTextureResourceInfo& info) {
Jim Van Verth9aa9a682020-04-01 10:13:48 -0400226 if (!info.fResource.get()) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400227 return false;
228 }
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400229 return true;
230}
231
232static bool check_tex_resource_info(const GrD3DCaps& caps, const GrD3DTextureResourceInfo& info) {
233 if (!caps.isFormatTexturable(info.fFormat)) {
234 return false;
235 }
236 return true;
237}
238
239static bool check_rt_resource_info(const GrD3DCaps& caps, const GrD3DTextureResourceInfo& info,
240 int sampleCnt) {
241 if (!caps.isFormatRenderable(info.fFormat, sampleCnt)) {
242 return false;
243 }
244 return true;
245}
246
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400247sk_sp<GrTexture> GrD3DGpu::onWrapBackendTexture(const GrBackendTexture& tex,
248 GrWrapOwnership,
249 GrWrapCacheable wrapType,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400250 GrIOType ioType) {
251 GrD3DTextureResourceInfo textureInfo;
252 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
253 return nullptr;
254 }
255
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400256 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400257 return nullptr;
258 }
259
260 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
261 return nullptr;
262 }
263
264 // TODO: support protected context
265 if (tex.isProtected()) {
266 return nullptr;
267 }
268
269 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
270 SkASSERT(state);
271 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, ioType, textureInfo,
272 std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500273}
274
275sk_sp<GrTexture> GrD3DGpu::onWrapCompressedBackendTexture(const GrBackendTexture& tex,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400276 GrWrapOwnership,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500277 GrWrapCacheable wrapType) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400278 GrD3DTextureResourceInfo textureInfo;
279 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
280 return nullptr;
281 }
282
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400283 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400284 return nullptr;
285 }
286
287 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
288 return nullptr;
289 }
290
291 // TODO: support protected context
292 if (tex.isProtected()) {
293 return nullptr;
294 }
295
296 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
297 SkASSERT(state);
298 return GrD3DTexture::MakeWrappedTexture(this, tex.dimensions(), wrapType, kRead_GrIOType,
299 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500300}
301
302sk_sp<GrTexture> GrD3DGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
303 int sampleCnt,
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500304 GrWrapOwnership ownership,
305 GrWrapCacheable cacheable) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400306 GrD3DTextureResourceInfo textureInfo;
307 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
308 return nullptr;
309 }
310
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400311 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400312 return nullptr;
313 }
314
315 if (!check_tex_resource_info(this->d3dCaps(), textureInfo)) {
316 return nullptr;
317 }
318 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
319 return nullptr;
320 }
321
322 // TODO: support protected context
323 if (tex.isProtected()) {
324 return nullptr;
325 }
326
327 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
328
329 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
330 SkASSERT(state);
331
332 return GrD3DTextureRenderTarget::MakeWrappedTextureRenderTarget(this, tex.dimensions(),
333 sampleCnt, cacheable,
334 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500335}
336
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400337sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400338 // Currently the Direct3D backend does not support wrapping of msaa render targets directly. In
339 // general this is not an issue since swapchain images in D3D are never multisampled. Thus if
340 // you want a multisampled RT it is best to wrap the swapchain images and then let Skia handle
341 // creating and owning the MSAA images.
342 if (rt.sampleCnt() > 1) {
343 return nullptr;
344 }
345
346 GrD3DTextureResourceInfo info;
347 if (!rt.getD3DTextureResourceInfo(&info)) {
348 return nullptr;
349 }
350
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400351 if (!check_resource_info(info)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400352 return nullptr;
353 }
354
355 if (!check_rt_resource_info(this->d3dCaps(), info, rt.sampleCnt())) {
356 return nullptr;
357 }
358
359 // TODO: support protected context
360 if (rt.isProtected()) {
361 return nullptr;
362 }
363
364 sk_sp<GrD3DResourceState> state = rt.getGrD3DResourceState();
365
366 sk_sp<GrD3DRenderTarget> tgt = GrD3DRenderTarget::MakeWrappedRenderTarget(
367 this, rt.dimensions(), 1, info, std::move(state));
368
369 // We don't allow the client to supply a premade stencil buffer. We always create one if needed.
370 SkASSERT(!rt.stencilBits());
371 if (tgt) {
372 SkASSERT(tgt->canAttemptStencilAttachment());
373 }
374
375 return std::move(tgt);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500376}
377
378sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400379 int sampleCnt) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400380
381 GrD3DTextureResourceInfo textureInfo;
382 if (!tex.getD3DTextureResourceInfo(&textureInfo)) {
383 return nullptr;
384 }
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400385 if (!check_resource_info(textureInfo)) {
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400386 return nullptr;
387 }
388
389 if (!check_rt_resource_info(this->d3dCaps(), textureInfo, sampleCnt)) {
390 return nullptr;
391 }
392
393 // TODO: support protected context
394 if (tex.isProtected()) {
395 return nullptr;
396 }
397
398 sampleCnt = this->d3dCaps().getRenderTargetSampleCount(sampleCnt, textureInfo.fFormat);
399 if (!sampleCnt) {
400 return nullptr;
401 }
402
403 sk_sp<GrD3DResourceState> state = tex.getGrD3DResourceState();
404 SkASSERT(state);
405
406 return GrD3DRenderTarget::MakeWrappedRenderTarget(this, tex.dimensions(), sampleCnt,
407 textureInfo, std::move(state));
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500408}
409
410sk_sp<GrGpuBuffer> GrD3DGpu::onCreateBuffer(size_t sizeInBytes, GrGpuBufferType type,
Jim Van Verthd6ad4802020-04-03 14:59:20 -0400411 GrAccessPattern accessPattern, const void* data) {
412 sk_sp<GrD3DBuffer> buffer = GrD3DBuffer::Make(this, sizeInBytes, type, accessPattern);
413 if (data && buffer) {
414 buffer->updateData(data, sizeInBytes);
415 }
416
417 return std::move(buffer);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500418}
419
420GrStencilAttachment* GrD3DGpu::createStencilAttachmentForRenderTarget(
421 const GrRenderTarget* rt, int width, int height, int numStencilSamples) {
Jim Van Verth4f51f472020-04-13 11:02:21 -0400422 SkASSERT(numStencilSamples == rt->numSamples() || this->caps()->mixedSamplesSupport());
423 SkASSERT(width >= rt->width());
424 SkASSERT(height >= rt->height());
425
426 const GrD3DCaps::StencilFormat& sFmt = this->d3dCaps().preferredStencilFormat();
427
428 GrD3DStencilAttachment* stencil(GrD3DStencilAttachment::Make(this,
429 width,
430 height,
431 numStencilSamples,
432 sFmt));
433 fStats.incStencilAttachmentCreates();
434 return stencil;
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500435}
436
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400437bool GrD3DGpu::createTextureResourceForBackendSurface(DXGI_FORMAT dxgiFormat,
438 SkISize dimensions,
439 GrTexturable texturable,
440 GrRenderable renderable,
441 GrMipMapped mipMapped,
442 GrD3DTextureResourceInfo* info,
443 GrProtected isProtected,
444 const BackendTextureData* data) {
445 SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
446 if (texturable == GrTexturable::kNo) {
447 SkASSERT(!data && mipMapped == GrMipMapped::kNo);
448 }
449
450 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
451 return false;
452 }
453
454 if (texturable == GrTexturable::kYes && !this->d3dCaps().isFormatTexturable(dxgiFormat)) {
455 return false;
456 }
457
458 if (renderable == GrRenderable::kYes && !this->d3dCaps().isFormatRenderable(dxgiFormat, 1)) {
459 return false;
460 }
461
462 int numMipLevels = 1;
463 if (mipMapped == GrMipMapped::kYes) {
464 numMipLevels = SkMipMap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
465 }
466
467 // create the texture
468 D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
469 if (renderable == GrRenderable::kYes) {
470 usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
471 }
472
473 D3D12_RESOURCE_DESC resourceDesc;
474 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
475 resourceDesc.Alignment = 0; // use default alignment
476 resourceDesc.Width = dimensions.fWidth;
477 resourceDesc.Height = dimensions.fHeight;
478 resourceDesc.DepthOrArraySize = 1;
479 resourceDesc.MipLevels = numMipLevels;
480 resourceDesc.Format = dxgiFormat;
481 resourceDesc.SampleDesc.Count = 1;
Greg Danielc9624d52020-04-13 15:36:31 -0400482 // quality levels are only supported for tiled resources so ignore for now
483 resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400484 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
485 resourceDesc.Flags = usageFlags;
486
487 if (!GrD3DTextureResource::InitTextureResourceInfo(this, resourceDesc, isProtected, info)) {
488 SkDebugf("Failed to init texture resource info\n");
489 return false;
490 }
491
492 if (!data) {
493 return true;
494 }
495
496 // TODO: upload the data
497
498 return true;
499}
500
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500501GrBackendTexture GrD3DGpu::onCreateBackendTexture(SkISize dimensions,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400502 const GrBackendFormat& format,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400503 GrRenderable renderable,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400504 GrMipMapped mipMapped,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400505 GrProtected isProtected,
506 const BackendTextureData* data) {
507 this->handleDirtyContext();
508
509 const GrD3DCaps& caps = this->d3dCaps();
510
511 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
512 return {};
513 }
514
515 DXGI_FORMAT dxgiFormat;
516 if (!format.asDxgiFormat(&dxgiFormat)) {
517 return {};
518 }
519
520 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
521 if (!caps.isFormatTexturable(dxgiFormat)) {
522 return {};
523 }
524
525 GrD3DTextureResourceInfo info;
526 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
527 renderable, mipMapped,
528 &info, isProtected, data)) {
529 return {};
530 }
531
532 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500533}
534
535GrBackendTexture GrD3DGpu::onCreateCompressedBackendTexture(SkISize dimensions,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400536 const GrBackendFormat& format,
537 GrMipMapped mipMapped,
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400538 GrProtected isProtected,
539 const BackendTextureData* data) {
540 this->handleDirtyContext();
541
542 const GrD3DCaps& caps = this->d3dCaps();
543
544 if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
545 return {};
546 }
547
548 DXGI_FORMAT dxgiFormat;
549 if (!format.asDxgiFormat(&dxgiFormat)) {
550 return {};
551 }
552
553 // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
554 if (!caps.isFormatTexturable(dxgiFormat)) {
555 return {};
556 }
557
558 GrD3DTextureResourceInfo info;
559 if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
560 GrRenderable::kNo, mipMapped,
561 &info, isProtected, data)) {
562 return {};
563 }
564
565 return GrBackendTexture(dimensions.width(), dimensions.height(), info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500566}
567
568void GrD3DGpu::deleteBackendTexture(const GrBackendTexture& tex) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400569 SkASSERT(GrBackendApi::kDirect3D == tex.fBackend);
570 // Nothing to do here, will get cleaned up when the GrBackendTexture object goes away
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500571}
572
Robert Phillips979b2232020-02-20 10:47:29 -0500573bool GrD3DGpu::compile(const GrProgramDesc&, const GrProgramInfo&) {
574 return false;
575}
576
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500577#if GR_TEST_UTILS
578bool GrD3DGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400579 SkASSERT(GrBackendApi::kDirect3D == tex.backend());
580
581 GrD3DTextureResourceInfo info;
582 if (!tex.getD3DTextureResourceInfo(&info)) {
583 return false;
584 }
585 ID3D12Resource* textureResource = info.fResource.get();
586 if (!textureResource) {
587 return false;
588 }
589 return !(textureResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500590}
591
592GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(int w, int h,
Jim Van Verthaa90dad2020-03-30 15:00:39 -0400593 GrColorType colorType) {
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400594 this->handleDirtyContext();
595
596 if (w > this->caps()->maxRenderTargetSize() || h > this->caps()->maxRenderTargetSize()) {
597 return GrBackendRenderTarget();
598 }
599
600 DXGI_FORMAT dxgiFormat = this->d3dCaps().getFormatFromColorType(colorType);
601
602 GrD3DTextureResourceInfo info;
603 if (!this->createTextureResourceForBackendSurface(dxgiFormat, { w, h }, GrTexturable::kNo,
604 GrRenderable::kYes, GrMipMapped::kNo,
605 &info, GrProtected::kNo, nullptr)) {
606 return {};
607 }
608
609 return GrBackendRenderTarget(w, h, 1, info);
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500610}
611
Jim Van Verth96bfeff2020-04-09 14:36:12 -0400612void GrD3DGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
613 SkASSERT(GrBackendApi::kDirect3D == rt.backend());
614
615 GrD3DTextureResourceInfo info;
616 if (rt.getD3DTextureResourceInfo(&info)) {
617 this->testingOnly_flushGpuAndSync();
618 // Nothing else to do here, will get cleaned up when the GrBackendRenderTarget
619 // is deleted.
620 }
621}
622
623void GrD3DGpu::testingOnly_flushGpuAndSync() {
624 // TODO
625}
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500626#endif