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