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 25GrD3DCaps::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 66bool 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 77bool 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 99bool 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 124void 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 184void 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 225void 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 262void GrD3DCaps::applyDriverCorrectnessWorkarounds(int vendorID) { 263 // Nothing yet. 264} 265 266 267bool 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 276void 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. 287static 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 305void 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 336const GrD3DCaps::FormatInfo& GrD3DCaps::getFormatInfo(DXGI_FORMAT format) const { 337 GrD3DCaps* nonConstThis = const_cast<GrD3DCaps*>(this); 338 return nonConstThis->getFormatInfo(format); 339} 340 341GrD3DCaps::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 353void 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 691void 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 716static 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 727void 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 757void 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 771bool 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 785bool 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 794bool GrD3DCaps::isFormatTexturable(DXGI_FORMAT format) const { 795 const FormatInfo& info = this->getFormatInfo(format); 796 return SkToBool(FormatInfo::kTexturable_Flag & info.fFlags); 797} 798 799bool 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 815bool 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 823bool GrD3DCaps::isFormatRenderable(DXGI_FORMAT format, int sampleCount) const { 824 return sampleCount <= this->maxRenderTargetSampleCount(format); 825} 826 827bool GrD3DCaps::isFormatUnorderedAccessible(DXGI_FORMAT format) const { 828 const FormatInfo& info = this->getFormatInfo(format); 829 return SkToBool(FormatInfo::kUnorderedAccess_Flag & info.fFlags); 830} 831 832int 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 842int 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 866int 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 874int 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 884GrColorType GrD3DCaps::getFormatColorType(DXGI_FORMAT format) const { 885 const FormatInfo& info = this->getFormatInfo(format); 886 return info.fFormatColorType; 887} 888 889GrCaps::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 911GrCaps::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 931bool 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 938bool 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 954GrBackendFormat 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 962GrBackendFormat 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 977GrSwizzle 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 992GrSwizzle 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 1007uint64_t GrD3DCaps::computeFormatKey(const GrBackendFormat& format) const { 1008 DXGI_FORMAT dxgiFormat; 1009 SkAssertResult(format.asDxgiFormat(&dxgiFormat)); 1010 1011 return (uint64_t)dxgiFormat; 1012} 1013 1014GrCaps::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 1041void 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 */ 1050GrProgramDesc 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 1076std::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