From b5fa7ebc8e414fe21b42fceef4ab8a9721ee6270 Mon Sep 17 00:00:00 2001
From: Evan Hemsley <[EMAIL REDACTED]>
Date: Mon, 28 Oct 2024 15:26:48 -0700
Subject: [PATCH] MSL: Remap resources based on descriptor set bindings (#30)
---
.../SDL_gpu_shadercross.h | 3 +-
src/SDL_gpu_shadercross.c | 484 +++++++++++++++++-
src/cli.c | 15 +-
3 files changed, 488 insertions(+), 14 deletions(-)
diff --git a/include/SDL3_gpu_shadercross/SDL_gpu_shadercross.h b/include/SDL3_gpu_shadercross/SDL_gpu_shadercross.h
index dd857e5..5d29bd5 100644
--- a/include/SDL3_gpu_shadercross/SDL_gpu_shadercross.h
+++ b/include/SDL3_gpu_shadercross/SDL_gpu_shadercross.h
@@ -88,7 +88,8 @@ extern SDL_DECLSPEC SDL_GPUShaderFormat SDLCALL SDL_ShaderCross_GetSPIRVShaderFo
extern SDL_DECLSPEC void * SDLCALL SDL_ShaderCross_TranspileMSLFromSPIRV(
const Uint8 *bytecode,
size_t bytecodeSize,
- const char *entrypoint);
+ const char *entrypoint,
+ SDL_ShaderCross_ShaderStage shaderStage);
/**
* Transpile to HLSL code from SPIRV code.
diff --git a/src/SDL_gpu_shadercross.c b/src/SDL_gpu_shadercross.c
index 4d3e25e..d69e3b0 100644
--- a/src/SDL_gpu_shadercross.c
+++ b/src/SDL_gpu_shadercross.c
@@ -292,12 +292,17 @@ static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
bool spirv,
size_t *size) // filled in with number of bytes of returned buffer
{
+ if (SDL_strstr(shaderProfile, "5_0")) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Cannot use Shader Model 5 with DXC!");
+ return NULL;
+ }
+
DxcBuffer source;
IDxcResult *dxcResult;
IDxcBlob *blob;
IDxcBlobUtf8 *errors;
size_t entryPointLength = SDL_utf8strlen(entrypoint) + 1;
- const char *entryPointUtf16 = SDL_iconv_string("UTF-16", "UTF-8", entrypoint, entryPointLength);
+ wchar_t *entryPointUtf16 = (wchar_t *)SDL_iconv_string("WCHAR_T", "UTF-8", entrypoint, entryPointLength);
LPCWSTR args[] = {
(LPCWSTR)L"-E",
(LPCWSTR)entryPointUtf16,
@@ -351,6 +356,8 @@ static void *SDL_ShaderCross_INTERNAL_CompileUsingDXC(
IID_IDxcResult,
(void **)&dxcResult);
+ SDL_free(entryPointUtf16);
+
if (ret < 0) {
SDL_LogError(SDL_LOG_CATEGORY_GPU,
"IDxcShaderCompiler3::Compile failed: %X",
@@ -712,8 +719,13 @@ typedef spvc_result (*pfn_spvc_context_parse_spirv)(spvc_context, const SpvId *,
typedef spvc_result (*pfn_spvc_context_create_compiler)(spvc_context, spvc_backend, spvc_parsed_ir, spvc_capture_mode, spvc_compiler *);
typedef spvc_result (*pfn_spvc_compiler_create_compiler_options)(spvc_compiler, spvc_compiler_options *);
typedef spvc_result (*pfn_spvc_compiler_options_set_uint)(spvc_compiler_options, spvc_compiler_option, unsigned);
+typedef spvc_result (*pfn_spvc_compiler_create_shader_resources)(spvc_compiler, spvc_resources *);
+typedef spvc_result (*pfn_spvc_compiler_msl_add_resource_binding)(spvc_compiler, const spvc_msl_resource_binding *);
+typedef spvc_result (*pfn_spvc_compiler_has_decoration)(spvc_compiler, SpvId, SpvDecoration);
+typedef spvc_result (*pfn_spvc_compiler_get_decoration)(spvc_compiler, SpvId, SpvDecoration);
typedef spvc_result (*pfn_spvc_compiler_install_compiler_options)(spvc_compiler, spvc_compiler_options);
typedef spvc_result (*pfn_spvc_compiler_compile)(spvc_compiler, const char **);
+typedef spvc_result (*pfn_spvc_resources_get_resource_list_for_type)(spvc_resources, spvc_resource_type, const spvc_reflected_resource **, size_t *);
typedef const char *(*pfn_spvc_context_get_last_error_string)(spvc_context);
typedef SpvExecutionModel (*pfn_spvc_compiler_get_execution_model)(spvc_compiler compiler);
typedef const char *(*pfn_spvc_compiler_get_cleansed_entry_point_name)(spvc_compiler compiler, const char *name, SpvExecutionModel model);
@@ -724,8 +736,13 @@ static pfn_spvc_context_parse_spirv SDL_spvc_context_parse_spirv = NULL;
static pfn_spvc_context_create_compiler SDL_spvc_context_create_compiler = NULL;
static pfn_spvc_compiler_create_compiler_options SDL_spvc_compiler_create_compiler_options = NULL;
static pfn_spvc_compiler_options_set_uint SDL_spvc_compiler_options_set_uint = NULL;
+static pfn_spvc_compiler_create_shader_resources SDL_spvc_compiler_create_shader_resources = NULL;
+static pfn_spvc_compiler_msl_add_resource_binding SDL_spvc_compiler_msl_add_resource_binding = NULL;
+static pfn_spvc_compiler_has_decoration SDL_spvc_compiler_has_decoration = NULL;
+static pfn_spvc_compiler_get_decoration SDL_spvc_compiler_get_decoration = NULL;
static pfn_spvc_compiler_install_compiler_options SDL_spvc_compiler_install_compiler_options = NULL;
static pfn_spvc_compiler_compile SDL_spvc_compiler_compile = NULL;
+static pfn_spvc_resources_get_resource_list_for_type SDL_spvc_resources_get_resource_list_for_type = NULL;
static pfn_spvc_context_get_last_error_string SDL_spvc_context_get_last_error_string = NULL;
static pfn_spvc_compiler_get_execution_model SDL_spvc_compiler_get_execution_model = NULL;
static pfn_spvc_compiler_get_cleansed_entry_point_name SDL_spvc_compiler_get_cleansed_entry_point_name = NULL;
@@ -738,8 +755,13 @@ static pfn_spvc_compiler_get_cleansed_entry_point_name SDL_spvc_compiler_get_cle
#define SDL_spvc_context_create_compiler spvc_context_create_compiler
#define SDL_spvc_compiler_create_compiler_options spvc_compiler_create_compiler_options
#define SDL_spvc_compiler_options_set_uint spvc_compiler_options_set_uint
+#define SDL_spvc_compiler_create_shader_resources spvc_compiler_create_shader_resources
+#define SDL_spvc_compiler_msl_add_resource_binding spvc_compiler_msl_add_resource_binding
+#define SDL_spvc_compiler_has_decoration spvc_compiler_has_decoration
+#define SDL_spvc_compiler_get_decoration spvc_compiler_get_decoration
#define SDL_spvc_compiler_install_compiler_options spvc_compiler_install_compiler_options
#define SDL_spvc_compiler_compile spvc_compiler_compile
+#define SDL_spvc_resources_get_resource_list_for_type spvc_resources_get_resource_list_for_type
#define SDL_spvc_context_get_last_error_string spvc_context_get_last_error_string
#define SDL_spvc_compiler_get_execution_model spvc_compiler_get_execution_model
#define SDL_spvc_compiler_get_cleansed_entry_point_name spvc_compiler_get_cleansed_entry_point_name
@@ -764,7 +786,8 @@ static void SDL_ShaderCross_INTERNAL_DestroyTranspileContext(
static SPIRVTranspileContext *SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
spvc_backend backend,
- unsigned shadermodel,
+ unsigned shadermodel, // only used for HLSL
+ SDL_ShaderCross_ShaderStage shaderStage, // only used for MSL
const Uint8 *code,
size_t codeSize,
const char *entrypoint
@@ -815,6 +838,436 @@ static SPIRVTranspileContext *SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
SDL_spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_HLSL_FLATTEN_MATRIX_VERTEX_INPUT_SEMANTICS, 1);
}
+ SpvExecutionModel executionModel;
+ if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_VERTEX) {
+ executionModel = SpvExecutionModelVertex;
+ } else if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_FRAGMENT) {
+ executionModel = SpvExecutionModelFragment;
+ } else { // compute
+ executionModel = SpvExecutionModelKernel;
+ }
+
+ // MSL doesn't have descriptor sets, so we have to set up index remapping
+ if (backend == SPVC_BACKEND_MSL && shaderStage != SDL_SHADERCROSS_SHADERSTAGE_COMPUTE) {
+ spvc_resources resources;
+ spvc_reflected_resource *reflected_resources;
+ size_t num_texture_samplers;
+ size_t num_storage_textures;
+ size_t num_storage_buffers;
+ size_t num_uniform_buffers;
+
+ result = SDL_spvc_compiler_create_shader_resources(compiler, &resources);
+ if (result < 0) {
+ SPVC_ERROR(spvc_compiler_create_shader_resources);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ // Combined texture-samplers
+ result = SDL_spvc_resources_get_resource_list_for_type(
+ resources,
+ SPVC_RESOURCE_TYPE_SAMPLED_IMAGE,
+ (const spvc_reflected_resource **)&reflected_resources,
+ &num_texture_samplers);
+ if (result < 0) {
+ SPVC_ERROR(spvc_resources_get_resource_list_for_type);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ spvc_msl_resource_binding binding;
+ for (size_t i = 0; i < num_texture_samplers; i += 1) {
+ if (!SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet) || !SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Shader resources must have descriptor set and binding index!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int descriptor_set_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet);
+ if (!(descriptor_set_index == 0 || descriptor_set_index == 2)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Descriptor set index for graphics texture-sampler must be 0 or 2!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int binding_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding);
+
+ binding.stage = executionModel;
+ binding.desc_set = descriptor_set_index;
+ binding.binding = binding_index;
+ binding.msl_texture = binding_index;
+ binding.msl_sampler = binding_index;
+ result = SDL_spvc_compiler_msl_add_resource_binding(compiler, &binding);
+ if (result < 0) {
+ SPVC_ERROR(spvc_compiler_msl_add_resource_binding);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+ }
+
+ // Storage textures
+ result = SDL_spvc_resources_get_resource_list_for_type(
+ resources,
+ SPVC_RESOURCE_TYPE_STORAGE_IMAGE,
+ (const spvc_reflected_resource **)&reflected_resources,
+ &num_storage_textures);
+ if (result < 0) {
+ SPVC_ERROR(spvc_resources_get_resource_list_for_type);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ for (size_t i = 0; i < num_storage_textures; i += 1) {
+ if (!SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet) || !SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Shader resources must have descriptor set and binding index!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int descriptor_set_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet);
+ if (!(descriptor_set_index == 0 || descriptor_set_index == 2)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Descriptor set index for graphics storage texture must be 0 or 2!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int binding_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding);
+
+ binding.stage = executionModel;
+ binding.desc_set = descriptor_set_index;
+ binding.binding = binding_index;
+ binding.msl_texture = num_texture_samplers + binding_index;
+ SDL_spvc_compiler_msl_add_resource_binding(compiler, &binding);
+ if (result < 0) {
+ SPVC_ERROR(spvc_compiler_msl_add_resource_binding);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+ }
+
+ // Storage buffers
+ result = SDL_spvc_resources_get_resource_list_for_type(
+ resources,
+ SPVC_RESOURCE_TYPE_STORAGE_BUFFER,
+ (const spvc_reflected_resource **)&reflected_resources,
+ &num_storage_buffers);
+ if (result < 0) {
+ SPVC_ERROR(spvc_resources_get_resource_list_for_type);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ for (size_t i = 0; i < num_storage_buffers; i += 1) {
+ if (!SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet) || !SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Shader resources must have descriptor set and binding index!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int descriptor_set_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet);
+ if (!(descriptor_set_index == 0 || descriptor_set_index == 2)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Descriptor set index for graphics storage buffer must be 0 or 2!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int binding_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding);
+
+ binding.stage = executionModel;
+ binding.desc_set = descriptor_set_index;
+ binding.binding = binding_index;
+ binding.msl_buffer = binding_index;
+ SDL_spvc_compiler_msl_add_resource_binding(compiler, &binding);
+ if (result < 0) {
+ SPVC_ERROR(spvc_compiler_msl_add_resource_binding);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+ }
+
+ // Uniform buffers
+ result = SDL_spvc_resources_get_resource_list_for_type(
+ resources,
+ SPVC_RESOURCE_TYPE_UNIFORM_BUFFER,
+ (const spvc_reflected_resource **)&reflected_resources,
+ &num_uniform_buffers);
+ if (result < 0) {
+ SPVC_ERROR(spvc_resources_get_resource_list_for_type);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ for (size_t i = 0; i< num_uniform_buffers; i += 1) {
+ if (!SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet) || !SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Shader resources must have descriptor set and binding index!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int descriptor_set_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet);
+ if (!(descriptor_set_index == 1 || descriptor_set_index == 3)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Descriptor set index for graphics uniform buffer must be 1 or 3!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int binding_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding);
+
+ binding.stage = executionModel;
+ binding.desc_set = descriptor_set_index;
+ binding.binding = binding_index;
+ binding.msl_buffer = num_storage_buffers + binding_index;
+ SDL_spvc_compiler_msl_add_resource_binding(compiler, &binding);
+ if (result < 0) {
+ SPVC_ERROR(spvc_compiler_msl_add_resource_binding);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+ }
+ }
+
+ if (backend == SPVC_BACKEND_MSL && shaderStage == SDL_SHADERCROSS_SHADERSTAGE_COMPUTE) {
+ spvc_resources resources;
+ spvc_reflected_resource *reflected_resources;
+ size_t num_texture_samplers;
+ size_t num_storage_textures; // total storage textures
+ size_t num_storage_buffers; // total storage buffers
+ size_t num_uniform_buffers;
+
+ result = SDL_spvc_compiler_create_shader_resources(compiler, &resources);
+ if (result < 0) {
+ SPVC_ERROR(spvc_compiler_create_shader_resources);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ spvc_msl_resource_binding binding;
+ unsigned int num_textures = 0;
+ unsigned int num_buffers = 0;
+
+ // Combined texture-samplers
+ result = SDL_spvc_resources_get_resource_list_for_type(
+ resources,
+ SPVC_RESOURCE_TYPE_SAMPLED_IMAGE,
+ (const spvc_reflected_resource **)&reflected_resources,
+ &num_texture_samplers);
+ if (result < 0) {
+ SPVC_ERROR(spvc_resources_get_resource_list_for_type);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ for (size_t i = 0; i < num_texture_samplers; i += 1) {
+ if (!SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet) || !SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Shader resources must have descriptor set and binding index!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int descriptor_set_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet);
+ if (descriptor_set_index != 0) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Descriptor set index for compute texture-sampler must be 0!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int binding_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding);
+
+ binding.stage = executionModel;
+ binding.desc_set = descriptor_set_index;
+ binding.binding = binding_index;
+ binding.msl_texture = num_textures;
+ binding.msl_sampler = num_textures;
+ result = SDL_spvc_compiler_msl_add_resource_binding(compiler, &binding);
+ if (result < 0) {
+ SPVC_ERROR(spvc_compiler_msl_add_resource_binding);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+ num_textures += 1;
+ }
+
+ // Storage textures
+ result = SDL_spvc_resources_get_resource_list_for_type(
+ resources,
+ SPVC_RESOURCE_TYPE_STORAGE_IMAGE,
+ (const spvc_reflected_resource **)&reflected_resources,
+ &num_storage_textures);
+ if (result < 0) {
+ SPVC_ERROR(spvc_resources_get_resource_list_for_type);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ // Readonly storage textures
+ for (size_t i = 0; i < num_storage_textures; i += 1) {
+ if (!SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet) || !SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Shader resources must have descriptor set and binding index!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int descriptor_set_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet);
+ if (!(descriptor_set_index == 0 || descriptor_set_index == 1)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Descriptor set index for compute storage texture must be 0 or 1!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ // Skip readwrite textures
+ if (descriptor_set_index != 0) { continue; }
+
+ unsigned int binding_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding);
+
+ binding.stage = executionModel;
+ binding.desc_set = descriptor_set_index;
+ binding.binding = binding_index;
+ binding.msl_texture = num_textures + binding_index;
+ SDL_spvc_compiler_msl_add_resource_binding(compiler, &binding);
+ if (result < 0) {
+ SPVC_ERROR(spvc_compiler_msl_add_resource_binding);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ num_textures += 1;
+ }
+
+ // Readwrite storage textures
+ for (size_t i = 0; i < num_storage_textures; i += 1) {
+ unsigned int descriptor_set_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet);
+
+ // Skip readonly textures
+ if (descriptor_set_index != 1) { continue; }
+
+ unsigned int binding_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding);
+
+ binding.stage = executionModel;
+ binding.desc_set = descriptor_set_index;
+ binding.binding = binding_index;
+ binding.msl_texture = num_textures + binding_index;
+ SDL_spvc_compiler_msl_add_resource_binding(compiler, &binding);
+ if (result < 0) {
+ SPVC_ERROR(spvc_compiler_msl_add_resource_binding);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ num_textures += 1;
+ }
+
+ // Storage buffers
+ result = SDL_spvc_resources_get_resource_list_for_type(
+ resources,
+ SPVC_RESOURCE_TYPE_STORAGE_BUFFER,
+ (const spvc_reflected_resource **)&reflected_resources,
+ &num_storage_buffers);
+ if (result < 0) {
+ SPVC_ERROR(spvc_resources_get_resource_list_for_type);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ // Readonly storage buffers
+ for (size_t i = 0; i < num_storage_buffers; i += 1) {
+ if (!SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet) || !SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Shader resources must have descriptor set and binding index!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int descriptor_set_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet);
+ if (!(descriptor_set_index == 0 || descriptor_set_index == 1)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Descriptor set index for compute storage buffer must be 0 or 1!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ // Skip readwrite buffers
+ if (descriptor_set_index != 0) { continue; }
+
+ unsigned int binding_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding);
+
+ binding.stage = executionModel;
+ binding.desc_set = descriptor_set_index;
+ binding.binding = binding_index;
+ binding.msl_buffer = binding_index;
+ SDL_spvc_compiler_msl_add_resource_binding(compiler, &binding);
+ if (result < 0) {
+ SPVC_ERROR(spvc_compiler_msl_add_resource_binding);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ num_buffers += 1;
+ }
+
+ // Readonly storage buffers
+ for (size_t i = 0; i < num_storage_buffers; i += 1) {
+ unsigned int descriptor_set_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet);
+
+ // Skip readonly buffers
+ if (descriptor_set_index != 1) { continue; }
+
+ unsigned int binding_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding);
+
+ binding.stage = executionModel;
+ binding.desc_set = descriptor_set_index;
+ binding.binding = binding_index;
+ binding.msl_buffer = num_buffers + binding_index;
+ SDL_spvc_compiler_msl_add_resource_binding(compiler, &binding);
+ if (result < 0) {
+ SPVC_ERROR(spvc_compiler_msl_add_resource_binding);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ num_buffers += 1;
+ }
+
+ // Uniform buffers
+ result = SDL_spvc_resources_get_resource_list_for_type(
+ resources,
+ SPVC_RESOURCE_TYPE_UNIFORM_BUFFER,
+ (const spvc_reflected_resource **)&reflected_resources,
+ &num_uniform_buffers);
+ if (result < 0) {
+ SPVC_ERROR(spvc_resources_get_resource_list_for_type);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ for (size_t i = 0; i < num_uniform_buffers; i += 1) {
+ if (!SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet) || !SDL_spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding)) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Shader resources must have descriptor set and binding index!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int descriptor_set_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet);
+ if (descriptor_set_index != 2) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", "Descriptor set index for compute uniform buffer must be 2!");
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ unsigned int binding_index = SDL_spvc_compiler_get_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding);
+
+ binding.stage = executionModel;
+ binding.desc_set = descriptor_set_index;
+ binding.binding = binding_index;
+ binding.msl_buffer = num_buffers + binding_index;
+ SDL_spvc_compiler_msl_add_resource_binding(compiler, &binding);
+ if (result < 0) {
+ SPVC_ERROR(spvc_compiler_msl_add_resource_binding);
+ SDL_spvc_context_destroy(context);
+ return NULL;
+ }
+
+ num_buffers += 1;
+ }
+ }
+
result = SDL_spvc_compiler_install_compiler_options(compiler, options);
if (result < 0) {
SPVC_ERROR(spvc_compiler_install_compiler_options);
@@ -847,7 +1300,7 @@ static void *SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
SDL_GPUDevice *device,
SDL_GPUShaderFormat shaderFormat,
const void *originalCreateInfo,
- bool isCompute
+ SDL_ShaderCross_ShaderStage shaderStage
) {
const SDL_GPUShaderCreateInfo *createInfo;
spvc_backend backend;
@@ -875,6 +1328,7 @@ static void *SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
SPIRVTranspileContext *transpileContext = SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
backend,
shadermodel,
+ shaderStage,
createInfo->code,
createInfo->code_size,
createInfo->entrypoint);
@@ -882,7 +1336,7 @@ static void *SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
void *shaderObject = NULL;
/* Copy the original create info, but with the new source code */
- if (isCompute) {
+ if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_COMPUTE) {
SDL_GPUComputePipelineCreateInfo newCreateInfo;
newCreateInfo = *(const SDL_GPUComputePipelineCreateInfo *)createInfo;
@@ -948,11 +1402,13 @@ static void *SDL_ShaderCross_INTERNAL_CompileFromSPIRV(
void *SDL_ShaderCross_TranspileMSLFromSPIRV(
const Uint8 *bytecode,
size_t bytecodeSize,
- const char *entrypoint)
+ const char *entrypoint,
+ SDL_ShaderCross_ShaderStage shaderStage)
{
SPIRVTranspileContext *context = SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
SPVC_BACKEND_MSL,
0,
+ shaderStage,
bytecode,
bytecodeSize,
entrypoint
@@ -986,6 +1442,7 @@ void *SDL_ShaderCross_TranspileHLSLFromSPIRV(
SPIRVTranspileContext *context = SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
SPVC_BACKEND_HLSL,
shadermodel,
+ 0, // unused for HLSL
bytecode,
bytecodeSize,
entrypoint
@@ -1009,6 +1466,7 @@ void *SDL_ShaderCross_CompileDXBCFromSPIRV(
SPIRVTranspileContext *context = SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
SPVC_BACKEND_HLSL,
50,
+ 0, // unused for HLSL
bytecode,
bytecodeSize,
entrypoint);
@@ -1042,6 +1500,7 @@ void *SDL_ShaderCross_CompileDXILFromSPIRV(
SPIRVTranspileContext *context = SDL_ShaderCross_INTERNAL_TranspileFromSPIRV(
SPVC_BACKEND_HLSL,
60,
+ 0, // unused for HLSL
bytecode,
bytecodeSize,
entrypoint);
@@ -1068,14 +1527,14 @@ void *SDL_ShaderCross_CompileDXILFromSPIRV(
static void *SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(
SDL_GPUDevice *device,
const void *originalCreateInfo,
- bool isCompute)
+ SDL_ShaderCross_ShaderStage shaderStage)
{
SDL_GPUShaderFormat format;
SDL_GPUShaderFormat shader_formats = SDL_GetGPUShaderFormats(device);
if (shader_formats & SDL_GPU_SHADERFORMAT_SPIRV) {
- if (isCompute) {
+ if (shaderStage == SDL_SHADERCROSS_SHADERSTAGE_COMPUTE) {
return SDL_CreateGPUComputePipeline(device, (const SDL_GPUComputePipelineCreateInfo *)originalCreateInfo);
} else {
return SDL_CreateGPUShader(device, (const SDL_GPUShaderCreateInfo *)originalCreateInfo);
@@ -1095,21 +1554,21 @@ static void *SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(
device,
format,
originalCreateInfo,
- isCompute);
+ shaderStage);
}
SDL_GPUShader *SDL_ShaderCross_CompileGraphicsShaderFromSPIRV(
SDL_GPUDevice *device,
const SDL_GPUShaderCreateInfo *createInfo)
{
- return (SDL_GPUShader *)SDL_ShaderCross_INTERNAL_CreateShaderFromSPIRV(device, createInfo, false);
+ return (SDL_GPUShader *)SDL_ShaderCross_INTERNAL_Cre
(Patch may be truncated, please check the link at the top of this post.)