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