• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/gpu/GrBackendSurface.h"
9 #include "include/gpu/GrContextOptions.h"
10 #include "include/gpu/d3d/GrD3DBackendContext.h"
11 #include "include/gpu/d3d/GrD3DTypes.h"
12 
13 #include "src/core/SkCompressedDataUtils.h"
14 #include "src/gpu/GrBackendUtils.h"
15 #include "src/gpu/GrProgramDesc.h"
16 #include "src/gpu/GrProgramInfo.h"
17 #include "src/gpu/GrShaderCaps.h"
18 #include "src/gpu/GrStencilSettings.h"
19 #include "src/gpu/KeyBuilder.h"
20 #include "src/gpu/d3d/GrD3DCaps.h"
21 #include "src/gpu/d3d/GrD3DGpu.h"
22 #include "src/gpu/d3d/GrD3DRenderTarget.h"
23 #include "src/gpu/d3d/GrD3DTexture.h"
24 #include "src/gpu/d3d/GrD3DUtil.h"
25 
GrD3DCaps(const GrContextOptions & contextOptions,IDXGIAdapter1 * adapter,ID3D12Device * device)26 GrD3DCaps::GrD3DCaps(const GrContextOptions& contextOptions, IDXGIAdapter1* adapter,
27                      ID3D12Device* device)
28         : INHERITED(contextOptions) {
29     /**************************************************************************
30      * GrCaps fields
31      **************************************************************************/
32     fMipmapSupport = true;   // always available in Direct3D
33     fNPOTTextureTileSupport = true;  // available in feature level 10_0 and up
34     fReuseScratchTextures = true; //TODO: figure this out
35     fGpuTracingSupport = false; //TODO: figure this out
36     fOversizedStencilSupport = false; //TODO: figure this out
37     fDrawInstancedSupport = true;
38     fNativeDrawIndirectSupport = true;
39 
40     fSemaphoreSupport = true;
41     fFenceSyncSupport = true;
42     // TODO: implement these
43     fCrossContextTextureSupport = false;
44     fHalfFloatVertexAttributeSupport = false;
45 
46     // We always copy in/out of a transfer buffer so it's trivial to support row bytes.
47     fReadPixelsRowBytesSupport = true;
48     fWritePixelsRowBytesSupport = true;
49     fTransferPixelsToRowBytesSupport = true;
50 
51     fTransferFromBufferToTextureSupport = true;
52     fTransferFromSurfaceToBufferSupport = true;
53 
54     fMaxRenderTargetSize = 16384;  // minimum required by feature level 11_0
55     fMaxTextureSize = 16384;       // minimum required by feature level 11_0
56 
57     fTransferBufferAlignment = D3D12_TEXTURE_DATA_PITCH_ALIGNMENT;
58 
59     // TODO: implement
60     fDynamicStateArrayGeometryProcessorTextureSupport = false;
61 
62     fShaderCaps = std::make_unique<GrShaderCaps>();
63 
64     this->init(contextOptions, adapter, device);
65 }
66 
canCopyTexture(DXGI_FORMAT dstFormat,int dstSampleCnt,DXGI_FORMAT srcFormat,int srcSampleCnt) const67 bool GrD3DCaps::canCopyTexture(DXGI_FORMAT dstFormat, int dstSampleCnt,
68                                DXGI_FORMAT srcFormat, int srcSampleCnt) const {
69     if ((dstSampleCnt > 1 || srcSampleCnt > 1) && dstSampleCnt != srcSampleCnt) {
70         return false;
71     }
72 
73     // D3D allows us to copy within the same format family but doesn't do conversions
74     // so we require strict identity.
75     return srcFormat == dstFormat;
76 }
77 
canCopyAsResolve(DXGI_FORMAT dstFormat,int dstSampleCnt,DXGI_FORMAT srcFormat,int srcSampleCnt) const78 bool GrD3DCaps::canCopyAsResolve(DXGI_FORMAT dstFormat, int dstSampleCnt,
79                                  DXGI_FORMAT srcFormat, int srcSampleCnt) const {
80     // The src surface must be multisampled.
81     if (srcSampleCnt <= 1) {
82         return false;
83     }
84 
85     // The dst must not be multisampled.
86     if (dstSampleCnt > 1) {
87         return false;
88     }
89 
90     // Surfaces must have the same format.
91     // D3D12 can resolve between typeless and non-typeless formats, but we are not using
92     // typeless formats. It's not possible to resolve within the same format family otherwise.
93     if (srcFormat != dstFormat) {
94         return false;
95     }
96 
97     return true;
98 }
99 
onCanCopySurface(const GrSurfaceProxy * dst,const GrSurfaceProxy * src,const SkIRect & srcRect,const SkIPoint & dstPoint) const100 bool GrD3DCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
101                                  const SkIRect& srcRect, const SkIPoint& dstPoint) const {
102     if (src->isProtected() == GrProtected::kYes && dst->isProtected() != GrProtected::kYes) {
103         return false;
104     }
105 
106     int dstSampleCnt = 0;
107     int srcSampleCnt = 0;
108     if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
109         dstSampleCnt = rtProxy->numSamples();
110     }
111     if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
112         srcSampleCnt = rtProxy->numSamples();
113     }
114     SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
115     SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));
116 
117     DXGI_FORMAT dstFormat, srcFormat;
118     SkAssertResult(dst->backendFormat().asDxgiFormat(&dstFormat));
119     SkAssertResult(src->backendFormat().asDxgiFormat(&srcFormat));
120 
121     return this->canCopyTexture(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt) ||
122            this->canCopyAsResolve(dstFormat, dstSampleCnt, srcFormat, srcSampleCnt);
123 }
124 
init(const GrContextOptions & contextOptions,IDXGIAdapter1 * adapter,ID3D12Device * device)125 void GrD3DCaps::init(const GrContextOptions& contextOptions, IDXGIAdapter1* adapter,
126                      ID3D12Device* device) {
127     D3D_FEATURE_LEVEL featureLevels[] = {
128         D3D_FEATURE_LEVEL_11_0,
129         D3D_FEATURE_LEVEL_11_1,
130         D3D_FEATURE_LEVEL_12_0,
131         D3D_FEATURE_LEVEL_12_1,
132     };
133     D3D12_FEATURE_DATA_FEATURE_LEVELS flDesc = {};
134     flDesc.NumFeatureLevels = _countof(featureLevels);
135     flDesc.pFeatureLevelsRequested = featureLevels;
136     GR_D3D_CALL_ERRCHECK(device->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &flDesc,
137                                                      sizeof(flDesc)));
138     // This had better be true
139     SkASSERT(flDesc.MaxSupportedFeatureLevel >= D3D_FEATURE_LEVEL_11_0);
140 
141     DXGI_ADAPTER_DESC adapterDesc;
142     GR_D3D_CALL_ERRCHECK(adapter->GetDesc(&adapterDesc));
143 
144     D3D12_FEATURE_DATA_D3D12_OPTIONS optionsDesc;
145     GR_D3D_CALL_ERRCHECK(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &optionsDesc,
146                                                      sizeof(optionsDesc)));
147 
148 
149     // See https://docs.microsoft.com/en-us/windows/win32/direct3d12/hardware-support
150     if (D3D12_RESOURCE_BINDING_TIER_1 == optionsDesc.ResourceBindingTier) {
151         fMaxPerStageShaderResourceViews = 128;
152         if (D3D_FEATURE_LEVEL_11_0 == flDesc.MaxSupportedFeatureLevel) {
153             fMaxPerStageUnorderedAccessViews = 8;
154         } else {
155             fMaxPerStageUnorderedAccessViews = 64;
156         }
157     } else {
158         // The doc above says "full heap", but practically it seems like it should be
159         // limited by the maximum number of samplers in a heap
160         fMaxPerStageUnorderedAccessViews = 2032;
161         fMaxPerStageShaderResourceViews = 2032;
162     }
163 
164     fStandardSwizzleLayoutSupport = (optionsDesc.StandardSwizzle64KBSupported);
165 
166     D3D12_FEATURE_DATA_D3D12_OPTIONS2 optionsDesc2;
167     GR_D3D_CALL_ERRCHECK(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS2, &optionsDesc2,
168                                                      sizeof(optionsDesc2)));
169     fResolveSubresourceRegionSupport = (optionsDesc2.ProgrammableSamplePositionsTier !=
170                                         D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED);
171 
172     this->initGrCaps(optionsDesc, device);
173     this->initShaderCaps(adapterDesc.VendorId, optionsDesc);
174 
175     this->initFormatTable(adapterDesc, device);
176     this->initStencilFormat(device);
177 
178     if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
179         this->applyDriverCorrectnessWorkarounds(adapterDesc.VendorId);
180     }
181 
182     this->finishInitialization(contextOptions);
183 }
184 
initGrCaps(const D3D12_FEATURE_DATA_D3D12_OPTIONS & optionsDesc,ID3D12Device * device)185 void GrD3DCaps::initGrCaps(const D3D12_FEATURE_DATA_D3D12_OPTIONS& optionsDesc,
186                            ID3D12Device* device) {
187     // We assume a minimum of Shader Model 5.1, which allows at most 32 vertex inputs.
188     fMaxVertexAttributes = 32;
189 
190     // Can use standard sample locations
191     fSampleLocationsSupport = true;
192 
193     if (D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED !=
194             optionsDesc.ConservativeRasterizationTier) {
195         fConservativeRasterSupport = true;
196     }
197 
198     fWireframeSupport = true;
199 
200     // Feature level 11_0 and up support up to 16K in texture dimension
201     fMaxTextureSize = 16384;
202     // There's no specific cap for RT size, so use texture size
203     fMaxRenderTargetSize = fMaxTextureSize;
204     if (fDriverBugWorkarounds.max_texture_size_limit_4096) {
205         fMaxTextureSize = std::min(fMaxTextureSize, 4096);
206     }
207     // Our render targets are always created with textures as the color
208     // attachment, hence this min:
209     fMaxRenderTargetSize = fMaxTextureSize;
210 
211     fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
212 
213     // Assuming since we will always map in the end to upload the data we might as well just map
214     // from the get go. There is no hard data to suggest this is faster or slower.
215     fBufferMapThreshold = 0;
216 
217     fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag | kAsyncRead_MapFlag;
218 
219     fOversizedStencilSupport = true;
220 
221     fTwoSidedStencilRefsAndMasksMustMatch = true;
222 
223     // Advanced blend modes don't appear to be supported.
224 }
225 
initShaderCaps(int vendorID,const D3D12_FEATURE_DATA_D3D12_OPTIONS & optionsDesc)226 void GrD3DCaps::initShaderCaps(int vendorID, const D3D12_FEATURE_DATA_D3D12_OPTIONS& optionsDesc) {
227     GrShaderCaps* shaderCaps = fShaderCaps.get();
228     shaderCaps->fVersionDeclString = "#version 330\n";
229 
230     // Shader Model 5 supports all of the following:
231     shaderCaps->fUsesPrecisionModifiers = true;
232     shaderCaps->fFlatInterpolationSupport = true;
233     // Flat interpolation appears to be slow on Qualcomm GPUs. This was tested in GL and is assumed
234     // to be true with D3D as well.
235     shaderCaps->fPreferFlatInterpolation = kQualcomm_D3DVendor != vendorID;
236 
237     shaderCaps->fSampleMaskSupport = true;
238 
239     shaderCaps->fShaderDerivativeSupport = true;
240 
241     shaderCaps->fDualSourceBlendingSupport = true;
242 
243     shaderCaps->fIntegerSupport = true;
244     shaderCaps->fNonsquareMatrixSupport = true;
245     // TODO(skia:12352) HLSL does not expose asinh/acosh/atanh
246     shaderCaps->fInverseHyperbolicSupport = false;
247     shaderCaps->fVertexIDSupport = true;
248     shaderCaps->fInfinitySupport = true;
249     shaderCaps->fNonconstantArrayIndexSupport = true;
250     shaderCaps->fBitManipulationSupport = true;
251 
252     shaderCaps->fFloatIs32Bits = true;
253     shaderCaps->fHalfIs32Bits =
254         D3D12_SHADER_MIN_PRECISION_SUPPORT_NONE == optionsDesc.MinPrecisionSupport;
255 
256     // See https://docs.microsoft.com/en-us/windows/win32/direct3d12/hardware-support
257     // The maximum number of samplers in a shader-visible descriptor heap is 2048, but
258     // 16 of those are reserved for the driver.
259     shaderCaps->fMaxFragmentSamplers =
260         (D3D12_RESOURCE_BINDING_TIER_1 == optionsDesc.ResourceBindingTier) ? 16 : 2032;
261 }
262 
applyDriverCorrectnessWorkarounds(int vendorID)263 void GrD3DCaps::applyDriverCorrectnessWorkarounds(int vendorID) {
264     // Nothing yet.
265 }
266 
267 
stencil_format_supported(ID3D12Device * device,DXGI_FORMAT format)268 bool stencil_format_supported(ID3D12Device* device, DXGI_FORMAT format) {
269     D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupportDesc;
270     formatSupportDesc.Format = format;
271     GR_D3D_CALL_ERRCHECK(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,
272                                                      &formatSupportDesc,
273                                                      sizeof(formatSupportDesc)));
274     return SkToBool(D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL & formatSupportDesc.Support1);
275 }
276 
initStencilFormat(ID3D12Device * device)277 void GrD3DCaps::initStencilFormat(ID3D12Device* device) {
278     if (stencil_format_supported(device, DXGI_FORMAT_D24_UNORM_S8_UINT)) {
279         fPreferredStencilFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
280     } else {
281         SkASSERT(stencil_format_supported(device, DXGI_FORMAT_D32_FLOAT_S8X24_UINT));
282         fPreferredStencilFormat = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
283     }
284 }
285 
286 // These are all the valid DXGI_FORMATs that we support in Skia. They are roughly ordered from most
287 // frequently used to least to improve look up times in arrays.
288 static constexpr DXGI_FORMAT kDxgiFormats[] = {
289     DXGI_FORMAT_R8G8B8A8_UNORM,
290     DXGI_FORMAT_R8_UNORM,
291     DXGI_FORMAT_B8G8R8A8_UNORM,
292     DXGI_FORMAT_B5G6R5_UNORM,
293     DXGI_FORMAT_R16G16B16A16_FLOAT,
294     DXGI_FORMAT_R16_FLOAT,
295     DXGI_FORMAT_R8G8_UNORM,
296     DXGI_FORMAT_R10G10B10A2_UNORM,
297     DXGI_FORMAT_B4G4R4A4_UNORM,
298     DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
299     DXGI_FORMAT_BC1_UNORM,
300     DXGI_FORMAT_R16_UNORM,
301     DXGI_FORMAT_R16G16_UNORM,
302     DXGI_FORMAT_R16G16B16A16_UNORM,
303     DXGI_FORMAT_R16G16_FLOAT
304 };
305 
setColorType(GrColorType colorType,std::initializer_list<DXGI_FORMAT> formats)306 void GrD3DCaps::setColorType(GrColorType colorType, std::initializer_list<DXGI_FORMAT> formats) {
307 #ifdef SK_DEBUG
308     for (size_t i = 0; i < kNumDxgiFormats; ++i) {
309         const auto& formatInfo = fFormatTable[i];
310         for (int j = 0; j < formatInfo.fColorTypeInfoCount; ++j) {
311             const auto& ctInfo = formatInfo.fColorTypeInfos[j];
312             if (ctInfo.fColorType == colorType &&
313                 !SkToBool(ctInfo.fFlags & ColorTypeInfo::kWrappedOnly_Flag)) {
314                 bool found = false;
315                 for (auto it = formats.begin(); it != formats.end(); ++it) {
316                     if (kDxgiFormats[i] == *it) {
317                         found = true;
318                     }
319                 }
320                 SkASSERT(found);
321             }
322         }
323     }
324 #endif
325     int idx = static_cast<int>(colorType);
326     for (auto it = formats.begin(); it != formats.end(); ++it) {
327         const auto& info = this->getFormatInfo(*it);
328         for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
329             if (info.fColorTypeInfos[i].fColorType == colorType) {
330                 fColorTypeToFormatTable[idx] = *it;
331                 return;
332             }
333         }
334     }
335 }
336 
getFormatInfo(DXGI_FORMAT format) const337 const GrD3DCaps::FormatInfo& GrD3DCaps::getFormatInfo(DXGI_FORMAT format) const {
338     GrD3DCaps* nonConstThis = const_cast<GrD3DCaps*>(this);
339     return nonConstThis->getFormatInfo(format);
340 }
341 
getFormatInfo(DXGI_FORMAT format)342 GrD3DCaps::FormatInfo& GrD3DCaps::getFormatInfo(DXGI_FORMAT format) {
343     static_assert(SK_ARRAY_COUNT(kDxgiFormats) == GrD3DCaps::kNumDxgiFormats,
344                   "Size of DXGI_FORMATs array must match static value in header");
345     for (size_t i = 0; i < SK_ARRAY_COUNT(kDxgiFormats); ++i) {
346         if (kDxgiFormats[i] == format) {
347             return fFormatTable[i];
348         }
349     }
350     static FormatInfo kInvalidFormat;
351     return kInvalidFormat;
352 }
353 
initFormatTable(const DXGI_ADAPTER_DESC & adapterDesc,ID3D12Device * device)354 void GrD3DCaps::initFormatTable(const DXGI_ADAPTER_DESC& adapterDesc, ID3D12Device* device) {
355     static_assert(SK_ARRAY_COUNT(kDxgiFormats) == GrD3DCaps::kNumDxgiFormats,
356                   "Size of DXGI_FORMATs array must match static value in header");
357 
358     std::fill_n(fColorTypeToFormatTable, kGrColorTypeCnt, DXGI_FORMAT_UNKNOWN);
359 
360     // Go through all the formats and init their support surface and data GrColorTypes.
361     // Format: DXGI_FORMAT_R8G8B8A8_UNORM
362     {
363         constexpr DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
364         auto& info = this->getFormatInfo(format);
365         info.init(adapterDesc, device, format);
366         info.fFormatColorType = GrColorType::kRGBA_8888;
367         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
368             info.fColorTypeInfoCount = 2;
369             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
370             int ctIdx = 0;
371             // Format: DXGI_FORMAT_R8G8B8A8_UNORM, Surface: kRGBA_8888
372             {
373                 constexpr GrColorType ct = GrColorType::kRGBA_8888;
374                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
375                 ctInfo.fColorType = ct;
376                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
377             }
378             // Format: DXGI_FORMAT_R8G8B8A8_UNORM, Surface: kRGB_888x
379             {
380                 constexpr GrColorType ct = GrColorType::kRGB_888x;
381                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
382                 ctInfo.fColorType = ct;
383                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
384                 ctInfo.fReadSwizzle = skgpu::Swizzle("rgb1");
385             }
386         }
387     }
388 
389     // Format: DXGI_FORMAT_R8_UNORM
390     {
391         constexpr DXGI_FORMAT format = DXGI_FORMAT_R8_UNORM;
392         auto& info = this->getFormatInfo(format);
393         info.init(adapterDesc, device, format);
394         info.fFormatColorType = GrColorType::kR_8;
395         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
396             info.fColorTypeInfoCount = 3;
397             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
398             int ctIdx = 0;
399             // Format: DXGI_FORMAT_R8_UNORM, Surface: kR_8
400             {
401                 constexpr GrColorType ct = GrColorType::kR_8;
402                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
403                 ctInfo.fColorType = ct;
404                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
405             }
406             // Format: DXGI_FORMAT_R8_UNORM, Surface: kAlpha_8
407             {
408                 constexpr GrColorType ct = GrColorType::kAlpha_8;
409                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
410                 ctInfo.fColorType = ct;
411                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
412                 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
413                 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
414             }
415             // Format: DXGI_FORMAT_R8_UNORM, Surface: kGray_8
416             {
417                 constexpr GrColorType ct = GrColorType::kGray_8;
418                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
419                 ctInfo.fColorType = ct;
420                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
421                 ctInfo.fReadSwizzle = skgpu::Swizzle("rrr1");
422             }
423         }
424     }
425     // Format: DXGI_FORMAT_B8G8R8A8_UNORM
426     {
427         constexpr DXGI_FORMAT format = DXGI_FORMAT_B8G8R8A8_UNORM;
428         auto& info = this->getFormatInfo(format);
429         info.init(adapterDesc, device, format);
430         info.fFormatColorType = GrColorType::kBGRA_8888;
431         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
432             info.fColorTypeInfoCount = 1;
433             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
434             int ctIdx = 0;
435             // Format: DXGI_FORMAT_B8G8R8A8_UNORM, Surface: kBGRA_8888
436             {
437                 constexpr GrColorType ct = GrColorType::kBGRA_8888;
438                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
439                 ctInfo.fColorType = ct;
440                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
441             }
442         }
443     }
444     // Format: DXGI_FORMAT_B5G6R5_UNORM
445     {
446         constexpr DXGI_FORMAT format = DXGI_FORMAT_B5G6R5_UNORM;
447         auto& info = this->getFormatInfo(format);
448         info.init(adapterDesc, device, format);
449         info.fFormatColorType = GrColorType::kBGR_565;
450         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
451             info.fColorTypeInfoCount = 1;
452             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
453             int ctIdx = 0;
454             // Format: DXGI_FORMAT_B5G6R5_UNORM, Surface: kBGR_565
455             {
456                 constexpr GrColorType ct = GrColorType::kBGR_565;
457                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
458                 ctInfo.fColorType = ct;
459                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
460             }
461         }
462     }
463     // Format: DXGI_FORMAT_R16G16B16A16_FLOAT
464     {
465         constexpr DXGI_FORMAT format = DXGI_FORMAT_R16G16B16A16_FLOAT;
466         auto& info = this->getFormatInfo(format);
467         info.init(adapterDesc, device, format);
468         info.fFormatColorType = GrColorType::kRGBA_F16;
469         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
470             info.fColorTypeInfoCount = 2;
471             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
472             int ctIdx = 0;
473             // Format: DXGI_FORMAT_R16G16B16A16_FLOAT, Surface: GrColorType::kRGBA_F16
474             {
475                 constexpr GrColorType ct = GrColorType::kRGBA_F16;
476                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
477                 ctInfo.fColorType = ct;
478                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
479             }
480             // Format: DXGI_FORMAT_R16G16B16A16_FLOAT, Surface: GrColorType::kRGBA_F16_Clamped
481             {
482                 constexpr GrColorType ct = GrColorType::kRGBA_F16_Clamped;
483                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
484                 ctInfo.fColorType = ct;
485                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
486             }
487         }
488     }
489     // Format: DXGI_FORMAT_R16_FLOAT
490     {
491         constexpr DXGI_FORMAT format = DXGI_FORMAT_R16_FLOAT;
492         auto& info = this->getFormatInfo(format);
493         info.init(adapterDesc, device, format);
494         info.fFormatColorType = GrColorType::kR_F16;
495         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
496             info.fColorTypeInfoCount = 1;
497             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
498             int ctIdx = 0;
499             // Format: DXGI_FORMAT_R16_FLOAT, Surface: kAlpha_F16
500             {
501                 constexpr GrColorType ct = GrColorType::kAlpha_F16;
502                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
503                 ctInfo.fColorType = ct;
504                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
505                 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
506                 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
507             }
508         }
509     }
510     // Format: DXGI_FORMAT_R8G8_UNORM
511     {
512         constexpr DXGI_FORMAT format = DXGI_FORMAT_R8G8_UNORM;
513         auto& info = this->getFormatInfo(format);
514         info.init(adapterDesc, device, format);
515         info.fFormatColorType = GrColorType::kRG_88;
516         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
517             info.fColorTypeInfoCount = 1;
518             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
519             int ctIdx = 0;
520             // Format: DXGI_FORMAT_R8G8_UNORM, Surface: kRG_88
521             {
522                 constexpr GrColorType ct = GrColorType::kRG_88;
523                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
524                 ctInfo.fColorType = ct;
525                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
526             }
527         }
528     }
529     // Format: DXGI_FORMAT_R10G10B10A2_UNORM
530     {
531         constexpr DXGI_FORMAT format = DXGI_FORMAT_R10G10B10A2_UNORM;
532         auto& info = this->getFormatInfo(format);
533         info.init(adapterDesc, device, format);
534         info.fFormatColorType = GrColorType::kRGBA_1010102;
535         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
536             info.fColorTypeInfoCount = 1;
537             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
538             int ctIdx = 0;
539             // Format: DXGI_FORMAT_R10G10B10A2_UNORM, Surface: kRGBA_1010102
540             {
541                 constexpr GrColorType ct = GrColorType::kRGBA_1010102;
542                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
543                 ctInfo.fColorType = ct;
544                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
545             }
546         }
547     }
548     // Format: DXGI_FORMAT_B4G4R4A4_UNORM
549     {
550         constexpr DXGI_FORMAT format = DXGI_FORMAT_B4G4R4A4_UNORM;
551         auto& info = this->getFormatInfo(format);
552         info.init(adapterDesc, device, format);
553         info.fFormatColorType = GrColorType::kBGRA_4444;
554         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
555             info.fColorTypeInfoCount = 1;
556             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
557             int ctIdx = 0;
558             // Format: DXGI_FORMAT_B4G4R4A4_UNORM, Surface: kABGR_4444
559             {
560                 constexpr GrColorType ct = GrColorType::kABGR_4444;
561                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
562                 ctInfo.fColorType = ct;
563                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
564                 ctInfo.fReadSwizzle = skgpu::Swizzle("argb");
565                 ctInfo.fWriteSwizzle = skgpu::Swizzle("gbar");
566             }
567         }
568     }
569     // Format: DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
570     {
571         constexpr DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
572         auto& info = this->getFormatInfo(format);
573         info.init(adapterDesc, device, format);
574         info.fFormatColorType = GrColorType::kRGBA_8888_SRGB;
575         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
576             info.fColorTypeInfoCount = 1;
577             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
578             int ctIdx = 0;
579             // Format: DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, Surface: kRGBA_8888_SRGB
580             {
581                 constexpr GrColorType ct = GrColorType::kRGBA_8888_SRGB;
582                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
583                 ctInfo.fColorType = ct;
584                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
585             }
586         }
587     }
588     // Format: DXGI_FORMAT_R16_UNORM
589     {
590         constexpr DXGI_FORMAT format = DXGI_FORMAT_R16_UNORM;
591         auto& info = this->getFormatInfo(format);
592         info.init(adapterDesc, device, format);
593         info.fFormatColorType = GrColorType::kR_16;
594         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
595             info.fColorTypeInfoCount = 1;
596             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
597             int ctIdx = 0;
598             // Format: DXGI_FORMAT_R16_UNORM, Surface: kAlpha_16
599             {
600                 constexpr GrColorType ct = GrColorType::kAlpha_16;
601                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
602                 ctInfo.fColorType = ct;
603                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
604                 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
605                 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
606             }
607         }
608     }
609     // Format: DXGI_FORMAT_R16G16_UNORM
610     {
611         constexpr DXGI_FORMAT format = DXGI_FORMAT_R16G16_UNORM;
612         auto& info = this->getFormatInfo(format);
613         info.init(adapterDesc, device, format);
614         info.fFormatColorType = GrColorType::kRG_1616;
615         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
616             info.fColorTypeInfoCount = 1;
617             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
618             int ctIdx = 0;
619             // Format: DXGI_FORMAT_R16G16_UNORM, Surface: kRG_1616
620             {
621                 constexpr GrColorType ct = GrColorType::kRG_1616;
622                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
623                 ctInfo.fColorType = ct;
624                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
625             }
626         }
627     }
628     // Format: DXGI_FORMAT_R16G16B16A16_UNORM
629     {
630         constexpr DXGI_FORMAT format = DXGI_FORMAT_R16G16B16A16_UNORM;
631         auto& info = this->getFormatInfo(format);
632         info.init(adapterDesc, device, format);
633         info.fFormatColorType = GrColorType::kRGBA_16161616;
634         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
635             info.fColorTypeInfoCount = 1;
636             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
637             int ctIdx = 0;
638             // Format: DXGI_FORMAT_R16G16B16A16_UNORM, Surface: kRGBA_16161616
639             {
640                 constexpr GrColorType ct = GrColorType::kRGBA_16161616;
641                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
642                 ctInfo.fColorType = ct;
643                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
644             }
645         }
646     }
647     // Format: DXGI_FORMAT_R16G16_FLOAT
648     {
649         constexpr DXGI_FORMAT format = DXGI_FORMAT_R16G16_FLOAT;
650         auto& info = this->getFormatInfo(format);
651         info.init(adapterDesc, device, format);
652         info.fFormatColorType = GrColorType::kRG_F16;
653         if (SkToBool(info.fFlags & FormatInfo::kTexturable_Flag)) {
654             info.fColorTypeInfoCount = 1;
655             info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
656             int ctIdx = 0;
657             // Format: DXGI_FORMAT_R16G16_FLOAT, Surface: kRG_F16
658             {
659                 constexpr GrColorType ct = GrColorType::kRG_F16;
660                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
661                 ctInfo.fColorType = ct;
662                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
663             }
664         }
665     }
666 
667     // Format: DXGI_FORMAT_BC1_UNORM
668     {
669         constexpr DXGI_FORMAT format = DXGI_FORMAT_BC1_UNORM;
670         auto& info = this->getFormatInfo(format);
671         info.init(adapterDesc, device, format);
672         // No supported GrColorTypes.
673     }
674 
675     ////////////////////////////////////////////////////////////////////////////
676     // Map GrColorTypes (used for creating GrSurfaces) to DXGI_FORMATs. The order in which the
677     // formats are passed into the setColorType function indicates the priority in selecting which
678     // format we use for a given GrcolorType.
679 
680     this->setColorType(GrColorType::kAlpha_8, { DXGI_FORMAT_R8_UNORM });
681     this->setColorType(GrColorType::kBGR_565, { DXGI_FORMAT_B5G6R5_UNORM });
682     this->setColorType(GrColorType::kABGR_4444, { DXGI_FORMAT_B4G4R4A4_UNORM });
683     this->setColorType(GrColorType::kRGBA_8888, { DXGI_FORMAT_R8G8B8A8_UNORM });
684     this->setColorType(GrColorType::kRGBA_8888_SRGB, { DXGI_FORMAT_R8G8B8A8_UNORM_SRGB });
685     this->setColorType(GrColorType::kRGB_888x, { DXGI_FORMAT_R8G8B8A8_UNORM });
686     this->setColorType(GrColorType::kRG_88, { DXGI_FORMAT_R8G8_UNORM });
687     this->setColorType(GrColorType::kBGRA_8888, { DXGI_FORMAT_B8G8R8A8_UNORM });
688     this->setColorType(GrColorType::kRGBA_1010102, { DXGI_FORMAT_R10G10B10A2_UNORM });
689     this->setColorType(GrColorType::kGray_8, { DXGI_FORMAT_R8_UNORM });
690     this->setColorType(GrColorType::kAlpha_F16, { DXGI_FORMAT_R16_FLOAT });
691     this->setColorType(GrColorType::kRGBA_F16, { DXGI_FORMAT_R16G16B16A16_FLOAT });
692     this->setColorType(GrColorType::kRGBA_F16_Clamped, { DXGI_FORMAT_R16G16B16A16_FLOAT });
693     this->setColorType(GrColorType::kAlpha_16, { DXGI_FORMAT_R16_UNORM });
694     this->setColorType(GrColorType::kRG_1616, { DXGI_FORMAT_R16G16_UNORM });
695     this->setColorType(GrColorType::kRGBA_16161616, { DXGI_FORMAT_R16G16B16A16_UNORM });
696     this->setColorType(GrColorType::kRG_F16, { DXGI_FORMAT_R16G16_FLOAT });
697 }
698 
InitFormatFlags(const D3D12_FEATURE_DATA_FORMAT_SUPPORT & formatSupport,uint16_t * flags)699 void GrD3DCaps::FormatInfo::InitFormatFlags(const D3D12_FEATURE_DATA_FORMAT_SUPPORT& formatSupport,
700                                             uint16_t* flags) {
701     if (SkToBool(D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE & formatSupport.Support1)) {
702         *flags = *flags | kTexturable_Flag;
703 
704         // Ganesh assumes that all renderable surfaces are also texturable
705         if (SkToBool(D3D12_FORMAT_SUPPORT1_RENDER_TARGET & formatSupport.Support1) &&
706             SkToBool(D3D12_FORMAT_SUPPORT1_BLENDABLE & formatSupport.Support1)) {
707             *flags = *flags | kRenderable_Flag;
708         }
709     }
710 
711     if (SkToBool(D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RENDERTARGET & formatSupport.Support1)) {
712         *flags = *flags | kMSAA_Flag;
713     }
714 
715     if (SkToBool(D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RESOLVE & formatSupport.Support1)) {
716         *flags = *flags | kResolve_Flag;
717     }
718 
719     if (SkToBool(D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW & formatSupport.Support1)) {
720         *flags = *flags | kUnorderedAccess_Flag;
721     }
722 }
723 
multisample_count_supported(ID3D12Device * device,DXGI_FORMAT format,int sampleCount)724 static bool multisample_count_supported(ID3D12Device* device, DXGI_FORMAT format, int sampleCount) {
725     D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msqLevels;
726     msqLevels.Format = format;
727     msqLevels.SampleCount = sampleCount;
728     msqLevels.Flags = D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE;
729     GR_D3D_CALL_ERRCHECK(device->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
730                                                      &msqLevels, sizeof(msqLevels)));
731 
732     return msqLevels.NumQualityLevels > 0;
733 }
734 
initSampleCounts(const DXGI_ADAPTER_DESC & adapterDesc,ID3D12Device * device,DXGI_FORMAT format)735 void GrD3DCaps::FormatInfo::initSampleCounts(const DXGI_ADAPTER_DESC& adapterDesc,
736                                              ID3D12Device* device, DXGI_FORMAT format) {
737     if (multisample_count_supported(device, format, 1)) {
738         fColorSampleCounts.push_back(1);
739     }
740     // TODO: test these
741     //if (kImagination_D3DVendor == adapterDesc.VendorId) {
742     //    // MSAA does not work on imagination
743     //    return;
744     //}
745     //if (kIntel_D3DVendor == adapterDesc.VendorId) {
746     //    // MSAA doesn't work well on Intel GPUs chromium:527565, chromium:983926
747     //    return;
748     //}
749     if (multisample_count_supported(device, format, 2)) {
750         fColorSampleCounts.push_back(2);
751     }
752     if (multisample_count_supported(device, format, 4)) {
753         fColorSampleCounts.push_back(4);
754     }
755     if (multisample_count_supported(device, format, 8)) {
756         fColorSampleCounts.push_back(8);
757     }
758     if (multisample_count_supported(device, format, 16)) {
759         fColorSampleCounts.push_back(16);
760     }
761     // Standard sample locations are not defined for more than 16 samples, and we don't need more
762     // than 16. Omit 32 and 64.
763 }
764 
init(const DXGI_ADAPTER_DESC & adapterDesc,ID3D12Device * device,DXGI_FORMAT format)765 void GrD3DCaps::FormatInfo::init(const DXGI_ADAPTER_DESC& adapterDesc, ID3D12Device* device,
766                                  DXGI_FORMAT format) {
767     D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupportDesc;
768     formatSupportDesc.Format = format;
769     GR_D3D_CALL_ERRCHECK(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,
770                                                      &formatSupportDesc,
771                                                      sizeof(formatSupportDesc)));
772 
773     InitFormatFlags(formatSupportDesc, &fFlags);
774     if (fFlags & kRenderable_Flag) {
775         this->initSampleCounts(adapterDesc, device, format);
776     }
777 }
778 
isFormatSRGB(const GrBackendFormat & format) const779 bool GrD3DCaps::isFormatSRGB(const GrBackendFormat& format) const {
780     DXGI_FORMAT dxgiFormat;
781     if (!format.asDxgiFormat(&dxgiFormat)) {
782         return false;
783     }
784 
785     switch (dxgiFormat) {
786         case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
787             return true;
788         default:
789             return false;
790     }
791 }
792 
isFormatTexturable(const GrBackendFormat & format,GrTextureType) const793 bool GrD3DCaps::isFormatTexturable(const GrBackendFormat& format, GrTextureType) const {
794     DXGI_FORMAT dxgiFormat;
795     if (!format.asDxgiFormat(&dxgiFormat)) {
796         return false;
797     }
798 
799     return this->isFormatTexturable(dxgiFormat);
800 }
801 
isFormatTexturable(DXGI_FORMAT format) const802 bool GrD3DCaps::isFormatTexturable(DXGI_FORMAT format) const {
803     const FormatInfo& info = this->getFormatInfo(format);
804     return SkToBool(FormatInfo::kTexturable_Flag & info.fFlags);
805 }
806 
isFormatAsColorTypeRenderable(GrColorType ct,const GrBackendFormat & format,int sampleCount) const807 bool GrD3DCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
808                                              int sampleCount) const {
809     DXGI_FORMAT dxgiFormat;
810     if (!format.asDxgiFormat(&dxgiFormat)) {
811         return false;
812     }
813     if (!this->isFormatRenderable(dxgiFormat, sampleCount)) {
814         return false;
815     }
816     const auto& info = this->getFormatInfo(dxgiFormat);
817     if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) {
818         return false;
819     }
820     return true;
821 }
822 
isFormatRenderable(const GrBackendFormat & format,int sampleCount) const823 bool GrD3DCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const {
824     DXGI_FORMAT dxgiFormat;
825     if (!format.asDxgiFormat(&dxgiFormat)) {
826         return false;
827     }
828     return this->isFormatRenderable(dxgiFormat, sampleCount);
829 }
830 
isFormatRenderable(DXGI_FORMAT format,int sampleCount) const831 bool GrD3DCaps::isFormatRenderable(DXGI_FORMAT format, int sampleCount) const {
832     return sampleCount <= this->maxRenderTargetSampleCount(format);
833 }
834 
isFormatUnorderedAccessible(DXGI_FORMAT format) const835 bool GrD3DCaps::isFormatUnorderedAccessible(DXGI_FORMAT format) const {
836     const FormatInfo& info = this->getFormatInfo(format);
837     return SkToBool(FormatInfo::kUnorderedAccess_Flag & info.fFlags);
838 }
839 
getRenderTargetSampleCount(int requestedCount,const GrBackendFormat & format) const840 int GrD3DCaps::getRenderTargetSampleCount(int requestedCount,
841                                          const GrBackendFormat& format) const {
842     DXGI_FORMAT dxgiFormat;
843     if (!format.asDxgiFormat(&dxgiFormat)) {
844         return 0;
845     }
846 
847     return this->getRenderTargetSampleCount(requestedCount, dxgiFormat);
848 }
849 
getRenderTargetSampleCount(int requestedCount,DXGI_FORMAT format) const850 int GrD3DCaps::getRenderTargetSampleCount(int requestedCount, DXGI_FORMAT format) const {
851     requestedCount = std::max(1, requestedCount);
852 
853     const FormatInfo& info = this->getFormatInfo(format);
854 
855     int count = info.fColorSampleCounts.count();
856 
857     if (!count) {
858         return 0;
859     }
860 
861     if (1 == requestedCount) {
862         SkASSERT(info.fColorSampleCounts.count() && info.fColorSampleCounts[0] == 1);
863         return 1;
864     }
865 
866     for (int i = 0; i < count; ++i) {
867         if (info.fColorSampleCounts[i] >= requestedCount) {
868             return info.fColorSampleCounts[i];
869         }
870     }
871     return 0;
872 }
873 
maxRenderTargetSampleCount(const GrBackendFormat & format) const874 int GrD3DCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const {
875     DXGI_FORMAT dxgiFormat;
876     if (!format.asDxgiFormat(&dxgiFormat)) {
877         return 0;
878     }
879     return this->maxRenderTargetSampleCount(dxgiFormat);
880 }
881 
maxRenderTargetSampleCount(DXGI_FORMAT format) const882 int GrD3DCaps::maxRenderTargetSampleCount(DXGI_FORMAT format) const {
883     const FormatInfo& info = this->getFormatInfo(format);
884 
885     const auto& table = info.fColorSampleCounts;
886     if (!table.count()) {
887         return 0;
888     }
889     return table[table.count() - 1];
890 }
891 
getFormatColorType(DXGI_FORMAT format) const892 GrColorType GrD3DCaps::getFormatColorType(DXGI_FORMAT format) const {
893     const FormatInfo& info = this->getFormatInfo(format);
894     return info.fFormatColorType;
895 }
896 
supportedWritePixelsColorType(GrColorType surfaceColorType,const GrBackendFormat & surfaceFormat,GrColorType srcColorType) const897 GrCaps::SupportedWrite GrD3DCaps::supportedWritePixelsColorType(
898         GrColorType surfaceColorType, const GrBackendFormat& surfaceFormat,
899         GrColorType srcColorType) const {
900     DXGI_FORMAT dxgiFormat;
901     if (!surfaceFormat.asDxgiFormat(&dxgiFormat)) {
902         return { GrColorType::kUnknown, 0 };
903     }
904 
905     // Any buffer data needs to be aligned to 512 bytes and that of a single texel.
906     size_t offsetAlignment = SkAlignTo(GrDxgiFormatBytesPerBlock(dxgiFormat),
907                                        D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
908 
909     const auto& info = this->getFormatInfo(dxgiFormat);
910     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
911         const auto& ctInfo = info.fColorTypeInfos[i];
912         if (ctInfo.fColorType == surfaceColorType) {
913             return { surfaceColorType, offsetAlignment };
914         }
915     }
916     return { GrColorType::kUnknown, 0 };
917 }
918 
surfaceSupportsReadPixels(const GrSurface * surface) const919 GrCaps::SurfaceReadPixelsSupport GrD3DCaps::surfaceSupportsReadPixels(
920         const GrSurface* surface) const {
921     if (surface->isProtected()) {
922         return SurfaceReadPixelsSupport::kUnsupported;
923     }
924     if (auto tex = static_cast<const GrD3DTexture*>(surface->asTexture())) {
925         // We can't directly read from a compressed format
926         if (GrDxgiFormatIsCompressed(tex->dxgiFormat())) {
927             return SurfaceReadPixelsSupport::kCopyToTexture2D;
928         }
929         return SurfaceReadPixelsSupport::kSupported;
930     } else if (auto rt = static_cast<const GrD3DRenderTarget*>(surface->asRenderTarget())) {
931         if (rt->numSamples() > 1) {
932             return SurfaceReadPixelsSupport::kCopyToTexture2D;
933         }
934         return SurfaceReadPixelsSupport::kSupported;
935     }
936     return SurfaceReadPixelsSupport::kUnsupported;
937 }
938 
onSurfaceSupportsWritePixels(const GrSurface * surface) const939 bool GrD3DCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
940     if (auto rt = surface->asRenderTarget()) {
941         return rt->numSamples() <= 1 && SkToBool(surface->asTexture());
942     }
943     return true;
944 }
945 
onAreColorTypeAndFormatCompatible(GrColorType ct,const GrBackendFormat & format) const946 bool GrD3DCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
947                                                   const GrBackendFormat& format) const {
948     DXGI_FORMAT dxgiFormat;
949     if (!format.asDxgiFormat(&dxgiFormat)) {
950         return false;
951     }
952 
953     const auto& info = this->getFormatInfo(dxgiFormat);
954     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
955         if (info.fColorTypeInfos[i].fColorType == ct) {
956             return true;
957         }
958     }
959     return false;
960 }
961 
onGetDefaultBackendFormat(GrColorType ct) const962 GrBackendFormat GrD3DCaps::onGetDefaultBackendFormat(GrColorType ct) const {
963     DXGI_FORMAT format = this->getFormatFromColorType(ct);
964     if (format == DXGI_FORMAT_UNKNOWN) {
965         return {};
966     }
967     return GrBackendFormat::MakeDxgi(format);
968 }
969 
getBackendFormatFromCompressionType(SkImage::CompressionType compressionType) const970 GrBackendFormat GrD3DCaps::getBackendFormatFromCompressionType(
971     SkImage::CompressionType compressionType) const {
972     switch (compressionType) {
973         case SkImage::CompressionType::kBC1_RGBA8_UNORM:
974             if (this->isFormatTexturable(DXGI_FORMAT_BC1_UNORM)) {
975                 return GrBackendFormat::MakeDxgi(DXGI_FORMAT_BC1_UNORM);
976             }
977             return {};
978         default:
979             return {};
980     }
981 
982     SkUNREACHABLE;
983 }
984 
onGetReadSwizzle(const GrBackendFormat & format,GrColorType colorType) const985 skgpu::Swizzle GrD3DCaps::onGetReadSwizzle(const GrBackendFormat& format,
986                                            GrColorType colorType) const {
987     DXGI_FORMAT dxgiFormat;
988     SkAssertResult(format.asDxgiFormat(&dxgiFormat));
989     const auto& info = this->getFormatInfo(dxgiFormat);
990     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
991         const auto& ctInfo = info.fColorTypeInfos[i];
992         if (ctInfo.fColorType == colorType) {
993             return ctInfo.fReadSwizzle;
994         }
995     }
996     SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.",
997                  (int)colorType, (int)dxgiFormat);
998     return {};
999 }
1000 
getWriteSwizzle(const GrBackendFormat & format,GrColorType colorType) const1001 skgpu::Swizzle GrD3DCaps::getWriteSwizzle(const GrBackendFormat& format,
1002                                           GrColorType colorType) const {
1003     DXGI_FORMAT dxgiFormat;
1004     SkAssertResult(format.asDxgiFormat(&dxgiFormat));
1005     const auto& info = this->getFormatInfo(dxgiFormat);
1006     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1007         const auto& ctInfo = info.fColorTypeInfos[i];
1008         if (ctInfo.fColorType == colorType) {
1009             return ctInfo.fWriteSwizzle;
1010         }
1011     }
1012     SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.",
1013                  (int)colorType, (int)dxgiFormat);
1014     return {};
1015 }
1016 
computeFormatKey(const GrBackendFormat & format) const1017 uint64_t GrD3DCaps::computeFormatKey(const GrBackendFormat& format) const {
1018     DXGI_FORMAT dxgiFormat;
1019     SkAssertResult(format.asDxgiFormat(&dxgiFormat));
1020 
1021     return (uint64_t)dxgiFormat;
1022 }
1023 
onSupportedReadPixelsColorType(GrColorType srcColorType,const GrBackendFormat & srcBackendFormat,GrColorType dstColorType) const1024 GrCaps::SupportedRead GrD3DCaps::onSupportedReadPixelsColorType(
1025         GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
1026         GrColorType dstColorType) const {
1027     DXGI_FORMAT dxgiFormat;
1028     if (!srcBackendFormat.asDxgiFormat(&dxgiFormat)) {
1029         return { GrColorType::kUnknown, 0 };
1030     }
1031 
1032     SkImage::CompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat);
1033     if (compression != SkImage::CompressionType::kNone) {
1034         return { SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
1035                                                         : GrColorType::kRGBA_8888, 0 };
1036     }
1037 
1038     // Any subresource buffer data offset we copy to needs to be aligned to 512 bytes.
1039     size_t offsetAlignment = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
1040 
1041     const auto& info = this->getFormatInfo(dxgiFormat);
1042     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1043         const auto& ctInfo = info.fColorTypeInfos[i];
1044         if (ctInfo.fColorType == srcColorType) {
1045             return { srcColorType, offsetAlignment };
1046         }
1047     }
1048     return { GrColorType::kUnknown, 0 };
1049 }
1050 
addExtraSamplerKey(skgpu::KeyBuilder * b,GrSamplerState samplerState,const GrBackendFormat & format) const1051 void GrD3DCaps::addExtraSamplerKey(skgpu::KeyBuilder* b,
1052                                    GrSamplerState samplerState,
1053                                    const GrBackendFormat& format) const {
1054     // TODO
1055 }
1056 
1057 /**
1058  * TODO: Determine what goes in the ProgramDesc
1059  */
makeDesc(GrRenderTarget * rt,const GrProgramInfo & programInfo,ProgramDescOverrideFlags overrideFlags) const1060 GrProgramDesc GrD3DCaps::makeDesc(GrRenderTarget* rt,
1061                                   const GrProgramInfo& programInfo,
1062                                   ProgramDescOverrideFlags overrideFlags) const {
1063     SkASSERT(overrideFlags == ProgramDescOverrideFlags::kNone);
1064     GrProgramDesc desc;
1065     GrProgramDesc::Build(&desc, programInfo, *this);
1066 
1067     skgpu::KeyBuilder b(desc.key());
1068 
1069     GrD3DRenderTarget* d3dRT = (GrD3DRenderTarget*) rt;
1070     d3dRT->genKey(&b);
1071 
1072     GrStencilSettings stencil = programInfo.nonGLStencilSettings();
1073     stencil.genKey(&b, false);
1074 
1075     programInfo.pipeline().genKey(&b, *this);
1076     // The num samples is already added in the render target key so we don't need to add it here.
1077 
1078     // D3D requires the full primitive type as part of its key
1079     b.add32(programInfo.primitiveTypeKey());
1080 
1081     b.flush();
1082     return desc;
1083 }
1084 
1085 #if GR_TEST_UTILS
getTestingCombinations() const1086 std::vector<GrCaps::TestFormatColorTypeCombination> GrD3DCaps::getTestingCombinations() const {
1087     std::vector<GrCaps::TestFormatColorTypeCombination> combos = {
1088         {GrColorType::kAlpha_8,        GrBackendFormat::MakeDxgi(DXGI_FORMAT_R8_UNORM)           },
1089         {GrColorType::kBGR_565,        GrBackendFormat::MakeDxgi(DXGI_FORMAT_B5G6R5_UNORM)       },
1090         {GrColorType::kABGR_4444,      GrBackendFormat::MakeDxgi(DXGI_FORMAT_B4G4R4A4_UNORM)     },
1091         {GrColorType::kRGBA_8888,      GrBackendFormat::MakeDxgi(DXGI_FORMAT_R8G8B8A8_UNORM)     },
1092         {GrColorType::kRGBA_8888_SRGB, GrBackendFormat::MakeDxgi(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)},
1093         {GrColorType::kRGB_888x,       GrBackendFormat::MakeDxgi(DXGI_FORMAT_R8G8B8A8_UNORM)     },
1094         {GrColorType::kRG_88,          GrBackendFormat::MakeDxgi(DXGI_FORMAT_R8G8_UNORM)         },
1095         {GrColorType::kBGRA_8888,      GrBackendFormat::MakeDxgi(DXGI_FORMAT_B8G8R8A8_UNORM)     },
1096         {GrColorType::kRGBA_1010102,   GrBackendFormat::MakeDxgi(DXGI_FORMAT_R10G10B10A2_UNORM)  },
1097         {GrColorType::kGray_8,         GrBackendFormat::MakeDxgi(DXGI_FORMAT_R8_UNORM)           },
1098         {GrColorType::kAlpha_F16,      GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16_FLOAT)          },
1099         {GrColorType::kRGBA_F16,       GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16G16B16A16_FLOAT) },
1100         {GrColorType::kRGBA_F16_Clamped, GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16G16B16A16_FLOAT)},
1101         {GrColorType::kAlpha_16,       GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16_UNORM)          },
1102         {GrColorType::kRG_1616,        GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16G16_UNORM)       },
1103         {GrColorType::kRGBA_16161616,  GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16G16B16A16_UNORM) },
1104         {GrColorType::kRG_F16,         GrBackendFormat::MakeDxgi(DXGI_FORMAT_R16G16_FLOAT)       },
1105         {GrColorType::kRGBA_8888,      GrBackendFormat::MakeDxgi(DXGI_FORMAT_BC1_UNORM)          },
1106     };
1107 
1108     return combos;
1109 }
1110 #endif
1111