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