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