1/* 2 * Copyright 2021 Google LLC 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/graphite/mtl/MtlCaps.h" 9 10#include "include/core/SkTextureCompressionType.h" 11#include "include/gpu/graphite/TextureInfo.h" 12#include "include/gpu/graphite/mtl/MtlGraphiteTypes.h" 13#include "src/gpu/SwizzlePriv.h" 14#include "src/gpu/graphite/CommandBuffer.h" 15#include "src/gpu/graphite/ComputePipelineDesc.h" 16#include "src/gpu/graphite/GraphicsPipelineDesc.h" 17#include "src/gpu/graphite/GraphiteResourceKey.h" 18#include "src/gpu/graphite/RenderPassDesc.h" 19#include "src/gpu/graphite/RendererProvider.h" 20#include "src/gpu/graphite/TextureProxy.h" 21#include "src/gpu/graphite/mtl/MtlGraphiteUtilsPriv.h" 22#include "src/gpu/mtl/MtlUtilsPriv.h" 23#include "src/sksl/SkSLUtil.h" 24 25namespace skgpu::graphite { 26 27MtlCaps::MtlCaps(const id<MTLDevice> device, const ContextOptions& options) 28 : Caps() { 29 this->initGPUFamily(device); 30 this->initCaps(device); 31 this->initShaderCaps(); 32 33 this->initFormatTable(device); 34 35 // Metal-specific MtlCaps 36 37 this->finishInitialization(options); 38} 39 40bool MtlCaps::GetGPUFamily(id<MTLDevice> device, GPUFamily* gpuFamily, int* group) { 41#if SKGPU_GRAPHITE_METAL_SDK_VERSION >= 220 42 if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { 43 // Apple Silicon 44#if SKGPU_GRAPHITE_METAL_SDK_VERSION >= 230 45 if ([device supportsFamily:MTLGPUFamilyApple7]) { 46 *gpuFamily = GPUFamily::kApple; 47 *group = 7; 48 return true; 49 } 50#endif 51#ifdef SK_BUILD_FOR_IOS 52 if ([device supportsFamily:MTLGPUFamilyApple6]) { 53 *gpuFamily = GPUFamily::kApple; 54 *group = 6; 55 return true; 56 } 57 if ([device supportsFamily:MTLGPUFamilyApple5]) { 58 *gpuFamily = GPUFamily::kApple; 59 *group = 5; 60 return true; 61 } 62 if ([device supportsFamily:MTLGPUFamilyApple4]) { 63 *gpuFamily = GPUFamily::kApple; 64 *group = 4; 65 return true; 66 } 67 if ([device supportsFamily:MTLGPUFamilyApple3]) { 68 *gpuFamily = GPUFamily::kApple; 69 *group = 3; 70 return true; 71 } 72 if ([device supportsFamily:MTLGPUFamilyApple2]) { 73 *gpuFamily = GPUFamily::kApple; 74 *group = 2; 75 return true; 76 } 77 if ([device supportsFamily:MTLGPUFamilyApple1]) { 78 *gpuFamily = GPUFamily::kApple; 79 *group = 1; 80 return true; 81 } 82#endif 83 84 // Older Macs 85#if SKGPU_GRAPHITE_METAL_SDK_VERSION >= 300 86 // TODO: replace with Metal 3 definitions 87 SkASSERT([device supportsFamily:MTLGPUFamilyMac2]); 88 *gpuFamily = GPUFamily::kMac; 89 *group = 2; 90 return true; 91#else 92 // At the moment MacCatalyst families have the same features as Mac, 93 // so we treat them the same 94 if ([device supportsFamily:MTLGPUFamilyMac2] || 95 [device supportsFamily:MTLGPUFamilyMacCatalyst2]) { 96 *gpuFamily = GPUFamily::kMac; 97 *group = 2; 98 return true; 99 } 100 if ([device supportsFamily:MTLGPUFamilyMac1] || 101 [device supportsFamily:MTLGPUFamilyMacCatalyst1]) { 102 *gpuFamily = GPUFamily::kMac; 103 *group = 1; 104 return true; 105 } 106#endif 107 } 108#endif 109 110 // No supported GPU families were found 111 return false; 112} 113 114void MtlCaps::initGPUFamily(id<MTLDevice> device) { 115 if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { 116 if (GetGPUFamily(device, &fGPUFamily, &fFamilyGroup)) { 117 return; 118 } 119 } 120 121 // We don't know what this is, fall back to minimum defaults 122#ifdef SK_BUILD_FOR_MAC 123 fGPUFamily = GPUFamily::kMac; 124 fFamilyGroup = 1; 125#else 126 fGPUFamily = GPUFamily::kApple; 127 fFamilyGroup = 1; 128#endif 129} 130 131void MtlCaps::initCaps(const id<MTLDevice> device) { 132#if defined(GRAPHITE_TEST_UTILS) 133 this->setDeviceName([[device name] UTF8String]); 134#endif 135 136 if (this->isMac() || fFamilyGroup >= 3) { 137 fMaxTextureSize = 16384; 138 } else { 139 fMaxTextureSize = 8192; 140 } 141 142 // We use constant address space for our uniform buffers which has various alignment 143 // requirements for the offset when binding the buffer. On MacOS Intel the offset must align 144 // to 256. On iOS or Apple Silicon we must align to the max of the data type consumed by the 145 // vertex function or 4 bytes, or we can ignore the data type and just use 16 bytes. 146 // 147 // On Mac, all copies must be aligned to at least 4 bytes; on iOS there is no alignment. 148 if (this->isMac()) { 149 fRequiredUniformBufferAlignment = 256; 150 fRequiredTransferBufferAlignment = 4; 151 } else { 152 fRequiredUniformBufferAlignment = 16; 153 fRequiredTransferBufferAlignment = 1; 154 } 155 156 fResourceBindingReqs.fUniformBufferLayout = Layout::kMetal; 157 fResourceBindingReqs.fStorageBufferLayout = Layout::kMetal; 158 fResourceBindingReqs.fDistinctIndexRanges = true; 159 160 // Metal does not distinguish between uniform and storage buffers. 161 fRequiredStorageBufferAlignment = fRequiredUniformBufferAlignment; 162 163 fStorageBufferSupport = true; 164 fStorageBufferPreferred = true; 165 166 fComputeSupport = true; 167 168 if (@available(macOS 10.12, iOS 14.0, tvOS 14.0, *)) { 169 fClampToBorderSupport = (this->isMac() || fFamilyGroup >= 7); 170 } else { 171 fClampToBorderSupport = false; 172 } 173 174 // Init sample counts. All devices support 1 (i.e. 0 in skia). 175 fColorSampleCounts.push_back(1); 176 if (![device.name containsString:@"Intel"]) { 177 if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) { 178 for (auto sampleCnt : {2, 4, 8}) { 179 if ([device supportsTextureSampleCount:sampleCnt]) { 180 fColorSampleCounts.push_back(sampleCnt); 181 } 182 } 183 } 184 } 185} 186 187void MtlCaps::initShaderCaps() { 188 SkSL::ShaderCaps* shaderCaps = fShaderCaps.get(); 189 190 // Dual source blending requires Metal 1.2. 191 if (@available(macOS 10.12, iOS 10.0, tvOS 10.0, *)) { 192 shaderCaps->fDualSourceBlendingSupport = true; 193 } 194 195 // Setting this true with the assumption that this cap will eventually mean we support varying 196 // precisions and not just via modifiers. 197 shaderCaps->fUsesPrecisionModifiers = true; 198 shaderCaps->fFlatInterpolationSupport = true; 199 200 shaderCaps->fShaderDerivativeSupport = true; 201 shaderCaps->fInfinitySupport = true; 202 203 if (@available(macOS 11.0, *)) { 204 if (this->isApple()) { 205 shaderCaps->fFBFetchSupport = true; 206 shaderCaps->fFBFetchColorName = "sk_LastFragColor"; 207 } 208 } 209 210 shaderCaps->fIntegerSupport = true; 211 shaderCaps->fNonsquareMatrixSupport = true; 212 shaderCaps->fInverseHyperbolicSupport = true; 213 214 // Metal uses IEEE floats so assuming those values here. 215 shaderCaps->fFloatIs32Bits = true; 216} 217 218// Define this so we can use it to initialize arrays and work around 219// the fact that these pixel formats are not always available. 220#define kMTLPixelFormatB5G6R5Unorm MTLPixelFormat(40) 221#define kMTLPixelFormatABGR4Unorm MTLPixelFormat(42) 222#define kMTLPixelFormatETC2_RGB8 MTLPixelFormat(180) 223 224// These are all the valid MTLPixelFormats that we currently support in Skia. They are roughly 225// ordered from most frequently used to least to improve look up times in arrays. 226static constexpr MTLPixelFormat kMtlFormats[] = { 227 MTLPixelFormatRGBA8Unorm, 228 MTLPixelFormatR8Unorm, 229 MTLPixelFormatA8Unorm, 230 MTLPixelFormatBGRA8Unorm, 231 kMTLPixelFormatB5G6R5Unorm, 232 MTLPixelFormatRGBA16Float, 233 MTLPixelFormatR16Float, 234 MTLPixelFormatRG8Unorm, 235 MTLPixelFormatRGB10A2Unorm, 236 // MTLPixelFormatBGR10A2Unorm 237 kMTLPixelFormatABGR4Unorm, 238 MTLPixelFormatRGBA8Unorm_sRGB, 239 MTLPixelFormatR16Unorm, 240 MTLPixelFormatRG16Unorm, 241 kMTLPixelFormatETC2_RGB8, 242#ifdef SK_BUILD_FOR_MAC 243 MTLPixelFormatBC1_RGBA, 244#endif 245 MTLPixelFormatRGBA16Unorm, 246 MTLPixelFormatRG16Float, 247 248 MTLPixelFormatStencil8, 249 MTLPixelFormatDepth16Unorm, 250 MTLPixelFormatDepth32Float, 251#ifdef SK_BUILD_FOR_MAC 252 MTLPixelFormatDepth24Unorm_Stencil8, 253#endif 254 MTLPixelFormatDepth32Float_Stencil8, 255 256 MTLPixelFormatInvalid, 257}; 258 259void MtlCaps::setColorType(SkColorType colorType, std::initializer_list<MTLPixelFormat> formats) { 260 int idx = static_cast<int>(colorType); 261 for (auto it = formats.begin(); it != formats.end(); ++it) { 262 const auto& info = this->getFormatInfo(*it); 263 for (int i = 0; i < info.fColorTypeInfoCount; ++i) { 264 if (info.fColorTypeInfos[i].fColorType == colorType) { 265 fColorTypeToFormatTable[idx] = *it; 266 return; 267 } 268 } 269 } 270} 271 272size_t MtlCaps::GetFormatIndex(MTLPixelFormat pixelFormat) { 273 static_assert(std::size(kMtlFormats) == MtlCaps::kNumMtlFormats, 274 "Size of kMtlFormats array must match static value in header"); 275 for (size_t i = 0; i < MtlCaps::kNumMtlFormats; ++i) { 276 if (kMtlFormats[i] == pixelFormat) { 277 return i; 278 } 279 } 280 return GetFormatIndex(MTLPixelFormatInvalid); 281} 282 283void MtlCaps::initFormatTable(const id<MTLDevice> device) { 284 FormatInfo* info; 285 286 if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) { 287 if (this->isApple()) { 288 SkASSERT(kMTLPixelFormatB5G6R5Unorm == MTLPixelFormatB5G6R5Unorm); 289 SkASSERT(kMTLPixelFormatABGR4Unorm == MTLPixelFormatABGR4Unorm); 290 } 291 } 292 293 // Format: RGBA8Unorm 294 { 295 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA8Unorm)]; 296 info->fFlags = FormatInfo::kAllFlags; 297 info->fColorTypeInfoCount = 2; 298 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 299 int ctIdx = 0; 300 // Format: RGBA8Unorm, Surface: kRGBA_8888 301 { 302 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 303 ctInfo.fColorType = kRGBA_8888_SkColorType; 304 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 305 } 306 // Format: RGBA8Unorm, Surface: kRGB_888x 307 { 308 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 309 ctInfo.fColorType = kRGB_888x_SkColorType; 310 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; 311 ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); 312 } 313 } 314 315 // Format: R8Unorm 316 { 317 info = &fFormatTable[GetFormatIndex(MTLPixelFormatR8Unorm)]; 318 info->fFlags = FormatInfo::kAllFlags; 319 info->fColorTypeInfoCount = 3; 320 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 321 int ctIdx = 0; 322 // Format: R8Unorm, Surface: kR8_unorm 323 { 324 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 325 ctInfo.fColorType = kR8_unorm_SkColorType; 326 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 327 } 328 // Format: R8Unorm, Surface: kAlpha_8 329 { 330 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 331 ctInfo.fColorType = kAlpha_8_SkColorType; 332 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 333 ctInfo.fReadSwizzle = skgpu::Swizzle("000r"); 334 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000"); 335 } 336 // Format: R8Unorm, Surface: kGray_8 337 { 338 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 339 ctInfo.fColorType = kGray_8_SkColorType; 340 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; 341 ctInfo.fReadSwizzle = skgpu::Swizzle("rrr1"); 342 } 343 } 344 345 // Format: A8Unorm 346 { 347 info = &fFormatTable[GetFormatIndex(MTLPixelFormatA8Unorm)]; 348 info->fFlags = FormatInfo::kTexturable_Flag; 349 info->fColorTypeInfoCount = 1; 350 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 351 int ctIdx = 0; 352 // Format: A8Unorm, Surface: kAlpha_8 353 { 354 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 355 ctInfo.fColorType = kAlpha_8_SkColorType; 356 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 357 } 358 } 359 360 // Format: BGRA8Unorm 361 { 362 info = &fFormatTable[GetFormatIndex(MTLPixelFormatBGRA8Unorm)]; 363 info->fFlags = FormatInfo::kAllFlags; 364 info->fColorTypeInfoCount = 1; 365 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 366 int ctIdx = 0; 367 // Format: BGRA8Unorm, Surface: kBGRA_8888 368 { 369 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 370 ctInfo.fColorType = kBGRA_8888_SkColorType; 371 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 372 } 373 } 374 375 if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) { 376 if (this->isApple()) { 377 // Format: B5G6R5Unorm 378 { 379 info = &fFormatTable[GetFormatIndex(MTLPixelFormatB5G6R5Unorm)]; 380 info->fFlags = FormatInfo::kAllFlags; 381 info->fColorTypeInfoCount = 1; 382 info->fColorTypeInfos = 383 std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 384 int ctIdx = 0; 385 // Format: B5G6R5Unorm, Surface: kBGR_565 386 { 387 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 388 ctInfo.fColorType = kRGB_565_SkColorType; 389 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | 390 ColorTypeInfo::kRenderable_Flag; 391 } 392 } 393 394 // Format: ABGR4Unorm 395 { 396 info = &fFormatTable[GetFormatIndex(MTLPixelFormatABGR4Unorm)]; 397 info->fFlags = FormatInfo::kAllFlags; 398 info->fColorTypeInfoCount = 1; 399 info->fColorTypeInfos = 400 std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 401 int ctIdx = 0; 402 // Format: ABGR4Unorm, Surface: kABGR_4444 403 { 404 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 405 ctInfo.fColorType = kARGB_4444_SkColorType; 406 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | 407 ColorTypeInfo::kRenderable_Flag; 408 } 409 } 410 } 411 } 412 413 // Format: RGBA8Unorm_sRGB 414 { 415 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA8Unorm_sRGB)]; 416 info->fFlags = FormatInfo::kAllFlags; 417 info->fColorTypeInfoCount = 1; 418 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 419 int ctIdx = 0; 420 // Format: RGBA8Unorm_sRGB, Surface: kSRGBA_8888 421 { 422 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 423 ctInfo.fColorType = kSRGBA_8888_SkColorType; 424 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 425 } 426 } 427 428 // Format: RGB10A2Unorm 429 { 430 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGB10A2Unorm)]; 431 if (this->isMac() || fFamilyGroup >= 3) { 432 info->fFlags = FormatInfo::kAllFlags; 433 } else { 434 info->fFlags = FormatInfo::kTexturable_Flag; 435 } 436 info->fColorTypeInfoCount = 1; 437 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 438 int ctIdx = 0; 439 // Format: RGB10A2Unorm, Surface: kRGBA_1010102 440 { 441 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 442 ctInfo.fColorType = kRGBA_1010102_SkColorType; 443 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 444 } 445 } 446 447 // Format: RGBA16Float 448 { 449 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA16Float)]; 450 info->fFlags = FormatInfo::kAllFlags; 451 info->fColorTypeInfoCount = 2; 452 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 453 int ctIdx = 0; 454 // Format: RGBA16Float, Surface: RGBA_F16 455 { 456 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 457 ctInfo.fColorType = kRGBA_F16_SkColorType; 458 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 459 } 460 // Format: RGBA16Float, Surface: RGBA_F16Norm 461 { 462 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 463 ctInfo.fColorType = kRGBA_F16Norm_SkColorType; 464 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 465 } 466 } 467 468 // Format: R16Float 469 { 470 info = &fFormatTable[GetFormatIndex(MTLPixelFormatR16Float)]; 471 info->fFlags = FormatInfo::kAllFlags; 472 info->fColorTypeInfoCount = 1; 473 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 474 int ctIdx = 0; 475 // Format: R16Float, Surface: kA16_float 476 { 477 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 478 ctInfo.fColorType = kA16_float_SkColorType; 479 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 480 ctInfo.fReadSwizzle = skgpu::Swizzle("000r"); 481 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000"); 482 } 483 } 484 485 // Format: RG8Unorm 486 { 487 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG8Unorm)]; 488 info->fFlags = FormatInfo::kAllFlags; 489 info->fColorTypeInfoCount = 1; 490 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 491 int ctIdx = 0; 492 // Format: RG8Unorm, Surface: kR8G8_unorm 493 { 494 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 495 ctInfo.fColorType = kR8G8_unorm_SkColorType; 496 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 497 } 498 } 499 500 // Format: RGBA16Unorm 501 { 502 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA16Unorm)]; 503 if (this->isMac()) { 504 info->fFlags = FormatInfo::kAllFlags; 505 } else { 506 info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag; 507 } 508 info->fColorTypeInfoCount = 1; 509 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 510 int ctIdx = 0; 511 // Format: RGBA16Unorm, Surface: kR16G16B16A16_unorm 512 { 513 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 514 ctInfo.fColorType = kR16G16B16A16_unorm_SkColorType; 515 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 516 } 517 } 518 519 // Format: RG16Float 520 { 521 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG16Float)]; 522 info->fFlags = FormatInfo::kAllFlags; 523 info->fColorTypeInfoCount = 1; 524 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 525 int ctIdx = 0; 526 // Format: RG16Float, Surface: kR16G16_float 527 { 528 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 529 ctInfo.fColorType = kR16G16_float_SkColorType; 530 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 531 } 532 } 533 534 // Format: R16Unorm 535 { 536 info = &fFormatTable[GetFormatIndex(MTLPixelFormatR16Unorm)]; 537 if (this->isMac()) { 538 info->fFlags = FormatInfo::kAllFlags; 539 } else { 540 info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag; 541 } 542 info->fColorTypeInfoCount = 1; 543 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 544 int ctIdx = 0; 545 // Format: R16Unorm, Surface: kA16_unorm 546 { 547 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 548 ctInfo.fColorType = kA16_unorm_SkColorType; 549 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 550 ctInfo.fReadSwizzle = skgpu::Swizzle("000r"); 551 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000"); 552 } 553 } 554 555 // Format: RG16Unorm 556 { 557 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG16Unorm)]; 558 if (this->isMac()) { 559 info->fFlags = FormatInfo::kAllFlags; 560 } else { 561 info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag; 562 } 563 info->fColorTypeInfoCount = 1; 564 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 565 int ctIdx = 0; 566 // Format: RG16Unorm, Surface: kR16G16_unorm 567 { 568 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 569 ctInfo.fColorType = kR16G16_unorm_SkColorType; 570 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; 571 } 572 } 573 574 // Format: ETC2_RGB8 575 { 576 if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) { 577 if (this->isApple()) { 578 info = &fFormatTable[GetFormatIndex(MTLPixelFormatETC2_RGB8)]; 579 info->fFlags = FormatInfo::kTexturable_Flag; 580 info->fColorTypeInfoCount = 1; 581 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 582 int ctIdx = 0; 583 // Format: ETC2_RGB8, Surface: kRGB_888x 584 { 585 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 586 ctInfo.fColorType = kRGB_888x_SkColorType; 587 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; 588 } 589 } 590 } 591 } 592 593 // Format: BC1_RGBA 594 { 595#ifdef SK_BUILD_FOR_MAC 596 if (this->isMac()) { 597 info = &fFormatTable[GetFormatIndex(MTLPixelFormatBC1_RGBA)]; 598 info->fFlags = FormatInfo::kTexturable_Flag; 599 info->fColorTypeInfoCount = 1; 600 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); 601 int ctIdx = 0; 602 // Format: BC1_RGBA, Surface: kRGBA_8888 603 { 604 auto& ctInfo = info->fColorTypeInfos[ctIdx++]; 605 ctInfo.fColorType = kRGBA_8888_SkColorType; 606 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; 607 } 608 } 609#endif 610 } 611 612 /* 613 * Non-color formats 614 */ 615 616 // Format: Stencil8 617 { 618 info = &fFormatTable[GetFormatIndex(MTLPixelFormatStencil8)]; 619 info->fFlags = FormatInfo::kMSAA_Flag; 620 info->fColorTypeInfoCount = 0; 621 } 622 623 // Format: Depth16Unorm 624 { 625 info = &fFormatTable[GetFormatIndex(MTLPixelFormatDepth16Unorm)]; 626 info->fFlags = FormatInfo::kMSAA_Flag; 627 if (this->isMac() || fFamilyGroup >= 3) { 628 info->fFlags |= FormatInfo::kResolve_Flag; 629 } 630 info->fColorTypeInfoCount = 0; 631 } 632 633 // Format: Depth32Float 634 { 635 info = &fFormatTable[GetFormatIndex(MTLPixelFormatDepth32Float)]; 636 info->fFlags = FormatInfo::kMSAA_Flag; 637 if (this->isMac() || fFamilyGroup >= 3) { 638 info->fFlags |= FormatInfo::kResolve_Flag; 639 } 640 info->fColorTypeInfoCount = 0; 641 } 642 643 // Format: Depth24Unorm_Stencil8 644 { 645#ifdef SK_BUILD_FOR_MAC 646 if (this->isMac() && [device isDepth24Stencil8PixelFormatSupported]) { 647 info = &fFormatTable[GetFormatIndex(MTLPixelFormatDepth24Unorm_Stencil8)]; 648 info->fFlags = FormatInfo::kMSAA_Flag | FormatInfo::kResolve_Flag; 649 info->fColorTypeInfoCount = 0; 650 } 651#endif 652 } 653 654 // Format: Depth32Float_Stencil8 655 { 656 info = &fFormatTable[GetFormatIndex(MTLPixelFormatDepth32Float_Stencil8)]; 657 info->fFlags = FormatInfo::kMSAA_Flag; 658 if (this->isMac() || fFamilyGroup >= 3) { 659 info->fFlags |= FormatInfo::kResolve_Flag; 660 } 661 info->fColorTypeInfoCount = 0; 662 } 663 664 //////////////////////////////////////////////////////////////////////////// 665 // Map SkColorTypes (used for creating SkSurfaces) to MTLPixelFormats. The order in which the 666 // formats are passed into the setColorType function indicates the priority in selecting which 667 // format we use for a given SkColorType. 668 669 std::fill_n(fColorTypeToFormatTable, kSkColorTypeCnt, MTLPixelFormatInvalid); 670 671 this->setColorType(kAlpha_8_SkColorType, { MTLPixelFormatR8Unorm, 672 MTLPixelFormatA8Unorm }); 673 if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) { 674 if (this->isApple()) { 675 this->setColorType(kRGB_565_SkColorType, {MTLPixelFormatB5G6R5Unorm}); 676 this->setColorType(kARGB_4444_SkColorType, { MTLPixelFormatABGR4Unorm }); 677 } 678 } 679 680 this->setColorType(kRGBA_8888_SkColorType, { MTLPixelFormatRGBA8Unorm }); 681 this->setColorType(kRGB_888x_SkColorType, { MTLPixelFormatRGBA8Unorm }); 682 this->setColorType(kBGRA_8888_SkColorType, { MTLPixelFormatBGRA8Unorm }); 683 this->setColorType(kRGBA_1010102_SkColorType, { MTLPixelFormatRGB10A2Unorm }); 684 // kBGRA_1010102_SkColorType 685 // kRGB_101010x_SkColorType 686 // kBGR_101010x_SkColorType 687 // kBGR_101010x_XR_SkColorType 688 this->setColorType(kGray_8_SkColorType, { MTLPixelFormatR8Unorm }); 689 this->setColorType(kRGBA_F16Norm_SkColorType, { MTLPixelFormatRGBA16Float }); 690 this->setColorType(kRGBA_F16_SkColorType, { MTLPixelFormatRGBA16Float }); 691 // kRGBA_F32_SkColorType 692 this->setColorType(kR8G8_unorm_SkColorType, { MTLPixelFormatRG8Unorm }); 693 this->setColorType(kA16_float_SkColorType, { MTLPixelFormatR16Float }); 694 this->setColorType(kR16G16_float_SkColorType, { MTLPixelFormatRG16Float }); 695 this->setColorType(kA16_unorm_SkColorType, { MTLPixelFormatR16Unorm }); 696 this->setColorType(kR16G16_unorm_SkColorType, { MTLPixelFormatRG16Unorm }); 697 this->setColorType(kR16G16B16A16_unorm_SkColorType,{ MTLPixelFormatRGBA16Unorm }); 698 this->setColorType(kSRGBA_8888_SkColorType, { MTLPixelFormatRGBA8Unorm_sRGB }); 699 this->setColorType(kR8_unorm_SkColorType, { MTLPixelFormatR8Unorm }); 700 701} 702 703TextureInfo MtlCaps::getDefaultSampledTextureInfo(SkColorType colorType, 704 Mipmapped mipmapped, 705 Protected, 706 Renderable renderable) const { 707 MTLTextureUsage usage = MTLTextureUsageShaderRead; 708 if (renderable == Renderable::kYes) { 709 usage |= MTLTextureUsageRenderTarget; 710 } 711 712 MtlPixelFormat format = this->getFormatFromColorType(colorType); 713 if (format == MTLPixelFormatInvalid) { 714 return {}; 715 } 716 717 MtlTextureInfo info; 718 info.fSampleCount = 1; 719 info.fMipmapped = mipmapped; 720 info.fFormat = format; 721 info.fUsage = usage; 722 info.fStorageMode = MTLStorageModePrivate; 723 info.fFramebufferOnly = false; 724 725 return info; 726} 727 728TextureInfo MtlCaps::getTextureInfoForSampledCopy(const TextureInfo& textureInfo, 729 Mipmapped mipmapped) const { 730 MtlTextureInfo info; 731 if (!textureInfo.getMtlTextureInfo(&info)) { 732 return {}; 733 } 734 735 info.fSampleCount = 1; 736 info.fMipmapped = mipmapped; 737 info.fUsage = MTLTextureUsageShaderRead; 738 info.fStorageMode = MTLStorageModePrivate; 739 info.fFramebufferOnly = false; 740 741 return info; 742} 743 744namespace { 745MTLPixelFormat format_from_compression(SkTextureCompressionType compression) { 746 switch (compression) { 747 case SkTextureCompressionType::kETC2_RGB8_UNORM: 748 return kMTLPixelFormatETC2_RGB8; 749 case SkTextureCompressionType::kBC1_RGBA8_UNORM: 750#ifdef SK_BUILD_FOR_MAC 751 return MTLPixelFormatBC1_RGBA; 752#endif 753 default: 754 return MTLPixelFormatInvalid; 755 } 756} 757} 758 759TextureInfo MtlCaps::getDefaultCompressedTextureInfo(SkTextureCompressionType compression, 760 Mipmapped mipmapped, 761 Protected) const { 762 MTLTextureUsage usage = MTLTextureUsageShaderRead; 763 764 MtlPixelFormat format = format_from_compression(compression); 765 if (format == MTLPixelFormatInvalid) { 766 return {}; 767 } 768 769 MtlTextureInfo info; 770 info.fSampleCount = 1; 771 info.fMipmapped = mipmapped; 772 info.fFormat = format; 773 info.fUsage = usage; 774 info.fStorageMode = MTLStorageModePrivate; 775 info.fFramebufferOnly = false; 776 777 return info; 778} 779 780MTLStorageMode MtlCaps::getDefaultMSAAStorageMode(Discardable discardable) const { 781 // Try to use memoryless if it's available (only on new Apple silicon) 782 if (discardable == Discardable::kYes && this->isApple()) { 783 if (@available(macOS 11.0, iOS 10.0, tvOS 10.0, *)) { 784 return MTLStorageModeMemoryless; 785 } 786 } 787 // If it's not discardable or not available, private is the best option 788 return MTLStorageModePrivate; 789} 790 791TextureInfo MtlCaps::getDefaultMSAATextureInfo(const TextureInfo& singleSampledInfo, 792 Discardable discardable) const { 793 if (fDefaultMSAASamples <= 1) { 794 return {}; 795 } 796 const MtlTextureSpec& singleSpec = singleSampledInfo.mtlTextureSpec(); 797 if (!this->isRenderable((MTLPixelFormat)singleSpec.fFormat, fDefaultMSAASamples)) { 798 return {}; 799 } 800 801 MTLTextureUsage usage = MTLTextureUsageRenderTarget; 802 803 MtlTextureInfo info; 804 info.fSampleCount = fDefaultMSAASamples; 805 info.fMipmapped = Mipmapped::kNo; 806 info.fFormat = singleSpec.fFormat; 807 info.fUsage = usage; 808 info.fStorageMode = this->getDefaultMSAAStorageMode(discardable); 809 info.fFramebufferOnly = false; 810 811 return info; 812} 813 814MTLPixelFormat MtlCaps::getFormatFromDepthStencilFlags( 815 SkEnumBitMask<DepthStencilFlags> mask) const { 816 // TODO: Decide if we want to change this to always return a combined depth and stencil format 817 // to allow more sharing of depth stencil allocations. 818 if (mask == DepthStencilFlags::kDepth) { 819 // Graphite only needs 16-bits for depth values, so save some memory. If needed for 820 // workarounds, MTLPixelFormatDepth32Float is also available. 821 return MTLPixelFormatDepth16Unorm; 822 } else if (mask == DepthStencilFlags::kStencil) { 823 return MTLPixelFormatStencil8; 824 } else if (mask == DepthStencilFlags::kDepthStencil) { 825#if defined(SK_BUILD_FOR_MAC) 826 if (SkToBool(this->getFormatInfo(MTLPixelFormatDepth24Unorm_Stencil8).fFlags)) { 827 return MTLPixelFormatDepth24Unorm_Stencil8; 828 } 829#endif 830 return MTLPixelFormatDepth32Float_Stencil8; 831 } 832 SkASSERT(false); 833 return MTLPixelFormatInvalid; 834} 835 836TextureInfo MtlCaps::getDefaultDepthStencilTextureInfo( 837 SkEnumBitMask<DepthStencilFlags> depthStencilType, 838 uint32_t sampleCount, 839 Protected) const { 840 MtlTextureInfo info; 841 info.fSampleCount = sampleCount; 842 info.fMipmapped = Mipmapped::kNo; 843 info.fFormat = this->getFormatFromDepthStencilFlags(depthStencilType); 844 info.fUsage = MTLTextureUsageRenderTarget; 845 info.fStorageMode = this->getDefaultMSAAStorageMode(Discardable::kYes); 846 info.fFramebufferOnly = false; 847 848 return info; 849} 850 851TextureInfo MtlCaps::getDefaultStorageTextureInfo(SkColorType colorType) const { 852 // Storage textures are currently always sampleable from a shader. 853 MTLPixelFormat format = static_cast<MTLPixelFormat>(this->getFormatFromColorType(colorType)); 854 if (format == MTLPixelFormatInvalid) { 855 return {}; 856 } 857 858 const FormatInfo& formatInfo = this->getFormatInfo(format); 859 if (!SkToBool(FormatInfo::kStorage_Flag & formatInfo.fFlags)) { 860 return {}; 861 } 862 863 MTLTextureUsage usage = MTLTextureUsageShaderWrite | MTLTextureUsageShaderRead; 864 MtlTextureInfo info; 865 info.fSampleCount = 1; 866 info.fMipmapped = Mipmapped::kNo; 867 info.fFormat = format; 868 info.fUsage = usage; 869 info.fStorageMode = MTLStorageModePrivate; 870 info.fFramebufferOnly = false; 871 872 return info; 873} 874 875const Caps::ColorTypeInfo* MtlCaps::getColorTypeInfo( 876 SkColorType ct, const TextureInfo& textureInfo) const { 877 MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(textureInfo.mtlTextureSpec().fFormat); 878 if (mtlFormat == MTLPixelFormatInvalid) { 879 return nullptr; 880 } 881 882 const FormatInfo& info = this->getFormatInfo(mtlFormat); 883 for (int i = 0; i < info.fColorTypeInfoCount; ++i) { 884 const ColorTypeInfo& ctInfo = info.fColorTypeInfos[i]; 885 if (ctInfo.fColorType == ct) { 886 return &ctInfo; 887 } 888 } 889 890 return nullptr; 891} 892 893static const skgpu::UniqueKey::Domain kGraphicsPipelineDomain = UniqueKey::GenerateDomain(); 894static const int kGraphicsPipelineKeyData32Count = 5; 895 896UniqueKey MtlCaps::makeGraphicsPipelineKey(const GraphicsPipelineDesc& pipelineDesc, 897 const RenderPassDesc& renderPassDesc) const { 898 UniqueKey pipelineKey; 899 { 900 // 5 uint32_t's (render step id, paint id, uint64 renderpass desc, uint16 write swizzle key) 901 UniqueKey::Builder builder(&pipelineKey, kGraphicsPipelineDomain, 902 kGraphicsPipelineKeyData32Count, "GraphicsPipeline"); 903 // add GraphicsPipelineDesc key 904 builder[0] = pipelineDesc.renderStepID(); 905 builder[1] = pipelineDesc.paintParamsID().asUInt(); 906 907 // add RenderPassDesc key 908 uint64_t renderPassKey = this->getRenderPassDescKey(renderPassDesc); 909 builder[2] = renderPassKey & 0xFFFFFFFF; 910 builder[3] = (renderPassKey >> 32) & 0xFFFFFFFF; 911 builder[4] = renderPassDesc.fWriteSwizzle.asKey(); 912 913 builder.finish(); 914 } 915 916 return pipelineKey; 917} 918 919bool MtlCaps::extractGraphicsDescs(const UniqueKey& key, 920 GraphicsPipelineDesc* pipelineDesc, 921 RenderPassDesc* renderPassDesc, 922 const RendererProvider* rendererProvider) const { 923 struct UnpackedKeyData { 924 // From the GraphicsPipelineDesc 925 uint32_t fRenderStepID = 0; 926 UniquePaintParamsID fPaintParamsID; 927 928 // From the RenderPassDesc 929 MtlPixelFormat fColorFormat = 0; 930 uint32_t fColorSampleCount = 1; 931 932 MtlPixelFormat fDSFormat = 0; 933 uint32_t fDSSampleCount = 1; 934 935 Swizzle fWriteSwizzle; 936 } keyData; 937 938 SkASSERT(key.domain() == kGraphicsPipelineDomain); 939 SkASSERT(key.dataSize() == 4 * kGraphicsPipelineKeyData32Count); 940 941 const uint32_t* rawKeyData = key.data(); 942 943 keyData.fRenderStepID = rawKeyData[0]; 944 keyData.fPaintParamsID = rawKeyData[1] ? UniquePaintParamsID(rawKeyData[1]) 945 : UniquePaintParamsID::InvalidID(); 946 947 keyData.fDSFormat = static_cast<MtlPixelFormat>((rawKeyData[2] >> 16) & 0xFFFF); 948 keyData.fDSSampleCount = rawKeyData[2] & 0xFFFF; 949 950 keyData.fColorFormat = static_cast<MtlPixelFormat>((rawKeyData[3] >> 16) & 0xFFFF); 951 keyData.fColorSampleCount = rawKeyData[3] & 0xFFFF; 952 953 keyData.fWriteSwizzle = SwizzleCtorAccessor::Make(rawKeyData[4]); 954 955 // Recreate the RenderPassDesc 956 SkASSERT(keyData.fColorSampleCount == keyData.fDSSampleCount); 957 958 MTLPixelFormat dsFormat = (MTLPixelFormat) keyData.fDSFormat; 959 SkEnumBitMask<DepthStencilFlags> dsFlags = DepthStencilFlags::kNone; 960 if (MtlFormatIsDepth(dsFormat)) { 961 dsFlags |= DepthStencilFlags::kDepth; 962 } 963 if (MtlFormatIsStencil(dsFormat)) { 964 dsFlags |= DepthStencilFlags::kStencil; 965 } 966 967 MtlTextureInfo mtlInfo(keyData.fColorSampleCount, 968 skgpu::Mipmapped::kNo, 969 keyData.fColorFormat, 970 MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget, 971 MTLStorageModePrivate, 972 /* framebufferOnly= */ false); 973 TextureInfo info(mtlInfo); 974 975 *renderPassDesc = RenderPassDesc::Make(this, 976 info, 977 LoadOp::kClear, 978 StoreOp::kStore, 979 dsFlags, 980 /* clearColor= */ { .0f, .0f, .0f, .0f }, 981 /* requiresMSAA= */ keyData.fColorSampleCount > 1, 982 keyData.fWriteSwizzle); 983 984 // Recreate the GraphicsPipelineDesc 985 const RenderStep* renderStep = rendererProvider->lookup(keyData.fRenderStepID); 986 987 UniquePaintParamsID paintID = renderStep->performsShading() ? keyData.fPaintParamsID 988 : UniquePaintParamsID::InvalidID(); 989 990 *pipelineDesc = GraphicsPipelineDesc(renderStep, paintID); 991 992 return true; 993} 994 995uint64_t MtlCaps::getRenderPassDescKey(const RenderPassDesc& renderPassDesc) const { 996 MtlTextureInfo colorInfo, depthStencilInfo; 997 renderPassDesc.fColorAttachment.fTextureInfo.getMtlTextureInfo(&colorInfo); 998 renderPassDesc.fDepthStencilAttachment.fTextureInfo.getMtlTextureInfo(&depthStencilInfo); 999 SkASSERT(colorInfo.fFormat < 65535 && depthStencilInfo.fFormat < 65535); 1000 uint32_t colorAttachmentKey = colorInfo.fFormat << 16 | colorInfo.fSampleCount; 1001 uint32_t dsAttachmentKey = depthStencilInfo.fFormat << 16 | depthStencilInfo.fSampleCount; 1002 return (((uint64_t) colorAttachmentKey) << 32) | dsAttachmentKey; 1003} 1004 1005UniqueKey MtlCaps::makeComputePipelineKey(const ComputePipelineDesc& pipelineDesc) const { 1006 UniqueKey pipelineKey; 1007 { 1008 static const skgpu::UniqueKey::Domain kComputePipelineDomain = UniqueKey::GenerateDomain(); 1009 // The key is made up of a single uint32_t corresponding to the compute step ID. 1010 UniqueKey::Builder builder(&pipelineKey, kComputePipelineDomain, 1, "ComputePipeline"); 1011 builder[0] = pipelineDesc.computeStep()->uniqueID(); 1012 1013 // TODO(b/240615224): The local work group size should factor into the key on platforms 1014 // that don't support specialization constants and require the workgroup/threadgroup size to 1015 // be specified in the shader text (D3D12, Vulkan 1.0, and OpenGL). 1016 1017 builder.finish(); 1018 } 1019 return pipelineKey; 1020} 1021 1022uint32_t MtlCaps::channelMask(const TextureInfo& info) const { 1023 return skgpu::MtlFormatChannels((MTLPixelFormat)info.mtlTextureSpec().fFormat); 1024} 1025 1026bool MtlCaps::onIsTexturable(const TextureInfo& info) const { 1027 if (!info.isValid()) { 1028 return false; 1029 } 1030 if (!(info.mtlTextureSpec().fUsage & MTLTextureUsageShaderRead)) { 1031 return false; 1032 } 1033 if (info.mtlTextureSpec().fFramebufferOnly) { 1034 return false; 1035 } 1036 return this->isTexturable((MTLPixelFormat)info.mtlTextureSpec().fFormat); 1037} 1038 1039bool MtlCaps::isTexturable(MTLPixelFormat format) const { 1040 const FormatInfo& formatInfo = this->getFormatInfo(format); 1041 return SkToBool(FormatInfo::kTexturable_Flag & formatInfo.fFlags); 1042} 1043 1044bool MtlCaps::isRenderable(const TextureInfo& info) const { 1045 return info.isValid() && 1046 (info.mtlTextureSpec().fUsage & MTLTextureUsageRenderTarget) && 1047 this->isRenderable((MTLPixelFormat)info.mtlTextureSpec().fFormat, info.numSamples()); 1048} 1049 1050bool MtlCaps::isRenderable(MTLPixelFormat format, uint32_t sampleCount) const { 1051 return sampleCount <= this->maxRenderTargetSampleCount(format); 1052} 1053 1054bool MtlCaps::isStorage(const TextureInfo& info) const { 1055 if (!info.isValid()) { 1056 return false; 1057 } 1058 if (!(info.mtlTextureSpec().fUsage & MTLTextureUsageShaderWrite)) { 1059 return false; 1060 } 1061 if (info.mtlTextureSpec().fFramebufferOnly) { 1062 return false; 1063 } 1064 const FormatInfo& formatInfo = 1065 this->getFormatInfo((MTLPixelFormat)info.mtlTextureSpec().fFormat); 1066 return info.numSamples() == 1 && SkToBool(FormatInfo::kStorage_Flag & formatInfo.fFlags); 1067} 1068 1069uint32_t MtlCaps::maxRenderTargetSampleCount(MTLPixelFormat format) const { 1070 const FormatInfo& formatInfo = this->getFormatInfo(format); 1071 if (!SkToBool(formatInfo.fFlags & FormatInfo::kRenderable_Flag)) { 1072 return 0; 1073 } 1074 if (SkToBool(formatInfo.fFlags & FormatInfo::kMSAA_Flag)) { 1075 return fColorSampleCounts[fColorSampleCounts.size() - 1]; 1076 } else { 1077 return 1; 1078 } 1079} 1080 1081bool MtlCaps::supportsWritePixels(const TextureInfo& texInfo) const { 1082 MtlTextureInfo mtlInfo; 1083 texInfo.getMtlTextureInfo(&mtlInfo); 1084 if (mtlInfo.fFramebufferOnly) { 1085 return false; 1086 } 1087 1088 if (texInfo.numSamples() > 1) { 1089 return false; 1090 } 1091 1092 return true; 1093} 1094 1095bool MtlCaps::supportsReadPixels(const TextureInfo& texInfo) const { 1096 MtlTextureInfo mtlInfo; 1097 texInfo.getMtlTextureInfo(&mtlInfo); 1098 if (mtlInfo.fFramebufferOnly) { 1099 return false; 1100 } 1101 1102 // We disallow reading back directly from compressed textures. 1103 if (MtlFormatIsCompressed((MTLPixelFormat)mtlInfo.fFormat)) { 1104 return false; 1105 } 1106 1107 if (texInfo.numSamples() > 1) { 1108 return false; 1109 } 1110 1111 return true; 1112} 1113 1114std::pair<SkColorType, bool /*isRGBFormat*/> MtlCaps::supportedWritePixelsColorType( 1115 SkColorType dstColorType, 1116 const TextureInfo& dstTextureInfo, 1117 SkColorType srcColorType) const { 1118 MtlTextureInfo mtlInfo; 1119 dstTextureInfo.getMtlTextureInfo(&mtlInfo); 1120 1121 const FormatInfo& info = this->getFormatInfo((MTLPixelFormat)mtlInfo.fFormat); 1122 for (int i = 0; i < info.fColorTypeInfoCount; ++i) { 1123 const auto& ctInfo = info.fColorTypeInfos[i]; 1124 if (ctInfo.fColorType == dstColorType) { 1125 return {dstColorType, false}; 1126 } 1127 } 1128 return {kUnknown_SkColorType, false}; 1129} 1130 1131std::pair<SkColorType, bool /*isRGBFormat*/> MtlCaps::supportedReadPixelsColorType( 1132 SkColorType srcColorType, 1133 const TextureInfo& srcTextureInfo, 1134 SkColorType dstColorType) const { 1135 MtlTextureInfo mtlInfo; 1136 srcTextureInfo.getMtlTextureInfo(&mtlInfo); 1137 1138 // TODO: handle compressed formats 1139 if (MtlFormatIsCompressed((MTLPixelFormat)mtlInfo.fFormat)) { 1140 SkASSERT(this->isTexturable((MTLPixelFormat)mtlInfo.fFormat)); 1141 return {kUnknown_SkColorType, false}; 1142 } 1143 1144 const FormatInfo& info = this->getFormatInfo((MTLPixelFormat)mtlInfo.fFormat); 1145 for (int i = 0; i < info.fColorTypeInfoCount; ++i) { 1146 const auto& ctInfo = info.fColorTypeInfos[i]; 1147 if (ctInfo.fColorType == srcColorType) { 1148 return {srcColorType, false}; 1149 } 1150 } 1151 return {kUnknown_SkColorType, false}; 1152} 1153 1154void MtlCaps::buildKeyForTexture(SkISize dimensions, 1155 const TextureInfo& info, 1156 ResourceType type, 1157 Shareable shareable, 1158 GraphiteResourceKey* key) const { 1159 const MtlTextureSpec& mtlSpec = info.mtlTextureSpec(); 1160 1161 SkASSERT(!dimensions.isEmpty()); 1162 1163 // A MTLPixelFormat is an NSUInteger type which is documented to be 32 bits in 32 bit 1164 // applications and 64 bits in 64 bit applications. So it should fit in an uint64_t, but adding 1165 // the assert heere to make sure. 1166 static_assert(sizeof(MTLPixelFormat) <= sizeof(uint64_t)); 1167 SkASSERT(mtlSpec.fFormat != MTLPixelFormatInvalid); 1168 uint64_t formatKey = static_cast<uint64_t>(mtlSpec.fFormat); 1169 1170 uint32_t samplesKey = SamplesToKey(info.numSamples()); 1171 // We don't have to key the number of mip levels because it is inherit in the combination of 1172 // isMipped and dimensions. 1173 bool isMipped = info.mipmapped() == Mipmapped::kYes; 1174 Protected isProtected = info.isProtected(); 1175 bool isFBOnly = mtlSpec.fFramebufferOnly; 1176 1177 // Confirm all the below parts of the key can fit in a single uint32_t. The sum of the shift 1178 // amounts in the asserts must be less than or equal to 32. 1179 SkASSERT(samplesKey < (1u << 3)); 1180 SkASSERT(static_cast<uint32_t>(isMipped) < (1u << 1)); 1181 SkASSERT(static_cast<uint32_t>(isProtected) < (1u << 1)); 1182 SkASSERT(mtlSpec.fUsage < (1u << 5)); 1183 SkASSERT(mtlSpec.fStorageMode < (1u << 2)); 1184 SkASSERT(static_cast<uint32_t>(isFBOnly) < (1u << 1)); 1185 1186 // We need two uint32_ts for dimensions, 2 for format, and 1 for the rest of the key; 1187 static int kNum32DataCnt = 2 + 2 + 1; 1188 1189 GraphiteResourceKey::Builder builder(key, type, kNum32DataCnt, shareable); 1190 1191 builder[0] = dimensions.width(); 1192 builder[1] = dimensions.height(); 1193 builder[2] = formatKey & 0xFFFFFFFF; 1194 builder[3] = (formatKey >> 32) & 0xFFFFFFFF; 1195 builder[4] = (samplesKey << 0) | 1196 (static_cast<uint32_t>(isMipped) << 3) | 1197 (static_cast<uint32_t>(isProtected) << 4) | 1198 (static_cast<uint32_t>(mtlSpec.fUsage) << 5) | 1199 (static_cast<uint32_t>(mtlSpec.fStorageMode) << 10)| 1200 (static_cast<uint32_t>(isFBOnly) << 12); 1201 1202} 1203 1204} // namespace skgpu::graphite 1205