How to compile two versions of metal files

六月ゝ 毕业季﹏ 提交于 2019-12-11 05:32:14

问题


I want to support both 10.13 and 10.14 however I want to support fast math on 10.14. I am only able to compile project if I force #define __CIKERNEL_METAL_VERSION__ 200 but this means on 10.13 it will crash. How do I configure the project so it creates 2 metal libraries? So far the result file is default.metallib (compiling using Xcode)

        BOOL supportsMetal;

#if TARGET_OS_IOS
        supportsMetal = MTLCreateSystemDefaultDevice() != nil; //this forces GPU on macbook to switch immediatelly
#else
        supportsMetal = [MTLCopyAllDevices() count] >= 1;
#endif

        if (@available(macOS 10.13, *)) {

            //only 10.14 fully supports metal with fast math, however there are hackintoshes etc...
            if (supportsMetal) {
                _kernel = [self metalKernel];
            } else {
                _kernel = [self GLSLKernel];
            }

        } else {
            _kernel = [self GLSLKernel];
        }

        if (_kernel == nil) return nil;

METAL file

#include <metal_stdlib>
using namespace metal;

//https://en.wikipedia.org/wiki/List_of_monochrome_and_RGB_palettes

//https://en.wikipedia.org/wiki/Relative_luminance
//https://en.wikipedia.org/wiki/Grayscale

//<CoreImage/CIKernelMetalLib.h>
//only if you enable fast math (macOS10.14 or iOS12) otherwise fall back to float4 instead of half4

//forcing compilation for macOS 10.14+//iOS12+
#define __CIKERNEL_METAL_VERSION__ 200

constant half3 kRec709Luma  = half3(0.2126, 0.7152, 0.0722);
constant half3 kRec601Luma  = half3(0.299 , 0.587 , 0.114);
//constant float3 kRec2100Luma = float3(0.2627, 0.6780, 0.0593);

#include <CoreImage/CoreImage.h>

extern "C" { namespace coreimage {

    float lumin601(half3 p)
    {
        return dot(p.rgb, kRec601Luma);
    }

    float lumin709(half3 p)
    {
        return dot(p.rgb, kRec709Luma);
    }

    half4 thresholdFilter(sample_h image, float threshold)
    {
        half4 pix = unpremultiply(image);
        float luma = lumin601(pix.rgb);
        pix.rgb = half3(step(threshold, luma));
        return premultiply(pix);
    }
}}

回答1:


XCode 11 supports Metal libraries.

  1. Add a new build target to your project.

  1. Add metal files in compile sources

  1. If you use Core Image add these linker flags. Change deployment targets (ios12+ ) and check for fast math.

  1. To your original project target add new dependencies and copy script

    cp "${BUILT_PRODUCTS_DIR}"/*.metallib "${METAL_LIBRARY_OUTPUT_DIR}"

Optional:

Avoiding hard coded strings everywhere in project. Add xconfig file to project

MY_METAL_LIBRARY_NAME_10_13 = Metal_10_13_aaa
MY_METAL_LIBRARY_NAME_10_14 = Metal_10_14_bbb
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) MY_METAL_LIBRARY_NAME_10_13='@"$(MY_METAL_LIBRARY_NAME_10_13)"' MY_METAL_LIBRARY_NAME_10_14='@"$(MY_METAL_LIBRARY_NAME_10_14)"'

Add xconfig as configuration (don't set it for project cause you will end up with double import)

Change PRODUCT_NAME variable of each metal library to a variable

Use preprocesor variables in code

static NSString *const kMetallibExtension = @"metallib";
NSString *const kMetalLibraryOldTarget = MY_METAL_LIBRARY_NAME_10_13; //@"Metal_10_13";
NSString *const kMetalLibraryFastMathTarget = MY_METAL_LIBRARY_NAME_10_14; //@"Metal_10_14";

+ (NSString *)metalLibraryName
{
    if (@available(macOS 10.14, *)) {
        return kMetalLibraryFastMathTarget;
    } else {
        return kMetalLibraryOldTarget;
    }
    //use default
    //return @"default";
}


来源:https://stackoverflow.com/questions/58451581/how-to-compile-two-versions-of-metal-files

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!