From 619feb059a283e8cd612e7fdce118bc3c8fc3165 Mon Sep 17 00:00:00 2001
From: cosmonaut <[EMAIL REDACTED]>
Date: Thu, 24 Oct 2024 14:15:25 -0700
Subject: [PATCH] Refactor to allow dumping bytecode
---
include/SDL_gpu_shadercross.h | 144 ++++++++++-
src/SDL_gpu_shadercross.c | 437 +++++++++++++++++++++++++++-------
2 files changed, 480 insertions(+), 101 deletions(-)
diff --git a/include/SDL_gpu_shadercross.h b/include/SDL_gpu_shadercross.h
index 58fed06..99c8656 100644
--- a/include/SDL_gpu_shadercross.h
+++ b/include/SDL_gpu_shadercross.h
@@ -44,6 +44,13 @@
#define SDL_GPU_SHADERCROSS_EXPORT
#endif
+typedef enum SDL_ShaderCross_ShaderStage
+{
+ SDL_SHADERCROSS_SHADERSTAGE_VERTEX,
+ SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT,
+ SDL_SHADERCROSS_SHADERSTAGE_COMPUTE
+} SDL_ShaderCross_ShaderStage;
+
/**
* Initializes SDL_gpu_shadercross
*
@@ -65,6 +72,58 @@ extern SHADERCROSSAPI void SDL_ShaderCross_Quit(void);
*/
extern SHADERCROSSAPI SDL_GPUShaderFormat SDL_ShaderCross_GetSPIRVShaderFormats(void);
+/**
+ * Transpile to MSL 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.
+ * \param shaderStage the shader stage to transpile the shader with.
+ */
+extern SHADERCROSSAPI void *SDL_ShaderCross_TranspileMSLFromSPIRV(
+ const Uint8 *bytecode,
+ size_t bytecodeSize,
+ const char *entrypoint,
+ SDL_ShaderCross_ShaderStage shaderStage);
+
+/**
+ * Compile DXBC bytecode from SPIRV code.
+ *
+ * You must SDL_free the returned buffer 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.
+ * \param shaderStage the shader stage to transpile the shader with.
+ * \param size filled in with the bytecode buffer size.
+ */
+extern SHADERCROSSAPI void *SDL_ShaderCross_CompileDXBCFromSPIRV(
+ const Uint8 *bytecode,
+ size_t bytecodeSize,
+ const char *entrypoint,
+ SDL_ShaderCross_ShaderStage shaderStage,
+ size_t *size);
+
+/**
+ * Compile DXIL bytecode from SPIRV code.
+ *
+ * You must SDL_free the returned buffer 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.
+ * \param shaderStage the shader stage to transpile the shader with.
+ * \param size filled in with the bytecode buffer size.
+ */
+extern SHADERCROSSAPI void *SDL_ShaderCross_CompileDXILFromSPIRV(
+ const Uint8 *bytecode,
+ size_t bytecodeSize,
+ const char *entrypoint,
+ SDL_ShaderCross_ShaderStage shaderStage,
+ size_t *size);
+
/**
* Compile an SDL GPU shader from SPIRV code.
*
@@ -74,8 +133,9 @@ extern SHADERCROSSAPI SDL_GPUShaderFormat SDL_ShaderCross_GetSPIRVShaderFormats(
*
* \threadsafety It is safe to call this function from any thread.
*/
-extern SHADERCROSSAPI SDL_GPUShader *SDL_ShaderCross_CompileGraphicsShaderFromSPIRV(SDL_GPUDevice *device,
- const SDL_GPUShaderCreateInfo *createInfo);
+extern SHADERCROSSAPI SDL_GPUShader *SDL_ShaderCross_CompileGraphicsShaderFromSPIRV(
+ SDL_GPUDevice *device,
+ const SDL_GPUShaderCreateInfo *createInfo);
/**
* Compile an SDL GPU compute pipeline from SPIRV code.
@@ -86,8 +146,9 @@ extern SHADERCROSSAPI SDL_GPUShader *SDL_ShaderCross_CompileGraphicsShaderFromSP
*
* \threadsafety It is safe to call this function from any thread.
*/
-extern SHADERCROSSAPI SDL_GPUComputePipeline *SDL_ShaderCross_CompileComputePipelineFromSPIRV(SDL_GPUDevice *device,
- const SDL_GPUComputePipelineCreateInfo *createInfo);
+extern SHADERCROSSAPI SDL_GPUComputePipeline *SDL_ShaderCross_CompileComputePipelineFromSPIRV(
+ SDL_GPUDevice *device,
+ const SDL_GPUComputePipelineCreateInfo *createInfo);
#endif /* SDL_GPU_SHADERCROSS_SPIRVCROSS */
#if SDL_GPU_SHADERCROSS_HLSL
@@ -98,6 +159,63 @@ extern SHADERCROSSAPI SDL_GPUComputePipeline *SDL_ShaderCross_CompileComputePipe
*/
extern SHADERCROSSAPI SDL_GPUShaderFormat SDL_ShaderCross_GetHLSLShaderFormats(void);
+/**
+ * Compile to DXBC bytecode from HLSL code.
+ *
+ * You must SDL_free the returned buffer once you are done with it.
+ *
+ * \param hlslSource the HLSL source code for the shader.
+ * \param entrypoint the entry point function name for the shader.
+ * \param shaderProfile the shader profile to compile the shader with.
+ * \param size filled in with the bytecode buffer size.
+ * \returns an SDL_malloc'd buffer containing DXBC bytecode.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ */
+extern SHADERCROSSAPI void *SDL_ShaderCross_CompileDXBCFromHLSL(
+ const char *hlslSource,
+ const char *entrypoint,
+ const char *shaderProfile,
+ size_t *size);
+
+/**
+ * Compile to DXIL bytecode from HLSL code.
+ *
+ * You must SDL_free the returned buffer once you are done with it.
+ *
+ * \param hlslSource the HLSL source code for the shader.
+ * \param entrypoint the entry point function name for the shader.
+ * \param shaderProfile the shader profile to compile the shader with.
+ * \param size filled in with the bytecode buffer size.
+ * \returns an SDL_malloc'd buffer containing DXIL bytecode.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ */
+extern SHADERCROSSAPI void *SDL_ShaderCross_CompileDXILFromHLSL(
+ const char *hlslSource,
+ const char *entrypoint,
+ const char *shaderProfile,
+ size_t *size);
+
+/**
+ * Compile to SPIRV bytecode from HLSL code.
+ *
+ * You must SDL_free the returned buffer once you are done with it.
+ *
+ * \param hlslSource the HLSL source code for the shader.
+ * \param entrypoint the entry point function name for the shader.
+ * \param shaderProfile the shader profile to compile the shader with.
+ * \param size filled in with the bytecode buffer size.
+ * \returns an SDL_malloc'd buffer containing SPIRV bytecode.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ */
+extern SHADERCROSSAPI void *SDL_ShaderCross_CompileSPIRVFromHLSL(
+ const char *hlslSource,
+ const char *entrypoint,
+ const char *shaderProfile,
+ size_t *size);
+
/**
* Compile an SDL GPU shader from HLSL code.
*
@@ -109,10 +227,11 @@ extern SHADERCROSSAPI SDL_GPUShaderFormat SDL_ShaderCross_GetHLSLShaderFormats(v
*
* \threadsafety It is safe to call this function from any thread.
*/
-extern SHADERCROSSAPI SDL_GPUShader *SDL_ShaderCross_CompileGraphicsShaderFromHLSL(SDL_GPUDevice *device,
- const SDL_GPUShaderCreateInfo *createInfo,
- const char *hlslSource,
- const char *shaderProfile);
+extern SHADERCROSSAPI SDL_GPUShader *SDL_ShaderCross_CompileGraphicsShaderFromHLSL(
+ SDL_GPUDevice *device,
+ const SDL_GPUShaderCreateInfo *createInfo,
+ const char *hlslSource,
+ const char *shaderProfile);
/**
* Compile an SDL GPU compute pipeline from HLSL code.
@@ -125,10 +244,11 @@ extern SHADERCROSSAPI SDL_GPUShader *SDL_ShaderCross_CompileGraphicsShaderFromHL
*
* \threadsafety It is safe to call this function from any thread.
*/
-extern SHADERCROSSAPI SDL_GPUComputePipeline *SDL_ShaderCross_CompileComputePipelineFromHLSL(SDL_GPUDevice *device,
- const SDL_GPUComputePipelineCreateInfo *createInfo,
- const char *hlslSource,
- const char *shaderProfile);
+extern SHADERCROSSAPI SDL_GPUComputePipeline *SDL_ShaderCross_CompileComputePipelineFromHLSL(
+ SDL_GPUDevice *device,
+ const SDL_GPUComputePipelineCreateInfo *createInfo,
+ const char *hlslSource,
+ const char *shaderProfile);
#endif /* SDL_GPU_SHADERCROSS_HLSL */
#endif /* SDL_GPU_SHADERCROSS_H */
diff --git a/src/SDL_gpu_shadercross.c b/src/SDL_gpu_shadercross.c
index d2a8774..ad64b95 100644
--- a/src/SDL_gpu_shadercross.c
+++ b/src/SDL_gpu_shadercross.c
@@ -285,13 +285,12 @@ typedef HRESULT(__stdcall *DxcCreateInstanceProc)(
static DxcCreateInstanceProc SDL_DxcCreateInstance = NULL;
-static void *SDL_ShaderCross_INTERNAL_CompileDXC(
- SDL_GPUDevice *device,
- const void *createInfo,
+static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
const char *hlslSource,
+ const char *entrypoint,
const char *shaderProfile,
- UINT encoding,
- bool spirv)
+ bool spirv,
+ size_t *size) // filled in with number of bytes of returned buffer
{
DxcBuffer source;
IDxcResult *dxcResult;
@@ -307,7 +306,6 @@ static void *SDL_ShaderCross_INTERNAL_CompileDXC(
};
Uint32 argCount = 2;
HRESULT ret;
- void *result;
/* Non-static DxcInstance, since the functions we call on it are not thread-safe */
IDxcCompiler3 *dxcInstance = NULL;
@@ -321,7 +319,7 @@ static void *SDL_ShaderCross_INTERNAL_CompileDXC(
source.Ptr = hlslSource;
source.Size = SDL_strlen(hlslSource) + 1;
- source.Encoding = encoding;
+ source.Encoding = DXC_CP_ACP;
if (SDL_strcmp(shaderProfile, "ps_6_0") == 0) {
args[argCount++] = (LPCWSTR)L"-T";
@@ -390,27 +388,84 @@ static void *SDL_ShaderCross_INTERNAL_CompileDXC(
return NULL;
}
+ *size = blob->lpVtbl->GetBufferSize(blob);
+ void *buffer = SDL_malloc(*size);
+ SDL_memcpy(buffer, blob->lpVtbl->GetBufferPointer(blob), *size);
+
+ dxcResult->lpVtbl->Release(dxcResult);
+ dxcInstance->lpVtbl->Release(dxcInstance);
+
+ return buffer;
+}
+
+void *SDL_ShaderCross_CompileDXILFromHLSL(
+ const char *hlslSource,
+ const char *entrypoint,
+ const char *shaderProfile,
+ size_t *size)
+{
+ return SDL_ShaderCross_INTERNAL_CompileUsingDXC(
+ hlslSource,
+ entrypoint,
+ shaderProfile,
+ false,
+ size);
+}
+
+void *SDL_ShaderCross_CompileSPIRVFromHLSL(
+ const char *hlslSource,
+ const char *entrypoint,
+ const char *shaderProfile,
+ size_t *size)
+{
+ return SDL_ShaderCross_INTERNAL_CompileUsingDXC(
+ hlslSource,
+ entrypoint,
+ shaderProfile,
+ true,
+ size);
+}
+
+static void *SDL_ShaderCross_INTERNAL_CreateShaderFromDXC(
+ SDL_GPUDevice *device,
+ const void *createInfo,
+ const char *hlslSource,
+ const char *shaderProfile,
+ bool spirv)
+{
+ void *result;
+ size_t bytecodeSize;
+
+ void *bytecode = SDL_ShaderCross_INTERNAL_CompileUsingDXC(
+ hlslSource,
+ ((const SDL_GPUShaderCreateInfo *)createInfo)->entrypoint,
+ shaderProfile,
+ spirv,
+ &bytecodeSize);
+
+ if (bytecode == NULL) {
+ return NULL;
+ }
+
if (shaderProfile[0] == 'c' && shaderProfile[1] == 's') {
SDL_GPUComputePipelineCreateInfo newCreateInfo;
newCreateInfo = *(const SDL_GPUComputePipelineCreateInfo *)createInfo;
- newCreateInfo.code = (const Uint8 *)blob->lpVtbl->GetBufferPointer(blob);
- newCreateInfo.code_size = blob->lpVtbl->GetBufferSize(blob);
+ newCreateInfo.code = (const Uint8 *)bytecode;
+ newCreateInfo.code_size = bytecodeSize;
newCreateInfo.format = spirv ? SDL_GPU_SHADERFORMAT_SPIRV : SDL_GPU_SHADERFORMAT_DXIL;
result = SDL_CreateGPUComputePipeline(device, &newCreateInfo);
} else {
SDL_GPUShaderCreateInfo newCreateInfo;
newCreateInfo = *(const SDL_GPUShaderCreateInfo *)createInfo;
- newCreateInfo.code = (const Uint8 *)blob->lpVtbl->GetBufferPointer(blob);
- newCreateInfo.code_size = blob->lpVtbl->GetBufferSize(blob);
+ newCreateInfo.code = (const Uint8 *)bytecode;
+ newCreateInfo.code_size = bytecodeSize;
newCreateInfo.format = spirv ? SDL_GPU_SHADERFORMAT_SPIRV : SDL_GPU_SHADERFORMAT_DXIL;
result = SDL_CreateGPUShader(device, &newCreateInfo);
}
- dxcResult->lpVtbl->Release(dxcResult);
-
- dxcInstance->lpVtbl->Release(dxcInstance);
+ SDL_free(bytecode);
return result;
}
@@ -487,16 +542,14 @@ typedef HRESULT(__stdcall *pfn_D3DCompile)(
static pfn_D3DCompile SDL_D3DCompile = NULL;
-static void *SDL_ShaderCross_INTERNAL_CompileFXC(
- SDL_GPUDevice *device,
- const void *createInfo,
+static ID3DBlob *SDL_ShaderCross_INTERNAL_CompileDXBC(
const char *hlslSource,
+ const char *entrypoint,
const char *shaderProfile)
{
ID3DBlob *blob;
ID3DBlob *errorBlob;
HRESULT ret;
- void *result;
ret = SDL_D3DCompile(
hlslSource,
@@ -504,7 +557,7 @@ static void *SDL_ShaderCross_INTERNAL_CompileFXC(
NULL,
NULL,
NULL,
- ((const SDL_GPUShaderCreateInfo *)createInfo)->entrypoint,
+ entrypoint,
shaderProfile,
0,
0,
@@ -519,46 +572,92 @@ static void *SDL_ShaderCross_INTERNAL_CompileFXC(
return NULL;
}
+ return blob;
+}
+
+// Returns raw byte buffer
+void *SDL_ShaderCross_CompileDXBCFromHLSL(
+ const char *hlslSource,
+ const char *entrypoint,
+ const char *shaderProfile,
+ size_t *size) // filled in with number of bytes of returned buffer
+{
+ ID3DBlob *blob = SDL_ShaderCross_INTERNAL_CompileDXBC(
+ hlslSource,
+ entrypoint,
+ shaderProfile);
+
+ if (blob == NULL) {
+ *size = 0;
+ return NULL;
+ }
+
+ *size = blob->lpVtbl->GetBufferSize(blob);
+ void *buffer = SDL_malloc(*size);
+ SDL_memcpy(buffer, blob->lpVtbl->GetBufferPointer(blob), *size);
+ blob->lpVtbl->Release(blob);
+
+ return buffer;
+}
+
+static void *SDL_ShaderCross_INTERNAL_CreateShaderFromDXBC(
+ SDL_GPUDevice *device,
+ const void *createInfo,
+ const char *hlslSource,
+ const char *shaderProfile)
+{
+ void *result;
+ size_t bytecodeSize;
+
+ void *bytecode = SDL_ShaderCross_CompileDXBCFromHLSL(
+ hlslSource,
+ ((const SDL_GPUShaderCreateInfo *)createInfo)->entrypoint,
+ shaderProfile,
+ &bytecodeSize);
+
+ if (bytecode == NULL) {
+ return NULL;
+ }
+
if (shaderProfile[0] == 'c' && shaderProfile[1] == 's') {
SDL_GPUComputePipelineCreateInfo newCreateInfo;
newCreateInfo = *(const SDL_GPUComputePipelineCreateInfo *)createInfo;
- newCreateInfo.code = (const Uint8 *)blob->lpVtbl->GetBufferPointer(blob);
- newCreateInfo.code_size = blob->lpVtbl->GetBufferSize(blob);
+ newCreateInfo.code = (const Uint8 *)bytecode;
+ newCreateInfo.code_size = bytecodeSize;
newCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC;
result = SDL_CreateGPUComputePipeline(device, &newCreateInfo);
} else {
SDL_GPUShaderCreateInfo newCreateInfo;
newCreateInfo = *(const SDL_GPUShaderCreateInfo *)createInfo;
- newCreateInfo.code = (const Uint8 *)blob->lpVtbl->GetBufferPointer(blob);
- newCreateInfo.code_size = blob->lpVtbl->GetBufferSize(blob);
+ newCreateInfo.code = (const Uint8 *)bytecode;
+ newCreateInfo.code_size = bytecodeSize;
newCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC;
result = SDL_CreateGPUShader(device, &newCreateInfo);
}
- blob->lpVtbl->Release(blob);
-
+ SDL_free(bytecode);
return result;
}
-static void *SDL_ShaderCross_INTERNAL_CompileFromHLSL(SDL_GPUDevice *device,
+static void *SDL_ShaderCross_INTERNAL_CreateShaderFromHLSL(SDL_GPUDevice *device,
const void *createInfo,
const char *hlslSource,
const char *shaderProfile)
{
SDL_GPUShaderFormat format = SDL_GetGPUShaderFormats(device);
if (format & SDL_GPU_SHADERFORMAT_DXBC) {
- return SDL_ShaderCross_INTERNAL_CompileFXC(device, createInfo, hlslSource, shaderProfile);
+ return SDL_ShaderCross_INTERNAL_CreateShaderFromDXBC(device, createInfo, hlslSource, shaderProfile);
}
if (format & SDL_GPU_SHADERFORMAT_DXIL) {
- return SDL_ShaderCross_INTERNAL_CompileDXC(device, createInfo, hlslSource, shaderProfile, DXC_CP_ACP, false);
+ return SDL_ShaderCross_INTERNAL_CreateShaderFromDXC(device, createInfo, hlslSource, shaderProfile, false);
}
if (format & SDL_GPU_SHADERFORMAT_SPIRV) {
- return SDL_ShaderCross_INTERNAL_CompileDXC(device, createInfo, hlslSource, shaderProfile, DXC_CP_ACP, true);
+ return SDL_ShaderCross_INTERNAL_CreateShaderFromDXC(device, createInfo, hlslSource, shaderProfile, true);
}
- SDL_SetError("SDL_ShaderCross_INTERNAL_CompileFromHLSL: Unexpected SDL_GPUShaderFormat");
+ SDL_SetError("SDL_ShaderCross_INTERNAL_CreateShaderFromHLSL: Unexpected SDL_GPUShaderFormat");
return NULL;
}
@@ -568,7 +667,7 @@ SDL_GPU_SHADERCROSS_EXPORT SDL_GPUShader *SDL_ShaderCross_CompileGraphicsShaderF
const char *hlslSource,
const char *shaderProfile)
{
- return (SDL_GPUShader *)SDL_ShaderCross_INTERNAL_CompileFromHLSL(device, createInfo, hlslSource, shaderProfile);
+ return (SDL_GPUShader *)SDL_ShaderCross_INTERNAL_CreateShaderFromHLSL(device, createInfo, hlslSource, shaderProfile);
}
SDL_GPU_SHADERCROSS_EXPORT SDL_GPUComputePipeline *SDL_ShaderCross_CompileComputePipelineFromHLSL(
@@ -577,7 +676,7 @@ SDL_GPU_SHADERCROSS_EXPORT SDL_GPUComputePipeline *SDL_ShaderCross_CompileComput
const char *hlslSource,
const char *shaderProfile)
{
- return (SDL_GPUComputePipeline *)SDL_ShaderCross_INTERNAL_CompileFromHLSL(device, createInfo, hlslSource, shaderProfile);
+ return (SDL_GPUComputePipeline *)SDL_ShaderCross_INTERNAL_CreateShaderFromHLSL(device, createInfo, hlslSource, shaderProfile);
}
#endif /* SDL_GPU_SHADERCROSS_HLSL */
@@ -647,45 +746,34 @@ 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))
-static void *SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
- SDL_GPUDevice *device,
+// 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)
-{
+ bool isCompute
+) {
const SDL_GPUShaderCreateInfo *createInfo;
spvc_result result;
spvc_backend backend;
unsigned shadermodel;
- SDL_GPUShaderFormat format;
spvc_context context = NULL;
spvc_parsed_ir ir = NULL;
spvc_compiler compiler = NULL;
spvc_compiler_options options = NULL;
const char *translated_source;
const char *cleansed_entrypoint;
- void *compiledResult;
-
- SDL_GPUShaderFormat shader_formats = SDL_GetGPUShaderFormats(device);
- if (shader_formats & SDL_GPU_SHADERFORMAT_SPIRV) {
- if (isCompute) {
- return SDL_CreateGPUComputePipeline(device, (const SDL_GPUComputePipelineCreateInfo *)originalCreateInfo);
- } else {
- return SDL_CreateGPUShader(device, (const SDL_GPUShaderCreateInfo *)originalCreateInfo);
- }
- } else if (shader_formats & SDL_GPU_SHADERFORMAT_DXBC) {
+ if (shaderFormat == SDL_GPU_SHADERFORMAT_DXBC) {
backend = SPVC_BACKEND_HLSL;
- format = SDL_GPU_SHADERFORMAT_DXBC;
shadermodel = 50;
- } else if (shader_formats & SDL_GPU_SHADERFORMAT_DXIL) {
+ } else if (shaderFormat == SDL_GPU_SHADERFORMAT_DXIL) {
backend = SPVC_BACKEND_HLSL;
- format = SDL_GPU_SHADERFORMAT_DXIL;
shadermodel = 60;
- } else if (shader_formats & SDL_GPU_SHADERFORMAT_MSL) {
+ } else if (shaderFormat == SDL_GPU_SHADERFORMAT_MSL) {
backend = SPVC_BACKEND_MSL;
- format = SDL_GPU_SHADERFORMAT_MSL;
} else {
- SDL_SetError("SDL_ShaderCross_INTERNAL_CompileFromSPIRV: Unexpected SDL_GPUBackend");
+ SDL_SetError("SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV: Unexpected SDL_GPUBackend");
return NULL;
}
@@ -753,51 +841,222 @@ static void *SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
createInfo->entrypoint,
SDL_spvc_compiler_get_execution_model(compiler));
+ void *translatedCreateInfo = NULL;
+
/* Copy the original create info, but with the new source code */
if (isCompute) {
- SDL_GPUComputePipelineCreateInfo newCreateInfo;
- newCreateInfo = *(const SDL_GPUComputePipelineCreateInfo *)createInfo;
- newCreateInfo.format = format;
- newCreateInfo.entrypoint = cleansed_entrypoint;
+ SDL_GPUComputePipelineCreateInfo *newCreateInfo = SDL_malloc(sizeof(SDL_GPUComputePipelineCreateInfo));
+ SDL_memcpy(newCreateInfo, createInfo, sizeof(SDL_GPUComputePipelineCreateInfo));
+
+ newCreateInfo->format = shaderFormat;
+
+ 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);
- if (backend == SPVC_BACKEND_HLSL) {
- compiledResult = SDL_ShaderCross_INTERNAL_CompileFromHLSL(
- device,
- &newCreateInfo,
+ if (shaderFormat == SDL_GPU_SHADERFORMAT_DXBC) {
+ newCreateInfo->code = SDL_ShaderCross_CompileDXBCFromHLSL(
translated_source,
- (shadermodel == 50) ? "cs_5_0" : "cs_6_0");
- } else {
- newCreateInfo.code = (const Uint8 *)translated_source;
- newCreateInfo.code_size = SDL_strlen(translated_source) + 1;
- compiledResult = SDL_CreateGPUComputePipeline(device, &newCreateInfo);
+ cleansed_entrypoint,
+ (shadermodel == 50) ? "cs_5_0" : "cs_6_0",
+ &newCreateInfo->code_size);
+ } else if (shaderFormat == SDL_GPU_SHADERFORMAT_DXIL) {
+ newCreateInfo->code = SDL_ShaderCross_CompileDXILFromHLSL(
+ translated_source,
+ cleansed_entrypoint,
+ (shadermodel == 50) ? "cs_5_0" : "cs_6_0",
+ &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);
}
+
+ translatedCreateInfo = newCreateInfo;
} else {
- SDL_GPUShaderCreateInfo newCreateInfo;
- newCreateInfo = *createInfo;
- newCreateInfo.format = format;
- newCreateInfo.entrypoint = cleansed_entrypoint;
-
- if (backend == SPVC_BACKEND_HLSL) {
- const char *profile;
- 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";
- }
- compiledResult = SDL_ShaderCross_INTERNAL_CompileFromHLSL(
- device,
- &newCreateInfo,
- translated_source,
- profile);
+ SDL_GPUShaderCreateInfo *newCreateInfo = SDL_malloc(sizeof(SDL_GPUShaderCreateInfo));
+ SDL_memcpy(newCreateInfo, createInfo, sizeof(SDL_GPUShaderCreateInfo));
+
+ newCreateInfo->format = shaderFormat;
+
+ 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);
+
+ const char *profile;
+ if (newCreateInfo->stage == SDL_GPU_SHADERSTAGE_VERTEX) {
+ profile = (shadermodel == 50) ? "vs_5_0" : "vs_6_0";
} else {
- newCreateInfo.code = (const Uint8 *)translated_source;
- newCreateInfo.code_size = SDL_strlen(translated_source) + 1;
- compiledResult = SDL_CreateGPUShader(device, &newCreateInfo);
+ profile = (shadermodel == 50) ? "ps_5_0" : "ps_6_0";
+ }
+
+ if (shaderFormat == SDL_GPU_SHADERFORMAT_DXBC) {
+ newCreateInfo->code = SDL_ShaderCross_CompileDXBCFromHLSL(
+ translated_source,
+ cleansed_entrypoint,
+ profile,
+ &newCreateInfo->code_size);
+ } else if (shaderFormat == SDL_GPU_SHADERFORMAT_DXIL) {
+ newCreateInfo->code = SDL_ShaderCross_CompileDXILFromHLSL(
+ translated_source,
+ cleansed_entrypoint,
+ profile,
+ &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);
}
+
+ translatedCreateInfo = newCreateInfo;
}
- /* Clean up */
SDL_spvc_context_destroy(context);
+ return translatedCreateInfo;
+}
+
+static void *SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
+ SDL_GPUShaderFormat format,
+ const Uint8 *bytecode,
+ size_t bytecodeSize,
+ const char *entrypoint,
+ SDL_ShaderCross_ShaderStage shaderStage,
+ size_t *size)
+{
+ 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;
+ }
+}
+
+void *SDL_ShaderCross_TranspileMSLFromSPIRV(
+ const Uint8 *bytecode,
+ size_t bytecodeSize,
+ const char *entrypoint,
+ SDL_ShaderCross_ShaderStage shaderStage)
+{
+ size_t size;
+ return SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
+ SDL_GPU_SHADERFORMAT_MSL,
+ bytecode,
+ bytecodeSize,
+ entrypoint,
+ shaderStage,
+ &size);
+}
+
+void *SDL_ShaderCross_CompileDXBCFromSPIRV(
+ const Uint8 *bytecode,
+ size_t bytecodeSize,
+ const char *entrypoint,
+ SDL_ShaderCross_ShaderStage shaderStage,
+ size_t *size)
+{
+ return SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
+ SDL_GPU_SHADERFORMAT_DXBC,
+ bytecode,
+ bytecodeSize,
+ entrypoint,
+ shaderStage,
+ size);
+}
+
+void *SDL_ShaderCross_CompileDXILFromSPIRV(
+ const Uint8 *bytecode,
+ size_t bytecodeSize,
+ const char *entrypoint,
+ SDL_ShaderCross_ShaderStage shaderStage,
+ size_t *size)
+{
+ return SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
+ SDL_GPU_SHADERFORMAT_DXIL,
+ bytecode,
+ bytecodeSize,
+ entrypoint,
+ shaderStage,
+ size);
+}
+
+static void *SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(
+ SDL_GPUDevice *device,
+ const void *originalCreateInfo,
+ bool isCompute)
+{
+ const SDL_GPUShaderCreateInfo *createInfo;
+ SDL_GPUShaderFormat format;
+ void *compiledResult;
+
+ SDL_GPUShaderFormat shader_formats = SDL_GetGPUShaderFormats(device);
+
+ if (shader_formats & SDL_GPU_SHADERFORMAT_SPIRV) {
+ if (isCompute) {
+ return SDL_CreateGPUComputePipeline(device, (const SDL_GPUComputePipelineCreateInfo *)originalCreateInfo);
+ } else {
+ return SDL_CreateGPUShader(device, (const SDL_GPUShaderCreateInfo *)originalCreateInfo);
+ }
+ } else if (shader_formats & SDL_GPU_SHADERFORMAT_DXBC) {
+ format = SDL_GPU_SHADERFORMAT_DXBC;
+ } else if (shader_formats & SDL_GPU_SHADERFORMAT_DXIL) {
+ format = SDL_GPU_SHADERFORMAT_DXIL;
+ } else if (shader_formats & SDL_GPU_SHADERFORMAT_MSL) {
+ format = SDL_GPU_SHADERFORMAT_MSL;
+ } else {
+ SDL_SetError("SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV: Unexpected SDL_GPUBackend");
+ return NULL;
+ }
+
+ void *translatedCreateInfo = SDL_ShaderCross_INTERNAL_TranslateFromSPIRV(
+ format,
+ createInfo,
+ 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;
}
@@ -806,14 +1065,14 @@ SDL_GPU_SHADERCROSS_EXPORT SDL_GPUShader *SDL_ShaderCross_CompileGraphicsShaderF
SDL_GPUDevice *device,
const SDL_GPUShaderCreateInfo *createInfo)
{
- return (SDL_GPUShader *)SDL_ShaderCross_INTERNAL_CompileFromSPIRV(device, createInfo, false);
+ return (SDL_GPUShader *)SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(device, createInfo, false);
}
SDL_GPU_SHADERCROSS_EXPORT SDL_GPUComputePipeline *SDL_ShaderCross_CompileComputePipelineFromSPIRV(
SDL_GPUDevice *device,
const SDL_GPUComputePipelineCreateInfo *createInfo)
{
- return (SDL_GPUComputePipeline *)SDL_ShaderCross_INTERNAL_CompileFromSPIRV(device, createInfo, true);
+ return (SDL_GPUComputePipeline *)SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(device, createInfo, true);
}
#endif /* SDL_GPU_SHADERCROSS_SPIRVCROSS */
(Patch may be truncated, please check the link at the top of this post.)