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