MoltenVKShaderConverter tool add MSL version and platform command-line options.

Add SPIRVToMSLConverterOptions::platform to track platform. Default to build platform.
Update default SPIRVToMSLConverterOptions MSL version to 2.1.
MoltenVKShaderConverter test MSL compilation use same MSL version as conversion.
Default min perf tracking value to 0.0.
SPIRVToMSLConverter.h reference spirv.hpp via SPIRV-Cross framework.
Update What's New document.
This commit is contained in:
Bill Hollings 2019-04-17 16:09:07 -04:00
parent 6bbd0eca75
commit eca03b8de1
10 changed files with 181 additions and 29 deletions

View File

@ -13,6 +13,17 @@ For best results, use a Markdown reader.*
MoltenVK 1.0.35
---------------
Released TBD
- Don't use setVertexBytes() for passing tessellation vertex counts.
- Fix zero local threadgroup size in indirect tessellated rendering.
- MoltenVKShaderConverter tool add MSL version and platform command-line options.
MoltenVK 1.0.34 MoltenVK 1.0.34
--------------- ---------------
@ -115,7 +126,7 @@ Released 2019/02/28
runtime environment variable. runtime environment variable.
Set MSL version for shader compiling from Metal feature set. Set MSL version for shader compiling from Metal feature set.
- Don't warn on identity swizzles when `fullImageViewSwizzle` config setting is enabled. - Don't warn on identity swizzles when `fullImageViewSwizzle` config setting is enabled.
- Track version of spvAux buffer struct in SPRIV-Cross and fail build if different - Track version of spvAux buffer struct in SPIRV-Cross and fail build if different
than version expected by MoltenVK. than version expected by MoltenVK.
- Add static and dynamic libraries to MoltenVKShaderConverter project. - Add static and dynamic libraries to MoltenVKShaderConverter project.
- Fix crash from use of MTLDevice registryID on early OS versions. - Fix crash from use of MTLDevice registryID on early OS versions.
@ -792,7 +803,7 @@ Released 2018/03/19
- Add build and runtime OS and device requirements to documentation. - Add build and runtime OS and device requirements to documentation.
- Add Compliance and Contribution sections to README.md. - Add Compliance and Contribution sections to README.md.
- Remove executable permissions from non-executable files. - Remove executable permissions from non-executable files.
- Update to latest SPRIV-Cross. - Update to latest SPIRV-Cross.
- Update copyright dates to 2018. - Update copyright dates to 2018.

View File

@ -1943,7 +1943,9 @@ void MVKDevice::addActivityPerformanceImpl(MVKPerformanceTracker& shaderCompilat
lock_guard<mutex> lock(_perfLock); lock_guard<mutex> lock(_perfLock);
double currInterval = mvkGetElapsedMilliseconds(startTime, endTime); double currInterval = mvkGetElapsedMilliseconds(startTime, endTime);
shaderCompilationEvent.minimumDuration = min(currInterval, shaderCompilationEvent.minimumDuration); shaderCompilationEvent.minimumDuration = ((shaderCompilationEvent.minimumDuration == 0.0)
? currInterval :
min(currInterval, shaderCompilationEvent.minimumDuration));
shaderCompilationEvent.maximumDuration = max(currInterval, shaderCompilationEvent.maximumDuration); shaderCompilationEvent.maximumDuration = max(currInterval, shaderCompilationEvent.maximumDuration);
double totalInterval = (shaderCompilationEvent.averageDuration * shaderCompilationEvent.count++) + currInterval; double totalInterval = (shaderCompilationEvent.averageDuration * shaderCompilationEvent.count++) + currInterval;
shaderCompilationEvent.averageDuration = totalInterval / shaderCompilationEvent.count; shaderCompilationEvent.averageDuration = totalInterval / shaderCompilationEvent.count;
@ -2072,7 +2074,7 @@ void MVKDevice::initPerformanceTracking() {
MVKPerformanceTracker initPerf; MVKPerformanceTracker initPerf;
initPerf.count = 0; initPerf.count = 0;
initPerf.averageDuration = 0.0; initPerf.averageDuration = 0.0;
initPerf.minimumDuration = numeric_limits<double>::max(); initPerf.minimumDuration = 0.0;
initPerf.maximumDuration = 0.0; initPerf.maximumDuration = 0.0;
_performanceStatistics.shaderCompilation.hashShaderCode = initPerf; _performanceStatistics.shaderCompilation.hashShaderCode = initPerf;

View File

@ -84,6 +84,15 @@ MVK_PUBLIC_SYMBOL std::string SPIRVToMSLConverterOptions::printMSLVersion(uint32
return verStr; return verStr;
} }
MVK_PUBLIC_SYMBOL mvk::SPIRVToMSLConverterOptions::Platform SPIRVToMSLConverterOptions::getNativePlatform() {
#if MVK_MACOS
return SPIRVToMSLConverterOptions::macOS;
#endif
#if MVK_IOS
return SPIRVToMSLConverterOptions::iOS;
#endif
}
MVK_PUBLIC_SYMBOL bool MSLVertexAttribute::matches(const MSLVertexAttribute& other) const { MVK_PUBLIC_SYMBOL bool MSLVertexAttribute::matches(const MSLVertexAttribute& other) const {
if (location != other.location) { return false; } if (location != other.location) { return false; }
if (mslBuffer != other.mslBuffer) { return false; } if (mslBuffer != other.mslBuffer) { return false; }
@ -182,6 +191,9 @@ MVK_PUBLIC_SYMBOL void SPIRVToMSLConverterContext::alignWith(const SPIRVToMSLCon
#pragma mark - #pragma mark -
#pragma mark SPIRVToMSLConverter #pragma mark SPIRVToMSLConverter
// Return the SPIRV-Cross platform enum corresponding to a SPIRVToMSLConverterOptions platform enum value.
SPIRV_CROSS_NAMESPACE::CompilerMSL::Options::Platform getCompilerMSLPlatform(SPIRVToMSLConverterOptions::Platform platform);
// Populates the entry point with info extracted from the SPRI-V compiler. // Populates the entry point with info extracted from the SPRI-V compiler.
void populateEntryPoint(SPIRVEntryPoint& entryPoint, SPIRV_CROSS_NAMESPACE::Compiler* pCompiler, SPIRVToMSLConverterOptions& options); void populateEntryPoint(SPIRVEntryPoint& entryPoint, SPIRV_CROSS_NAMESPACE::Compiler* pCompiler, SPIRVToMSLConverterOptions& options);
@ -238,14 +250,7 @@ MVK_PUBLIC_SYMBOL bool SPIRVToMSLConverter::convert(SPIRVToMSLConverterContext&
// Establish the MSL options for the compiler // Establish the MSL options for the compiler
// This needs to be done in two steps...for CompilerMSL and its superclass. // This needs to be done in two steps...for CompilerMSL and its superclass.
auto mslOpts = pMSLCompiler->get_msl_options(); auto mslOpts = pMSLCompiler->get_msl_options();
mslOpts.platform = getCompilerMSLPlatform(context.options.platform);
#if MVK_MACOS
mslOpts.platform = SPIRV_CROSS_NAMESPACE::CompilerMSL::Options::macOS;
#endif
#if MVK_IOS
mslOpts.platform = SPIRV_CROSS_NAMESPACE::CompilerMSL::Options::iOS;
#endif
mslOpts.msl_version = context.options.mslVersion; mslOpts.msl_version = context.options.mslVersion;
mslOpts.texel_buffer_texture_width = context.options.texelBufferTextureWidth; mslOpts.texel_buffer_texture_width = context.options.texelBufferTextureWidth;
mslOpts.aux_buffer_index = context.options.auxBufferIndex; mslOpts.aux_buffer_index = context.options.auxBufferIndex;
@ -441,6 +446,14 @@ void SPIRVToMSLConverter::logSource(string& src, const char* srcLang, const char
#pragma mark Support functions #pragma mark Support functions
// Return the SPIRV-Cross platform enum corresponding to a SPIRVToMSLConverterOptions platform enum value.
SPIRV_CROSS_NAMESPACE::CompilerMSL::Options::Platform getCompilerMSLPlatform(SPIRVToMSLConverterOptions::Platform platform) {
switch (platform) {
case SPIRVToMSLConverterOptions::macOS: return SPIRV_CROSS_NAMESPACE::CompilerMSL::Options::macOS;
case SPIRVToMSLConverterOptions::iOS: return SPIRV_CROSS_NAMESPACE::CompilerMSL::Options::iOS;
}
}
// Populate a workgroup size dimension. // Populate a workgroup size dimension.
void populateWorkgroupDimension(SPIRVWorkgroupSizeDimension& wgDim, uint32_t size, SPIRV_CROSS_NAMESPACE::SpecializationConstant& spvSpecConst) { void populateWorkgroupDimension(SPIRVWorkgroupSizeDimension& wgDim, uint32_t size, SPIRV_CROSS_NAMESPACE::SpecializationConstant& spvSpecConst) {
wgDim.size = max(size, 1u); wgDim.size = max(size, 1u);

View File

@ -19,7 +19,7 @@
#ifndef __SPIRVToMSLConverter_h_ #ifndef __SPIRVToMSLConverter_h_
#define __SPIRVToMSLConverter_h_ 1 #define __SPIRVToMSLConverter_h_ 1
#include "../SPIRV-Cross/spirv.hpp" #include <SPIRV-Cross/spirv.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
@ -32,11 +32,18 @@ namespace mvk {
/** Options for converting SPIR-V to Metal Shading Language */ /** Options for converting SPIR-V to Metal Shading Language */
typedef struct SPIRVToMSLConverterOptions { typedef struct SPIRVToMSLConverterOptions {
enum Platform {
iOS = 0,
macOS = 1
};
std::string entryPointName; std::string entryPointName;
spv::ExecutionModel entryPointStage = spv::ExecutionModelMax; spv::ExecutionModel entryPointStage = spv::ExecutionModelMax;
spv::ExecutionMode tessPatchKind = spv::ExecutionModeMax; spv::ExecutionMode tessPatchKind = spv::ExecutionModeMax;
uint32_t mslVersion = makeMSLVersion(2); uint32_t mslVersion = makeMSLVersion(2, 1);
Platform platform = getNativePlatform();
uint32_t texelBufferTextureWidth = 4096; uint32_t texelBufferTextureWidth = 4096;
uint32_t auxBufferIndex = 0; uint32_t auxBufferIndex = 0;
uint32_t indirectParamsBufferIndex = 0; uint32_t indirectParamsBufferIndex = 0;
@ -81,6 +88,8 @@ namespace mvk {
static std::string printMSLVersion(uint32_t mslVersion, bool includePatch = false); static std::string printMSLVersion(uint32_t mslVersion, bool includePatch = false);
static Platform getNativePlatform();
} SPIRVToMSLConverterOptions; } SPIRVToMSLConverterOptions;
/** /**

View File

@ -920,6 +920,7 @@
GCC_WARN_UNUSED_VARIABLE = NO; GCC_WARN_UNUSED_VARIABLE = NO;
HEADER_SEARCH_PATHS = ( HEADER_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"\"$(SRCROOT)\"",
"\"$(SRCROOT)/glslang/External/spirv-tools/include\"", "\"$(SRCROOT)/glslang/External/spirv-tools/include\"",
"\"$(SRCROOT)/glslang/External/spirv-tools/external/spirv-headers/include\"", "\"$(SRCROOT)/glslang/External/spirv-tools/external/spirv-headers/include\"",
); );
@ -973,6 +974,7 @@
GCC_WARN_UNUSED_VARIABLE = NO; GCC_WARN_UNUSED_VARIABLE = NO;
HEADER_SEARCH_PATHS = ( HEADER_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"\"$(SRCROOT)\"",
"\"$(SRCROOT)/glslang/External/spirv-tools/include\"", "\"$(SRCROOT)/glslang/External/spirv-tools/include\"",
"\"$(SRCROOT)/glslang/External/spirv-tools/external/spirv-headers/include\"", "\"$(SRCROOT)/glslang/External/spirv-tools/external/spirv-headers/include\"",
); );

View File

@ -103,6 +103,22 @@
argument = "-mo" argument = "-mo"
isEnabled = "YES"> isEnabled = "YES">
</CommandLineArgument> </CommandLineArgument>
<CommandLineArgument
argument = "-mv"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "2.1"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "-mp"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "ios"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument <CommandLineArgument
argument = "-XS" argument = "-XS"
isEnabled = "NO"> isEnabled = "NO">

View File

@ -45,7 +45,7 @@ uint64_t MVKPerformanceTracker::getTimestamp() { return mvkGetTimestamp(); }
void MVKPerformanceTracker::accumulate(uint64_t startTime, uint64_t endTime) { void MVKPerformanceTracker::accumulate(uint64_t startTime, uint64_t endTime) {
double currInterval = mvkGetElapsedMilliseconds(startTime, endTime); double currInterval = mvkGetElapsedMilliseconds(startTime, endTime);
minimumDuration = min(currInterval, minimumDuration); minimumDuration = (minimumDuration == 0.0) ? currInterval : min(currInterval, minimumDuration);
maximumDuration = max(currInterval, maximumDuration); maximumDuration = max(currInterval, maximumDuration);
double totalInterval = (averageDuration * count++) + currInterval; double totalInterval = (averageDuration * count++) + currInterval;
averageDuration = totalInterval / count; averageDuration = totalInterval / count;
@ -57,6 +57,8 @@ void MVKPerformanceTracker::accumulate(uint64_t startTime, uint64_t endTime) {
int MoltenVKShaderConverterTool::run() { int MoltenVKShaderConverterTool::run() {
if ( !_isActive ) { return EXIT_FAILURE; }
bool success = false; bool success = false;
if ( !_directoryPath.empty() ) { if ( !_directoryPath.empty() ) {
string errMsg; string errMsg;
@ -203,6 +205,8 @@ bool MoltenVKShaderConverterTool::convertSPIRV(const vector<uint32_t>& spv,
// Derive the context under which conversion will occur // Derive the context under which conversion will occur
SPIRVToMSLConverterContext mslContext; SPIRVToMSLConverterContext mslContext;
mslContext.options.platform = _mslPlatform;
mslContext.options.setMSLVersion(_mslVersionMajor, _mslVersionMinor, _mslVersionPatch);
mslContext.options.shouldFlipVertexY = _shouldFlipVertexY; mslContext.options.shouldFlipVertexY = _shouldFlipVertexY;
SPIRVToMSLConverter spvConverter; SPIRVToMSLConverter spvConverter;
@ -227,9 +231,9 @@ bool MoltenVKShaderConverterTool::convertSPIRV(const vector<uint32_t>& spv,
const string& msl = spvConverter.getMSL(); const string& msl = spvConverter.getMSL();
string compileErrMsg; string compileErrMsg;
bool wasCompiled = compile(msl, compileErrMsg); bool wasCompiled = compile(msl, compileErrMsg, _mslVersionMajor, _mslVersionMinor, _mslVersionPatch);
if (compileErrMsg.size() > 0) { if (compileErrMsg.size() > 0) {
string preamble = wasCompiled ? "is valid but the validation compilation produced warnings " : "failed a validation compilation "; string preamble = wasCompiled ? "is valid but the validation compilation produced warnings: " : "failed a validation compilation: ";
compileErrMsg = "Generated MSL " + preamble + compileErrMsg; compileErrMsg = "Generated MSL " + preamble + compileErrMsg;
log(compileErrMsg.c_str()); log(compileErrMsg.c_str());
} else { } else {
@ -305,6 +309,12 @@ void MoltenVKShaderConverterTool::showUsage() {
log(" The optional path parameter specifies the path to a single"); log(" The optional path parameter specifies the path to a single");
log(" file to contain the MSL code. When using the -d option,"); log(" file to contain the MSL code. When using the -d option,");
log(" the path parameter is ignored."); log(" the path parameter is ignored.");
log(" -mv mslVersion - MSL version to output.");
log(" Must be in form n[.n][.n] (eg. 2, 2.1, or 2.1.0).");
log(" Defaults to the most recent MSL version for the platform");
log(" on which this tool is executed.");
log(" -mp mslPlatform - MSL platform. Must be one of macos or ios.");
log(" Defaults to the platform on which this tool is executed (macos).");
log(" -t shaderType - Shader type: vertex or fragment. Must be one of v, f, or c."); log(" -t shaderType - Shader type: vertex or fragment. Must be one of v, f, or c.");
log(" May be omitted to auto-detect."); log(" May be omitted to auto-detect.");
log(" -c - Combine the GLSL and converted Metal Shader source code"); log(" -c - Combine the GLSL and converted Metal Shader source code");
@ -363,7 +373,6 @@ MoltenVKShaderConverterTool::MoltenVKShaderConverterTool(int argc, const char* a
extractTokens(_defaultSPIRVShaderExtns, _spvFileExtns); extractTokens(_defaultSPIRVShaderExtns, _spvFileExtns);
_origPathExtnSep = "_"; _origPathExtnSep = "_";
_shaderStage = kMVKShaderStageAuto; _shaderStage = kMVKShaderStageAuto;
_isActive = false;
_shouldUseDirectoryRecursion = false; _shouldUseDirectoryRecursion = false;
_shouldReadGLSL = false; _shouldReadGLSL = false;
_shouldReadSPIRV = false; _shouldReadSPIRV = false;
@ -375,6 +384,11 @@ MoltenVKShaderConverterTool::MoltenVKShaderConverterTool(int argc, const char* a
_shouldLogConversions = false; _shouldLogConversions = false;
_shouldReportPerformance = false; _shouldReportPerformance = false;
_mslVersionMajor = 2;
_mslVersionMinor = 1;
_mslVersionPatch = 0;
_mslPlatform = SPIRVToMSLConverterOptions::getNativePlatform();
_isActive = parseArgs(argc, argv); _isActive = parseArgs(argc, argv);
if ( !_isActive ) { showUsage(); } if ( !_isActive ) { showUsage(); }
} }
@ -427,6 +441,39 @@ bool MoltenVKShaderConverterTool::parseArgs(int argc, const char* argv[]) {
continue; continue;
} }
if (equal(arg, "-mv", true)) {
int optIdx = argIdx;
string mslVerStr;
argIdx = optionalParam(mslVerStr, argIdx, argc, argv);
if (argIdx == optIdx || mslVerStr.length() == 0) { return false; }
vector<uint32_t> mslVerTokens;
extractTokens(mslVerStr, mslVerTokens);
auto tknCnt = mslVerTokens.size();
_mslVersionMajor = (tknCnt > 0) ? mslVerTokens[0] : 0;
_mslVersionMinor = (tknCnt > 1) ? mslVerTokens[1] : 0;
_mslVersionPatch = (tknCnt > 2) ? mslVerTokens[2] : 0;
continue;
}
if (equal(arg, "-mp", true)) {
int optIdx = argIdx;
string shdrTypeStr;
argIdx = optionalParam(shdrTypeStr, argIdx, argc, argv);
if (argIdx == optIdx || shdrTypeStr.length() == 0) { return false; }
switch (shdrTypeStr.front()) {
case 'm':
_mslPlatform = SPIRVToMSLConverterOptions::macOS;
break;
case 'i':
_mslPlatform = SPIRVToMSLConverterOptions::iOS;
break;
default:
return false;
}
continue;
}
if (equal(arg, "-t", true)) { if (equal(arg, "-t", true)) {
int optIdx = argIdx; int optIdx = argIdx;
string shdrTypeStr; string shdrTypeStr;
@ -444,7 +491,7 @@ bool MoltenVKShaderConverterTool::parseArgs(int argc, const char* argv[]) {
_shaderStage = kMVKShaderStageCompute; _shaderStage = kMVKShaderStageCompute;
break; break;
default: default:
break; return false;
} }
continue; continue;
} }
@ -577,6 +624,14 @@ void mvk::extractTokens(string str, vector<string>& tokens) {
split(tokens, str, " \t\n\f", false); split(tokens, str, " \t\n\f", false);
} }
void mvk::extractTokens(string str, vector<uint32_t>& tokens) {
vector<string> stringTokens;
split(stringTokens, str, ".", false);
for (auto& st : stringTokens) {
tokens.push_back((uint32_t)strtol(st.c_str(), nullptr, 0));
}
}
// Compares the specified characters ignoring case. // Compares the specified characters ignoring case.
static bool compareIgnoringCase(unsigned char a, unsigned char b) { static bool compareIgnoringCase(unsigned char a, unsigned char b) {
return tolower(a) == tolower(b); return tolower(a) == tolower(b);

View File

@ -20,6 +20,7 @@
#include "GLSLConversion.h" #include "GLSLConversion.h"
#include "SPIRVToMSLConverter.h"
#include <string> #include <string>
#include <vector> #include <vector>
@ -28,9 +29,9 @@ namespace mvk {
typedef struct { typedef struct {
uint32_t count = 0; uint32_t count = 0;
double averageDuration = 0; double averageDuration = 0.0;
double minimumDuration = std::numeric_limits<double>::max(); double minimumDuration = 0.0;
double maximumDuration = 0; double maximumDuration = 0.0;
uint64_t getTimestamp(); uint64_t getTimestamp();
void accumulate(uint64_t startTime, uint64_t endTime = 0); void accumulate(uint64_t startTime, uint64_t endTime = 0);
@ -102,6 +103,10 @@ namespace mvk {
MVKShaderStage _shaderStage; MVKShaderStage _shaderStage;
MVKPerformanceTracker _glslConversionPerformance; MVKPerformanceTracker _glslConversionPerformance;
MVKPerformanceTracker _spvConversionPerformance; MVKPerformanceTracker _spvConversionPerformance;
uint32_t _mslVersionMajor;
uint32_t _mslVersionMinor;
uint32_t _mslVersionPatch;
SPIRVToMSLConverterOptions::Platform _mslPlatform;
bool _isActive; bool _isActive;
bool _shouldUseDirectoryRecursion; bool _shouldUseDirectoryRecursion;
bool _shouldReadGLSL; bool _shouldReadGLSL;
@ -121,10 +126,16 @@ namespace mvk {
/** /**
* Extracts whitespace-delimited tokens from the specified string and * Extracts whitespace-delimited tokens from the specified string and
* appends them to the specified vector. The vector is not cleared first. * appends them to the specified vector. The vector is cleared first.
*/ */
void extractTokens(std::string str, std::vector<std::string>& tokens); void extractTokens(std::string str, std::vector<std::string>& tokens);
/**
* Extracts period-delimited tokens from the specified string and
* appends them to the specified vector. The vector is cleared first.
*/
void extractTokens(std::string str, std::vector<uint32_t>& tokens);
/** Compares the specified strings, with or without sensitivity to case. */ /** Compares the specified strings, with or without sensitivity to case. */
bool equal(std::string const& a, std::string const& b, bool checkCase = true); bool equal(std::string const& a, std::string const& b, bool checkCase = true);

View File

@ -48,6 +48,10 @@ namespace mvk {
* If unsuccessful, the return value will be false and the errMsg will contain an * If unsuccessful, the return value will be false and the errMsg will contain an
* error message. Otherwise the return value will be true and the errMsg will be empty. * error message. Otherwise the return value will be true and the errMsg will be empty.
*/ */
bool compile(const std::string& mslSourceCode, std::string& errMsg); bool compile(const std::string& mslSourceCode,
std::string& errMsg,
uint32_t mslVersionMajor,
uint32_t mslVersionMinor = 0,
uint32_t mslVersionPoint = 0);
} }

View File

@ -55,20 +55,49 @@ bool mvk::iterateDirectory(const string& dirPath,
return success; return success;
} }
/** Concrete template implementation to allow MoltenVKShaderConverterTool to iterate the files in a directory. */ // Concrete template implementation to allow MoltenVKShaderConverterTool to iterate the files in a directory.
template bool mvk::iterateDirectory<MoltenVKShaderConverterTool>(const string& dirPath, template bool mvk::iterateDirectory<MoltenVKShaderConverterTool>(const string& dirPath,
MoltenVKShaderConverterTool& fileProcessor, MoltenVKShaderConverterTool& fileProcessor,
bool isRecursive, bool isRecursive,
string& errMsg); string& errMsg);
bool mvk::compile(const string& mslSourceCode, string& errMsg) { bool mvk::compile(const string& mslSourceCode,
string& errMsg,
uint32_t mslVersionMajor,
uint32_t mslVersionMinor,
uint32_t mslVersionPoint) {
#define mslVer(MJ, MN, PT) mslVersionMajor == MJ && mslVersionMinor == MN && mslVersionPoint == PT
MTLLanguageVersion mslVerEnum = (MTLLanguageVersion)0;
if (mslVer(2, 1, 0)) {
if (@available(macOS 10.14, *)) {
mslVerEnum = MTLLanguageVersion2_1;
}
} else if (mslVer(2, 0, 0)) {
if (@available(macOS 10.13, *)) {
mslVerEnum = MTLLanguageVersion2_0;
}
} else if (mslVer(1, 2, 0)) {
mslVerEnum = MTLLanguageVersion1_2;
} else if (mslVer(1, 1, 0)) {
mslVerEnum = MTLLanguageVersion1_1;
}
if ( !mslVerEnum ) {
errMsg = [NSString stringWithFormat: @"%d.%d.%d is not a valid MSL version number on this device",
mslVersionMajor, mslVersionMinor, mslVersionPoint].UTF8String;
return false;
}
@autoreleasepool { @autoreleasepool {
MTLCompileOptions* mtlCompileOptions = [[MTLCompileOptions new] autorelease];
mtlCompileOptions.languageVersion = mslVerEnum;
NSError* err = nil; NSError* err = nil;
id<MTLLibrary> mtlLib = [[MTLCreateSystemDefaultDevice() newLibraryWithSource: @(mslSourceCode.c_str()) id<MTLLibrary> mtlLib = [[MTLCreateSystemDefaultDevice() newLibraryWithSource: @(mslSourceCode.c_str())
options: [[MTLCompileOptions new] autorelease] options: mtlCompileOptions
error: &err] autorelease]; error: &err] autorelease];
errMsg = err ? [NSString stringWithFormat: @"(Error code %li):\n%@", (long)err.code, err.localizedDescription].UTF8String errMsg = err ? [NSString stringWithFormat: @"(Error code %li):\n%@", (long)err.code, err.localizedDescription].UTF8String : "";
: "";
return !!mtlLib; return !!mtlLib;
} }
} }