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/mtl/GrMtlUtil.h" 9 10#include "include/gpu/GrSurface.h" 11#include "include/private/GrTypesPriv.h" 12#include "src/gpu/mtl/GrMtlGpu.h" 13#include "src/gpu/mtl/GrMtlRenderTarget.h" 14#include "src/gpu/mtl/GrMtlTexture.h" 15#include "src/sksl/SkSLCompiler.h" 16 17#import <Metal/Metal.h> 18 19#if !__has_feature(objc_arc) 20#error This file must be compiled with Arc. Use -fobjc-arc flag 21#endif 22 23#define PRINT_MSL 0 // print out the MSL code generated 24 25bool GrPixelConfigToMTLFormat(GrPixelConfig config, MTLPixelFormat* format) { 26 MTLPixelFormat dontCare; 27 if (!format) { 28 format = &dontCare; 29 } 30 31 switch (config) { 32 case kUnknown_GrPixelConfig: 33 return false; 34 case kRGBA_8888_GrPixelConfig: 35 *format = MTLPixelFormatRGBA8Unorm; 36 return true; 37 case kRGB_888_GrPixelConfig: 38 *format = MTLPixelFormatRGBA8Unorm; 39 return true; 40 case kRGB_888X_GrPixelConfig: 41 *format = MTLPixelFormatRGBA8Unorm; 42 return true; 43 case kRG_88_GrPixelConfig: 44 *format = MTLPixelFormatRG8Unorm; 45 return true; 46 case kBGRA_8888_GrPixelConfig: 47 *format = MTLPixelFormatBGRA8Unorm; 48 return true; 49 case kSRGBA_8888_GrPixelConfig: 50 *format = MTLPixelFormatRGBA8Unorm_sRGB; 51 return true; 52 case kRGBA_1010102_GrPixelConfig: 53 *format = MTLPixelFormatRGB10A2Unorm; 54 return true; 55 case kRGB_565_GrPixelConfig: 56#ifdef SK_BUILD_FOR_IOS 57 *format = MTLPixelFormatB5G6R5Unorm; 58 return true; 59#else 60 return false; 61#endif 62 case kRGBA_4444_GrPixelConfig: 63#ifdef SK_BUILD_FOR_IOS 64 *format = MTLPixelFormatABGR4Unorm; 65 return true; 66#else 67 return false; 68#endif 69 case kAlpha_8_GrPixelConfig: // fall through 70 case kAlpha_8_as_Red_GrPixelConfig: 71 *format = MTLPixelFormatR8Unorm; 72 return true; 73 case kAlpha_8_as_Alpha_GrPixelConfig: 74 *format = MTLPixelFormatA8Unorm; 75 return true; 76 case kGray_8_GrPixelConfig: // fall through 77 case kGray_8_as_Red_GrPixelConfig: 78 *format = MTLPixelFormatR8Unorm; 79 return true; 80 case kGray_8_as_Lum_GrPixelConfig: 81 return false; 82 case kRGBA_float_GrPixelConfig: 83 *format = MTLPixelFormatRGBA32Float; 84 return true; 85 case kRGBA_half_GrPixelConfig: 86 *format = MTLPixelFormatRGBA16Float; 87 return true; 88 case kRGBA_half_Clamped_GrPixelConfig: 89 *format = MTLPixelFormatRGBA16Float; 90 return true; 91 case kAlpha_half_GrPixelConfig: // fall through 92 case kAlpha_half_as_Red_GrPixelConfig: 93 *format = MTLPixelFormatR16Float; 94 return true; 95 case kAlpha_half_as_Lum_GrPixelConfig: 96 return false; 97 case kRGB_ETC1_GrPixelConfig: 98#ifdef SK_BUILD_FOR_IOS 99 *format = MTLPixelFormatETC2_RGB8; 100 return true; 101#else 102 return false; 103#endif 104 case kR_16_GrPixelConfig: 105 *format = MTLPixelFormatR16Unorm; 106 return true; 107 case kRG_1616_GrPixelConfig: 108 *format = MTLPixelFormatRG16Unorm; 109 return true; 110 111 // Experimental (for Y416 and mutant P016/P010) 112 case kRGBA_16161616_GrPixelConfig: 113 *format = MTLPixelFormatRGBA16Unorm; 114 return true; 115 case kRG_half_GrPixelConfig: 116 *format = MTLPixelFormatRG16Float; 117 return true; 118 } 119 SK_ABORT("Unexpected config"); 120} 121 122MTLTextureDescriptor* GrGetMTLTextureDescriptor(id<MTLTexture> mtlTexture) { 123 MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init]; 124 texDesc.textureType = mtlTexture.textureType; 125 texDesc.pixelFormat = mtlTexture.pixelFormat; 126 texDesc.width = mtlTexture.width; 127 texDesc.height = mtlTexture.height; 128 texDesc.depth = mtlTexture.depth; 129 texDesc.mipmapLevelCount = mtlTexture.mipmapLevelCount; 130 texDesc.arrayLength = mtlTexture.arrayLength; 131 texDesc.sampleCount = mtlTexture.sampleCount; 132 texDesc.usage = mtlTexture.usage; 133 return texDesc; 134} 135 136#if PRINT_MSL 137void print_msl(const char* source) { 138 SkTArray<SkString> lines; 139 SkStrSplit(source, "\n", kStrict_SkStrSplitMode, &lines); 140 for (int i = 0; i < lines.count(); i++) { 141 SkString& line = lines[i]; 142 line.prependf("%4i\t", i + 1); 143 SkDebugf("%s\n", line.c_str()); 144 } 145} 146#endif 147 148id<MTLLibrary> GrCompileMtlShaderLibrary(const GrMtlGpu* gpu, 149 const char* shaderString, 150 SkSL::Program::Kind kind, 151 const SkSL::Program::Settings& settings, 152 SkSL::Program::Inputs* outInputs) { 153 std::unique_ptr<SkSL::Program> program = 154 gpu->shaderCompiler()->convertProgram(kind, 155 SkSL::String(shaderString), 156 settings); 157 158 if (!program) { 159 SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str()); 160 SkASSERT(false); 161 return nil; 162 } 163 164 *outInputs = program->fInputs; 165 SkSL::String code; 166 if (!gpu->shaderCompiler()->toMetal(*program, &code)) { 167 SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str()); 168 SkASSERT(false); 169 return nil; 170 } 171 NSString* mtlCode = [[NSString alloc] initWithCString: code.c_str() 172 encoding: NSASCIIStringEncoding]; 173#if PRINT_MSL 174 print_msl([mtlCode cStringUsingEncoding: NSASCIIStringEncoding]); 175#endif 176 177 MTLCompileOptions* defaultOptions = [[MTLCompileOptions alloc] init]; 178#if defined(SK_BUILD_FOR_MAC) && defined(GR_USE_COMPLETION_HANDLER) 179 bool timedout; 180 id<MTLLibrary> compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), mtlCode, 181 defaultOptions, &timedout); 182 if (timedout) { 183 // try again 184 compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), mtlCode, 185 defaultOptions, &timedout); 186 } 187#else 188 NSError* error = nil; 189 id<MTLLibrary> compiledLibrary = [gpu->device() newLibraryWithSource: mtlCode 190 options: defaultOptions 191 error: &error]; 192 if (error) { 193 SkDebugf("Error compiling MSL shader: %s\n%s\n", 194 code.c_str(), 195 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]); 196 return nil; 197 } 198#endif 199 return compiledLibrary; 200} 201 202id<MTLLibrary> GrMtlNewLibraryWithSource(id<MTLDevice> device, NSString* mslCode, 203 MTLCompileOptions* options, bool* timedout) { 204 dispatch_semaphore_t compilerSemaphore = dispatch_semaphore_create(0); 205 206 __block dispatch_semaphore_t semaphore = compilerSemaphore; 207 __block id<MTLLibrary> compiledLibrary; 208 [device newLibraryWithSource: mslCode 209 options: options 210 completionHandler: 211 ^(id<MTLLibrary> library, NSError* error) { 212 if (error) { 213 SkDebugf("Error compiling MSL shader: %s\n%s\n", 214 mslCode, 215 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]); 216 } 217 compiledLibrary = library; 218 dispatch_semaphore_signal(semaphore); 219 } 220 ]; 221 222 // Wait 100 ms for the compiler 223 if (dispatch_semaphore_wait(compilerSemaphore, dispatch_time(DISPATCH_TIME_NOW, 100000))) { 224 SkDebugf("Timeout compiling MSL shader\n"); 225 *timedout = true; 226 return nil; 227 } 228 229 *timedout = false; 230 return compiledLibrary; 231} 232 233id<MTLRenderPipelineState> GrMtlNewRenderPipelineStateWithDescriptor( 234 id<MTLDevice> device, MTLRenderPipelineDescriptor* pipelineDescriptor, bool* timedout) { 235 dispatch_semaphore_t pipelineSemaphore = dispatch_semaphore_create(0); 236 237 __block dispatch_semaphore_t semaphore = pipelineSemaphore; 238 __block id<MTLRenderPipelineState> pipelineState; 239 [device newRenderPipelineStateWithDescriptor: pipelineDescriptor 240 completionHandler: 241 ^(id<MTLRenderPipelineState> state, NSError* error) { 242 if (error) { 243 SkDebugf("Error creating pipeline: %s\n", 244 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]); 245 } 246 pipelineState = state; 247 dispatch_semaphore_signal(semaphore); 248 } 249 ]; 250 251 // Wait 500 ms for pipeline creation 252 if (dispatch_semaphore_wait(pipelineSemaphore, dispatch_time(DISPATCH_TIME_NOW, 500000))) { 253 SkDebugf("Timeout creating pipeline.\n"); 254 *timedout = true; 255 return nil; 256 } 257 258 *timedout = false; 259 return pipelineState; 260} 261 262id<MTLTexture> GrGetMTLTextureFromSurface(GrSurface* surface) { 263 id<MTLTexture> mtlTexture = nil; 264 265 GrMtlRenderTarget* renderTarget = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget()); 266 GrMtlTexture* texture; 267 if (renderTarget) { 268 // We should not be using this for multisampled rendertargets 269 if (renderTarget->numSamples() > 1) { 270 SkASSERT(false); 271 return nil; 272 } 273 mtlTexture = renderTarget->mtlColorTexture(); 274 } else { 275 texture = static_cast<GrMtlTexture*>(surface->asTexture()); 276 if (texture) { 277 mtlTexture = texture->mtlTexture(); 278 } 279 } 280 return mtlTexture; 281} 282 283 284////////////////////////////////////////////////////////////////////////////// 285// CPP Utils 286 287GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo& info) { 288 id<MTLTexture> mtlTexture = GrGetMTLTexture(info.fTexture.get()); 289 return static_cast<GrMTLPixelFormat>(mtlTexture.pixelFormat); 290} 291 292size_t GrMtlBytesPerFormat(MTLPixelFormat format) { 293 switch (format) { 294 case MTLPixelFormatA8Unorm: 295 case MTLPixelFormatR8Unorm: 296 return 1; 297 298#ifdef SK_BUILD_FOR_IOS 299 case MTLPixelFormatB5G6R5Unorm: 300 case MTLPixelFormatABGR4Unorm: 301#endif 302 case MTLPixelFormatRG8Unorm: 303 case MTLPixelFormatR16Float: 304 case MTLPixelFormatR16Unorm: 305 return 2; 306 307 case MTLPixelFormatRGBA8Unorm: 308 case MTLPixelFormatBGRA8Unorm: 309 case MTLPixelFormatRGBA8Unorm_sRGB: 310 case MTLPixelFormatRGB10A2Unorm: 311 case MTLPixelFormatRG16Unorm: 312 case MTLPixelFormatRG16Float: 313 return 4; 314 315 case MTLPixelFormatRGBA16Float: 316 case MTLPixelFormatRGBA16Unorm: 317 return 8; 318 319 case MTLPixelFormatRGBA32Float: 320 return 16; 321 322#ifdef SK_BUILD_FOR_IOS 323 case MTLPixelFormatETC2_RGB8: 324 return 0; 325#endif 326 default: 327 SK_ABORT("Invalid Mtl format"); 328 } 329 330 SK_ABORT("Invalid Mtl format"); 331} 332 333#if GR_TEST_UTILS 334const char* GrMtlFormatToStr(GrMTLPixelFormat mtlFormat) { 335 switch (mtlFormat) { 336 case MTLPixelFormatInvalid: return "Invalid"; 337 case MTLPixelFormatRGBA8Unorm: return "RGBA8Unorm"; 338 case MTLPixelFormatR8Unorm: return "R8Unorm"; 339 case MTLPixelFormatA8Unorm: return "A8Unorm"; 340 case MTLPixelFormatBGRA8Unorm: return "BGRA8Unorm"; 341#ifdef SK_BUILD_FOR_IOS 342 case MTLPixelFormatB5G6R5Unorm: return "B5G6R5Unorm"; 343#endif 344 case MTLPixelFormatRGBA16Float: return "RGBA16Float"; 345 case MTLPixelFormatR16Float: return "R16Float"; 346 case MTLPixelFormatRG8Unorm: return "RG8Unorm"; 347 case MTLPixelFormatRGB10A2Unorm: return "RGB10A2Unorm"; 348#ifdef SK_BUILD_FOR_IOS 349 case MTLPixelFormatABGR4Unorm: return "ABGR4Unorm"; 350#endif 351 case MTLPixelFormatRGBA32Float: return "RGBA32Float"; 352 case MTLPixelFormatRGBA8Unorm_sRGB: return "RGBA8Unorm_sRGB"; 353 case MTLPixelFormatR16Unorm: return "R16Unorm"; 354 case MTLPixelFormatRG16Unorm: return "RG16Unorm"; 355#ifdef SK_BUILD_FOR_IOS 356 case MTLPixelFormatETC2_RGB8: return "ETC2_RGB8"; 357#endif 358 case MTLPixelFormatRGBA16Unorm: return "RGBA16Unorm"; 359 case MTLPixelFormatRG16Float: return "RG16Float"; 360 361 default: return "Unknown"; 362 } 363} 364 365#endif 366 367 368 369