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