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