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