From 93876db239273006df362eca5af8b6533a699d78 Mon Sep 17 00:00:00 2001
From: Evan Hemsley <[EMAIL REDACTED]>
Date: Thu, 19 Dec 2024 13:49:56 -0800
Subject: [PATCH] Refactor parameters to info structs and add debug support
(#71)
---
include/SDL3_shadercross/SDL_shadercross.h | 230 +++-----
src/SDL_shadercross.c | 618 ++++++++++-----------
src/cli.c | 188 ++++---
3 files changed, 491 insertions(+), 545 deletions(-)
diff --git a/include/SDL3_shadercross/SDL_shadercross.h b/include/SDL3_shadercross/SDL_shadercross.h
index 08cc9e0..493e6a4 100644
--- a/include/SDL3_shadercross/SDL_shadercross.h
+++ b/include/SDL3_shadercross/SDL_shadercross.h
@@ -45,35 +45,66 @@ typedef enum SDL_ShaderCross_ShaderStage
SDL_SHADERCROSS_SHADERSTAGE_COMPUTE
} SDL_ShaderCross_ShaderStage;
-typedef struct SDL_ShaderCross_GraphicsShaderInfo
+typedef struct SDL_ShaderCross_GraphicsShaderMetadata
{
- Uint32 numSamplers; /**< The number of samplers defined in the shader. */
- Uint32 numStorageTextures; /**< The number of storage textures defined in the shader. */
- Uint32 numStorageBuffers; /**< The number of storage buffers defined in the shader. */
- Uint32 numUniformBuffers; /**< The number of uniform buffers defined in the shader. */
-} SDL_ShaderCross_GraphicsShaderInfo;
+ Uint32 num_samplers; /**< The number of samplers defined in the shader. */
+ Uint32 num_storage_textures; /**< The number of storage textures defined in the shader. */
+ Uint32 num_storage_buffers; /**< The number of storage buffers defined in the shader. */
+ Uint32 num_uniform_buffers; /**< The number of uniform buffers defined in the shader. */
+} SDL_ShaderCross_GraphicsShaderMetadata;
-typedef struct SDL_ShaderCross_ComputePipelineInfo
+typedef struct SDL_ShaderCross_ComputePipelineMetadata
{
- Uint32 numSamplers; /**< The number of samplers defined in the shader. */
- Uint32 numReadOnlyStorageTextures; /**< The number of readonly storage textures defined in the shader. */
- Uint32 numReadOnlyStorageBuffers; /**< The number of readonly storage buffers defined in the shader. */
- Uint32 numReadWriteStorageTextures; /**< The number of read-write storage textures defined in the shader. */
- Uint32 numReadWriteStorageBuffers; /**< The number of read-write storage buffers defined in the shader. */
- Uint32 numUniformBuffers; /**< The number of uniform buffers defined in the shader. */
- Uint32 threadCountX; /**< The number of threads in the X dimension. */
- Uint32 threadCountY; /**< The number of threads in the Y dimension. */
- Uint32 threadCountZ; /**< The number of threads in the Z dimension. */
-} SDL_ShaderCross_ComputePipelineInfo;
+ Uint32 num_samplers; /**< The number of samplers defined in the shader. */
+ Uint32 num_readonly_storage_textures; /**< The number of readonly storage textures defined in the shader. */
+ Uint32 num_readonly_storage_buffers; /**< The number of readonly storage buffers defined in the shader. */
+ Uint32 num_readwrite_storage_textures; /**< The number of read-write storage textures defined in the shader. */
+ Uint32 num_readwrite_storage_buffers; /**< The number of read-write storage buffers defined in the shader. */
+ Uint32 num_uniform_buffers; /**< The number of uniform buffers defined in the shader. */
+ Uint32 threadcount_x; /**< The number of threads in the X dimension. */
+ Uint32 threadcount_y; /**< The number of threads in the Y dimension. */
+ Uint32 threadcount_z; /**< The number of threads in the Z dimension. */
+} SDL_ShaderCross_ComputePipelineMetadata;
+
+typedef struct SDL_ShaderCross_SPIRV_Info
+{
+ const Uint8 *bytecode; /**< The SPIRV bytecode. */
+ size_t bytecode_size; /**< The length of the SPIRV bytecode. */
+ const char *entrypoint; /**< The entry point function name for the shader in UTF-8. */
+ SDL_ShaderCross_ShaderStage shader_stage; /**< The shader stage to transpile the shader with. */
+ bool enable_debug; /**< Allows debug info to be emitted when relevant. Can be useful for graphics debuggers like RenderDoc. */
+ const char *name; /**< A UTF-8 name to associate with the shader. Optional, can be NULL. */
+
+ SDL_PropertiesID props; /**< A properties ID for extensions. Should be 0 if no extensions are needed. */
+} SDL_ShaderCross_SPIRV_Info;
+
+typedef struct SDL_ShaderCross_HLSL_Define
+{
+ char *name; /**< The define name. */
+ char *value; /**< An optional value for the define. Can be NULL. */
+} SDL_ShaderCross_HLSL_Define;
+
+typedef struct SDL_ShaderCross_HLSL_Info
+{
+ const char *source; /**< The HLSL source code for the shader. */
+ const char *entrypoint; /**< The entry point function name for the shader in UTF-8. */
+ const char *include_dir; /**< The include directory for shader code. Optional, can be NULL. */
+ SDL_ShaderCross_HLSL_Define *defines; /**< An array of defines. Optional, can be NULL. If not NULL, must be terminated with a fully NULL define struct. */
+ SDL_ShaderCross_ShaderStage shader_stage; /**< The shader stage to compile the shader with. */
+ bool enable_debug; /**< Allows debug info to be emitted when relevant. Can be useful for graphics debuggers like RenderDoc. */
+ const char *name; /**< A UTF-8 name to associate with the shader. Optional, can be NULL. */
+
+ SDL_PropertiesID props; /**< A properties ID for extensions. Should be 0 if no extensions are needed. */
+} SDL_ShaderCross_HLSL_Info;
/**
- * Initializes SDL_gpu_shadercross
+ * Initializes SDL_shadercross
*
* \threadsafety This should only be called once, from a single thread.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_ShaderCross_Init(void);
/**
- * De-initializes SDL_gpu_shadercross
+ * De-initializes SDL_shadercross
*
* \threadsafety This should only be called once, from a single thread.
*/
@@ -91,52 +122,34 @@ extern SDL_DECLSPEC SDL_GPUShaderFormat SDLCALL SDL_ShaderCross_GetSPIRVShaderFo
*
* 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 shaderStage the shader stage to transpile the shader with.
+ * \param info a struct describing the shader to transpile.
* \returns an SDL_malloc'd string containing MSL code.
*/
extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_TranspileMSLFromSPIRV(
- const Uint8 *bytecode,
- size_t bytecodeSize,
- const char *entrypoint,
- SDL_ShaderCross_ShaderStage shaderStage);
+ const SDL_ShaderCross_SPIRV_Info *info);
/**
* 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 shaderStage the shader stage to transpile the shader with.
- * \param shaderModel the shader model to transpile the shader with.
+ * \param info a struct describing the shader to transpile.
* \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,
- SDL_ShaderCross_ShaderStage shaderStage);
+ const SDL_ShaderCross_SPIRV_Info *info);
/**
* 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 in UTF-8.
- * \param shaderStage the shader stage to compile the shader with.
+ * \param info a struct describing the shader to transpile.
* \param size filled in with the bytecode buffer size.
+ * \returns an SDL_malloc'd buffer containing DXBC bytecode.
*/
extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXBCFromSPIRV(
- const Uint8 *bytecode,
- size_t bytecodeSize,
- const char *entrypoint,
- SDL_ShaderCross_ShaderStage shaderStage,
+ const SDL_ShaderCross_SPIRV_Info *info,
size_t *size);
/**
@@ -144,86 +157,71 @@ extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXBCFromSPIRV(
*
* 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 in UTF-8.
- * \param shaderStage the shader stage to compile the shader with.
+ * \param info a struct describing the shader to transpile.
* \param size filled in with the bytecode buffer size.
+ * \returns an SDL_malloc'd buffer containing DXIL bytecode.
*/
extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXILFromSPIRV(
- const Uint8 *bytecode,
- size_t bytecodeSize,
- const char *entrypoint,
- SDL_ShaderCross_ShaderStage shaderStage,
+ const SDL_ShaderCross_SPIRV_Info *info,
size_t *size);
/**
* Compile an SDL GPU shader from SPIRV code.
*
* \param device the SDL GPU device.
- * \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 compile the shader with.
- * \param info a pointer filled in with shader metadata.
+ * \param info a struct describing the shader to transpile.
+ * \param metadata a pointer filled in with shader metadata.
* \returns a compiled SDL_GPUShader
*
* \threadsafety It is safe to call this function from any thread.
*/
extern SDL_DECLSPEC SDL_GPUShader * SDLCALL SDL_ShaderCross_CompileGraphicsShaderFromSPIRV(
SDL_GPUDevice *device,
- const Uint8 *bytecode,
- size_t bytecodeSize,
- const char *entrypoint,
- SDL_GPUShaderStage shaderStage,
- SDL_ShaderCross_GraphicsShaderInfo *info);
+ const SDL_ShaderCross_SPIRV_Info *info,
+ SDL_ShaderCross_GraphicsShaderMetadata *metadata);
/**
* Compile an SDL GPU compute pipeline from SPIRV code.
*
* \param device the SDL GPU device.
- * \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 info a pointer filled in with compute pipeline metadata.
+ * \param info a struct describing the shader to transpile.
+ * \param metadata a pointer filled in with compute pipeline metadata.
* \returns a compiled SDL_GPUComputePipeline
*
* \threadsafety It is safe to call this function from any thread.
*/
extern SDL_DECLSPEC SDL_GPUComputePipeline * SDLCALL SDL_ShaderCross_CompileComputePipelineFromSPIRV(
SDL_GPUDevice *device,
- const Uint8 *bytecode,
- size_t bytecodeSize,
- const char *entrypoint,
- SDL_ShaderCross_ComputePipelineInfo *info);
+ const SDL_ShaderCross_SPIRV_Info *info,
+ SDL_ShaderCross_ComputePipelineMetadata *metadata);
/**
* Reflect graphics shader info from SPIRV code.
*
* \param bytecode the SPIRV bytecode.
- * \param bytecodeSize the length of the SPIRV bytecode.
- * \param info a pointer filled in with shader metadata.
+ * \param bytecode_size the length of the SPIRV bytecode.
+ * \param metadata a pointer filled in with shader metadata.
*
* \threadsafety It is safe to call this function from any thread.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_ShaderCross_ReflectGraphicsSPIRV(
const Uint8 *bytecode,
- size_t bytecodeSize,
- SDL_ShaderCross_GraphicsShaderInfo *info);
+ size_t bytecode_size,
+ SDL_ShaderCross_GraphicsShaderMetadata *metadata);
/**
* Reflect compute pipeline info from SPIRV code.
*
* \param bytecode the SPIRV bytecode.
- * \param bytecodeSize the length of the SPIRV bytecode.
- * \param info a pointer filled in with compute pipeline metadata.
+ * \param bytecode_size the length of the SPIRV bytecode.
+ * \param metadata a pointer filled in with compute pipeline metadata.
*
* \threadsafety It is safe to call this function from any thread.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_ShaderCross_ReflectComputeSPIRV(
const Uint8 *bytecode,
- size_t bytecodeSize,
- SDL_ShaderCross_ComputePipelineInfo *info);
+ size_t bytecode_size,
+ SDL_ShaderCross_ComputePipelineMetadata *metadata);
/**
* Get the supported shader formats that HLSL cross-compilation can output
@@ -237,24 +235,14 @@ extern SDL_DECLSPEC SDL_GPUShaderFormat SDLCALL SDL_ShaderCross_GetHLSLShaderFor
*
* 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 in UTF-8.
- * \param includeDir the include directory for shader code. Optional, can be NULL.
- * \param defines an array of define strings. Optional, can be NULL.
- * \param numDefines the number of strings in the defines array.
- * \param shaderStage the shader stage to compile the shader with.
+ * \param info a struct describing the shader to transpile.
* \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 SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXBCFromHLSL(
- const char *hlslSource,
- const char *entrypoint,
- const char *includeDir,
- char **defines,
- Uint32 numDefines,
- SDL_ShaderCross_ShaderStage shaderStage,
+ const SDL_ShaderCross_HLSL_Info *info,
size_t *size);
/**
@@ -262,24 +250,14 @@ extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXBCFromHLSL(
*
* 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 in UTF-8.
- * \param includeDir the include directory for shader code. Optional, can be NULL.
- * \param defines an array of define strings. Optional, can be NULL.
- * \param numDefines the number of strings in the defines array.
- * \param shaderStage the shader stage to compile the shader with.
+ * \param info a struct describing the shader to transpile.
* \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 SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXILFromHLSL(
- const char *hlslSource,
- const char *entrypoint,
- const char *includeDir,
- char **defines,
- Uint32 numDefines,
- SDL_ShaderCross_ShaderStage shaderStage,
+ const SDL_ShaderCross_HLSL_Info *info,
size_t *size);
/**
@@ -287,73 +265,45 @@ extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXILFromHLSL(
*
* 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 in UTF-8.
- * \param includeDir the include directory for shader code. Optional, can be NULL.
- * \param defines an array of define strings. Optional, can be NULL.
- * \param numDefines the number of strings in the defines array.
- * \param shaderStage the shader stage to compile the shader with.
+ * \param info a struct describing the shader to transpile.
* \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 SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileSPIRVFromHLSL(
- const char *hlslSource,
- const char *entrypoint,
- const char *includeDir,
- char **defines,
- Uint32 numDefines,
- SDL_ShaderCross_ShaderStage shaderStage,
+ const SDL_ShaderCross_HLSL_Info *info,
size_t *size);
/**
* Compile an SDL GPU shader from HLSL code.
*
* \param device the SDL GPU device.
- * \param hlslSource the HLSL source code for the shader.
- * \param entrypoint the entry point function name for the shader in UTF-8.
- * \param includeDir the include directory for shader code. Optional, can be NULL.
- * \param defines an array of define strings. Optional, can be NULL.
- * \param numDefines the number of strings in the defines array.
- * \param graphicsShaderStage the shader stage to compile the shader with.
- * \param info a pointer filled in with shader metadata.
+ * \param info a struct describing the shader to transpile.
+ * \param metadata a pointer filled in with shader metadata.
* \returns a compiled SDL_GPUShader
*
* \threadsafety It is safe to call this function from any thread.
*/
extern SDL_DECLSPEC SDL_GPUShader * SDLCALL SDL_ShaderCross_CompileGraphicsShaderFromHLSL(
SDL_GPUDevice *device,
- const char *hlslSource,
- const char *entrypoint,
- const char *includeDir,
- char **defines,
- Uint32 numDefines,
- SDL_GPUShaderStage graphicsShaderStage,
- SDL_ShaderCross_GraphicsShaderInfo *info);
+ const SDL_ShaderCross_HLSL_Info *info,
+ SDL_ShaderCross_GraphicsShaderMetadata *metadata);
/**
* Compile an SDL GPU compute pipeline from code.
*
* \param device the SDL GPU device.
- * \param hlslSource the HLSL source code for the shader.
- * \param entrypoint the entry point function name for the shader in UTF-8.
- * \param includeDir the include directory for shader code. Optional, can be NULL.
- * \param defines an array of define strings. Optional, can be NULL.
- * \param numDefines the number of strings in the defines array.
- * \param info a pointer filled in with compute pipeline metadata.
+ * \param info a struct describing the shader to transpile.
+ * \param metadata a pointer filled in with compute pipeline metadata.
* \returns a compiled SDL_GPUComputePipeline
*
* \threadsafety It is safe to call this function from any thread.
*/
extern SDL_DECLSPEC SDL_GPUComputePipeline * SDLCALL SDL_ShaderCross_CompileComputePipelineFromHLSL(
SDL_GPUDevice *device,
- const char *hlslSource,
- const char *entrypoint,
- const char *includeDir,
- char **defines,
- Uint32 numDefines,
- SDL_ShaderCross_ComputePipelineInfo *info);
+ const SDL_ShaderCross_HLSL_Info *info,
+ SDL_ShaderCross_ComputePipelineMetadata *metadata);
#ifdef __cplusplus
}
diff --git a/src/SDL_shadercross.c b/src/SDL_shadercross.c
index aaa6510..32db3e8 100644
--- a/src/SDL_shadercross.c
+++ b/src/SDL_shadercross.c
@@ -23,6 +23,10 @@
#include <SDL3/SDL_loadso.h>
#include <SDL3/SDL_log.h>
+/* Constants */
+#define MAX_DEFINES 64
+#define MAX_DEFINE_STRING_LENGTH 256
+
/* Win32 Type Definitions */
typedef int HRESULT;
@@ -329,12 +333,7 @@ HRESULT DxcCreateInstance(REFCLSID rclsid, REFIID riid, LPVOID *ppv);
#endif /* SDL_SHADERCROSS_DXC */
static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
- const char *hlslSource,
- const char *entrypoint,
- const char *includeDir,
- char **defines,
- Uint32 numDefines,
- SDL_ShaderCross_ShaderStage shaderStage,
+ const SDL_ShaderCross_HLSL_Info *info,
bool spirv,
size_t *size) // filled in with number of bytes of returned buffer
{
@@ -343,10 +342,13 @@ static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
IDxcResult *dxcResult;
IDxcBlob *blob;
IDxcBlobUtf8 *errors;
- size_t entryPointLength = SDL_utf8strlen(entrypoint) + 1;
+ size_t entryPointLength = SDL_utf8strlen(info->entrypoint) + 1;
wchar_t *entryPointUtf16 = NULL;
size_t includeDirLength = 0;
wchar_t *includeDirUtf16 = NULL;
+ wchar_t *nameUtf16 = NULL;
+ wchar_t **defineStringsUtf16 = NULL;
+ size_t numDefineStrings = 0;
HRESULT ret;
/* Non-static DxcInstance, since the functions we call on it are not thread-safe */
@@ -399,7 +401,7 @@ static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
return NULL;
}
- entryPointUtf16 = (wchar_t *)SDL_iconv_string("WCHAR_T", "UTF-8", entrypoint, entryPointLength);
+ entryPointUtf16 = (wchar_t *)SDL_iconv_string("WCHAR_T", "UTF-8", info->entrypoint, entryPointLength);
if (entryPointUtf16 == NULL) {
SDL_SetError("%s", "Failed to convert entrypoint to WCHAR_T!");
dxcInstance->lpVtbl->Release(dxcInstance);
@@ -407,26 +409,38 @@ static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
return NULL;
}
- LPCWSTR *args = SDL_malloc(sizeof(LPCWSTR) * (numDefines + 8));
- Uint32 argCount = 0;
+ for (Uint32 i = 0; i < MAX_DEFINES; i += 1) {
+ if (info->defines[i].name == NULL) {
+ break;
+ }
+ numDefineStrings += 1;
+ }
- for (Uint32 i = 0; i < numDefines; i += 1) {
- args[argCount++] = (wchar_t *)SDL_iconv_string("WCHAR_T", "UTF-8", defines[i], SDL_utf8strlen(defines[i]) + 1);
- if (args[argCount - 1] == NULL) {
- SDL_SetError("%s", "Failed to convert define argument to WCHAR_T!");
- SDL_free(args);
- dxcInstance->lpVtbl->Release(dxcInstance);
- utils->lpVtbl->Release(utils);
- return NULL;
+ char defineString[MAX_DEFINE_STRING_LENGTH];
+ defineStringsUtf16 = SDL_malloc(sizeof(LPCWSTR) * numDefineStrings);
+ for (Uint32 i = 0; i < numDefineStrings; i += 1) {
+ if (info->defines[i].value == NULL) {
+ SDL_snprintf(defineString, MAX_DEFINE_STRING_LENGTH, "-D%s=%s", info->defines[i].name, "1");
+ } else {
+ SDL_snprintf(defineString, MAX_DEFINE_STRING_LENGTH, "-D%s=%s", info->defines[i].name, info->defines[i].value);
}
+
+ defineStringsUtf16[i] = (wchar_t *)SDL_iconv_string("WCHAR_T", "UTF-8", defineString, MAX_DEFINE_STRING_LENGTH);
+ }
+
+ LPCWSTR *args = SDL_malloc(sizeof(LPCWSTR) * (numDefineStrings + 10));
+ Uint32 argCount = 0;
+
+ for (Uint32 i = 0; i < numDefineStrings; i += 1) {
+ args[argCount++] = defineStringsUtf16[i];
}
args[argCount++] = (LPCWSTR)L"-E";
args[argCount++] = (LPCWSTR)entryPointUtf16;
- if (includeDir != NULL) {
- includeDirLength = SDL_utf8strlen(includeDir) + 1;
- includeDirUtf16 = (wchar_t *)SDL_iconv_string("WCHAR_T", "UTF-8", includeDir, includeDirLength);
+ if (info->include_dir != NULL) {
+ includeDirLength = SDL_utf8strlen(info->include_dir) + 1;
+ includeDirUtf16 = (wchar_t *)SDL_iconv_string("WCHAR_T", "UTF-8", info->include_dir, includeDirLength);
if (includeDirUtf16 == NULL) {
SDL_SetError("%s", "Failed to convert include dir to WCHAR_T!");
@@ -440,14 +454,14 @@ static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
argCount += 2;
}
- source.Ptr = hlslSource;
- source.Size = SDL_strlen(hlslSource) + 1;
+ source.Ptr = info->source;
+ source.Size = SDL_strlen(info->source) + 1;
source.Encoding = DXC_CP_ACP;
- if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_VERTEX) {
+ if (info->shader_stage == SDL_SHADERCROSS_SHADERSTAGE_VERTEX) {
args[argCount++] = (LPCWSTR)L"-T";
args[argCount++] = (LPCWSTR)L"vs_6_0";
- } else if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT) {
+ } else if (info->shader_stage == SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT) {
args[argCount++] = (LPCWSTR)L"-T";
args[argCount++] = (LPCWSTR)L"ps_6_0";
} else { // compute
@@ -459,6 +473,23 @@ static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
args[argCount++] = (LPCWSTR)L"-spirv";
}
+ if (info->enable_debug) {
+ if (spirv) {
+ // https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#debugging
+ args[argCount++] = (LPCWSTR)L"-fspv-debug=vulkan-with-source";
+ } else {
+ // https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/SourceLevelDebuggingHLSL.rst#command-line-options
+ args[argCount++] = (LPCWSTR)L"-Zi";
+ }
+ }
+
+ if (info->name) {
+ nameUtf16 = (wchar_t *)SDL_iconv_string("WCHAR_T", "UTF-8", info->name, SDL_utf8strlen(info->name) + 1);
+ if (nameUtf16 != NULL) {
+ args[argCount++] = nameUtf16; // a bare string inserted into the arguments is treated as the source file name
+ }
+ }
+
#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
args[argCount++] = L"-D__XBOX_DISABLE_PRECOMPILE=1";
#endif
@@ -476,6 +507,9 @@ static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
if (includeDirUtf16 != NULL) {
SDL_free(includeDirUtf16);
}
+ if (nameUtf16 != NULL) {
+ SDL_free(nameUtf16);
+ }
if (ret < 0) {
SDL_SetError("IDxcShaderCompiler3::Compile failed: %X", ret);
@@ -528,8 +562,8 @@ static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
dxcInstance->lpVtbl->Release(dxcInstance);
utils->lpVtbl->Release(utils);
- for (Uint32 i = 0; i < numDefines; i += 1) {
- SDL_free(args[i]);
+ for (Uint32 i = 0; i < numDefineStrings; i += 1) {
+ SDL_free(defineStringsUtf16[i]);
}
SDL_free(args);
@@ -541,67 +575,52 @@ static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
}
void *SDL_ShaderCross_CompileDXILFromHLSL(
- const char *hlslSource,
- const char *entrypoint,
- const char *includeDir,
- char **defines,
- Uint32 numDefines,
- SDL_ShaderCross_ShaderStage shaderStage,
+ const SDL_ShaderCross_HLSL_Info *info,
size_t *size)
{
// Roundtrip to SPIR-V to support things like Structured Buffers.
size_t spirvSize;
void *spirv = SDL_ShaderCross_CompileSPIRVFromHLSL(
- hlslSource,
- entrypoint,
- includeDir,
- defines,
- numDefines,
- shaderStage,
+ info,
&spirvSize);
if (spirv == NULL) {
return NULL;
}
+ SDL_ShaderCross_SPIRV_Info spirvInfo;
+ spirvInfo.bytecode = spirv;
+ spirvInfo.bytecode_size = spirvSize;
+ spirvInfo.entrypoint = info->entrypoint;
+ spirvInfo.shader_stage = info->shader_stage;
+ spirvInfo.enable_debug = info->enable_debug;
+ spirvInfo.name = info->name;
+ spirvInfo.props = 0;
+
void *translatedSource = SDL_ShaderCross_TranspileHLSLFromSPIRV(
- spirv,
- spirvSize,
- entrypoint,
- shaderStage);
+ &spirvInfo);
SDL_free(spirv);
if (translatedSource == NULL) {
return NULL;
}
+ SDL_ShaderCross_HLSL_Info translatedHlslInfo;
+ SDL_memcpy(&translatedHlslInfo, info, sizeof(SDL_ShaderCross_HLSL_Info));
+ translatedHlslInfo.source = translatedSource;
+
return SDL_ShaderCross_INTERNAL_CompileUsingDXC(
- translatedSource,
- entrypoint,
- includeDir,
- defines,
- numDefines,
- shaderStage,
+ &translatedHlslInfo,
false,
size);
}
void *SDL_ShaderCross_CompileSPIRVFromHLSL(
- const char *hlslSource,
- const char *entrypoint,
- const char *includeDir,
- char **defines,
- Uint32 numDefines,
- SDL_ShaderCross_ShaderStage shaderStage,
+ const SDL_ShaderCross_HLSL_Info *info,
size_t *size)
{
return SDL_ShaderCross_INTERNAL_CompileUsingDXC(
- hlslSource,
- entrypoint,
- includeDir,
- defines,
- numDefines,
- shaderStage,
+ info,
true,
size);
}
@@ -679,10 +698,12 @@ typedef HRESULT(__stdcall *pfn_D3DCompile)(
static pfn_D3DCompile SDL_D3DCompile = NULL;
+// FIXME: includes and defines
static ID3DBlob *SDL_ShaderCross_INTERNAL_CompileDXBC(
const char *hlslSource,
const char *entrypoint,
- const char *shaderProfile)
+ const char *shaderProfile,
+ bool enableDebug)
{
ID3DBlob *blob;
ID3DBlob *errorBlob;
@@ -701,7 +722,7 @@ static ID3DBlob *SDL_ShaderCross_INTERNAL_CompileDXBC(
NULL,
entrypoint,
shaderProfile,
- 0,
+ enableDebug ? 1 : 0, // D3DCOMPILE_DEBUG = 1
0,
&blob,
&errorBlob);
@@ -721,12 +742,7 @@ static ID3DBlob *SDL_ShaderCross_INTERNAL_CompileDXBC(
}
void *SDL_ShaderCross_INTERNAL_CompileDXBCFromHLSL(
- const char *hlslSource,
- const char *entrypoint,
- const char *includeDir,
- char **defines,
- Uint32 numDefines,
- SDL_ShaderCross_ShaderStage shaderStage,
+ const SDL_ShaderCross_HLSL_Info *info,
bool enableRoundtrip,
size_t *size) // filled in with number of bytes of returned buffer
{
@@ -736,23 +752,24 @@ void *SDL_ShaderCross_INTERNAL_CompileDXBCFromHLSL(
// Need to roundtrip to SM 5.1
size_t spirv_size;
void *spirv = SDL_ShaderCross_CompileSPIRVFromHLSL(
- hlslSource,
- entrypoint,
- includeDir,
- defines,
- numDefines,
- shaderStage,
+ info,
&spirv_size);
if (spirv == NULL) {
return NULL;
}
+ SDL_ShaderCross_SPIRV_Info spirvInfo;
+ spirvInfo.bytecode = spirv;
+ spirvInfo.bytecode_size = spirv_size;
+ spirvInfo.entrypoint = info->entrypoint;
+ spirvInfo.shader_stage = info->shader_stage;
+ spirvInfo.enable_debug = info->enable_debug;
+ spirvInfo.name = info->name;
+ spirvInfo.props = 0;
+
transpiledSource = SDL_ShaderCross_TranspileHLSLFromSPIRV(
- spirv,
- spirv_size,
- entrypoint,
- shaderStage);
+ &spirvInfo);
SDL_free(spirv);
if (transpiledSource == NULL) {
@@ -761,18 +778,19 @@ void *SDL_ShaderCross_INTERNAL_CompileDXBCFromHLSL(
}
const char *shaderProfile;
- if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_VERTEX) {
+ if (info->shader_stage == SDL_SHADERCROSS_SHADERSTAGE_VERTEX) {
shaderProfile = "vs_5_1";
- } else if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT) {
+ } else if (info->shader_stage == SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT) {
shaderProfile = "ps_5_1";
} else { // compute
shaderProfile = "cs_5_1";
}
ID3DBlob *blob = SDL_ShaderCross_INTERNAL_CompileDXBC(
- transpiledSource != NULL ? transpiledSource : hlslSource,
- entrypoint,
- shaderProfile);
+ transpiledSource != NULL ? transpiledSource : info->source,
+ info->entrypoint,
+ shaderProfile,
+ info->enable_debug);
if (blob == NULL) {
*size = 0;
@@ -793,45 +811,25 @@ void *SDL_ShaderCross_INTERNAL_CompileDXBCFromHLSL(
// Returns raw byte buffer
void *SDL_ShaderCross_CompileDXBCFromHLSL(
- const char *hlslSource,
- const char *entrypoint,
- const char *includeDir,
- char **defines,
- Uint32 numDefines,
- SDL_ShaderCross_ShaderStage shaderStage,
+ const SDL_ShaderCross_HLSL_Info *info,
size_t *size) // filled in with number of bytes of returned
(Patch may be truncated, please check the link at the top of this post.)