1/* 2 * Copyright 2017 Google Inc. 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 "src/gpu/ganesh/mtl/GrMtlCaps.h" 9 10#include "include/core/SkRect.h" 11#include "include/core/SkTextureCompressionType.h" 12#include "include/gpu/GrBackendSurface.h" 13#include "include/gpu/ganesh/mtl/GrMtlBackendSurface.h" 14#include "src/core/SkCompressedDataUtils.h" 15#include "src/core/SkReadBuffer.h" 16#include "src/gpu/KeyBuilder.h" 17#include "src/gpu/ganesh/GrBackendUtils.h" 18#include "src/gpu/ganesh/GrProcessor.h" 19#include "src/gpu/ganesh/GrProgramDesc.h" 20#include "src/gpu/ganesh/GrProgramInfo.h" 21#include "src/gpu/ganesh/GrRenderTarget.h" 22#include "src/gpu/ganesh/GrRenderTargetProxy.h" 23#include "src/gpu/ganesh/GrShaderCaps.h" 24#include "src/gpu/ganesh/GrSurfaceProxy.h" 25#include "src/gpu/ganesh/mtl/GrMtlRenderTarget.h" 26#include "src/gpu/ganesh/mtl/GrMtlTexture.h" 27#include "src/gpu/ganesh/mtl/GrMtlUtil.h" 28#include "src/gpu/mtl/MtlUtilsPriv.h" 29 30#if defined(GR_TEST_UTILS) 31 #include "src/gpu/ganesh/TestFormatColorTypeCombination.h" 32#endif 33 34#if !__has_feature(objc_arc) 35#error This file must be compiled with Arc. Use -fobjc-arc flag 36#endif 37 38GR_NORETAIN_BEGIN 39 40GrMtlCaps::GrMtlCaps(const GrContextOptions& contextOptions, const id<MTLDevice> device) 41 : INHERITED(contextOptions) { 42 fShaderCaps = std::make_unique<GrShaderCaps>(); 43 44 this->initGPUFamily(device); 45 this->initGrCaps(device); 46 this->initShaderCaps(); 47 if (!contextOptions.fDisableDriverCorrectnessWorkarounds) { 48 this->applyDriverCorrectnessWorkarounds(contextOptions, device); 49 } 50 51 this->initFormatTable(); 52 this->initStencilFormat(device); 53 54 // TODO: appears to be slow with Mac msaa8, disabled for now 55 fStoreAndMultisampleResolveSupport = (fGPUFamily == GPUFamily::kApple && 56 fFamilyGroup >= 3); 57 // Also slow with non-Apple silicon 58 fPreferDiscardableMSAAAttachment = (fGPUFamily == GPUFamily::kApple); 59 60 this->finishInitialization(contextOptions); 61} 62 63// translates from older MTLFeatureSet interface to MTLGPUFamily interface 64bool GrMtlCaps::getGPUFamilyFromFeatureSet(id<MTLDevice> device, 65 GPUFamily* gpuFamily, 66 int* group) { 67// MTLFeatureSet is deprecated for newer versions of the SDK 68#if GR_METAL_SDK_VERSION < 300 69 70#if defined(SK_BUILD_FOR_MAC) 71 // Apple Silicon is only available in later OSes 72 *gpuFamily = GPUFamily::kMac; 73 // Mac OSX 14 74 if (@available(macOS 10.14, *)) { 75 if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) { 76 *group = 2; 77 return true; 78 } 79 if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v4]) { 80 *group = 1; 81 return true; 82 } 83 } 84 // Mac OSX 13 85 if (@available(macOS 10.13, *)) { 86 if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v3]) { 87 *group = 1; 88 return true; 89 } 90 } 91 // Mac OSX 12 92 if (@available(macOS 10.12, *)) { 93 if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v2]) { 94 *group = 1; 95 return true; 96 } 97 } 98 // Mac OSX 11 99 if (@available(macOS 10.11, *)) { 100 if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) { 101 *group = 1; 102 return true; 103 } 104 } 105#elif defined(SK_BUILD_FOR_IOS) 106 // TODO: support tvOS 107 *gpuFamily = GPUFamily::kApple; 108 // iOS 12 109 if (@available(iOS 12.0, tvOS 12.0, *)) { 110 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily5_v1]) { 111 *group = 5; 112 return true; 113 } 114 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v2]) { 115 *group = 4; 116 return true; 117 } 118 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v4]) { 119 *group = 3; 120 return true; 121 } 122 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v5]) { 123 *group = 2; 124 return true; 125 } 126 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v5]) { 127 *group = 1; 128 return true; 129 } 130 } 131 // iOS 11 132 if (@available(iOS 11.0, tvOS 11.0, *)) { 133 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v1]) { 134 *group = 4; 135 return true; 136 } 137 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v3]) { 138 *group = 3; 139 return true; 140 } 141 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v4]) { 142 *group = 2; 143 return true; 144 } 145 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v4]) { 146 *group = 1; 147 return true; 148 } 149 } 150 // iOS 10 151 if (@available(iOS 10.0, tvOS 10.0, *)) { 152 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2]) { 153 *group = 3; 154 return true; 155 } 156 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v3]) { 157 *group = 2; 158 return true; 159 } 160 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v3]) { 161 *group = 1; 162 return true; 163 } 164 } 165 // We don't support earlier OSes 166#endif 167 168#endif // GR_METAL_SDK_VERSION < 300 169 170 // No supported GPU families were found 171 return false; 172} 173 174bool GrMtlCaps::getGPUFamily(id<MTLDevice> device, GPUFamily* gpuFamily, int* group) { 175#if GR_METAL_SDK_VERSION >= 220 176 if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { 177 // Apple Silicon 178#if GR_METAL_SDK_VERSION >= 230 179 if ([device supportsFamily:MTLGPUFamilyApple7]) { 180 *gpuFamily = GPUFamily::kApple; 181 *group = 7; 182 return true; 183 } 184#endif 185#ifdef SK_BUILD_FOR_IOS 186 if ([device supportsFamily:MTLGPUFamilyApple6]) { 187 *gpuFamily = GPUFamily::kApple; 188 *group = 6; 189 return true; 190 } 191 if ([device supportsFamily:MTLGPUFamilyApple5]) { 192 *gpuFamily = GPUFamily::kApple; 193 *group = 5; 194 return true; 195 } 196 if ([device supportsFamily:MTLGPUFamilyApple4]) { 197 *gpuFamily = GPUFamily::kApple; 198 *group = 4; 199 return true; 200 } 201 if ([device supportsFamily:MTLGPUFamilyApple3]) { 202 *gpuFamily = GPUFamily::kApple; 203 *group = 3; 204 return true; 205 } 206 if ([device supportsFamily:MTLGPUFamilyApple2]) { 207 *gpuFamily = GPUFamily::kApple; 208 *group = 2; 209 return true; 210 } 211 if ([device supportsFamily:MTLGPUFamilyApple1]) { 212 *gpuFamily = GPUFamily::kApple; 213 *group = 1; 214 return true; 215 } 216#endif 217 218 // Older Macs 219#if GR_METAL_SDK_VERSION >= 300 220 // TODO: replace with Metal 3 definitions 221 SkASSERT([device supportsFamily:MTLGPUFamilyMac2]); 222 *gpuFamily = GPUFamily::kMac; 223 *group = 2; 224 return true; 225#else 226 // At the moment MacCatalyst families have the same features as Mac, 227 // so we treat them the same 228 if ([device supportsFamily:MTLGPUFamilyMac2] || 229 [device supportsFamily:MTLGPUFamilyMacCatalyst2]) { 230 *gpuFamily = GPUFamily::kMac; 231 *group = 2; 232 return true; 233 } 234 if ([device supportsFamily:MTLGPUFamilyMac1] || 235 [device supportsFamily:MTLGPUFamilyMacCatalyst1]) { 236 *gpuFamily = GPUFamily::kMac; 237 *group = 1; 238 return true; 239 } 240#endif 241 } 242#endif 243 244 // No supported GPU families were found 245 return false; 246} 247 248void GrMtlCaps::initGPUFamily(id<MTLDevice> device) { 249 if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { 250 if (this->getGPUFamily(device, &fGPUFamily, &fFamilyGroup)) { 251 return; 252 } 253 } else { 254 if (this->getGPUFamilyFromFeatureSet(device, &fGPUFamily, &fFamilyGroup)) { 255 return; 256 } 257 } 258 // We don't know what this is, fall back to minimum defaults 259#ifdef SK_BUILD_FOR_MAC 260 fGPUFamily = GPUFamily::kMac; 261 fFamilyGroup = 1; 262#else 263 fGPUFamily = GPUFamily::kApple; 264 fFamilyGroup = 1; 265#endif 266} 267 268bool GrMtlCaps::canCopyAsBlit(MTLPixelFormat dstFormat, int dstSampleCount, 269 MTLPixelFormat srcFormat, int srcSampleCount, 270 const SkIRect& srcRect, const SkIPoint& dstPoint, 271 bool areDstSrcSameObj) const { 272 if (!dstFormat || dstFormat != srcFormat) { 273 return false; 274 } 275 if ((dstSampleCount > 1 || srcSampleCount > 1) && (dstSampleCount != srcSampleCount)) { 276 return false; 277 } 278 if (areDstSrcSameObj) { 279 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(), 280 srcRect.width(), srcRect.height()); 281 if (dstRect.intersect(srcRect)) { 282 return false; 283 } 284 } 285 return true; 286} 287 288bool GrMtlCaps::canCopyAsResolve(MTLPixelFormat dstFormat, int dstSampleCount, 289 MTLPixelFormat srcFormat, int srcSampleCount, 290 bool srcIsRenderTarget, const SkISize srcDimensions, 291 const SkIRect& srcRect, 292 const SkIPoint& dstPoint, 293 bool areDstSrcSameObj) const { 294 if (areDstSrcSameObj) { 295 return false; 296 } 297 if (dstFormat != srcFormat) { 298 return false; 299 } 300 if (dstSampleCount > 1 || srcSampleCount == 1 || !srcIsRenderTarget) { 301 return false; 302 } 303 304 // TODO: Support copying subrectangles 305 if (dstPoint != SkIPoint::Make(0, 0)) { 306 return false; 307 } 308 if (srcRect != SkIRect::MakeSize(srcDimensions)) { 309 return false; 310 } 311 312 return true; 313} 314 315bool GrMtlCaps::onCanCopySurface(const GrSurfaceProxy* dst, const SkIRect& dstRect, 316 const GrSurfaceProxy* src, const SkIRect& srcRect) const { 317 // Metal does not support scaling copies 318 if (srcRect.size() != dstRect.size()) { 319 return false; 320 } 321 322 int dstSampleCnt = 1; 323 int srcSampleCnt = 1; 324 if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) { 325 dstSampleCnt = rtProxy->numSamples(); 326 } 327 if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) { 328 srcSampleCnt = rtProxy->numSamples(); 329 } 330 331 // TODO: need some way to detect whether the proxy is framebufferOnly 332 333 const SkIPoint dstPoint = dstRect.topLeft(); 334 if (this->canCopyAsBlit(GrBackendFormatAsMTLPixelFormat(dst->backendFormat()), dstSampleCnt, 335 GrBackendFormatAsMTLPixelFormat(src->backendFormat()), srcSampleCnt, 336 srcRect, dstPoint, dst == src)) { 337 return true; 338 } 339 bool srcIsRenderTarget = src->asRenderTargetProxy(); 340 MTLPixelFormat dstFormat = GrBackendFormatAsMTLPixelFormat(dst->backendFormat()); 341 MTLPixelFormat srcFormat = GrBackendFormatAsMTLPixelFormat(src->backendFormat()); 342 return this->canCopyAsResolve(dstFormat, dstSampleCnt, 343 srcFormat, srcSampleCnt, 344 srcIsRenderTarget, src->backingStoreDimensions(), srcRect, 345 dstPoint, 346 dst == src); 347} 348 349void GrMtlCaps::initGrCaps(id<MTLDevice> device) { 350#if defined(GR_TEST_UTILS) 351 this->setDeviceName([[device name] UTF8String]); 352#endif 353 354 // Max vertex attribs is the same on all devices 355 fMaxVertexAttributes = 31; 356 357 // Metal does not support scissor + clear 358 fPerformPartialClearsAsDraws = true; 359 360 // We always copy in/out of a transfer buffer so it's trivial to support row bytes. 361 fReadPixelsRowBytesSupport = true; 362 fWritePixelsRowBytesSupport = true; 363 fTransferPixelsToRowBytesSupport = true; 364 365 // RenderTarget and Texture size 366 if (this->isMac() || fFamilyGroup >= 3) { 367 fMaxRenderTargetSize = 16384; 368 } else { 369 fMaxRenderTargetSize = 8192; 370 } 371 fMaxPreferredRenderTargetSize = fMaxRenderTargetSize; 372 fMaxTextureSize = fMaxRenderTargetSize; 373 374 fMaxPushConstantsSize = 4*1024; 375 fTransferBufferRowBytesAlignment = 1; 376 377 // This is documented to be 4 for all Macs. However, on Apple GPUs on Mac it appears there is 378 // no actual alignment requirement 379 // https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400767-copyfrombuffer 380 if (this->isMac()) { 381 fTransferFromBufferToBufferAlignment = 4; 382 // Buffer updates are sometimes implemented through transfers in GrMtlBuffer. 383 fBufferUpdateDataPreserveAlignment = 4; 384 } 385 386 // Metal buffers are initialized to zero (if not created with initial data) 387 fBuffersAreInitiallyZero = true; 388 389 // Init sample counts. All devices support 1 (i.e. 0 in skia). 390 fSampleCounts.push_back(1); 391 if (@available(iOS 9.0, tvOS 9.0, *)) { 392 for (auto sampleCnt : {2, 4, 8}) { 393 if ([device supportsTextureSampleCount:sampleCnt]) { 394 fSampleCounts.push_back(sampleCnt); 395 } 396 } 397 } 398 399 // Clamp to border is supported on Mac 10.12 and higher. It is not supported on iOS. 400 fClampToBorderSupport = false; 401#ifdef SK_BUILD_FOR_MAC 402 if (@available(macOS 10.12, *)) { 403 fClampToBorderSupport = true; 404 } 405#endif 406 407 // Starting with the assumption that there isn't a reason to not map small buffers. 408 fBufferMapThreshold = 0; 409 410 // Buffers are always fully mapped. 411 fMapBufferFlags = kCanMap_MapFlag | kAsyncRead_MapFlag; 412 413 fOversizedStencilSupport = true; 414 415 fNPOTTextureTileSupport = true; // always available in Metal 416 fMipmapSupport = true; // always available in Metal 417 fAnisoSupport = true; // always available in Metal 418 419 fReuseScratchTextures = true; // Assuming this okay 420 421 fTransferFromBufferToTextureSupport = true; 422 fTransferFromSurfaceToBufferSupport = true; 423 fTransferFromBufferToBufferSupport = true; 424 425 fTextureBarrierSupport = false; // Need to figure out if we can do this 426 427 fSampleLocationsSupport = false; 428 429 if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) { 430 if (this->isMac() || fFamilyGroup >= 3) { 431 fDrawInstancedSupport = true; 432 fNativeDrawIndirectSupport = true; 433 } 434 } 435 436 fGpuTracingSupport = false; 437 438 bool supportsMTLEvent = false; 439 if (@available(macOS 10.14, iOS 12.0, tvOS 12.0, *)) { 440 supportsMTLEvent = true; 441 } 442 fSemaphoreSupport = supportsMTLEvent; 443 fBackendSemaphoreSupport = fSemaphoreSupport; 444 fFinishedProcAsyncCallbackSupport = true; 445 446 fCrossContextTextureSupport = true; 447 fHalfFloatVertexAttributeSupport = true; 448 449 fDynamicStateArrayGeometryProcessorTextureSupport = true; 450} 451 452static bool format_is_srgb(MTLPixelFormat format) { 453 switch (format) { 454 case MTLPixelFormatRGBA8Unorm_sRGB: 455 case MTLPixelFormatBGRA8Unorm_sRGB: 456 return true; 457 default: 458 return false; 459 } 460} 461 462bool GrMtlCaps::isFormatSRGB(const GrBackendFormat& format) const { 463 return format_is_srgb(GrBackendFormatAsMTLPixelFormat(format)); 464} 465 466bool GrMtlCaps::isFormatTexturable(const GrBackendFormat& format, GrTextureType) const { 467 MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); 468 return this->isFormatTexturable(mtlFormat); 469} 470 471bool GrMtlCaps::isFormatTexturable(MTLPixelFormat format) const { 472 const FormatInfo& formatInfo = this->getFormatInfo(format); 473 return SkToBool(FormatInfo::kTexturable_Flag & formatInfo.fFlags); 474} 475 476bool GrMtlCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format, 477 int sampleCount) const { 478 if (!this->isFormatRenderable(format, sampleCount)) { 479 return false; 480 } 481 MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); 482 SkASSERT(mtlFormat != MTLPixelFormatInvalid); 483 const auto& info = this->getFormatInfo(mtlFormat); 484 if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) { 485 return false; 486 } 487 return true; 488} 489 490bool GrMtlCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const { 491 return this->isFormatRenderable(GrBackendFormatAsMTLPixelFormat(format), sampleCount); 492} 493 494bool GrMtlCaps::isFormatRenderable(MTLPixelFormat format, int sampleCount) const { 495 return sampleCount <= this->maxRenderTargetSampleCount(format); 496} 497 498int GrMtlCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const { 499 return this->maxRenderTargetSampleCount(GrBackendFormatAsMTLPixelFormat(format)); 500} 501 502int GrMtlCaps::maxRenderTargetSampleCount(MTLPixelFormat format) const { 503 const FormatInfo& formatInfo = this->getFormatInfo(format); 504 if (formatInfo.fFlags & FormatInfo::kMSAA_Flag) { 505 return fSampleCounts[fSampleCounts.size() - 1]; 506 } else if (formatInfo.fFlags & FormatInfo::kRenderable_Flag) { 507 return 1; 508 } 509 return 0; 510} 511 512int GrMtlCaps::getRenderTargetSampleCount(int requestedCount, 513 const GrBackendFormat& format) const { 514 MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); 515 516 return this->getRenderTargetSampleCount(requestedCount, mtlFormat); 517} 518 519int GrMtlCaps::getRenderTargetSampleCount(int requestedCount, MTLPixelFormat format) const { 520 requestedCount = std::max(requestedCount, 1); 521 const FormatInfo& formatInfo = this->getFormatInfo(format); 522 if (!(formatInfo.fFlags & FormatInfo::kRenderable_Flag)) { 523 return 0; 524 } 525 if (formatInfo.fFlags & FormatInfo::kMSAA_Flag) { 526 int count = fSampleCounts.size(); 527 for (int i = 0; i < count; ++i) { 528 if (fSampleCounts[i] >= requestedCount) { 529 return fSampleCounts[i]; 530 } 531 } 532 } 533 return 1 == requestedCount ? 1 : 0; 534} 535 536void GrMtlCaps::initShaderCaps() { 537 GrShaderCaps* shaderCaps = fShaderCaps.get(); 538 539 // Setting this true with the assumption that this cap will eventually mean we support varying 540 // precisions and not just via modifiers. 541 shaderCaps->fUsesPrecisionModifiers = true; 542 shaderCaps->fFlatInterpolationSupport = true; 543 // We haven't yet tested that using flat attributes perform well. 544 shaderCaps->fPreferFlatInterpolation = true; 545 546 shaderCaps->fShaderDerivativeSupport = true; 547 shaderCaps->fExplicitTextureLodSupport = true; 548 549 if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) { 550 shaderCaps->fDualSourceBlendingSupport = true; 551 } else { 552 shaderCaps->fDualSourceBlendingSupport = false; 553 } 554 555 // TODO(skia:8270): Re-enable this once bug 8270 is fixed. Will also need to remove asserts in 556 // GrMtlPipelineStateBuilder which assert we aren't using this feature. 557#if 0 558 if (this->isIOS()) { 559 shaderCaps->fFBFetchSupport = true; 560 shaderCaps->fFBFetchNeedsCustomOutput = true; // ?? 561 shaderCaps->fFBFetchColorName = ""; // Somehow add [[color(0)]] to arguments to frag shader 562 } 563#endif 564 shaderCaps->fDstReadInShaderSupport = shaderCaps->fFBFetchSupport; 565 566 shaderCaps->fIntegerSupport = true; 567 shaderCaps->fNonsquareMatrixSupport = true; 568 shaderCaps->fInverseHyperbolicSupport = true; 569 shaderCaps->fVertexIDSupport = true; 570 shaderCaps->fInfinitySupport = true; 571 shaderCaps->fNonconstantArrayIndexSupport = true; 572 573 // Metal uses IEEE float and half floats so assuming those values here. 574 shaderCaps->fFloatIs32Bits = true; 575 shaderCaps->fHalfIs32Bits = false; 576 577 shaderCaps->fMaxFragmentSamplers = 16; 578} 579 580void GrMtlCaps::applyDriverCorrectnessWorkarounds(const GrContextOptions&, const id<MTLDevice>) { 581 // We don't have any active Metal workarounds. 582} 583 584// Define these so we can use them to initialize arrays and work around 585// the fact that these pixel formats are not always available. 586#define kMTLPixelFormatB5G6R5Unorm MTLPixelFormat(40) 587#define kMTLPixelFormatABGR4Unorm MTLPixelFormat(42) 588#define kMTLPixelFormatETC2_RGB8 MTLPixelFormat(180) 589 590// These are all the valid MTLPixelFormats that we support in Skia. They are roughly ordered from 591// most frequently used to least to improve look up times in arrays. 592static constexpr MTLPixelFormat kMtlFormats[] = { 593 MTLPixelFormatRGBA8Unorm, 594 MTLPixelFormatR8Unorm, 595 MTLPixelFormatA8Unorm, 596 MTLPixelFormatBGRA8Unorm, 597 kMTLPixelFormatB5G6R5Unorm, 598 MTLPixelFormatRGBA16Float, 599 MTLPixelFormatR16Float, 600 MTLPixelFormatRG8Unorm, 601 MTLPixelFormatRGB10A2Unorm, 602 MTLPixelFormatBGR10A2Unorm, 603 kMTLPixelFormatABGR4Unorm, 604 MTLPixelFormatRGBA8Unorm_sRGB, 605 MTLPixelFormatR16Unorm, 606 MTLPixelFormatRG16Unorm, 607 kMTLPixelFormatETC2_RGB8, 608#ifdef SK_BUILD_FOR_MAC 609 MTLPixelFormatBC1_RGBA, 610#endif 611 MTLPixelFormatRGBA16Unorm, 612 MTLPixelFormatRG16Float, 613 614 MTLPixelFormatInvalid, 615}; 616 617void GrMtlCaps::setColorType(GrColorType colorType, std::initializer_list<MTLPixelFormat> formats) { 618#ifdef SK_DEBUG 619 for (size_t i = 0; i < kNumMtlFormats; ++i) { 620 const auto& formatInfo = fFormatTable[i]; 621 for (int j = 0; j < formatInfo.fColorTypeInfoCount; ++j) { 622 const auto& ctInfo = formatInfo.fColorTypeInfos[j]; 623 if (ctInfo.fColorType == colorType) { 624 bool found = false; 625 for (auto it = formats.begin(); it != formats.end(); ++it) { 626 if (kMtlFormats[i] == *it) { 627 found = true; 628 } 629 } 630 SkASSERT(found); 631 } 632 } 633 } 634#endif 635 int idx = static_cast<int>(colorType); 636 for (auto it = formats.begin(); it != formats.end(); ++it) { 637 const auto& info = this->getFormatInfo(*it); 638 for (int i = 0; i < info.fColorTypeInfoCount; ++i) { 639 if (info.fColorTypeInfos[i].fColorType == colorType) { 640 fColorTypeToFormatTable[idx] = *it; 641 return; 642 } 643 } 644 } 645} 646 647size_t GrMtlCaps::GetFormatIndex(MTLPixelFormat pixelFormat) { 648 static_assert(std::size(kMtlFormats) == GrMtlCaps::kNumMtlFormats, 649 "Size of kMtlFormats array must match static value in header"); 650 for (size_t i = 0; i < GrMtlCaps::kNumMtlFormats; ++i) { 651 if (kMtlFormats[i] == pixelFormat) { 652 return i; 653 } 654 } 655 SK_ABORT("Invalid MTLPixelFormat: %d", static_cast<int>(pixelFormat)); 656} 657 658void GrMtlCaps::initFormatTable() { 659 FormatInfo* info; 660 661 if (@available(macos 11.0, *)) { 662 SkASSERT(kMTLPixelFormatB5G6R5Unorm == MTLPixelFormatB5G6R5Unorm); 663 SkASSERT(kMTLPixelFormatABGR4Unorm == MTLPixelFormatABGR4Unorm); 664 SkASSERT(kMTLPixelFormatETC2_RGB8 == MTLPixelFormatETC2_RGB8); 665 } 666 667 // Format: R8Unorm 668 { 669 info = &fFormatTable[GetFormatIndex(MTLPixelFormatR8Unorm)]; 670 info->fFlags = FormatInfo::kAllFlags; 671 info->fColorTypeInfoCount = 3; 672 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 673 int ctIdx = 0; 674 // Format: R8Unorm, Surface: kAlpha_8 675 { 676 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 677 ctInfo.fColorType = GrColorType::kR_8; 678 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 679 } 680 // Format: R8Unorm, Surface: kAlpha_8 681 { 682 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 683 ctInfo.fColorType = GrColorType::kAlpha_8; 684 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 685 ctInfo.fReadSwizzle = skgpu::Swizzle("000r"); 686 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000"); 687 } 688 // Format: R8Unorm, Surface: kGray_8 689 { 690 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 691 ctInfo.fColorType = GrColorType::kGray_8; 692 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; 693 ctInfo.fReadSwizzle = skgpu::Swizzle("rrr1"); 694 } 695 } 696 697 // Format: A8Unorm 698 { 699 info = &fFormatTable[GetFormatIndex(MTLPixelFormatA8Unorm)]; 700 info->fFlags = FormatInfo::kTexturable_Flag; 701 info->fColorTypeInfoCount = 1; 702 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 703 int ctIdx = 0; 704 // Format: A8Unorm, Surface: kAlpha_8 705 { 706 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 707 ctInfo.fColorType = GrColorType::kAlpha_8; 708 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 709 } 710 } 711 712 if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) { 713 if (this->isApple()) { 714 // Format: B5G6R5Unorm 715 { 716 info = &fFormatTable[GetFormatIndex(MTLPixelFormatB5G6R5Unorm)]; 717 info->fFlags = FormatInfo::kAllFlags; 718 info->fColorTypeInfoCount = 1; 719 info->fColorTypeInfos = 720 std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 721 int ctIdx = 0; 722 // Format: B5G6R5Unorm, Surface: kBGR_565 723 { 724 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 725 ctInfo.fColorType = GrColorType::kBGR_565; 726 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | 727 ColorTypeInfo::kRenderable_Flag; 728 } 729 } 730 731 // Format: ABGR4Unorm 732 { 733 info = &fFormatTable[GetFormatIndex(MTLPixelFormatABGR4Unorm)]; 734 info->fFlags = FormatInfo::kAllFlags; 735 info->fColorTypeInfoCount = 1; 736 info->fColorTypeInfos = 737 std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 738 int ctIdx = 0; 739 // Format: ABGR4Unorm, Surface: kABGR_4444 740 { 741 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 742 ctInfo.fColorType = GrColorType::kABGR_4444; 743 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | 744 ColorTypeInfo::kRenderable_Flag; 745 } 746 } 747 } 748 } 749 750 // Format: RGBA8Unorm 751 { 752 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA8Unorm)]; 753 info->fFlags = FormatInfo::kAllFlags; 754 info->fColorTypeInfoCount = 2; 755 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 756 int ctIdx = 0; 757 // Format: RGBA8Unorm, Surface: kRGBA_8888 758 { 759 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 760 ctInfo.fColorType = GrColorType::kRGBA_8888; 761 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 762 } 763 // Format: RGBA8Unorm, Surface: kRGB_888x 764 { 765 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 766 ctInfo.fColorType = GrColorType::kRGB_888x; 767 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; 768 ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); 769 } 770 } 771 772 // Format: RG8Unorm 773 { 774 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG8Unorm)]; 775 info->fFlags = FormatInfo::kAllFlags; 776 info->fColorTypeInfoCount = 1; 777 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 778 int ctIdx = 0; 779 // Format: RG8Unorm, Surface: kRG_88 780 { 781 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 782 ctInfo.fColorType = GrColorType::kRG_88; 783 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 784 } 785 } 786 787 // Format: BGRA8Unorm 788 { 789 info = &fFormatTable[GetFormatIndex(MTLPixelFormatBGRA8Unorm)]; 790 info->fFlags = FormatInfo::kAllFlags; 791 info->fColorTypeInfoCount = 1; 792 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 793 int ctIdx = 0; 794 // Format: BGRA8Unorm, Surface: kBGRA_8888 795 { 796 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 797 ctInfo.fColorType = GrColorType::kBGRA_8888; 798 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 799 } 800 } 801 802 // Format: RGBA8Unorm_sRGB 803 { 804 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA8Unorm_sRGB)]; 805 info->fFlags = FormatInfo::kAllFlags; 806 info->fColorTypeInfoCount = 1; 807 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 808 int ctIdx = 0; 809 // Format: RGBA8Unorm_sRGB, Surface: kRGBA_8888_SRGB 810 { 811 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 812 ctInfo.fColorType = GrColorType::kRGBA_8888_SRGB; 813 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 814 } 815 } 816 817 // Format: RGB10A2Unorm 818 { 819 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGB10A2Unorm)]; 820 if (this->isMac() || fFamilyGroup >= 3) { 821 info->fFlags = FormatInfo::kAllFlags; 822 } else { 823 info->fFlags = FormatInfo::kTexturable_Flag; 824 } 825 info->fColorTypeInfoCount = 1; 826 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 827 int ctIdx = 0; 828 // Format: RGB10A2Unorm, Surface: kRGBA_1010102 829 { 830 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 831 ctInfo.fColorType = GrColorType::kRGBA_1010102; 832 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 833 } 834 } 835 836 // Format: BGR10A2Unorm 837 if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { 838 info = &fFormatTable[GetFormatIndex(MTLPixelFormatBGR10A2Unorm)]; 839 if (this->isMac() && fFamilyGroup == 1) { 840 info->fFlags = FormatInfo::kTexturable_Flag; 841 } else { 842 info->fFlags = FormatInfo::kAllFlags; 843 } 844 info->fColorTypeInfoCount = 1; 845 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 846 int ctIdx = 0; 847 // Format: BGR10A2Unorm, Surface: kBGRA_1010102 848 { 849 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 850 ctInfo.fColorType = GrColorType::kBGRA_1010102; 851 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 852 } 853 } 854 855 // Format: R16Float 856 { 857 info = &fFormatTable[GetFormatIndex(MTLPixelFormatR16Float)]; 858 info->fFlags = FormatInfo::kAllFlags; 859 info->fColorTypeInfoCount = 1; 860 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 861 int ctIdx = 0; 862 // Format: R16Float, Surface: kAlpha_F16 863 { 864 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 865 ctInfo.fColorType = GrColorType::kAlpha_F16; 866 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 867 ctInfo.fReadSwizzle = skgpu::Swizzle("000r"); 868 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000"); 869 } 870 } 871 872 // Format: RGBA16Float 873 { 874 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA16Float)]; 875 info->fFlags = FormatInfo::kAllFlags; 876 info->fColorTypeInfoCount = 2; 877 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 878 int ctIdx = 0; 879 // Format: RGBA16Float, Surface: kRGBA_F16 880 { 881 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 882 ctInfo.fColorType = GrColorType::kRGBA_F16; 883 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 884 } 885 // Format: RGBA16Float, Surface: kRGBA_F16_Clamped 886 { 887 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 888 ctInfo.fColorType = GrColorType::kRGBA_F16_Clamped; 889 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 890 } 891 } 892 893 // Format: R16Unorm 894 { 895 info = &fFormatTable[GetFormatIndex(MTLPixelFormatR16Unorm)]; 896 if (this->isMac()) { 897 info->fFlags = FormatInfo::kAllFlags; 898 } else { 899 info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag; 900 } 901 info->fColorTypeInfoCount = 1; 902 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 903 int ctIdx = 0; 904 // Format: R16Unorm, Surface: kAlpha_16 905 { 906 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 907 ctInfo.fColorType = GrColorType::kAlpha_16; 908 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 909 ctInfo.fReadSwizzle = skgpu::Swizzle("000r"); 910 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000"); 911 } 912 } 913 914 // Format: RG16Unorm 915 { 916 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG16Unorm)]; 917 if (this->isMac()) { 918 info->fFlags = FormatInfo::kAllFlags; 919 } else { 920 info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag; 921 } 922 info->fColorTypeInfoCount = 1; 923 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 924 int ctIdx = 0; 925 // Format: RG16Unorm, Surface: kRG_1616 926 { 927 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 928 ctInfo.fColorType = GrColorType::kRG_1616; 929 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 930 } 931 } 932 933 if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) { 934 if (this->isApple()) { 935 // ETC2_RGB8 936 info = &fFormatTable[GetFormatIndex(MTLPixelFormatETC2_RGB8)]; 937 info->fFlags = FormatInfo::kTexturable_Flag; 938 // NO supported colorTypes 939 } 940 } 941#ifdef SK_BUILD_FOR_MAC 942 if (this->isMac()) { 943 // BC1_RGBA 944 info = &fFormatTable[GetFormatIndex(MTLPixelFormatBC1_RGBA)]; 945 info->fFlags = FormatInfo::kTexturable_Flag; 946 // NO supported colorTypes 947 } 948#endif 949 950 // Format: RGBA16Unorm 951 { 952 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA16Unorm)]; 953 if (this->isMac()) { 954 info->fFlags = FormatInfo::kAllFlags; 955 } else { 956 info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag; 957 } 958 info->fColorTypeInfoCount = 1; 959 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 960 int ctIdx = 0; 961 // Format: RGBA16Unorm, Surface: kRGBA_16161616 962 { 963 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 964 ctInfo.fColorType = GrColorType::kRGBA_16161616; 965 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 966 } 967 } 968 969 // Format: RG16Float 970 { 971 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG16Float)]; 972 info->fFlags = FormatInfo::kAllFlags; 973 info->fColorTypeInfoCount = 1; 974 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 975 int ctIdx = 0; 976 // Format: RG16Float, Surface: kRG_F16 977 { 978 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 979 ctInfo.fColorType = GrColorType::kRG_F16; 980 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 981 } 982 } 983 984 //////////////////////////////////////////////////////////////////////////// 985 // Map GrColorTypes (used for creating GrSurfaces) to MTLPixelFormats. The order in which the 986 // formats are passed into the setColorType function indicates the priority in selecting which 987 // format we use for a given GrcolorType. 988 989 std::fill_n(fColorTypeToFormatTable, kGrColorTypeCnt, MTLPixelFormatInvalid); 990 991 this->setColorType(GrColorType::kAlpha_8, { MTLPixelFormatR8Unorm, 992 MTLPixelFormatA8Unorm }); 993 if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) { 994 if (this->isApple()) { 995 this->setColorType(GrColorType::kBGR_565, { MTLPixelFormatB5G6R5Unorm }); 996 this->setColorType(GrColorType::kABGR_4444, { MTLPixelFormatABGR4Unorm }); 997 } 998 } 999 this->setColorType(GrColorType::kRGBA_8888, { MTLPixelFormatRGBA8Unorm }); 1000 this->setColorType(GrColorType::kRGBA_8888_SRGB, { MTLPixelFormatRGBA8Unorm_sRGB }); 1001 this->setColorType(GrColorType::kRGB_888x, { MTLPixelFormatRGBA8Unorm }); 1002 this->setColorType(GrColorType::kRG_88, { MTLPixelFormatRG8Unorm }); 1003 this->setColorType(GrColorType::kBGRA_8888, { MTLPixelFormatBGRA8Unorm }); 1004 this->setColorType(GrColorType::kRGBA_1010102, { MTLPixelFormatRGB10A2Unorm }); 1005 if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { 1006 this->setColorType(GrColorType::kBGRA_1010102, { MTLPixelFormatBGR10A2Unorm }); 1007 } 1008 this->setColorType(GrColorType::kGray_8, { MTLPixelFormatR8Unorm }); 1009 this->setColorType(GrColorType::kAlpha_F16, { MTLPixelFormatR16Float }); 1010 this->setColorType(GrColorType::kRGBA_F16, { MTLPixelFormatRGBA16Float }); 1011 this->setColorType(GrColorType::kRGBA_F16_Clamped, { MTLPixelFormatRGBA16Float }); 1012 this->setColorType(GrColorType::kAlpha_16, { MTLPixelFormatR16Unorm }); 1013 this->setColorType(GrColorType::kRG_1616, { MTLPixelFormatRG16Unorm }); 1014 this->setColorType(GrColorType::kRGBA_16161616, { MTLPixelFormatRGBA16Unorm }); 1015 this->setColorType(GrColorType::kRG_F16, { MTLPixelFormatRG16Float }); 1016} 1017 1018void GrMtlCaps::initStencilFormat(id<MTLDevice> physDev) { 1019 fPreferredStencilFormat = MTLPixelFormatStencil8; 1020} 1021 1022bool GrMtlCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const { 1023 if (auto rt = surface->asRenderTarget()) { 1024 return rt->numSamples() <= 1 && SkToBool(surface->asTexture()); 1025 } 1026 return true; 1027} 1028 1029GrCaps::SurfaceReadPixelsSupport GrMtlCaps::surfaceSupportsReadPixels( 1030 const GrSurface* surface) const { 1031 if (auto tex = static_cast<const GrMtlTexture*>(surface->asTexture())) { 1032 // We disallow reading back directly from compressed textures. 1033 if (skgpu::MtlFormatIsCompressed(tex->attachment()->mtlFormat())) { 1034 return SurfaceReadPixelsSupport::kCopyToTexture2D; 1035 } 1036 } 1037 1038 if (auto mtlRT = static_cast<const GrMtlRenderTarget*>(surface->asRenderTarget())) { 1039 if (mtlRT->numSamples() > 1 && !mtlRT->resolveAttachment()) { 1040 return SurfaceReadPixelsSupport::kCopyToTexture2D; 1041 } 1042 } 1043 return SurfaceReadPixelsSupport::kSupported; 1044} 1045 1046GrCaps::DstCopyRestrictions GrMtlCaps::getDstCopyRestrictions(const GrRenderTargetProxy* src, 1047 GrColorType ct) const { 1048 // If the src is a MSAA RT then the only supported copy action (not considering falling back 1049 // to a draw) is to resolve from the MSAA src to the non-MSAA dst. Currently we only support 1050 // resolving the entire texture to a resolve buffer of the same size. 1051 DstCopyRestrictions restrictions = {}; 1052 if (auto rtProxy = src->asRenderTargetProxy()) { 1053 if (rtProxy->numSamples() > 1) { 1054 restrictions.fMustCopyWholeSrc = true; 1055 restrictions.fRectsMustMatch = GrSurfaceProxy::RectsMustMatch::kYes; 1056 } 1057 } 1058 return restrictions; 1059} 1060 1061bool GrMtlCaps::onAreColorTypeAndFormatCompatible(GrColorType ct, 1062 const GrBackendFormat& format) const { 1063 MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); 1064 1065 const auto& info = this->getFormatInfo(mtlFormat); 1066 for (int i = 0; i < info.fColorTypeInfoCount; ++i) { 1067 if (info.fColorTypeInfos[i].fColorType == ct) { 1068 return true; 1069 } 1070 } 1071 return false; 1072} 1073 1074GrBackendFormat GrMtlCaps::onGetDefaultBackendFormat(GrColorType ct) const { 1075 MTLPixelFormat format = this->getFormatFromColorType(ct); 1076 if (!format) { 1077 return {}; 1078 } 1079 return GrBackendFormats::MakeMtl(format); 1080} 1081 1082GrBackendFormat GrMtlCaps::getBackendFormatFromCompressionType( 1083 SkTextureCompressionType compressionType) const { 1084 switch (compressionType) { 1085 case SkTextureCompressionType::kNone: 1086 return {}; 1087 case SkTextureCompressionType::kETC2_RGB8_UNORM: 1088 if (@available(macOS 11.0, *)) { 1089 if (this->isApple()) { 1090 return GrBackendFormats::MakeMtl(MTLPixelFormatETC2_RGB8); 1091 } else { 1092 return {}; 1093 } 1094 } else { 1095 return {}; 1096 } 1097 case SkTextureCompressionType::kBC1_RGB8_UNORM: 1098 // Metal only supports the RGBA BC1 variant (see following) 1099 return {}; 1100 case SkTextureCompressionType::kBC1_RGBA8_UNORM: 1101#ifdef SK_BUILD_FOR_MAC 1102 if (this->isMac()) { 1103 return GrBackendFormats::MakeMtl(MTLPixelFormatBC1_RGBA); 1104 } else { 1105 return {}; 1106 } 1107#else 1108 return {}; 1109#endif 1110 1111 } 1112 SK_ABORT("Invalid compression type"); 1113} 1114 1115skgpu::Swizzle GrMtlCaps::onGetReadSwizzle(const GrBackendFormat& format, 1116 GrColorType colorType) const { 1117 MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); 1118 SkASSERT(mtlFormat != MTLPixelFormatInvalid); 1119 const auto& info = this->getFormatInfo(mtlFormat); 1120 for (int i = 0; i < info.fColorTypeInfoCount; ++i) { 1121 const auto& ctInfo = info.fColorTypeInfos[i]; 1122 if (ctInfo.fColorType == colorType) { 1123 return ctInfo.fReadSwizzle; 1124 } 1125 } 1126 SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.", (int)colorType, 1127 static_cast<int>(mtlFormat)); 1128 return {}; 1129} 1130 1131skgpu::Swizzle GrMtlCaps::getWriteSwizzle(const GrBackendFormat& format, 1132 GrColorType colorType) const { 1133 MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); 1134 SkASSERT(mtlFormat != MTLPixelFormatInvalid); 1135 const auto& info = this->getFormatInfo(mtlFormat); 1136 for (int i = 0; i < info.fColorTypeInfoCount; ++i) { 1137 const auto& ctInfo = info.fColorTypeInfos[i]; 1138 if (ctInfo.fColorType == colorType) { 1139 return ctInfo.fWriteSwizzle; 1140 } 1141 } 1142 SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.", (int)colorType, 1143 static_cast<int>(mtlFormat)); 1144 return {}; 1145} 1146 1147uint64_t GrMtlCaps::computeFormatKey(const GrBackendFormat& format) const { 1148 MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); 1149 SkASSERT(mtlFormat != MTLPixelFormatInvalid); 1150 // A MTLPixelFormat is an NSUInteger type which is documented to be 32 bits in 32 bit 1151 // applications and 64 bits in 64 bit applications. So it should fit in an uint64_t, but adding 1152 // the assert heere to make sure. 1153 static_assert(sizeof(MTLPixelFormat) <= sizeof(uint64_t)); 1154 return (uint64_t)mtlFormat; 1155} 1156 1157GrCaps::SupportedWrite GrMtlCaps::supportedWritePixelsColorType( 1158 GrColorType surfaceColorType, const GrBackendFormat& surfaceFormat, 1159 GrColorType srcColorType) const { 1160 // Metal requires the destination offset for copyFromTexture to be a multiple of the textures 1161 // pixels size. 1162 size_t offsetAlignment = GrColorTypeBytesPerPixel(surfaceColorType); 1163 1164 const auto& info = this->getFormatInfo(GrBackendFormatAsMTLPixelFormat(surfaceFormat)); 1165 for (int i = 0; i < info.fColorTypeInfoCount; ++i) { 1166 const auto& ctInfo = info.fColorTypeInfos[i]; 1167 if (ctInfo.fColorType == surfaceColorType) { 1168 return {surfaceColorType, offsetAlignment}; 1169 } 1170 } 1171 return {GrColorType::kUnknown, 0}; 1172} 1173 1174GrCaps::SupportedRead GrMtlCaps::onSupportedReadPixelsColorType( 1175 GrColorType srcColorType, const GrBackendFormat& srcBackendFormat, 1176 GrColorType dstColorType) const { 1177 SkTextureCompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat); 1178 if (compression != SkTextureCompressionType::kNone) { 1179#ifdef SK_BUILD_FOR_IOS 1180 // Reading back to kRGB_888x doesn't work on Metal/iOS (skbug.com/9839) 1181 return { GrColorType::kUnknown, 0 }; 1182#else 1183 return { SkTextureCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x 1184 : GrColorType::kRGBA_8888, 0 }; 1185#endif 1186 } 1187 1188 // Metal requires the destination offset for copyFromTexture to be a multiple of the textures 1189 // pixels size. 1190 size_t offsetAlignment = GrColorTypeBytesPerPixel(srcColorType); 1191 MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(srcBackendFormat); 1192 1193 const auto& info = this->getFormatInfo(mtlFormat); 1194 for (int i = 0; i < info.fColorTypeInfoCount; ++i) { 1195 const auto& ctInfo = info.fColorTypeInfos[i]; 1196 if (ctInfo.fColorType == srcColorType) { 1197 return {srcColorType, offsetAlignment}; 1198 } 1199 } 1200 return {GrColorType::kUnknown, 0}; 1201} 1202 1203/** 1204 * For Metal we want to cache the entire pipeline for reuse of draws. The Desc here holds all 1205 * the information needed to differentiate one pipeline from another. 1206 * 1207 * The GrProgramDesc contains all the information need to create the actual shaders for the 1208 * pipeline. 1209 * 1210 * For Metal we need to add to the GrProgramDesc to include the rest of the state on the 1211 * pipeline. This includes blending information and primitive type. The pipeline is immutable 1212 * so any remaining dynamic state is set via the MtlRenderCmdEncoder. 1213 */ 1214GrProgramDesc GrMtlCaps::makeDesc(GrRenderTarget*, const GrProgramInfo& programInfo, 1215 ProgramDescOverrideFlags overrideFlags) const { 1216 SkASSERT(overrideFlags == ProgramDescOverrideFlags::kNone); 1217 GrProgramDesc desc; 1218 GrProgramDesc::Build(&desc, programInfo, *this); 1219 1220 skgpu::KeyBuilder b(desc.key()); 1221 1222 // If ordering here is changed, update getStencilPixelFormat() below 1223 b.add32(GrBackendFormats::AsMtlFormat(programInfo.backendFormat())); 1224 1225 b.add32(programInfo.numSamples()); 1226 1227 b.add32(programInfo.needsStencil() ? this->preferredStencilFormat() : MTLPixelFormatInvalid); 1228 b.add32((uint32_t)programInfo.isStencilEnabled()); 1229 // Stencil samples don't seem to be tracked in the MTLRenderPipeline 1230 1231 programInfo.pipeline().genKey(&b, *this); 1232 1233 b.add32(programInfo.primitiveTypeKey()); 1234 1235 b.flush(); 1236 return desc; 1237} 1238 1239MTLPixelFormat GrMtlCaps::getStencilPixelFormat(const GrProgramDesc& desc) const { 1240 // Set up read buffer to point to platform-dependent part of the key 1241 SkReadBuffer readBuffer(desc.asKey() + desc.initialKeyLength()/sizeof(uint32_t), 1242 desc.keyLength() - desc.initialKeyLength()); 1243 // skip backend format 1244 readBuffer.readUInt(); 1245 // skip raster samples 1246 readBuffer.readUInt(); 1247 1248 return (MTLPixelFormat) readBuffer.readUInt(); 1249} 1250 1251bool GrMtlCaps::renderTargetSupportsDiscardableMSAA(const GrMtlRenderTarget* rt) const { 1252 return rt->resolveAttachment() && 1253 !rt->resolveAttachment()->framebufferOnly() && 1254 (rt->numSamples() > 1 && this->preferDiscardableMSAAAttachment()); 1255} 1256 1257#if defined(GR_TEST_UTILS) 1258std::vector<GrTest::TestFormatColorTypeCombination> GrMtlCaps::getTestingCombinations() const { 1259 std::vector<GrTest::TestFormatColorTypeCombination> combos = { 1260 { GrColorType::kAlpha_8, GrBackendFormats::MakeMtl(MTLPixelFormatA8Unorm) }, 1261 { GrColorType::kAlpha_8, GrBackendFormats::MakeMtl(MTLPixelFormatR8Unorm) }, 1262 { GrColorType::kBGR_565, GrBackendFormats::MakeMtl(kMTLPixelFormatB5G6R5Unorm) }, 1263 { GrColorType::kABGR_4444, GrBackendFormats::MakeMtl(kMTLPixelFormatABGR4Unorm) }, 1264 { GrColorType::kRGBA_8888, GrBackendFormats::MakeMtl(MTLPixelFormatRGBA8Unorm) }, 1265 { GrColorType::kRGBA_8888_SRGB, GrBackendFormats::MakeMtl(MTLPixelFormatRGBA8Unorm_sRGB) }, 1266 { GrColorType::kRGB_888x, GrBackendFormats::MakeMtl(MTLPixelFormatRGBA8Unorm) }, 1267 { GrColorType::kRGB_888x, GrBackendFormats::MakeMtl(kMTLPixelFormatETC2_RGB8) }, 1268#ifdef SK_BUILD_FOR_MAC 1269 { GrColorType::kRGBA_8888, GrBackendFormats::MakeMtl(MTLPixelFormatBC1_RGBA) }, 1270#endif 1271 { GrColorType::kRG_88, GrBackendFormats::MakeMtl(MTLPixelFormatRG8Unorm) }, 1272 { GrColorType::kBGRA_8888, GrBackendFormats::MakeMtl(MTLPixelFormatBGRA8Unorm) }, 1273 { GrColorType::kRGBA_1010102, GrBackendFormats::MakeMtl(MTLPixelFormatRGB10A2Unorm) }, 1274 { GrColorType::kBGRA_1010102, GrBackendFormats::MakeMtl(MTLPixelFormatBGR10A2Unorm) }, 1275 { GrColorType::kGray_8, GrBackendFormats::MakeMtl(MTLPixelFormatR8Unorm) }, 1276 { GrColorType::kAlpha_F16, GrBackendFormats::MakeMtl(MTLPixelFormatR16Float) }, 1277 { GrColorType::kRGBA_F16, GrBackendFormats::MakeMtl(MTLPixelFormatRGBA16Float) }, 1278 { GrColorType::kRGBA_F16_Clamped, GrBackendFormats::MakeMtl(MTLPixelFormatRGBA16Float) }, 1279 { GrColorType::kAlpha_16, GrBackendFormats::MakeMtl(MTLPixelFormatR16Unorm) }, 1280 { GrColorType::kRG_1616, GrBackendFormats::MakeMtl(MTLPixelFormatRG16Unorm) }, 1281 { GrColorType::kRGBA_16161616, GrBackendFormats::MakeMtl(MTLPixelFormatRGBA16Unorm) }, 1282 { GrColorType::kRG_F16, GrBackendFormats::MakeMtl(MTLPixelFormatRG16Float) }, 1283 }; 1284 1285 return combos; 1286} 1287#endif 1288 1289#ifdef SK_ENABLE_DUMP_GPU 1290#include "src/utils/SkJSONWriter.h" 1291void GrMtlCaps::onDumpJSON(SkJSONWriter* writer) const { 1292 1293 // We are called by the base class, which has already called beginObject(). We choose to nest 1294 // all of our caps information in a named sub-object. 1295 writer->beginObject("Metal caps"); 1296 1297 writer->beginObject("Preferred Stencil Format"); 1298 writer->appendS32("stencil bits", GrMtlFormatStencilBits(fPreferredStencilFormat)); 1299 writer->appendS32("total bytes", skgpu::MtlFormatBytesPerBlock(fPreferredStencilFormat)); 1300 writer->endObject(); 1301 1302 switch (fGPUFamily) { 1303 case GPUFamily::kMac: 1304 writer->appendNString("GPU Family", "Mac"); 1305 break; 1306 case GPUFamily::kApple: 1307 writer->appendNString("GPU Family", "Apple"); 1308 break; 1309 default: 1310 writer->appendNString("GPU Family", "unknown"); 1311 break; 1312 } 1313 writer->appendS32("Family Group", fFamilyGroup); 1314 1315 writer->beginArray("Sample Counts"); 1316 for (int v : fSampleCounts) { 1317 writer->appendS32(nullptr, v); 1318 } 1319 writer->endArray(); 1320 1321 writer->endObject(); 1322} 1323#else 1324void GrMtlCaps::onDumpJSON(SkJSONWriter* writer) const { } 1325#endif 1326 1327GR_NORETAIN_END 1328