From db758697661c59718ae02786d667d24f94d3c88b Mon Sep 17 00:00:00 2001
From: Wilson <[EMAIL REDACTED]>
Date: Wed, 5 Mar 2025 20:01:01 +0100
Subject: [PATCH] Add SDL_SHADERCROSS_PROP_MSL_VERSION property (#114)
---
include/SDL3_shadercross/SDL_shadercross.h | 2 ++
src/SDL_shadercross.c | 20 ++++++++++++++++++++
src/cli.c | 20 ++++++++++++++++++--
3 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/include/SDL3_shadercross/SDL_shadercross.h b/include/SDL3_shadercross/SDL_shadercross.h
index 693884d..f5011ff 100644
--- a/include/SDL3_shadercross/SDL_shadercross.h
+++ b/include/SDL3_shadercross/SDL_shadercross.h
@@ -84,6 +84,8 @@ typedef struct SDL_ShaderCross_SPIRV_Info
#define SDL_SHADERCROSS_PROP_SPIRV_PSSL_COMPATIBILITY "SDL.shadercross.spirv.pssl.compatibility"
+#define SDL_SHADERCROSS_PROP_SPIRV_MSL_VERSION "SDL.shadercross.spirv.msl.version"
+
typedef struct SDL_ShaderCross_HLSL_Define
{
char *name; /**< The define name. */
diff --git a/src/SDL_shadercross.c b/src/SDL_shadercross.c
index b7c3316..bd0963b 100644
--- a/src/SDL_shadercross.c
+++ b/src/SDL_shadercross.c
@@ -119,6 +119,15 @@ struct IDxcBlob
IDxcBlobVtbl *lpVtbl;
};
+static int parse_version_number(const char* str)
+{
+ unsigned major, minor, patch;
+ if (SDL_sscanf(str, "%u.%u.%u", &major, &minor, &patch) == 3) {
+ return (major * 10000) + (minor) * 100 + patch;
+ }
+ return -1;
+}
+
static Uint8 IID_IDxcBlobUtf8[] = {
0xC9, 0x36, 0xA6, 0x3D,
0x71, 0xBA,
@@ -957,6 +966,17 @@ static SPIRVTranspileContext *SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
}
}
+ if (backend == SPVC_BACKEND_MSL) {
+ const char *_mslVersion = SDL_GetStringProperty(props, SDL_SHADERCROSS_PROP_SPIRV_MSL_VERSION, "1.2.0");
+ int mslVersion = parse_version_number(_mslVersion);
+ if (mslVersion == - 1) {
+ SDL_SetError("failed to parse MSL version string \"%s\"", _mslVersion);
+ spvc_context_destroy(context);
+ return NULL;
+ }
+ spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_MSL_VERSION, mslVersion);
+ }
+
// MSL doesn't have descriptor sets, so we have to set up index remapping
if (backend == SPVC_BACKEND_MSL && shaderStage != SDL_SHADERCROSS_SHADERSTAGE_COMPUTE) {
spvc_resources resources;
diff --git a/src/cli.c b/src/cli.c
index 05ce89c..6c9ce1b 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -49,6 +49,7 @@ void print_help(void)
SDL_Log(" %-*s %s", column_width, "-I | --include <value>", "HLSL include directory. Only used with HLSL source.");
SDL_Log(" %-*s %s", column_width, "-D<name>[=<value>]", "HLSL define. Only used with HLSL source. Can be repeated.");
SDL_Log(" %-*s %s", column_width, "", "If =<value> is omitted the define will be treated as equal to 1.");
+ SDL_Log(" %-*s %s", column_width, "--msl-version <value>", "Target MSL version. Only used when transpiling to MSL. The default is 1.2.0.");
SDL_Log(" %-*s %s", column_width, "-g | --debug", "Generate debug information when possible. Shaders are valid only when graphics debuggers are attached.");
}
@@ -103,6 +104,7 @@ int main(int argc, char *argv[])
size_t numDefines = 0;
bool enableDebug = false;
+ char *mslVersion = NULL;
for (int i = 1; i < argc; i += 1) {
char *arg = argv[i];
@@ -224,6 +226,14 @@ int main(int argc, char *argv[])
defines[numDefines - 1].name = SDL_malloc(len);
SDL_utf8strlcpy(defines[numDefines - 1].name, (const char *)argv[i] + 2, len);
}
+ } else if (SDL_strcmp(arg, "--msl-version") == 0) {
+ if (i + 1 >= argc) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s requires an argument", arg);
+ print_help();
+ return 1;
+ }
+ i += 1;
+ mslVersion = argv[i];
} else if (SDL_strcmp(argv[i], "-g") == 0 || SDL_strcmp(arg, "--debug") == 0) {
enableDebug = true;
} else if (SDL_strcmp(arg, "--") == 0) {
@@ -334,7 +344,10 @@ int main(int argc, char *argv[])
spirvInfo.shader_stage = shaderStage;
spirvInfo.enable_debug = enableDebug;
spirvInfo.name = filename;
- spirvInfo.props = 0;
+ spirvInfo.props = SDL_CreateProperties();
+ if (mslVersion) {
+ SDL_SetStringProperty(spirvInfo.props, SDL_SHADERCROSS_PROP_SPIRV_MSL_VERSION, mslVersion);
+ }
switch (destinationFormat) {
case SHADERFORMAT_DXBC: {
@@ -487,7 +500,10 @@ int main(int argc, char *argv[])
spirvInfo.entrypoint = entrypointName;
spirvInfo.shader_stage = shaderStage;
spirvInfo.enable_debug = enableDebug;
- spirvInfo.props = 0;
+ spirvInfo.props = SDL_CreateProperties();
+ if (mslVersion) {
+ SDL_SetStringProperty(spirvInfo.props, SDL_SHADERCROSS_PROP_SPIRV_MSL_VERSION, mslVersion);
+ }
char *buffer = SDL_ShaderCross_TranspileMSLFromSPIRV(
&spirvInfo);
if (buffer == NULL) {