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