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