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