From 3acf9c17e5c6de6b7e6d6627f3db28ad87c1b148 Mon Sep 17 00:00:00 2001
From: cosmonaut <[EMAIL REDACTED]>
Date: Thu, 7 Nov 2024 14:10:35 -0800
Subject: [PATCH] Rework Compile APIs
---
CMakeLists.txt | 1 +
.../SDL_gpu_shadercross.h | 59 +++++-
src/SDL_gpu_shadercross.c | 190 +++++++++++++++---
3 files changed, 214 insertions(+), 36 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ee61f15..8c5e51e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -138,6 +138,7 @@ else()
endif()
endif()
+ set(DirectXShaderCompiler_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/external/DirectXShaderCompiler-binaries")
find_package(DirectXShaderCompiler REQUIRED)
endif()
diff --git a/include/SDL3_gpu_shadercross/SDL_gpu_shadercross.h b/include/SDL3_gpu_shadercross/SDL_gpu_shadercross.h
index e4b873a..e929111 100644
--- a/include/SDL3_gpu_shadercross/SDL_gpu_shadercross.h
+++ b/include/SDL3_gpu_shadercross/SDL_gpu_shadercross.h
@@ -60,6 +60,25 @@ typedef enum SDL_ShaderCross_ShaderModel
SDL_SHADERCROSS_SHADERMODEL_6_0
} SDL_ShaderCross_ShaderModel;
+typedef struct SDL_ShaderCross_ShaderResourceInfo {
+ 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_ShaderResourceInfo;
+
+typedef struct SDL_ShaderCross_ComputeResourceInfo {
+ Uint32 num_samplers; /**< The number of samplers defined in the shader. */
+ Uint32 num_readonly_storage_textures; /**< The number of storage textures defined in the shader. */
+ Uint32 num_readonly_storage_buffers; /**< The number of 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. This should match the value in the shader. */
+ Uint32 threadcount_y; /**< The number of threads in the Y dimension. This should match the value in the shader. */
+ Uint32 threadcount_z; /**< The number of threads in the Z dimension. This should match the value in the shader. */
+} SDL_ShaderCross_ComputeResourceInfo;
+
/**
* Initializes SDL_gpu_shadercross
*
@@ -157,27 +176,42 @@ extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileDXILFromSPIRV(
* Compile an SDL GPU shader from SPIRV code.
*
* \param device the SDL GPU device.
- * \param createInfo a pointer to an SDL_GPUShaderCreateInfo.
+ * \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 resourceInfo a pointer to an SDL_ShaderCross_ShaderResourceInfo.
* \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 SDL_GPUShaderCreateInfo *createInfo);
+ const Uint8 *bytecode,
+ size_t bytecodeSize,
+ const char *entrypoint,
+ SDL_GPUShaderStage shaderStage,
+ const SDL_ShaderCross_ShaderResourceInfo *resourceInfo);
/**
* Compile an SDL GPU compute pipeline from SPIRV code.
*
* \param device the SDL GPU device.
- * \param createInfo a pointer to an SDL_GPUComputePipelineCreateInfo.
+ * \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 resourceInfo a pointer to an SDL_ShaderCross_ShaderResourceInfo.
* \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 SDL_GPUComputePipelineCreateInfo *createInfo);
+ const Uint8 *bytecode,
+ size_t bytecodeSize,
+ const char *entrypoint,
+ const SDL_ShaderCross_ComputeResourceInfo *resourceInfo);
+
#endif /* SDL_GPU_SHADERCROSS_SPIRVCROSS */
#if SDL_GPU_SHADERCROSS_HLSL
@@ -249,34 +283,37 @@ extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_CompileSPIRVFromHLSL(
* Compile an SDL GPU shader from HLSL Shader Model 6.0 code.
*
* \param device the SDL GPU device.
- * \param createInfo a pointer to an SDL_GPUShaderCreateInfo.
* \param hlslSource the HLSL source code for the shader.
+ * \param entrypoint the entry point function name for the shader in UTF-8.
* \param graphicsShaderStage the shader stage to compile the shader with.
+ * \param resourceInfo a pointer to an SDL_ShaderCross_ShaderResourceInfo.
* \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 SDL_GPUShaderCreateInfo *createInfo,
const char *hlslSource,
- SDL_GPUShaderStage graphicsShaderStage);
+ const char *entrypoint,
+ SDL_GPUShaderStage graphicsShaderStage,
+ const SDL_ShaderCross_ShaderResourceInfo *resourceInfo);
/**
* Compile an SDL GPU compute pipeline from HLSL Shader Model 6.0 code.
*
* \param device the SDL GPU device.
- * \param createInfo a pointer to an SDL_GPUComputePipelineCreateInfo.
* \param hlslSource the HLSL source code for the shader.
- * \param shaderStage the shader stage to compile the shader with.
+ * \param entrypoint the entry point function name for the shader in UTF-8.
+ * \param resourceInfo a pointer to an SDL_ShaderCross_ComputeResourceInfo.
* \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 SDL_GPUComputePipelineCreateInfo *createInfo,
- const char *hlslSource);
+ const char *hlslSource,
+ const char *entrypoint,
+ const SDL_ShaderCross_ComputeResourceInfo *resourceInfo);
#endif /* SDL_GPU_SHADERCROSS_HLSL */
diff --git a/src/SDL_gpu_shadercross.c b/src/SDL_gpu_shadercross.c
index 2be9df8..8a466f5 100644
--- a/src/SDL_gpu_shadercross.c
+++ b/src/SDL_gpu_shadercross.c
@@ -454,9 +454,10 @@ void *SDL_ShaderCross_CompileSPIRVFromHLSL(
static void *SDL_ShaderCross_INTERNAL_CreateShaderFromDXC(
SDL_GPUDevice *device,
- const void *createInfo,
const char *hlslSource,
+ const char *entrypoint,
SDL_ShaderCross_ShaderStage shaderStage,
+ const void *resourceInfo,
bool spirv)
{
void *result;
@@ -467,14 +468,14 @@ static void *SDL_ShaderCross_INTERNAL_CreateShaderFromDXC(
// If destination is DXIL, force roundtrip through SPIRV-Cross.
bytecode = SDL_ShaderCross_CompileDXILFromHLSL(
hlslSource,
- ((const SDL_GPUShaderCreateInfo *)createInfo)->entrypoint,
+ entrypoint,
shaderStage,
&bytecodeSize);
} else {
// Otherwise just compile straight to SPIRV.
bytecode = SDL_ShaderCross_INTERNAL_CompileUsingDXC(
hlslSource,
- ((const SDL_GPUShaderCreateInfo *)createInfo)->entrypoint,
+ entrypoint,
shaderStage,
spirv,
&bytecodeSize);
@@ -485,19 +486,37 @@ static void *SDL_ShaderCross_INTERNAL_CreateShaderFromDXC(
}
if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_COMPUTE) {
+ SDL_ShaderCross_ComputeResourceInfo *info = (SDL_ShaderCross_ComputeResourceInfo *)resourceInfo;
SDL_GPUComputePipelineCreateInfo newCreateInfo;
- newCreateInfo = *(const SDL_GPUComputePipelineCreateInfo *)createInfo;
newCreateInfo.code = (const Uint8 *)bytecode;
newCreateInfo.code_size = bytecodeSize;
+ newCreateInfo.entrypoint = entrypoint;
newCreateInfo.format = spirv ? SDL_GPU_SHADERFORMAT_SPIRV : SDL_GPU_SHADERFORMAT_DXIL;
+ newCreateInfo.num_samplers = info->num_samplers;
+ newCreateInfo.num_readonly_storage_textures = info->num_readonly_storage_textures;
+ newCreateInfo.num_readonly_storage_buffers = info->num_readonly_storage_buffers;
+ newCreateInfo.num_readwrite_storage_textures = info->num_readwrite_storage_textures;
+ newCreateInfo.num_readwrite_storage_buffers = info->num_readwrite_storage_buffers;
+ newCreateInfo.num_uniform_buffers = info->num_uniform_buffers;
+ newCreateInfo.threadcount_x = info->threadcount_x;
+ newCreateInfo.threadcount_y = info->threadcount_y;
+ newCreateInfo.threadcount_z = info->threadcount_z;
+ newCreateInfo.props = 0;
result = SDL_CreateGPUComputePipeline(device, &newCreateInfo);
} else {
+ SDL_ShaderCross_ShaderResourceInfo *info = (SDL_ShaderCross_ShaderResourceInfo *)resourceInfo;
SDL_GPUShaderCreateInfo newCreateInfo;
- newCreateInfo = *(const SDL_GPUShaderCreateInfo *)createInfo;
newCreateInfo.code = (const Uint8 *)bytecode;
newCreateInfo.code_size = bytecodeSize;
+ newCreateInfo.entrypoint = entrypoint;
newCreateInfo.format = spirv ? SDL_GPU_SHADERFORMAT_SPIRV : SDL_GPU_SHADERFORMAT_DXIL;
+ newCreateInfo.stage = (SDL_GPUShaderStage)shaderStage;
+ newCreateInfo.num_samplers = info->num_samplers;
+ newCreateInfo.num_storage_textures = info->num_storage_textures;
+ newCreateInfo.num_storage_buffers = info->num_storage_buffers;
+ newCreateInfo.num_uniform_buffers = info->num_uniform_buffers;
+ newCreateInfo.props = 0;
result = SDL_CreateGPUShader(device, &newCreateInfo);
}
@@ -675,16 +694,17 @@ void *SDL_ShaderCross_CompileDXBCFromHLSL(
static void *SDL_ShaderCross_INTERNAL_CreateShaderFromDXBC(
SDL_GPUDevice *device,
- const void *createInfo,
const char *hlslSource,
- SDL_ShaderCross_ShaderStage shaderStage)
+ const char *entrypoint,
+ SDL_ShaderCross_ShaderStage shaderStage,
+ const void *resourceInfo)
{
void *result;
size_t bytecodeSize;
void *bytecode = SDL_ShaderCross_CompileDXBCFromHLSL(
hlslSource,
- ((const SDL_GPUShaderCreateInfo *)createInfo)->entrypoint,
+ entrypoint,
shaderStage,
&bytecodeSize);
@@ -693,19 +713,37 @@ static void *SDL_ShaderCross_INTERNAL_CreateShaderFromDXBC(
}
if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_COMPUTE) {
+ SDL_ShaderCross_ComputeResourceInfo *info = (SDL_ShaderCross_ComputeResourceInfo *)resourceInfo;
SDL_GPUComputePipelineCreateInfo newCreateInfo;
- newCreateInfo = *(const SDL_GPUComputePipelineCreateInfo *)createInfo;
newCreateInfo.code = (const Uint8 *)bytecode;
newCreateInfo.code_size = bytecodeSize;
+ newCreateInfo.entrypoint = entrypoint;
newCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC;
+ newCreateInfo.num_samplers = info->num_samplers;
+ newCreateInfo.num_readonly_storage_textures = info->num_readonly_storage_textures;
+ newCreateInfo.num_readonly_storage_buffers = info->num_readonly_storage_buffers;
+ newCreateInfo.num_readwrite_storage_textures = info->num_readwrite_storage_textures;
+ newCreateInfo.num_readwrite_storage_buffers = info->num_readwrite_storage_buffers;
+ newCreateInfo.num_uniform_buffers = info->num_uniform_buffers;
+ newCreateInfo.threadcount_x = info->threadcount_x;
+ newCreateInfo.threadcount_y = info->threadcount_y;
+ newCreateInfo.threadcount_z = info->threadcount_z;
+ newCreateInfo.props = 0;
result = SDL_CreateGPUComputePipeline(device, &newCreateInfo);
} else {
+ SDL_ShaderCross_ShaderResourceInfo *info = (SDL_ShaderCross_ShaderResourceInfo *)resourceInfo;
SDL_GPUShaderCreateInfo newCreateInfo;
- newCreateInfo = *(const SDL_GPUShaderCreateInfo *)createInfo;
newCreateInfo.code = (const Uint8 *)bytecode;
newCreateInfo.code_size = bytecodeSize;
+ newCreateInfo.entrypoint = entrypoint;
newCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC;
+ newCreateInfo.stage = (SDL_GPUShaderStage)shaderStage;
+ newCreateInfo.num_samplers = info->num_samplers;
+ newCreateInfo.num_storage_textures = info->num_storage_textures;
+ newCreateInfo.num_storage_buffers = info->num_storage_buffers;
+ newCreateInfo.num_uniform_buffers = info->num_uniform_buffers;
+ newCreateInfo.props = 0;
result = SDL_CreateGPUShader(device, &newCreateInfo);
}
@@ -716,19 +754,68 @@ static void *SDL_ShaderCross_INTERNAL_CreateShaderFromDXBC(
static void *SDL_ShaderCross_INTERNAL_CreateShaderFromHLSL(
SDL_GPUDevice *device,
- const void *createInfo,
const char *hlslSource,
- SDL_ShaderCross_ShaderStage shaderStage)
+ const char *entrypoint,
+ SDL_ShaderCross_ShaderStage shaderStage,
+ const void *resourceInfo)
{
SDL_GPUShaderFormat format = SDL_GetGPUShaderFormats(device);
if (format & SDL_GPU_SHADERFORMAT_DXBC) {
- return SDL_ShaderCross_INTERNAL_CreateShaderFromDXBC(device, createInfo, hlslSource, shaderStage);
+ return SDL_ShaderCross_INTERNAL_CreateShaderFromDXBC(
+ device,
+ hlslSource,
+ entrypoint,
+ shaderStage,
+ resourceInfo);
}
if (format & SDL_GPU_SHADERFORMAT_DXIL) {
- return SDL_ShaderCross_INTERNAL_CreateShaderFromDXC(device, createInfo, hlslSource, shaderStage, false);
+ return SDL_ShaderCross_INTERNAL_CreateShaderFromDXC(
+ device,
+ hlslSource,
+ entrypoint,
+ shaderStage,
+ resourceInfo,
+ false);
}
if (format & SDL_GPU_SHADERFORMAT_SPIRV) {
- return SDL_ShaderCross_INTERNAL_CreateShaderFromDXC(device, createInfo, hlslSource, shaderStage, true);
+ return SDL_ShaderCross_INTERNAL_CreateShaderFromDXC(
+ device,
+ hlslSource,
+ entrypoint,
+ shaderStage,
+ resourceInfo,
+ true);
+ }
+ if (format & SDL_GPU_SHADERFORMAT_MSL) {
+ size_t bytecodeSize;
+ void *spirv = SDL_ShaderCross_CompileSPIRVFromHLSL(
+ hlslSource,
+ entrypoint,
+ shaderStage,
+ &bytecodeSize);
+ if (spirv == NULL) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Failed to compile SPIR-V!");
+ return NULL;
+ }
+ void *result;
+ if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_COMPUTE) {
+ result = SDL_ShaderCross_CompileComputePipelineFromSPIRV(
+ device,
+ spirv,
+ bytecodeSize,
+ entrypoint,
+ (SDL_ShaderCross_ComputeResourceInfo *)resourceInfo);
+ } else {
+ result = SDL_ShaderCross_CompileGraphicsShaderFromSPIRV(
+ device,
+ spirv,
+ bytecodeSize,
+ entrypoint,
+ (SDL_GPUShaderStage)shaderStage,
+ (SDL_ShaderCross_ShaderResourceInfo *)resourceInfo);
+ }
+ SDL_free(spirv);
+ return result;
}
SDL_SetError("SDL_ShaderCross_INTERNAL_CreateShaderFromHLSL: Unexpected SDL_GPUShaderFormat");
@@ -737,19 +824,31 @@ static void *SDL_ShaderCross_INTERNAL_CreateShaderFromHLSL(
SDL_GPUShader *SDL_ShaderCross_CompileGraphicsShaderFromHLSL(
SDL_GPUDevice *device,
- const SDL_GPUShaderCreateInfo *createInfo,
const char *hlslSource,
- SDL_GPUShaderStage graphicsShaderStage)
+ const char *entrypoint,
+ SDL_GPUShaderStage graphicsShaderStage,
+ const SDL_ShaderCross_ShaderResourceInfo *resourceInfo)
{
- return (SDL_GPUShader *)SDL_ShaderCross_INTERNAL_CreateShaderFromHLSL(device, createInfo, hlslSource, (SDL_ShaderCross_ShaderStage)graphicsShaderStage);
+ return (SDL_GPUShader *)SDL_ShaderCross_INTERNAL_CreateShaderFromHLSL(
+ device,
+ hlslSource,
+ entrypoint,
+ (SDL_ShaderCross_ShaderStage)graphicsShaderStage,
+ (const void *)resourceInfo);
}
SDL_GPUComputePipeline *SDL_ShaderCross_CompileComputePipelineFromHLSL(
SDL_GPUDevice *device,
- const SDL_GPUComputePipelineCreateInfo *createInfo,
- const char *hlslSource)
+ const char *hlslSource,
+ const char *entrypoint,
+ const SDL_ShaderCross_ComputeResourceInfo *resourceInfo)
{
- return (SDL_GPUComputePipeline *)SDL_ShaderCross_INTERNAL_CreateShaderFromHLSL(device, createInfo, hlslSource, SDL_SHADERCROSS_SHADERSTAGE_COMPUTE);
+ return (SDL_GPUComputePipeline *)SDL_ShaderCross_INTERNAL_CreateShaderFromHLSL(
+ device,
+ hlslSource,
+ entrypoint,
+ SDL_SHADERCROSS_SHADERSTAGE_COMPUTE,
+ (const void *)resourceInfo);
}
#endif /* SDL_GPU_SHADERCROSS_HLSL */
@@ -1529,16 +1628,57 @@ static void *SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(
SDL_GPUShader *SDL_ShaderCross_CompileGraphicsShaderFromSPIRV(
SDL_GPUDevice *device,
- const SDL_GPUShaderCreateInfo *createInfo)
+ const Uint8 *bytecode,
+ size_t bytecodeSize,
+ const char *entrypoint,
+ SDL_GPUShaderStage shaderStage,
+ const SDL_ShaderCross_ShaderResourceInfo *resourceInfo)
{
- return (SDL_GPUShader *)SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(device, createInfo, (SDL_ShaderCross_ShaderStage)createInfo->stage);
+ SDL_GPUShaderCreateInfo createInfo;
+ createInfo.code = bytecode;
+ createInfo.code_size = bytecodeSize;
+ createInfo.entrypoint = entrypoint;
+ createInfo.format = SDL_GPU_SHADERFORMAT_SPIRV;
+ createInfo.stage = shaderStage;
+ createInfo.num_samplers = resourceInfo->num_samplers;
+ createInfo.num_storage_textures = resourceInfo->num_storage_textures;
+ createInfo.num_storage_buffers = resourceInfo->num_storage_buffers;
+ createInfo.num_uniform_buffers = resourceInfo->num_uniform_buffers;
+ createInfo.props = 0;
+
+ return (SDL_GPUShader *)SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(
+ device,
+ &createInfo,
+ (SDL_ShaderCross_ShaderStage)shaderStage);
}
SDL_GPUComputePipeline *SDL_ShaderCross_CompileComputePipelineFromSPIRV(
SDL_GPUDevice *device,
- const SDL_GPUComputePipelineCreateInfo *createInfo)
+ const Uint8 *bytecode,
+ size_t bytecodeSize,
+ const char *entrypoint,
+ const SDL_ShaderCross_ComputeResourceInfo *resourceInfo)
{
- return (SDL_GPUComputePipeline *)SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(device, createInfo, SDL_SHADERCROSS_SHADERSTAGE_COMPUTE);
+ SDL_GPUComputePipelineCreateInfo createInfo;
+ createInfo.code = bytecode;
+ createInfo.code_size = bytecodeSize;
+ createInfo.entrypoint = entrypoint;
+ createInfo.format = SDL_GPU_SHADERFORMAT_SPIRV;
+ createInfo.num_samplers = resourceInfo->num_samplers;
+ createInfo.num_readonly_storage_textures = resourceInfo->num_readonly_storage_textures;
+ createInfo.num_readonly_storage_buffers = resourceInfo->num_readonly_storage_buffers;
+ createInfo.num_readwrite_storage_textures = resourceInfo->num_readwrite_storage_textures;
+ createInfo.num_readwrite_storage_buffers = resourceInfo->num_readwrite_storage_buffers;
+ createInfo.num_uniform_buffers = resourceInfo->num_uniform_buffers;
+ createInfo.threadcount_x = resourceInfo->threadcount_x;
+ createInfo.threadcount_y = resourceInfo->threadcount_y;
+ createInfo.threadcount_z = resourceInfo->threadcount_z;
+ createInfo.props = 0;
+
+ return (SDL_GPUComputePipeline *)SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(
+ device,
+ &createInfo,
+ SDL_SHADERCROSS_SHADERSTAGE_COMPUTE);
}
#endif /* SDL_GPU_SHADERCROSS_SPIRVCROSS */