1/* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "src/gpu/ganesh/mtl/GrMtlUtil.h" 9 10#include "include/gpu/GrBackendSurface.h" 11#include "include/private/base/SkMutex.h" 12#include "include/private/gpu/ganesh/GrTypesPriv.h" 13#include "src/core/SkTraceEvent.h" 14#include "src/gpu/ganesh/GrSurface.h" 15#include "src/gpu/ganesh/mtl/GrMtlGpu.h" 16#include "src/gpu/ganesh/mtl/GrMtlRenderTarget.h" 17#include "src/gpu/ganesh/mtl/GrMtlTexture.h" 18#include "src/sksl/SkSLCompiler.h" 19#include "src/sksl/SkSLProgramSettings.h" 20#include "src/utils/SkShaderUtils.h" 21 22#import <Metal/Metal.h> 23#ifdef SK_BUILD_FOR_IOS 24#import <UIKit/UIApplication.h> 25#endif 26 27#if !__has_feature(objc_arc) 28#error This file must be compiled with Arc. Use -fobjc-arc flag 29#endif 30 31GR_NORETAIN_BEGIN 32 33NSError* GrCreateMtlError(NSString* description, GrMtlErrorCode errorCode) { 34 NSDictionary* userInfo = [NSDictionary dictionaryWithObject:description 35 forKey:NSLocalizedDescriptionKey]; 36 return [NSError errorWithDomain:@"org.skia.ganesh" 37 code:(NSInteger)errorCode 38 userInfo:userInfo]; 39} 40 41MTLTextureDescriptor* GrGetMTLTextureDescriptor(id<MTLTexture> mtlTexture) { 42 MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init]; 43 texDesc.textureType = mtlTexture.textureType; 44 texDesc.pixelFormat = mtlTexture.pixelFormat; 45 texDesc.width = mtlTexture.width; 46 texDesc.height = mtlTexture.height; 47 texDesc.depth = mtlTexture.depth; 48 texDesc.mipmapLevelCount = mtlTexture.mipmapLevelCount; 49 texDesc.arrayLength = mtlTexture.arrayLength; 50 texDesc.sampleCount = mtlTexture.sampleCount; 51 if (@available(macOS 10.11, iOS 9.0, *)) { 52 texDesc.usage = mtlTexture.usage; 53 } 54 return texDesc; 55} 56 57// Print the source code for all shaders generated. 58static const bool gPrintSKSL = false; 59static const bool gPrintMSL = false; 60 61bool GrSkSLToMSL(const GrMtlGpu* gpu, 62 const std::string& sksl, 63 SkSL::ProgramKind programKind, 64 const SkSL::ProgramSettings& settings, 65 std::string* msl, 66 SkSL::Program::Inputs* outInputs, 67 GrContextOptions::ShaderErrorHandler* errorHandler) { 68#ifdef SK_DEBUG 69 std::string src = SkShaderUtils::PrettyPrint(sksl); 70#else 71 const std::string& src = sksl; 72#endif 73 SkSL::Compiler* compiler = gpu->shaderCompiler(); 74 std::unique_ptr<SkSL::Program> program = 75 gpu->shaderCompiler()->convertProgram(programKind, 76 src, 77 settings); 78 if (!program || !compiler->toMetal(*program, msl)) { 79 errorHandler->compileError(src.c_str(), compiler->errorText().c_str()); 80 return false; 81 } 82 83 if (gPrintSKSL || gPrintMSL) { 84 SkShaderUtils::PrintShaderBanner(programKind); 85 if (gPrintSKSL) { 86 SkDebugf("SKSL:\n"); 87 SkShaderUtils::PrintLineByLine(SkShaderUtils::PrettyPrint(sksl)); 88 } 89 if (gPrintMSL) { 90 SkDebugf("MSL:\n"); 91 SkShaderUtils::PrintLineByLine(SkShaderUtils::PrettyPrint(*msl)); 92 } 93 } 94 95 *outInputs = program->fInputs; 96 return true; 97} 98 99id<MTLLibrary> GrCompileMtlShaderLibrary(const GrMtlGpu* gpu, 100 const std::string& msl, 101 GrContextOptions::ShaderErrorHandler* errorHandler) { 102 TRACE_EVENT0("skia.shaders", "driver_compile_shader"); 103 NSString* nsSource = [[NSString alloc] initWithBytesNoCopy:const_cast<char*>(msl.c_str()) 104 length:msl.size() 105 encoding:NSUTF8StringEncoding 106 freeWhenDone:NO]; 107 if (!nsSource) { 108 return nil; 109 } 110 MTLCompileOptions* options = [[MTLCompileOptions alloc] init]; 111 // array<> is supported in MSL 2.0 on MacOS 10.13+ and iOS 11+, 112 // and in MSL 1.2 on iOS 10+ (but not MacOS). 113 if (@available(macOS 10.13, iOS 11.0, *)) { 114 options.languageVersion = MTLLanguageVersion2_0; 115#if defined(SK_BUILD_FOR_IOS) 116 } else if (@available(macOS 10.12, iOS 10.0, *)) { 117 options.languageVersion = MTLLanguageVersion1_2; 118#endif 119 } 120 options.fastMathEnabled = YES; 121 122 NSError* error = nil; 123 id<MTLLibrary> compiledLibrary; 124 if (@available(macOS 10.15, *)) { 125 compiledLibrary = [gpu->device() newLibraryWithSource:(NSString* _Nonnull)nsSource 126 options:options 127 error:&error]; 128 } else { 129 compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), (NSString* _Nonnull)nsSource, 130 options, &error); 131 } 132 if (!compiledLibrary) { 133 errorHandler->compileError(msl.c_str(), error.debugDescription.UTF8String); 134 return nil; 135 } 136 137 return compiledLibrary; 138} 139 140void GrPrecompileMtlShaderLibrary(const GrMtlGpu* gpu, 141 const std::string& msl) { 142 NSString* nsSource = [[NSString alloc] initWithBytesNoCopy:const_cast<char*>(msl.c_str()) 143 length:msl.size() 144 encoding:NSUTF8StringEncoding 145 freeWhenDone:NO]; 146 if (!nsSource) { 147 return; 148 } 149 // Do nothing after completion for now. 150 // TODO: cache the result somewhere so we can use it later. 151 MTLNewLibraryCompletionHandler completionHandler = ^(id<MTLLibrary> library, NSError* error) {}; 152 [gpu->device() newLibraryWithSource:(NSString* _Nonnull)nsSource 153 options:nil 154 completionHandler:completionHandler]; 155} 156 157// Wrapper to get atomic assignment for compiles and pipeline creation 158class MtlCompileResult : public SkRefCnt { 159public: 160 MtlCompileResult() : fCompiledObject(nil), fError(nil) {} 161 void set(id compiledObject, NSError* error) { 162 SkAutoMutexExclusive automutex(fMutex); 163 fCompiledObject = compiledObject; 164 fError = error; 165 } 166 std::pair<id, NSError*> get() { 167 SkAutoMutexExclusive automutex(fMutex); 168 return std::make_pair(fCompiledObject, fError); 169 } 170private: 171 SkMutex fMutex; 172 id fCompiledObject SK_GUARDED_BY(fMutex); 173 NSError* fError SK_GUARDED_BY(fMutex); 174}; 175 176id<MTLLibrary> GrMtlNewLibraryWithSource(id<MTLDevice> device, NSString* mslCode, 177 MTLCompileOptions* options, NSError** error) { 178 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 179 sk_sp<MtlCompileResult> compileResult(new MtlCompileResult); 180 // We have to increment the ref for the Obj-C block manually because it won't do it for us 181 compileResult->ref(); 182 MTLNewLibraryCompletionHandler completionHandler = 183 ^(id<MTLLibrary> library, NSError* compileError) { 184 compileResult->set(library, compileError); 185 dispatch_semaphore_signal(semaphore); 186 compileResult->unref(); 187 }; 188 189 [device newLibraryWithSource: mslCode 190 options: options 191 completionHandler: completionHandler]; 192 193 // Wait 1 second for the compiler 194 constexpr auto kTimeoutNS = 1000000000UL; 195 if (dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, kTimeoutNS))) { 196 if (error) { 197 constexpr auto kTimeoutMS = kTimeoutNS/1000000UL; 198 NSString* description = 199 [NSString stringWithFormat:@"Compilation took longer than %lu ms", 200 kTimeoutMS]; 201 *error = GrCreateMtlError(description, GrMtlErrorCode::kTimeout); 202 } 203 return nil; 204 } 205 206 id<MTLLibrary> compiledLibrary; 207 std::tie(compiledLibrary, *error) = compileResult->get(); 208 209 return compiledLibrary; 210} 211 212id<MTLRenderPipelineState> GrMtlNewRenderPipelineStateWithDescriptor( 213 id<MTLDevice> device, MTLRenderPipelineDescriptor* pipelineDescriptor, NSError** error) { 214 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 215 sk_sp<MtlCompileResult> compileResult(new MtlCompileResult); 216 // We have to increment the ref for the Obj-C block manually because it won't do it for us 217 compileResult->ref(); 218 MTLNewRenderPipelineStateCompletionHandler completionHandler = 219 ^(id<MTLRenderPipelineState> state, NSError* compileError) { 220 compileResult->set(state, compileError); 221 dispatch_semaphore_signal(semaphore); 222 compileResult->unref(); 223 }; 224 225 [device newRenderPipelineStateWithDescriptor: pipelineDescriptor 226 completionHandler: completionHandler]; 227 228 // Wait 1 second for pipeline creation 229 constexpr auto kTimeoutNS = 1000000000UL; 230 if (dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, kTimeoutNS))) { 231 if (error) { 232 constexpr auto kTimeoutMS = kTimeoutNS/1000000UL; 233 NSString* description = 234 [NSString stringWithFormat:@"Pipeline creation took longer than %lu ms", 235 kTimeoutMS]; 236 *error = GrCreateMtlError(description, GrMtlErrorCode::kTimeout); 237 } 238 return nil; 239 } 240 241 id<MTLRenderPipelineState> pipelineState; 242 std::tie(pipelineState, *error) = compileResult->get(); 243 244 return pipelineState; 245} 246 247id<MTLTexture> GrGetMTLTextureFromSurface(GrSurface* surface) { 248 id<MTLTexture> mtlTexture = nil; 249 250 GrMtlRenderTarget* renderTarget = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget()); 251 GrMtlTexture* texture; 252 if (renderTarget) { 253 // We should not be using this for multisampled rendertargets with a separate resolve 254 // texture. 255 if (renderTarget->resolveAttachment()) { 256 SkASSERT(renderTarget->numSamples() > 1); 257 SkASSERT(false); 258 return nil; 259 } 260 mtlTexture = renderTarget->colorMTLTexture(); 261 } else { 262 texture = static_cast<GrMtlTexture*>(surface->asTexture()); 263 if (texture) { 264 mtlTexture = texture->mtlTexture(); 265 } 266 } 267 return mtlTexture; 268} 269 270 271////////////////////////////////////////////////////////////////////////////// 272// CPP Utils 273 274GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo& info) { 275 id<MTLTexture> GR_NORETAIN mtlTexture = GrGetMTLTexture(info.fTexture.get()); 276 return static_cast<GrMTLPixelFormat>(mtlTexture.pixelFormat); 277} 278 279uint32_t GrMtlFormatChannels(GrMTLPixelFormat mtlFormat) { 280 switch (mtlFormat) { 281 case MTLPixelFormatRGBA8Unorm: return kRGBA_SkColorChannelFlags; 282 case MTLPixelFormatR8Unorm: return kRed_SkColorChannelFlag; 283 case MTLPixelFormatA8Unorm: return kAlpha_SkColorChannelFlag; 284 case MTLPixelFormatBGRA8Unorm: return kRGBA_SkColorChannelFlags; 285 case MTLPixelFormatB5G6R5Unorm: return kRGB_SkColorChannelFlags; 286 case MTLPixelFormatRGBA16Float: return kRGBA_SkColorChannelFlags; 287 case MTLPixelFormatR16Float: return kRed_SkColorChannelFlag; 288 case MTLPixelFormatRG8Unorm: return kRG_SkColorChannelFlags; 289 case MTLPixelFormatRGB10A2Unorm: return kRGBA_SkColorChannelFlags; 290 case MTLPixelFormatBGR10A2Unorm: return kRGBA_SkColorChannelFlags; 291 case MTLPixelFormatABGR4Unorm: return kRGBA_SkColorChannelFlags; 292 case MTLPixelFormatRGBA8Unorm_sRGB: return kRGBA_SkColorChannelFlags; 293 case MTLPixelFormatR16Unorm: return kRed_SkColorChannelFlag; 294 case MTLPixelFormatRG16Unorm: return kRG_SkColorChannelFlags; 295 case MTLPixelFormatETC2_RGB8: return kRGB_SkColorChannelFlags; 296#ifdef SK_BUILD_FOR_MAC 297 case MTLPixelFormatBC1_RGBA: return kRGBA_SkColorChannelFlags; 298#endif 299 case MTLPixelFormatRGBA16Unorm: return kRGBA_SkColorChannelFlags; 300 case MTLPixelFormatRG16Float: return kRG_SkColorChannelFlags; 301 case MTLPixelFormatStencil8: return 0; 302 303 default: return 0; 304 } 305} 306 307GrColorFormatDesc GrMtlFormatDesc(GrMTLPixelFormat mtlFormat) { 308 switch (mtlFormat) { 309 case MTLPixelFormatRGBA8Unorm: 310 return GrColorFormatDesc::MakeRGBA(8, GrColorTypeEncoding::kUnorm); 311 case MTLPixelFormatR8Unorm: 312 return GrColorFormatDesc::MakeR(8, GrColorTypeEncoding::kUnorm); 313 case MTLPixelFormatA8Unorm: 314 return GrColorFormatDesc::MakeAlpha(8, GrColorTypeEncoding::kUnorm); 315 case MTLPixelFormatBGRA8Unorm: 316 return GrColorFormatDesc::MakeRGBA(8, GrColorTypeEncoding::kUnorm); 317 case MTLPixelFormatB5G6R5Unorm: 318 return GrColorFormatDesc::MakeRGB(5, 6, 5, GrColorTypeEncoding::kUnorm); 319 case MTLPixelFormatRGBA16Float: 320 return GrColorFormatDesc::MakeRGBA(16, GrColorTypeEncoding::kFloat); 321 case MTLPixelFormatR16Float: 322 return GrColorFormatDesc::MakeR(16, GrColorTypeEncoding::kFloat); 323 case MTLPixelFormatRG8Unorm: 324 return GrColorFormatDesc::MakeRG(8, GrColorTypeEncoding::kUnorm); 325 case MTLPixelFormatRGB10A2Unorm: 326 return GrColorFormatDesc::MakeRGBA(10, 2, GrColorTypeEncoding::kUnorm); 327 case MTLPixelFormatBGR10A2Unorm: 328 return GrColorFormatDesc::MakeRGBA(10, 2, GrColorTypeEncoding::kUnorm); 329 case MTLPixelFormatABGR4Unorm: 330 return GrColorFormatDesc::MakeRGBA(4, GrColorTypeEncoding::kUnorm); 331 case MTLPixelFormatRGBA8Unorm_sRGB: 332 return GrColorFormatDesc::MakeRGBA(8, GrColorTypeEncoding::kSRGBUnorm); 333 case MTLPixelFormatR16Unorm: 334 return GrColorFormatDesc::MakeR(16, GrColorTypeEncoding::kUnorm); 335 case MTLPixelFormatRG16Unorm: 336 return GrColorFormatDesc::MakeRG(16, GrColorTypeEncoding::kUnorm); 337 case MTLPixelFormatRGBA16Unorm: 338 return GrColorFormatDesc::MakeRGBA(16, GrColorTypeEncoding::kUnorm); 339 case MTLPixelFormatRG16Float: 340 return GrColorFormatDesc::MakeRG(16, GrColorTypeEncoding::kFloat); 341 342 // Compressed texture formats are not expected to have a description. 343 case MTLPixelFormatETC2_RGB8: return GrColorFormatDesc::MakeInvalid(); 344#ifdef SK_BUILD_FOR_MAC 345 case MTLPixelFormatBC1_RGBA: return GrColorFormatDesc::MakeInvalid(); 346#endif 347 348 // This type only describes color channels. 349 case MTLPixelFormatStencil8: return GrColorFormatDesc::MakeInvalid(); 350 351 default: 352 return GrColorFormatDesc::MakeInvalid(); 353 } 354} 355 356SkImage::CompressionType GrMtlBackendFormatToCompressionType(const GrBackendFormat& format) { 357 MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); 358 return GrMtlFormatToCompressionType(mtlFormat); 359} 360 361bool GrMtlFormatIsCompressed(MTLPixelFormat mtlFormat) { 362 switch (mtlFormat) { 363 case MTLPixelFormatETC2_RGB8: 364 return true; 365#ifdef SK_BUILD_FOR_MAC 366 case MTLPixelFormatBC1_RGBA: 367 return true; 368#endif 369 default: 370 return false; 371 } 372} 373 374SkImage::CompressionType GrMtlFormatToCompressionType(MTLPixelFormat mtlFormat) { 375 switch (mtlFormat) { 376 case MTLPixelFormatETC2_RGB8: return SkImage::CompressionType::kETC2_RGB8_UNORM; 377#ifdef SK_BUILD_FOR_MAC 378 case MTLPixelFormatBC1_RGBA: return SkImage::CompressionType::kBC1_RGBA8_UNORM; 379#endif 380 default: return SkImage::CompressionType::kNone; 381 } 382 383 SkUNREACHABLE; 384} 385 386int GrMtlTextureInfoSampleCount(const GrMtlTextureInfo& info) { 387 id<MTLTexture> texture = GrGetMTLTexture(info.fTexture.get()); 388 if (!texture) { 389 return 0; 390 } 391 return texture.sampleCount; 392} 393 394size_t GrMtlBackendFormatBytesPerBlock(const GrBackendFormat& format) { 395 MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); 396 return GrMtlFormatBytesPerBlock(mtlFormat); 397} 398 399size_t GrMtlFormatBytesPerBlock(MTLPixelFormat mtlFormat) { 400 switch (mtlFormat) { 401 case MTLPixelFormatInvalid: return 0; 402 case MTLPixelFormatRGBA8Unorm: return 4; 403 case MTLPixelFormatR8Unorm: return 1; 404 case MTLPixelFormatA8Unorm: return 1; 405 case MTLPixelFormatBGRA8Unorm: return 4; 406 case MTLPixelFormatB5G6R5Unorm: return 2; 407 case MTLPixelFormatRGBA16Float: return 8; 408 case MTLPixelFormatR16Float: return 2; 409 case MTLPixelFormatRG8Unorm: return 2; 410 case MTLPixelFormatRGB10A2Unorm: return 4; 411 case MTLPixelFormatBGR10A2Unorm: return 4; 412 case MTLPixelFormatABGR4Unorm: return 2; 413 case MTLPixelFormatRGBA8Unorm_sRGB: return 4; 414 case MTLPixelFormatR16Unorm: return 2; 415 case MTLPixelFormatRG16Unorm: return 4; 416 case MTLPixelFormatETC2_RGB8: return 8; 417#ifdef SK_BUILD_FOR_MAC 418 case MTLPixelFormatBC1_RGBA: return 8; 419#endif 420 case MTLPixelFormatRGBA16Unorm: return 8; 421 case MTLPixelFormatRG16Float: return 4; 422 case MTLPixelFormatStencil8: return 1; 423 424 default: return 0; 425 } 426} 427 428int GrMtlBackendFormatStencilBits(const GrBackendFormat& format) { 429 MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); 430 return GrMtlFormatStencilBits(mtlFormat); 431} 432 433int GrMtlFormatStencilBits(MTLPixelFormat mtlFormat) { 434 switch(mtlFormat) { 435 case MTLPixelFormatStencil8: 436 return 8; 437 default: 438 return 0; 439 } 440} 441 442#ifdef SK_BUILD_FOR_IOS 443bool GrMtlIsAppInBackground() { 444 return [NSThread isMainThread] && 445 ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground); 446} 447#endif 448 449#if defined(SK_DEBUG) || GR_TEST_UTILS 450bool GrMtlFormatIsBGRA8(GrMTLPixelFormat mtlFormat) { 451 return mtlFormat == MTLPixelFormatBGRA8Unorm; 452} 453 454const char* GrMtlFormatToStr(GrMTLPixelFormat mtlFormat) { 455 switch (mtlFormat) { 456 case MTLPixelFormatInvalid: return "Invalid"; 457 case MTLPixelFormatRGBA8Unorm: return "RGBA8Unorm"; 458 case MTLPixelFormatR8Unorm: return "R8Unorm"; 459 case MTLPixelFormatA8Unorm: return "A8Unorm"; 460 case MTLPixelFormatBGRA8Unorm: return "BGRA8Unorm"; 461 case MTLPixelFormatB5G6R5Unorm: return "B5G6R5Unorm"; 462 case MTLPixelFormatRGBA16Float: return "RGBA16Float"; 463 case MTLPixelFormatR16Float: return "R16Float"; 464 case MTLPixelFormatRG8Unorm: return "RG8Unorm"; 465 case MTLPixelFormatRGB10A2Unorm: return "RGB10A2Unorm"; 466 case MTLPixelFormatBGR10A2Unorm: return "BGR10A2Unorm"; 467 case MTLPixelFormatABGR4Unorm: return "ABGR4Unorm"; 468 case MTLPixelFormatRGBA8Unorm_sRGB: return "RGBA8Unorm_sRGB"; 469 case MTLPixelFormatR16Unorm: return "R16Unorm"; 470 case MTLPixelFormatRG16Unorm: return "RG16Unorm"; 471 case MTLPixelFormatETC2_RGB8: return "ETC2_RGB8"; 472#ifdef SK_BUILD_FOR_MAC 473 case MTLPixelFormatBC1_RGBA: return "BC1_RGBA"; 474#endif 475 case MTLPixelFormatRGBA16Unorm: return "RGBA16Unorm"; 476 case MTLPixelFormatRG16Float: return "RG16Float"; 477 case MTLPixelFormatStencil8: return "Stencil8"; 478 479 default: return "Unknown"; 480 } 481} 482 483#endif 484 485GR_NORETAIN_END 486