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 "GrMtlUtil.h" 9 10 #include "GrTypesPriv.h" 11 #include "GrSurface.h" 12 #include "mtl/GrMtlGpu.h" 13 #include "mtl/GrMtlTexture.h" 14 #include "mtl/GrMtlRenderTarget.h" 15 #include "SkSLCompiler.h" 16 17 #import <Metal/Metal.h> 18 19 #define PRINT_MSL 0 // print out the MSL code generated 20 21 bool GrPixelConfigToMTLFormat(GrPixelConfig config, MTLPixelFormat* format) { 22 MTLPixelFormat dontCare; 23 if (!format) { 24 format = &dontCare; 25 } 26 27 switch (config) { 28 case kUnknown_GrPixelConfig: 29 return false; 30 case kRGBA_8888_GrPixelConfig: 31 *format = MTLPixelFormatRGBA8Unorm; 32 return true; 33 case kRGB_888_GrPixelConfig: 34 // TODO: MTLPixelFormatRGB8Unorm 35 return false; 36 case kRG_88_GrPixelConfig: 37 // TODO: MTLPixelFormatRG8Unorm 38 return false; 39 case kBGRA_8888_GrPixelConfig: 40 *format = MTLPixelFormatBGRA8Unorm; 41 return true; 42 case kSRGBA_8888_GrPixelConfig: 43 *format = MTLPixelFormatRGBA8Unorm_sRGB; 44 return true; 45 case kSBGRA_8888_GrPixelConfig: 46 *format = MTLPixelFormatBGRA8Unorm_sRGB; 47 return true; 48 case kRGBA_1010102_GrPixelConfig: 49 *format = MTLPixelFormatRGB10A2Unorm; 50 return true; 51 case kRGB_565_GrPixelConfig: 52 #ifdef SK_BUILD_FOR_IOS 53 *format = MTLPixelFormatB5G6R5Unorm; 54 return true; 55 #else 56 return false; 57 #endif 58 case kRGBA_4444_GrPixelConfig: 59 #ifdef SK_BUILD_FOR_IOS 60 *format = MTLPixelFormatABGR4Unorm; 61 return true; 62 #else 63 return false; 64 #endif 65 case kAlpha_8_GrPixelConfig: // fall through 66 case kAlpha_8_as_Red_GrPixelConfig: 67 *format = MTLPixelFormatR8Unorm; 68 return true; 69 case kAlpha_8_as_Alpha_GrPixelConfig: 70 return false; 71 case kGray_8_GrPixelConfig: // fall through 72 case kGray_8_as_Red_GrPixelConfig: 73 *format = MTLPixelFormatR8Unorm; 74 return true; 75 case kGray_8_as_Lum_GrPixelConfig: 76 return false; 77 case kRGBA_float_GrPixelConfig: 78 *format = MTLPixelFormatRGBA32Float; 79 return true; 80 case kRG_float_GrPixelConfig: 81 *format = MTLPixelFormatRG32Float; 82 return true; 83 case kRGBA_half_GrPixelConfig: 84 *format = MTLPixelFormatRGBA16Float; 85 return true; 86 case kAlpha_half_GrPixelConfig: // fall through 87 case kAlpha_half_as_Red_GrPixelConfig: 88 *format = MTLPixelFormatR16Float; 89 return true; 90 case kRGB_ETC1_GrPixelConfig: 91 #ifdef SK_BUILD_FOR_IOS 92 *format = MTLPixelFormatETC2_RGB8; 93 return true; 94 #else 95 return false; 96 #endif 97 } 98 SK_ABORT("Unexpected config"); 99 return false; 100 } 101 102 GrPixelConfig GrMTLFormatToPixelConfig(MTLPixelFormat format) { 103 switch (format) { 104 case MTLPixelFormatRGBA8Unorm: 105 return kRGBA_8888_GrPixelConfig; 106 case MTLPixelFormatBGRA8Unorm: 107 return kBGRA_8888_GrPixelConfig; 108 case MTLPixelFormatRGBA8Unorm_sRGB: 109 return kSRGBA_8888_GrPixelConfig; 110 case MTLPixelFormatBGRA8Unorm_sRGB: 111 return kSBGRA_8888_GrPixelConfig; 112 case MTLPixelFormatRGB10A2Unorm: 113 return kRGBA_1010102_GrPixelConfig; 114 #ifdef SK_BUILD_FOR_IOS 115 case MTLPixelFormatB5G6R5Unorm: 116 return kRGB_565_GrPixelConfig; 117 case MTLPixelFormatABGR4Unorm: 118 return kRGBA_4444_GrPixelConfig; 119 #endif 120 case MTLPixelFormatRG8Unorm: 121 return kRG_88_GrPixelConfig; 122 case MTLPixelFormatR8Unorm: 123 // We currently set this to be Alpha_8 and have no way to go to Gray_8 124 return kAlpha_8_GrPixelConfig; 125 case MTLPixelFormatRGBA32Float: 126 return kRGBA_float_GrPixelConfig; 127 case MTLPixelFormatRG32Float: 128 return kRG_float_GrPixelConfig; 129 case MTLPixelFormatRGBA16Float: 130 return kRGBA_half_GrPixelConfig; 131 case MTLPixelFormatR16Float: 132 return kAlpha_half_GrPixelConfig; 133 #ifdef SK_BUILD_FOR_IOS 134 case MTLPixelFormatETC2_RGB8: 135 return kRGB_ETC1_GrPixelConfig; 136 #endif 137 default: 138 return kUnknown_GrPixelConfig; 139 } 140 } 141 142 id<MTLTexture> GrGetMTLTexture(const void* mtlTexture, GrWrapOwnership wrapOwnership) { 143 if (GrWrapOwnership::kAdopt_GrWrapOwnership == wrapOwnership) { 144 return (__bridge_transfer id<MTLTexture>)mtlTexture; 145 } else { 146 return (__bridge id<MTLTexture>)mtlTexture; 147 } 148 } 149 150 const void* GrGetPtrFromId(id idObject) { 151 return (__bridge const void*)idObject; 152 } 153 154 const void* GrReleaseId(id idObject) { 155 return (__bridge_retained const void*)idObject; 156 } 157 158 MTLTextureDescriptor* GrGetMTLTextureDescriptor(id<MTLTexture> mtlTexture) { 159 MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init]; 160 texDesc.textureType = mtlTexture.textureType; 161 texDesc.pixelFormat = mtlTexture.pixelFormat; 162 texDesc.width = mtlTexture.width; 163 texDesc.height = mtlTexture.height; 164 texDesc.depth = mtlTexture.depth; 165 texDesc.mipmapLevelCount = mtlTexture.mipmapLevelCount; 166 texDesc.arrayLength = mtlTexture.arrayLength; 167 texDesc.sampleCount = mtlTexture.sampleCount; 168 texDesc.usage = mtlTexture.usage; 169 return texDesc; 170 } 171 172 #if PRINT_MSL 173 void print_msl(const char* source) { 174 SkTArray<SkString> lines; 175 SkStrSplit(source, "\n", kStrict_SkStrSplitMode, &lines); 176 for (int i = 0; i < lines.count(); i++) { 177 SkString& line = lines[i]; 178 line.prependf("%4i\t", i + 1); 179 SkDebugf("%s\n", line.c_str()); 180 } 181 } 182 #endif 183 184 id<MTLLibrary> GrCompileMtlShaderLibrary(const GrMtlGpu* gpu, 185 const char* shaderString, 186 SkSL::Program::Kind kind, 187 const SkSL::Program::Settings& settings, 188 SkSL::Program::Inputs* outInputs) { 189 std::unique_ptr<SkSL::Program> program = 190 gpu->shaderCompiler()->convertProgram(kind, 191 SkSL::String(shaderString), 192 settings); 193 194 if (!program) { 195 SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str()); 196 SkASSERT(false); 197 } 198 199 *outInputs = program->fInputs; 200 SkSL::String code; 201 if (!gpu->shaderCompiler()->toMetal(*program, &code)) { 202 SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str()); 203 SkASSERT(false); 204 return nil; 205 } 206 NSString* mtlCode = [[NSString alloc] initWithCString: code.c_str() 207 encoding: NSASCIIStringEncoding]; 208 #if PRINT_MSL 209 print_msl([mtlCode cStringUsingEncoding: NSASCIIStringEncoding]); 210 #endif 211 212 MTLCompileOptions* defaultOptions = [[MTLCompileOptions alloc] init]; 213 NSError* error = nil; 214 id<MTLLibrary> compiledLibrary = [gpu->device() newLibraryWithSource: mtlCode 215 options: defaultOptions 216 error: &error]; 217 if (error) { 218 SkDebugf("Error compiling MSL shader: %s\n", 219 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]); 220 return nil; 221 } 222 return compiledLibrary; 223 } 224 225 id<MTLTexture> GrGetMTLTextureFromSurface(GrSurface* surface, bool doResolve) { 226 id<MTLTexture> mtlTexture = nil; 227 228 GrMtlRenderTarget* renderTarget = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget()); 229 GrMtlTexture* texture; 230 if (renderTarget) { 231 if (doResolve) { 232 // TODO: do resolve and set mtlTexture to resolved texture. As of now, we shouldn't 233 // have any multisampled render targets. 234 SkASSERT(false); 235 } else { 236 mtlTexture = renderTarget->mtlRenderTexture(); 237 } 238 } else { 239 texture = static_cast<GrMtlTexture*>(surface->asTexture()); 240 if (texture) { 241 mtlTexture = texture->mtlTexture(); 242 } 243 } 244 return mtlTexture; 245 } 246 247 248 ////////////////////////////////////////////////////////////////////////////// 249 // CPP Utils 250 251 GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo& info) { 252 id<MTLTexture> mtlTexture = GrGetMTLTexture(info.fTexture, 253 GrWrapOwnership::kBorrow_GrWrapOwnership); 254 return static_cast<GrMTLPixelFormat>(mtlTexture.pixelFormat); 255 } 256