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