Home | History | Annotate | Download | only in mtl
      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