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