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