From 03b1168085549f16c61abbc94569127389918458 Mon Sep 17 00:00:00 2001
From: cosmonaut <[EMAIL REDACTED]>
Date: Fri, 25 Oct 2024 11:34:38 -0700
Subject: [PATCH] Refactor to allow HLSL destination
---
include/SDL_gpu_shadercross.h | 22 ++-
src/SDL_gpu_shadercross.c | 332 +++++++++++++++++++---------------
src/cli.c | 113 +++++++++---
3 files changed, 287 insertions(+), 180 deletions(-)
diff --git a/include/SDL_gpu_shadercross.h b/include/SDL_gpu_shadercross.h
index a0eb9b6..27cff7e 100644
--- a/include/SDL_gpu_shadercross.h
+++ b/include/SDL_gpu_shadercross.h
@@ -76,6 +76,7 @@ extern SDL_DECLSPEC SDL_GPUShaderFormat SDLCALL SDL_ShaderCross_GetSPIRVShaderFo
* \param bytecodeSize the length of the SPIRV bytecode.
* \param entrypoint the entry point function name for the shader in UTF-8.
* \param shaderStage the shader stage to transpile the shader with.
+ * \returns an SDL_malloc'd string containing MSL code.
*/
extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_TranspileMSLFromSPIRV(
const Uint8 *bytecode,
@@ -83,6 +84,23 @@ extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_TranspileMSLFromSPIRV(
const char *entrypoint,
SDL_ShaderCross_ShaderStage shaderStage);
+/**
+ * Transpile to HLSL code from SPIRV code.
+ *
+ * You must SDL_free the returned string once you are done with it.
+ *
+ * \param bytecode the SPIRV bytecode.
+ * \param bytecodeSize the length of the SPIRV bytecode.
+ * \param entrypoint the entry point function name for the shader in UTF-8.
+ * \param shaderProfile the HLSL shader profile to transpile with.
+ * \returns an SDL_malloc'd string containing HLSL code.
+ */
+extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_TranspileHLSLFromSPIRV(
+ const Uint8 *bytecode,
+ size_t bytecodeSize,
+ const char *entrypoint,
+ const char *shaderProfile);
+
/**
* Compile DXBC bytecode from SPIRV code.
*
@@ -91,7 +109,7 @@ extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_TranspileMSLFromSPIRV(
* \param bytecode the SPIRV bytecode.
* \param bytecodeSize the length of the SPIRV bytecode.
* \param entrypoint the entry point function name for the shader in UTF-8.
- * \param shaderStage the shader stage to transpile the shader with.
+ * \param shaderStage the shader stage to compile the shader with.
* \param size filled in with the bytecode buffer size.
*/
extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXBCFromSPIRV(
@@ -109,7 +127,7 @@ extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXBCFromSPIRV(
* \param bytecode the SPIRV bytecode.
* \param bytecodeSize the length of the SPIRV bytecode.
* \param entrypoint the entry point function name for the shader in UTF-8.
- * \param shaderStage the shader stage to transpile the shader with.
+ * \param shaderStage the shader stage to compile the shader with.
* \param size filled in with the bytecode buffer size.
*/
extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXILFromSPIRV(
diff --git a/src/SDL_gpu_shadercross.c b/src/SDL_gpu_shadercross.c
index c93672e..862da93 100644
--- a/src/SDL_gpu_shadercross.c
+++ b/src/SDL_gpu_shadercross.c
@@ -748,37 +748,35 @@ static pfn_spvc_compiler_get_cleansed_entry_point_name SDL_spvc_compiler_get_cle
#define SPVC_ERROR(func) \
SDL_SetError(#func " failed: %s", SDL_spvc_context_get_last_error_string(context))
-// Returns a malloc'd CreateInfo struct.
-// It also malloc's the bytecode pointer and entrypoint string.
-static void *SDL_ShaderCross_INTERNAL_TranslateFromSPIRV(
- SDL_GPUShaderFormat shaderFormat,
- const void *originalCreateInfo,
- bool isCompute
+typedef struct SPIRVTranspileContext {
+ spvc_context context;
+ const char *translated_source;
+ const char *cleansed_entrypoint;
+} SPIRVTranspileContext;
+
+static void SDL_ShaderCross_INTERNAL_DestroyTranspileContext(
+ SPIRVTranspileContext *context)
+{
+ SDL_spvc_context_destroy(context->context);
+ SDL_free(context);
+}
+
+static SPIRVTranspileContext *SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
+ spvc_backend backend,
+ unsigned shadermodel,
+ const Uint8 *code,
+ size_t codeSize,
+ const char *entrypoint
) {
- const SDL_GPUShaderCreateInfo *createInfo;
spvc_result result;
- spvc_backend backend;
- unsigned shadermodel;
spvc_context context = NULL;
spvc_parsed_ir ir = NULL;
spvc_compiler compiler = NULL;
spvc_compiler_options options = NULL;
+ SPIRVTranspileContext *transpileContext = NULL;
const char *translated_source;
const char *cleansed_entrypoint;
- if (shaderFormat == SDL_GPU_SHADERFORMAT_DXBC) {
- backend = SPVC_BACKEND_HLSL;
- shadermodel = 50;
- } else if (shaderFormat == SDL_GPU_SHADERFORMAT_DXIL) {
- backend = SPVC_BACKEND_HLSL;
- shadermodel = 60;
- } else if (shaderFormat == SDL_GPU_SHADERFORMAT_MSL) {
- backend = SPVC_BACKEND_MSL;
- } else {
- SDL_SetError("SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV: Unexpected SDL_GPUBackend");
- return NULL;
- }
-
/* Create the SPIRV-Cross context */
result = SDL_spvc_context_create(&context);
if (result < 0) {
@@ -786,14 +784,8 @@ static void *SDL_ShaderCross_INTERNAL_TranslateFromSPIRV(
return NULL;
}
- /* SDL_GPUShaderCreateInfo and SDL_GPUComputePipelineCreateInfo
- * share the same struct layout for their first 3 members, which
- * is all we need to transpile them!
- */
- createInfo = (const SDL_GPUShaderCreateInfo *)originalCreateInfo;
-
/* Parse the SPIR-V into IR */
- result = SDL_spvc_context_parse_spirv(context, (const SpvId *)createInfo->code, createInfo->code_size / sizeof(SpvId), &ir);
+ result = SDL_spvc_context_parse_spirv(context, (const SpvId *)code, codeSize / sizeof(SpvId), &ir);
if (result < 0) {
SPVC_ERROR(spvc_context_parse_spirv);
SDL_spvc_context_destroy(context);
@@ -840,145 +832,171 @@ static void *SDL_ShaderCross_INTERNAL_TranslateFromSPIRV(
/* Determine the "cleansed" entrypoint name (e.g. main -> main0 on MSL) */
cleansed_entrypoint = SDL_spvc_compiler_get_cleansed_entry_point_name(
compiler,
- createInfo->entrypoint,
+ entrypoint,
SDL_spvc_compiler_get_execution_model(compiler));
- void *translatedCreateInfo = NULL;
+ transpileContext = SDL_malloc(sizeof(SPIRVTranspileContext));
+ transpileContext->context = context;
+ transpileContext->cleansed_entrypoint = cleansed_entrypoint;
+ transpileContext->translated_source = translated_source;
+ return transpileContext;
+}
+
+static void *SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
+ SDL_GPUDevice *device,
+ SDL_GPUShaderFormat shaderFormat,
+ const void *originalCreateInfo,
+ bool isCompute
+) {
+ const SDL_GPUShaderCreateInfo *createInfo;
+ spvc_backend backend;
+ unsigned shadermodel = 0;
+
+ if (shaderFormat == SDL_GPU_SHADERFORMAT_DXBC) {
+ backend = SPVC_BACKEND_HLSL;
+ shadermodel = 50;
+ } else if (shaderFormat == SDL_GPU_SHADERFORMAT_DXIL) {
+ backend = SPVC_BACKEND_HLSL;
+ shadermodel = 60;
+ } else if (shaderFormat == SDL_GPU_SHADERFORMAT_MSL) {
+ backend = SPVC_BACKEND_MSL;
+ } else {
+ SDL_SetError("SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV: Unexpected SDL_GPUBackend");
+ return NULL;
+ }
+
+ /* SDL_GPUShaderCreateInfo and SDL_GPUComputePipelineCreateInfo
+ * share the same struct layout for their first 3 members, which
+ * is all we need to transpile them!
+ */
+ createInfo = (const SDL_GPUShaderCreateInfo *)originalCreateInfo;
+
+ SPIRVTranspileContext *transpileContext = SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
+ backend,
+ shadermodel,
+ createInfo->code,
+ createInfo->code_size,
+ createInfo->entrypoint);
+
+ void *shaderObject = NULL;
/* Copy the original create info, but with the new source code */
if (isCompute) {
- SDL_GPUComputePipelineCreateInfo *newCreateInfo = SDL_malloc(sizeof(SDL_GPUComputePipelineCreateInfo));
- SDL_memcpy(newCreateInfo, createInfo, sizeof(SDL_GPUComputePipelineCreateInfo));
-
- newCreateInfo->format = shaderFormat;
+ SDL_GPUComputePipelineCreateInfo newCreateInfo;
+ newCreateInfo = *(const SDL_GPUComputePipelineCreateInfo *)createInfo;
- size_t cleansed_entrypoint_length = SDL_utf8strlen(cleansed_entrypoint) + 1;
- newCreateInfo->entrypoint = SDL_malloc(cleansed_entrypoint_length);
- SDL_utf8strlcpy((char *)newCreateInfo->entrypoint, cleansed_entrypoint, cleansed_entrypoint_length);
+ newCreateInfo.entrypoint = transpileContext->cleansed_entrypoint;
+ newCreateInfo.format = shaderFormat;
if (shaderFormat == SDL_GPU_SHADERFORMAT_DXBC) {
- newCreateInfo->code = SDL_ShaderCross_CompileDXBCFromHLSL(
- translated_source,
- cleansed_entrypoint,
+ newCreateInfo.code = SDL_ShaderCross_CompileDXBCFromHLSL(
+ transpileContext->translated_source,
+ transpileContext->cleansed_entrypoint,
(shadermodel == 50) ? "cs_5_0" : "cs_6_0",
- &newCreateInfo->code_size);
+ &newCreateInfo.code_size);
} else if (shaderFormat == SDL_GPU_SHADERFORMAT_DXIL) {
- newCreateInfo->code = SDL_ShaderCross_CompileDXILFromHLSL(
- translated_source,
- cleansed_entrypoint,
+ newCreateInfo.code = SDL_ShaderCross_CompileDXILFromHLSL(
+ transpileContext->translated_source,
+ transpileContext->cleansed_entrypoint,
(shadermodel == 50) ? "cs_5_0" : "cs_6_0",
- &newCreateInfo->code_size);
+ &newCreateInfo.code_size);
} else { // MSL
- newCreateInfo->code_size = SDL_strlen(translated_source) + 1;
- newCreateInfo->code = SDL_malloc(newCreateInfo->code_size);
- SDL_strlcpy((char *)newCreateInfo->code, translated_source, newCreateInfo->code_size);
+ newCreateInfo.code = (const Uint8 *)transpileContext->translated_source;
+ newCreateInfo.code_size = SDL_strlen(transpileContext->translated_source) + 1;
}
- translatedCreateInfo = newCreateInfo;
+ shaderObject = SDL_CreateGPUComputePipeline(device, &newCreateInfo);
} else {
- SDL_GPUShaderCreateInfo *newCreateInfo = SDL_malloc(sizeof(SDL_GPUShaderCreateInfo));
- SDL_memcpy(newCreateInfo, createInfo, sizeof(SDL_GPUShaderCreateInfo));
-
- newCreateInfo->format = shaderFormat;
+ SDL_GPUShaderCreateInfo newCreateInfo;
+ newCreateInfo = *createInfo;
- size_t cleansed_entrypoint_length = SDL_utf8strlen(cleansed_entrypoint) + 1;
- newCreateInfo->entrypoint = SDL_malloc(cleansed_entrypoint_length);
- SDL_utf8strlcpy((char *)newCreateInfo->entrypoint, cleansed_entrypoint, cleansed_entrypoint_length);
+ newCreateInfo.format = shaderFormat;
+ newCreateInfo.entrypoint = transpileContext->cleansed_entrypoint;
const char *profile;
- if (newCreateInfo->stage == SDL_GPU_SHADERSTAGE_VERTEX) {
+ if (newCreateInfo.stage == SDL_GPU_SHADERSTAGE_VERTEX) {
profile = (shadermodel == 50) ? "vs_5_0" : "vs_6_0";
} else {
profile = (shadermodel == 50) ? "ps_5_0" : "ps_6_0";
}
if (shaderFormat == SDL_GPU_SHADERFORMAT_DXBC) {
- newCreateInfo->code = SDL_ShaderCross_CompileDXBCFromHLSL(
- translated_source,
- cleansed_entrypoint,
+ newCreateInfo.code = SDL_ShaderCross_CompileDXBCFromHLSL(
+ transpileContext->translated_source,
+ transpileContext->cleansed_entrypoint,
profile,
- &newCreateInfo->code_size);
+ &newCreateInfo.code_size);
} else if (shaderFormat == SDL_GPU_SHADERFORMAT_DXIL) {
- newCreateInfo->code = SDL_ShaderCross_CompileDXILFromHLSL(
- translated_source,
- cleansed_entrypoint,
+ newCreateInfo.code = SDL_ShaderCross_CompileDXILFromHLSL(
+ transpileContext->translated_source,
+ transpileContext->cleansed_entrypoint,
profile,
- &newCreateInfo->code_size);
+ &newCreateInfo.code_size);
} else { // MSL
- newCreateInfo->code_size = SDL_strlen(translated_source) + 1;
- newCreateInfo->code = SDL_malloc(newCreateInfo->code_size);
- SDL_strlcpy((char *)newCreateInfo->code, translated_source, newCreateInfo->code_size);
+ newCreateInfo.code = (const Uint8 *)transpileContext->translated_source;
+ newCreateInfo.code_size = SDL_strlen(transpileContext->translated_source) + 1;
}
- translatedCreateInfo = newCreateInfo;
+ shaderObject = SDL_CreateGPUShader(device, &newCreateInfo);
}
- SDL_spvc_context_destroy(context);
- return translatedCreateInfo;
+ SDL_ShaderCross_INTERNAL_DestroyTranspileContext(transpileContext);
+ return shaderObject;
}
-static void *SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
- SDL_GPUShaderFormat format,
+void *SDL_ShaderCross_TranspileMSLFromSPIRV(
const Uint8 *bytecode,
size_t bytecodeSize,
const char *entrypoint,
- SDL_ShaderCross_ShaderStage shaderStage,
- size_t *size)
+ SDL_ShaderCross_ShaderStage shaderStage)
{
- if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_COMPUTE) {
- SDL_GPUComputePipelineCreateInfo createInfo;
- createInfo.code = bytecode;
- createInfo.code_size = bytecodeSize;
- createInfo.entrypoint = entrypoint;
- createInfo.format = SDL_GPU_SHADERFORMAT_SPIRV;
-
- SDL_GPUComputePipelineCreateInfo *translatedCreateInfo = (SDL_GPUComputePipelineCreateInfo *)SDL_ShaderCross_INTERNAL_TranslateFromSPIRV(
- format,
- &createInfo,
- true);
-
- void *result = (void *)translatedCreateInfo->code;
- *size = translatedCreateInfo->code_size;
- SDL_free((void *)translatedCreateInfo->entrypoint);
- SDL_free(translatedCreateInfo);
-
- return result;
- } else {
- SDL_GPUShaderCreateInfo createInfo;
- createInfo.code = bytecode;
- createInfo.code_size = bytecodeSize;
- createInfo.entrypoint = entrypoint;
- createInfo.format = SDL_GPU_SHADERFORMAT_SPIRV;
- createInfo.stage = (SDL_GPUShaderStage)shaderStage;
-
- SDL_GPUShaderCreateInfo *translatedCreateInfo = (SDL_GPUShaderCreateInfo *)SDL_ShaderCross_INTERNAL_TranslateFromSPIRV(
- format,
- &createInfo,
- false);
-
- void *result = (void *)translatedCreateInfo->code;
- *size = translatedCreateInfo->code_size;
- SDL_free((void *)translatedCreateInfo->entrypoint);
- SDL_free(translatedCreateInfo);
-
- return result;
- }
+ SPIRVTranspileContext *context = SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
+ SPVC_BACKEND_MSL,
+ 0,
+ bytecode,
+ bytecodeSize,
+ entrypoint
+ );
+
+ size_t length = SDL_strlen(context->translated_source) + 1;
+ char *result = SDL_malloc(length);
+ SDL_strlcpy(result, context->translated_source, length);
+
+ SDL_ShaderCross_INTERNAL_DestroyTranspileContext(context);
+ return result;
}
-void *SDL_ShaderCross_TranspileMSLFromSPIRV(
+void *SDL_ShaderCross_TranspileHLSLFromSPIRV(
const Uint8 *bytecode,
size_t bytecodeSize,
const char *entrypoint,
- SDL_ShaderCross_ShaderStage shaderStage)
+ const char *shaderProfile)
{
- size_t size;
- return SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
- SDL_GPU_SHADERFORMAT_MSL,
+ unsigned int shadermodel = 0;
+
+ if (SDL_strstr(shaderProfile, "5_0")) {
+ shadermodel = 50;
+ } else if (SDL_strstr(shaderProfile, "6_0")) {
+ shadermodel = 60;
+ } else {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Invalid shader profile!");
+ return NULL;
+ }
+
+ SPIRVTranspileContext *context = SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
+ SPVC_BACKEND_HLSL,
+ shadermodel,
bytecode,
bytecodeSize,
- entrypoint,
- shaderStage,
- &size);
+ entrypoint
+ );
+
+ size_t length = SDL_strlen(context->translated_source) + 1;
+ char *result = SDL_malloc(length);
+ SDL_strlcpy(result, context->translated_source, length);
+
+ SDL_ShaderCross_INTERNAL_DestroyTranspileContext(context);
+ return result;
}
void *SDL_ShaderCross_CompileDXBCFromSPIRV(
@@ -988,13 +1006,30 @@ void *SDL_ShaderCross_CompileDXBCFromSPIRV(
SDL_ShaderCross_ShaderStage shaderStage,
size_t *size)
{
- return SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
- SDL_GPU_SHADERFORMAT_DXBC,
+ SPIRVTranspileContext *context = SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
+ SPVC_BACKEND_HLSL,
+ 50,
bytecode,
bytecodeSize,
- entrypoint,
- shaderStage,
+ entrypoint);
+
+ const char *profile;
+ if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_VERTEX) {
+ profile = "vs_5_0";
+ } else if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT) {
+ profile = "ps_5_0";
+ } else { // compute
+ profile = "cs_5_0";
+ }
+
+ void *result = SDL_ShaderCross_CompileDXBCFromHLSL(
+ context->translated_source,
+ context->cleansed_entrypoint,
+ profile,
size);
+
+ SDL_ShaderCross_INTERNAL_DestroyTranspileContext(context);
+ return result;
}
void *SDL_ShaderCross_CompileDXILFromSPIRV(
@@ -1004,13 +1039,30 @@ void *SDL_ShaderCross_CompileDXILFromSPIRV(
SDL_ShaderCross_ShaderStage shaderStage,
size_t *size)
{
- return SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
- SDL_GPU_SHADERFORMAT_DXIL,
+ SPIRVTranspileContext *context = SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
+ SPVC_BACKEND_HLSL,
+ 60,
bytecode,
bytecodeSize,
- entrypoint,
- shaderStage,
+ entrypoint);
+
+ const char *profile;
+ if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_VERTEX) {
+ profile = "vs_6_0";
+ } else if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT) {
+ profile = "ps_6_0";
+ } else { // compute
+ profile = "cs_6_0";
+ }
+
+ void *result = SDL_ShaderCross_CompileDXILFromHLSL(
+ context->translated_source,
+ context->cleansed_entrypoint,
+ profile,
size);
+
+ SDL_ShaderCross_INTERNAL_DestroyTranspileContext(context);
+ return result;
}
static void *SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(
@@ -1019,7 +1071,6 @@ static void *SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(
bool isCompute)
{
SDL_GPUShaderFormat format;
- void *compiledResult;
SDL_GPUShaderFormat shader_formats = SDL_GetGPUShaderFormats(device);
@@ -1040,26 +1091,11 @@ static void *SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(
return NULL;
}
- void *translatedCreateInfo = SDL_ShaderCross_INTERNAL_TranslateFromSPIRV(
+ return SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
+ device,
format,
originalCreateInfo,
isCompute);
-
- if (isCompute) {
- SDL_GPUComputePipelineCreateInfo *computeCreateInfo = (SDL_GPUComputePipelineCreateInfo *)translatedCreateInfo;
- compiledResult = SDL_CreateGPUComputePipeline(device, computeCreateInfo);
- SDL_free((void *)computeCreateInfo->entrypoint);
- SDL_free((void *)computeCreateInfo->code);
- SDL_free(computeCreateInfo);
- } else {
- SDL_GPUShaderCreateInfo *shaderCreateInfo = (SDL_GPUShaderCreateInfo *)translatedCreateInfo;
- compiledResult = SDL_CreateGPUShader(device, shaderCreateInfo);
- SDL_free((void *)shaderCreateInfo->entrypoint);
- SDL_free((void *)shaderCreateInfo->code);
- SDL_free(shaderCreateInfo);
- }
-
- return compiledResult;
}
SDL_GPUShader *SDL_ShaderCross_CompileGraphicsShaderFromSPIRV(
diff --git a/src/cli.c b/src/cli.c
index ac28eea..d9be75a 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -23,16 +23,26 @@
#include <SDL3/SDL_log.h>
#include <SDL3/SDL_iostream.h>
+// We can emit HLSL as a destination, so let's redefine the shader format enum.
+typedef enum ShaderCross_DestinationFormat {
+ SHADERFORMAT_INVALID,
+ SHADERFORMAT_SPIRV,
+ SHADERFORMAT_DXBC,
+ SHADERFORMAT_DXIL,
+ SHADERFORMAT_MSL,
+ SHADERFORMAT_HLSL
+} ShaderCross_ShaderFormat;
+
void print_help()
{
int column_width = 32;
SDL_Log("%s", "Usage: shadercross <input> [options]");
SDL_Log("%s", "Required options:\n");
SDL_Log(" %-*s %s", column_width, "-s | --source <value>", "Source language format. May be inferred from the filename. Values: [SPIRV, HLSL]");
- SDL_Log(" %-*s %s", column_width, "-d | --dest <value>", "Destination format. May be inferred from the filename. Values: [DXBC, DXIL, MSL, SPIRV]");
+ SDL_Log(" %-*s %s", column_width, "-d | --dest <value>", "Destination format. May be inferred from the filename. Values: [DXBC, DXIL, MSL, SPIRV, HLSL]");
SDL_Log(" %-*s %s", column_width, "-t | --stage <value>", "Shader stage. May be inferred from the filename. Values: [vertex, fragment, compute]");
SDL_Log(" %-*s %s", column_width, "-e | --entrypoint <value>", "Entrypoint function name. Default: \"main\".");
- SDL_Log(" %-*s %s", column_width, "-m | --shadermodel <value>", "HLSL Shader Model. Only used with HLSL source. Values: [50, 51, 60]");
+ SDL_Log(" %-*s %s", column_width, "-m | --shadermodel <value>", "HLSL Shader Model. Only used with HLSL source or destination. Values: [50, 60]");
SDL_Log(" %-*s %s", column_width, "-o | --output <value>", "Output file.");
}
@@ -44,7 +54,7 @@ int main(int argc, char *argv[])
bool stageValid = false;
bool spirvSource = false;
- SDL_GPUShaderFormat destinationFormat = SDL_GPU_SHADERFORMAT_INVALID;
+ ShaderCross_ShaderFormat destinationFormat = SHADERFORMAT_INVALID;
SDL_ShaderCross_ShaderStage shaderStage = SDL_SHADERCROSS_SHADERSTAGE_VERTEX;
char *outputFilename = NULL;
char *entrypointName = "main";
@@ -88,16 +98,16 @@ int main(int argc, char *argv[])
}
i += 1;
if (SDL_strcasecmp(argv[i], "DXBC") == 0) {
- destinationFormat = SDL_GPU_SHADERFORMAT_DXBC;
+ destinationFormat = SHADERFORMAT_DXBC;
destinationValid = true;
} else if (SDL_strcasecmp(argv[i], "DXIL") == 0) {
- destinationFormat = SDL_GPU_SHADERFORMAT_DXIL;
+ destinationFormat = SHADERFORMAT_DXIL;
destinationValid = true;
} else if (SDL_strcasecmp(argv[i], "MSL") == 0) {
- destinationFormat = SDL_GPU_SHADERFORMAT_MSL;
+ destinationFormat = SHADERFORMAT_MSL;
destinationValid = true;
} else if (SDL_strcasecmp(argv[i], "SPIRV") == 0) {
- destinationFormat = SDL_GPU_SHADERFORMAT_SPIRV;
+ destinationFormat = SHADERFORMAT_SPIRV;
destinationValid = true;
} else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unrecognized destination input %s, destination must be DXBC, DXIL, MSL or SPIRV!", argv[i]);
@@ -153,14 +163,14 @@ int main(int argc, char *argv[])
accept_optionals = false;
} else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s: Unknown argument: %s", argv[0], arg);
- print_help(1);
+ print_help();
return 1;
}
} else if (!filename) {
filename = arg;
} else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s: Unknown argument: %s", argv[0], arg);
- print_help(1);
+ print_help();
return 1;
}
}
@@ -194,13 +204,15 @@ int main(int argc, char *argv[])
if (!destinationValid) {
if (SDL_strstr(outputFilename, ".dxbc")) {
- destinationFormat = SDL_GPU_SHADERFORMAT_DXBC;
+ destinationFormat = SHADERFORMAT_DXBC;
} else if (SDL_strstr(outputFilename, ".dxil")) {
- destinationFormat = SDL_GPU_SHADERFORMAT_DXIL;
+ destinationFormat = SHADERFORMAT_DXIL;
} else if (SDL_strstr(outputFilename, ".msl")) {
- destinationFormat = SDL_GPU_SHADERFORMAT_MSL;
+ destinationFormat = SHADERFORMAT_MSL;
} else if (SDL_strstr(outputFilename, ".spv")) {
- destinationFormat = SDL_GPU_SHADERFORMAT_SPIRV;
+ destinationFormat = SHADERFORMAT_SPIRV;
+ } else if (SDL_strstr(outputFilename, ".hlsl")) {
+ destinationFormat = SHADERFORMAT_HLSL;
} else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Could not infer destination format!");
print_help();
@@ -233,7 +245,7 @@ int main(int argc, char *argv[])
if (spirvSource) {
switch (destinationFormat) {
- case SDL_GPU_SHADERFORMAT_DXBC: {
+ case SHADERFORMAT_DXBC: {
Uint8 *buffer = SDL_ShaderCross_CompileDXBCFromSPIRV(
fileData,
fileSize,
@@ -247,7 +259,7 @@ int main(int argc, char *argv[])
break;
}
- case SDL_GPU_SHADERFORMAT_DXIL: {
+ case SHADERFORMAT_DXIL: {
Uint8 *buffer = SDL_ShaderCross_CompileDXILFromSPIRV(
fileData,
fileSize,
@@ -261,21 +273,60 @@ int main(int argc, char *argv[])
break;
}
- case SDL_GPU_SHADERFORMAT_MSL: {
+ case SHADERFORMAT_MSL: {
char *buffer = SDL_ShaderCross_TranspileMSLFromSPIRV(
fileData,
fileSize,
entrypointName,
- SDL_SHADERCROSS_SHADERSTAGE_VERTEX);
+ shaderStage);
+ SDL_IOprintf(outputIO, "%s", buffer);
+ SDL_free(buffer);
+ break;
+ }
+
+ case SHADERFORMAT_HLSL: {
+ char *profileName;
+ if (shaderModel == 50) {
+ if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_VERTEX) {
+ profileName = "vs_5_0";
+ } else if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT) {
+ profileName = "ps_5_0";
+ } else {
+ profileName = "cs_5_0";
+ }
+ } else if (shaderModel == 60) {
+ if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_VERTEX) {
+ profileName = "vs_6_0";
+ } else if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT) {
+ profileName = "ps_6_0";
+ } else {
+ profileName = "cs_6_0";
+ }
+ } else {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Unrecognized shader model!");
+ print_help();
+ return 1;
+ }
+
+ char *buffer = SDL_ShaderCross_TranspileHLSLFromSPIRV(
+ fileData,
+ fileSize,
+ entrypointName,
+ profileName);
SDL_IOprintf(outputIO, "%s", buffer);
SDL_free(buffer);
break;
}
- case SDL_GPU_SHADERFORMAT_SPIRV: {
+ case SHADERFORMAT_SPIRV: {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Input and output are both SPIRV. Did you mean to do that?");
return 1;
}
+
+ case SHADERFORMAT_INVALID: {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Destination format not provided!");
+ return 1;
+ }
}
} else {
char *profileName;
@@ -287,14 +338,6 @@ int main(int argc, char *argv[])
} else {
profileName = "cs_5_0";
}
- } else if (shaderModel == 51) {
- if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_VERTEX) {
- profileName = "vs_5_1";
- } else if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT) {
- profileName = "ps_5_1";
- } else {
- profileName = "cs_5_1";
- }
} else if (shaderModel == 60) {
if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_VERTEX) {
profileName = "vs_6_0";
@@ -310,7 +353,7 @@ int main(int argc, char *argv[])
}
switch (destinationFormat) {
- case SDL_GPU_SHADERFORMAT_DXBC: {
+ case SHADERFORMAT_DXBC: {
Uint8 *buffer = SDL_ShaderCross_CompileDXBCFromHLSL(
fileData,
entrypointName,
@@ -323,7 +366,7 @@ int main(int argc, char *argv[])
break;
}
- case SDL_GPU_SHADERFORMAT_DXIL: {
+ case SHADERFORMAT_DXIL: {
Uint8 *buffer = SDL_ShaderCross_CompileDXILFromHLSL(
fileData,
entrypointName,
@@ -336,7 +379,7 @@ int main(int argc, char *argv[])
break;
}
- case SDL_GPU_SHADERFORMAT_MSL: {
+ case SHADERFORMAT_MSL: {
void *spirv = SDL_ShaderCross_CompileSPIRVFromHLSL(
fileData,
entrypointName,
@@ -353,7 +396,7 @@ int main(int argc, char *argv[])
break;
}
- case SDL_GPU_SHADERFORMAT_SPIRV: {
+ case SHADERFORMAT_SPIRV: {
Uint8 *buffer = SDL_ShaderCross_CompileSPIRVFromHLSL(
fileData,
entrypointName,
@@ -365,6 +408,16 @@ int main(int argc, char *argv[])
SDL_free(buffer);
return 0;
}
+
+ case SHADERFORMAT_HLSL: {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Input and output are both HLSL. Did you mean to do that?");
+ return 1;
+ }
+
+ case SHADERFORMAT_INVALID: {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Destination format not provided!");
+ return 1;
+ }
}
}
(Patch may be truncated, please check the link at the top of this post.)