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