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