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