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