From 0a52299595d1ba2ed89c643368cfe6772b4ac72f Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 2 Oct 2024 16:48:59 +0200 Subject: [PATCH 01/37] wip sokol-gfx bindings cleanup support --- src/shdc/spirv.cc | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/shdc/spirv.cc b/src/shdc/spirv.cc index 5333854d..25c7b9b8 100644 --- a/src/shdc/spirv.cc +++ b/src/shdc/spirv.cc @@ -224,6 +224,48 @@ static bool compile(EShLanguage stage, Slang::Enum slang, const MergedSource& so return false; } + // do intermediate reflection to figure out number of uniform blocks, textures and samplers + // in each shader stage + fmt::print("---\n"); + if (program.buildReflection(EShReflectionSeparateBuffers)) { + for (int i = 0; i < program.getNumUniformVariables(); i++) { + const auto& uniform = program.getUniform(i); + if (uniform.getType()->isTexture()) { + fmt::print("texture:\n"); + } else if (uniform.getType()->getSampler().sampler) { + fmt::print("sampler:\n"); + } else { + continue; + } + fmt::print(" name: {}\n", uniform.name); + if (uniform.stages & EShLangVertexMask) { + fmt::print(" stage: vertex\n"); + } else if (uniform.stages & EShLangFragmentMask) { + fmt::print(" stage: fragment\n"); + } + } + for (int i = 0; i < program.getNumUniformBlocks(); i++) { + const auto& ub = program.getUniformBlock(i); + fmt::print("uniform block:\n"); + fmt::print(" name: {}\n", ub.name); + if (ub.stages & EShLangVertexMask) { + fmt::print(" stage: vertex\n"); + } else if (ub.stages & EShLangFragmentMask) { + fmt::print(" stage: fragment\n"); + } + } + for (int i = 0; i < program.getNumBufferBlocks(); i++) { + const auto& bb = program.getBufferBlock(i); + fmt::print("buffer block:\n"); + fmt::print(" name: {}\n", bb.name); + if (bb.stages & EShLangVertexMask) { + fmt::print(" stage: vertex\n"); + } else if (bb.stages & EShLangFragmentMask) { + fmt::print(" stage: fragment\n"); + } + } + } + // translate intermediate representation to SPIRV const glslang::TIntermediate* im = program.getIntermediate(stage); assert(im); From fed3268685d194218479cbbbdff8fc1f52fda6ad Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Thu, 3 Oct 2024 16:09:39 +0200 Subject: [PATCH 02/37] write num ubs, images, sampler and storage buffers to SpirvBlob --- src/shdc/spirv.cc | 75 ++++++++++++++----------------------- src/shdc/types/spirv_blob.h | 6 ++- 2 files changed, 34 insertions(+), 47 deletions(-) diff --git a/src/shdc/spirv.cc b/src/shdc/spirv.cc index 25c7b9b8..c0cb4157 100644 --- a/src/shdc/spirv.cc +++ b/src/shdc/spirv.cc @@ -189,6 +189,8 @@ static bool compile(EShLanguage stage, Slang::Enum slang, const MergedSource& so const char* sourcesNames[1] = { inp.base_path.c_str() }; const int linenr_offset = source.linenr_offset; + SpirvBlob spirv_blob = SpirvBlob(snippet_index); + // compile GLSL vertex- or fragment-shader glslang::TShader shader(stage); // FIXME: add custom defines here: compiler.addProcess(...) @@ -224,45 +226,19 @@ static bool compile(EShLanguage stage, Slang::Enum slang, const MergedSource& so return false; } - // do intermediate reflection to figure out number of uniform blocks, textures and samplers - // in each shader stage - fmt::print("---\n"); - if (program.buildReflection(EShReflectionSeparateBuffers)) { - for (int i = 0; i < program.getNumUniformVariables(); i++) { - const auto& uniform = program.getUniform(i); - if (uniform.getType()->isTexture()) { - fmt::print("texture:\n"); - } else if (uniform.getType()->getSampler().sampler) { - fmt::print("sampler:\n"); - } else { - continue; - } - fmt::print(" name: {}\n", uniform.name); - if (uniform.stages & EShLangVertexMask) { - fmt::print(" stage: vertex\n"); - } else if (uniform.stages & EShLangFragmentMask) { - fmt::print(" stage: fragment\n"); - } - } - for (int i = 0; i < program.getNumUniformBlocks(); i++) { - const auto& ub = program.getUniformBlock(i); - fmt::print("uniform block:\n"); - fmt::print(" name: {}\n", ub.name); - if (ub.stages & EShLangVertexMask) { - fmt::print(" stage: vertex\n"); - } else if (ub.stages & EShLangFragmentMask) { - fmt::print(" stage: fragment\n"); - } - } - for (int i = 0; i < program.getNumBufferBlocks(); i++) { - const auto& bb = program.getBufferBlock(i); - fmt::print("buffer block:\n"); - fmt::print(" name: {}\n", bb.name); - if (bb.stages & EShLangVertexMask) { - fmt::print(" stage: vertex\n"); - } else if (bb.stages & EShLangFragmentMask) { - fmt::print(" stage: fragment\n"); - } + // extract limited reflection info needed for bind slot mapping + if (!program.buildReflection(EShReflectionSeparateBuffers)) { + fmt::print("TProgram.buildReflection(EShReflectionSeparateBuffers) failed!\n"); + return false; + } + spirv_blob.num_uniform_blocks = program.getNumUniformBlocks(); + spirv_blob.num_storage_buffers = program.getNumBufferBlocks(); + for (int i = 0; i < program.getNumUniformVariables(); i++) { + const auto uniform_type = program.getUniform(i).getType(); + if (uniform_type->isTexture()) { + spirv_blob.num_images += 1; + } else if (uniform_type->getSampler().sampler) { + spirv_blob.num_samplers += 1; } } @@ -280,17 +256,19 @@ static bool compile(EShLanguage stage, Slang::Enum slang, const MergedSource& so spv_options.validate = false; spv_options.emitNonSemanticShaderDebugInfo = false; spv_options.emitNonSemanticShaderDebugSource = false; - out_spirv.blobs.push_back(SpirvBlob(snippet_index)); - out_spirv.blobs.back().source = source.src; - glslang::GlslangToSpv(*im, out_spirv.blobs.back().bytecode, &spv_logger, &spv_options); + spirv_blob.source = source.src; + glslang::GlslangToSpv(*im, spirv_blob.bytecode, &spv_logger, &spv_options); std::string spirv_log = spv_logger.getAllMessages(); if (!spirv_log.empty()) { // FIXME: need to parse string for errors and translate to ErrMsg objects? // haven't seen a case yet where this generates log messages - fmt::print("{}", spirv_log); + fmt::print(stderr, "{}", spirv_log); } // run optimizer passes - spirv_optimize(slang, out_spirv.blobs.back().bytecode); + spirv_optimize(slang, spirv_blob.bytecode); + + // and done + out_spirv.blobs.push_back(spirv_blob); return true; } @@ -369,7 +347,12 @@ void Spirv::dump_debug(const Input& inp, ErrMsg::Format err_fmt) const { fmt::print(stderr, " errors: none\n\n"); } for (const SpirvBlob& blob : blobs) { - fmt::print(stderr, " source for snippet '{}':\n", inp.snippets[blob.snippet_index].name); + fmt::print(stderr, " snippet: {}\n", inp.snippets[blob.snippet_index].name); + fmt::print(stderr, " uniform blocks: {}\n", blob.num_uniform_blocks); + fmt::print(stderr, " images: {}\n", blob.num_images); + fmt::print(stderr, " samplers: {}\n", blob.num_samplers); + fmt::print(stderr, " storage buffers: {}\n", blob.num_storage_buffers); + fmt::print(stderr, " source:\n", inp.snippets[blob.snippet_index].name); std::vector src_lines; pystring::splitlines(blob.source, src_lines); for (const std::string& src_line: src_lines) { @@ -377,7 +360,7 @@ void Spirv::dump_debug(const Input& inp, ErrMsg::Format err_fmt) const { } fmt::print(stderr, "\n"); - fmt::print(stderr, " SPIR-V for snippet '{}':\n", inp.snippets[blob.snippet_index].name); + fmt::print(stderr, " spirv:\n", inp.snippets[blob.snippet_index].name); spvtools::SpirvTools spirv_tools(SPV_ENV_OPENGL_4_5); std::string dasm_str; spirv_tools.Disassemble(blob.bytecode, &dasm_str, spvtools::SpirvTools::kDefaultDisassembleOption); diff --git a/src/shdc/types/spirv_blob.h b/src/shdc/types/spirv_blob.h index 8057b5b2..84cfc5b2 100644 --- a/src/shdc/types/spirv_blob.h +++ b/src/shdc/types/spirv_blob.h @@ -4,11 +4,15 @@ namespace shdc { -// a SPIRV-bytecode blob with "back-link" to Input.snippets +// a SPIRV-bytecode blob with "back-link" to Input.snippets and some limited reflection info struct SpirvBlob { int snippet_index = -1; // index into Input.snippets std::string source; // source code this blob was compiled from std::vector bytecode; // the resulting SPIRV blob + int num_uniform_blocks = 0; + int num_images = 0; + int num_samplers = 0; + int num_storage_buffers = 0; SpirvBlob(int snippet_index); }; From eb58238d655b95ec02201b30761644a158e3116e Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Thu, 3 Oct 2024 17:00:59 +0200 Subject: [PATCH 03/37] roll back the 'early reflection' code since it's useless --- src/shdc/spirv.cc | 20 -------------------- src/shdc/spirvcross.cc | 3 +++ src/shdc/types/spirv_blob.h | 4 ---- 3 files changed, 3 insertions(+), 24 deletions(-) diff --git a/src/shdc/spirv.cc b/src/shdc/spirv.cc index c0cb4157..c09dd701 100644 --- a/src/shdc/spirv.cc +++ b/src/shdc/spirv.cc @@ -226,22 +226,6 @@ static bool compile(EShLanguage stage, Slang::Enum slang, const MergedSource& so return false; } - // extract limited reflection info needed for bind slot mapping - if (!program.buildReflection(EShReflectionSeparateBuffers)) { - fmt::print("TProgram.buildReflection(EShReflectionSeparateBuffers) failed!\n"); - return false; - } - spirv_blob.num_uniform_blocks = program.getNumUniformBlocks(); - spirv_blob.num_storage_buffers = program.getNumBufferBlocks(); - for (int i = 0; i < program.getNumUniformVariables(); i++) { - const auto uniform_type = program.getUniform(i).getType(); - if (uniform_type->isTexture()) { - spirv_blob.num_images += 1; - } else if (uniform_type->getSampler().sampler) { - spirv_blob.num_samplers += 1; - } - } - // translate intermediate representation to SPIRV const glslang::TIntermediate* im = program.getIntermediate(stage); assert(im); @@ -348,10 +332,6 @@ void Spirv::dump_debug(const Input& inp, ErrMsg::Format err_fmt) const { } for (const SpirvBlob& blob : blobs) { fmt::print(stderr, " snippet: {}\n", inp.snippets[blob.snippet_index].name); - fmt::print(stderr, " uniform blocks: {}\n", blob.num_uniform_blocks); - fmt::print(stderr, " images: {}\n", blob.num_images); - fmt::print(stderr, " samplers: {}\n", blob.num_samplers); - fmt::print(stderr, " storage buffers: {}\n", blob.num_storage_buffers); fmt::print(stderr, " source:\n", inp.snippets[blob.snippet_index].name); std::vector src_lines; pystring::splitlines(blob.source, src_lines); diff --git a/src/shdc/spirvcross.cc b/src/shdc/spirvcross.cc index 57dc2fc0..0860fc2a 100644 --- a/src/shdc/spirvcross.cc +++ b/src/shdc/spirvcross.cc @@ -43,6 +43,9 @@ static void fix_bind_slots(Compiler& compiler, Snippet::Type type, Slang::Enum s } // combined image samplers + // FIXME: technically this is wrong since image-samplers have a common + // bind space across shader stages, but since the binding happens via + // name lookup the DecorationBinding is actually ignored. { uint32_t binding = 0; for (const Resource& res: shader_resources.sampled_images) { diff --git a/src/shdc/types/spirv_blob.h b/src/shdc/types/spirv_blob.h index 84cfc5b2..0d8a528b 100644 --- a/src/shdc/types/spirv_blob.h +++ b/src/shdc/types/spirv_blob.h @@ -9,10 +9,6 @@ struct SpirvBlob { int snippet_index = -1; // index into Input.snippets std::string source; // source code this blob was compiled from std::vector bytecode; // the resulting SPIRV blob - int num_uniform_blocks = 0; - int num_images = 0; - int num_samplers = 0; - int num_storage_buffers = 0; SpirvBlob(int snippet_index); }; From f075f203624751b0d087534ba4b93d1531123c3e Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Thu, 3 Oct 2024 18:06:20 +0200 Subject: [PATCH 04/37] more wip sokol-gfx bindings cleanup support --- src/shdc/reflection.cc | 5 +- src/shdc/reflection.h | 3 + src/shdc/spirvcross.cc | 69 ++++++++++++++-------- src/shdc/types/reflection/image.h | 2 +- src/shdc/types/reflection/image_sampler.h | 2 +- src/shdc/types/reflection/sampler.h | 2 +- src/shdc/types/reflection/storage_buffer.h | 2 +- src/shdc/types/reflection/uniform_block.h | 2 +- 8 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/shdc/reflection.cc b/src/shdc/reflection.cc index a00926c3..49b49f83 100644 --- a/src/shdc/reflection.cc +++ b/src/shdc/reflection.cc @@ -74,8 +74,9 @@ static ErrMsg validate_linking(const Input& inp, const Program& prog, const Prog Reflection Reflection::build(const Args& args, const Input& inp, const std::array& spirvcross_array) { Reflection res; - // for each program, just pick the reflection info from the first compiled slang - // FIXME: we should check whether the reflection info of all compiled slangs actually matches + // for each program, just pick the reflection info from the first compiled slang, + // the reflection info is the same for each Slang because it has been generated + // with the special Slang::REFLECTION, not the actual slang. for (const auto& item: inp.programs) { const Program& prog = item.second; int vs_snippet_index = inp.snippet_map.at(prog.vs_name); diff --git a/src/shdc/reflection.h b/src/shdc/reflection.h index 1f49db48..046985c6 100644 --- a/src/shdc/reflection.h +++ b/src/shdc/reflection.h @@ -24,6 +24,9 @@ struct Reflection { static Reflection build(const Args& args, const Input& inp, const std::array& spirvcross); // parse per-snippet reflection info for a compiled shader source static StageReflection parse_snippet_reflection(const spirv_cross::Compiler& compiler, const Snippet& snippet, ErrMsg& out_error); + +FIXME: add a static helper function which returns binding base by slang, stage and resource type + // print a debug dump to stderr void dump_debug(ErrMsg::Format err_fmt) const; diff --git a/src/shdc/spirvcross.cc b/src/shdc/spirvcross.cc index 0860fc2a..14dee5e0 100644 --- a/src/shdc/spirvcross.cc +++ b/src/shdc/spirvcross.cc @@ -31,8 +31,14 @@ const SpirvcrossSource* Spirvcross::find_source_by_snippet_index(int snippet_ind } static void fix_bind_slots(Compiler& compiler, Snippet::Type type, Slang::Enum slang) { + // WGSL bindslot fixup is handled elsewhere + // Also note that this function can be called with the special Slang::REFLECTION + // which guarantees zero-based bindings for each resource type + assert(!Slang::is_wgsl(slang)); ShaderResources shader_resources = compiler.get_shader_resources(); +FIXME: use the new Reflection::binding_base() helper function + // uniform buffers { uint32_t binding = 0; @@ -43,11 +49,17 @@ static void fix_bind_slots(Compiler& compiler, Snippet::Type type, Slang::Enum s } // combined image samplers - // FIXME: technically this is wrong since image-samplers have a common - // bind space across shader stages, but since the binding happens via - // name lookup the DecorationBinding is actually ignored. { - uint32_t binding = 0; + uint32_t binding; + if (Slang::is_glsl(slang)) { + // GLSL has a common bind space across shader stages, so make sure + // that bindings can't collide. + // NOTE though that currently that binding isn't used by sokol-gfx + // because image-samplers use name-lookup + binding = Snippet::is_vs(type) ? 0 : ImageSampler::Num; + } else { + binding = 0; + } for (const Resource& res: shader_resources.sampled_images) { compiler.set_decoration(res.id, spv::DecorationDescriptorSet, 0); compiler.set_decoration(res.id, spv::DecorationBinding, binding++); @@ -76,17 +88,17 @@ static void fix_bind_slots(Compiler& compiler, Snippet::Type type, Slang::Enum s { uint32_t binding; if (Slang::is_msl(slang)) { - // in Metal, on the vertex stage, storage buffers are bound after uniform- and vertex-buffers, - // and on the fragment stage, after the uniform buffers - binding = Snippet::is_vs(type) ? 12 : 4; + // in Metal, all buffers have a common bind space per stage, + // bind storage buffers after uniform buffers + binding = UniformBlock::Num; } else if (Slang::is_hlsl(slang)) { - // in D3D11, storage buffers share bind slots with textures, put textures into - // the first 16 slots, and storage buffers starting at slot 16 - binding = 16; + // in D3D11, textures and storage buffers have a common bind space + // per stage, bind storage buffers after textures + binding = Image::Num; } else if (Slang::is_glsl(slang)) { // in GL, the shader stages share a common bind space, need to offset // fragment bindings - binding = Snippet::is_vs(type) ? 0 : 8; + binding = Snippet::is_vs(type) ? 0 : StorageBuffer::Num; } else { binding = 0; } @@ -103,25 +115,30 @@ static void fix_bind_slots(Compiler& compiler, Snippet::Type type, Slang::Enum s static void wgsl_patch_bind_slots(Compiler& compiler, Snippet::Type type, std::vector& inout_bytecode) { ShaderResources shader_resources = compiler.get_shader_resources(); - // WGPU bindgroups and binding offsets are hardwired: + // even though sokol-gfx is flexible now, still use specific + // bind slot ranges here: + // // - bindgroup 0 for uniform buffer bindings // - vertex stage bindings start at 0 - // - fragment stage bindings start at 4 + // - fragment stage bindings start at UniformBlock::Num (8) // - bindgroup 1 for all images, samplers and storage buffers // - vertex stage image bindings start at 0 - // - vertex stage sampler bindings start at 16 - // - vertex stage storage buffer bindings start at 32 - // - fragment stage image bindings start at 48 - // - fragment stage sampler bindings start at 64 - // - fragment stage storage buffer bindings start at 80 + // - vertex stage sampler bindings start at Image::Num (16) + // - vertex stage storage buffer bindings start at Image::Num + Sampler::Num (32) + // - fragment stage image bindings start at 64 + // - fragment stage sampler bindings start at 64 + Image::Num (80) + // - fragment stage storage buffer bindings start at 64 + Image::Num + Sampler::Num (96) + +FIXME: use the new Reflection::binding_base() helper function instead + const uint32_t wgsl_vs_ub_bind_offset = 0; - const uint32_t wgsl_fs_ub_bind_offset = 4; + const uint32_t wgsl_fs_ub_bind_offset = UniformBlock::Num; const uint32_t wgsl_vs_img_bind_offset = 0; - const uint32_t wgsl_vs_smp_bind_offset = 16; - const uint32_t wgsl_vs_sbuf_bind_offset = 32; - const uint32_t wgsl_fs_img_bind_offset = 48; - const uint32_t wgsl_fs_smp_bind_offset = 64; - const uint32_t wgsl_fs_sbuf_bind_offset = 80; + const uint32_t wgsl_vs_smp_bind_offset = Image::Num; + const uint32_t wgsl_vs_sbuf_bind_offset = Image::Num + Sampler::Num; + const uint32_t wgsl_fs_img_bind_offset = 64; + const uint32_t wgsl_fs_smp_bind_offset = 64 + Image::Num; + const uint32_t wgsl_fs_sbuf_bind_offset = 64 + Image::Num + Sampler::Num; const uint32_t ub_bindgroup = 0; const uint32_t res_bindgroup = 1; @@ -130,7 +147,6 @@ static void wgsl_patch_bind_slots(Compiler& compiler, Snippet::Type type, std::v uint32_t cur_sampler_binding = Snippet::is_vs(type) ? wgsl_vs_smp_bind_offset : wgsl_fs_smp_bind_offset; uint32_t cur_sbuf_binding = Snippet::is_vs(type) ? wgsl_vs_sbuf_bind_offset : wgsl_fs_sbuf_bind_offset; - // uniform buffers { for (const Resource& res: shader_resources.uniform_buffers) { @@ -315,6 +331,9 @@ static StageReflection parse_reflection(const std::vector& bytecode, c compiler.set_common_options(options); flatten_uniform_blocks(compiler); to_combined_image_samplers(compiler); + // passing Slang::REFLECTION here makes sure that the bind slots + // are zero-based per stage and resource type (otherwise 3D API + // specific bind slot allocations would apply) fix_bind_slots(compiler, snippet.type, Slang::REFLECTION); // NOTE: we need to compile here, otherwise the reflection won't be // able to detect depth-textures and comparison-samplers! diff --git a/src/shdc/types/reflection/image.h b/src/shdc/types/reflection/image.h index cfd175c3..54ef92e2 100644 --- a/src/shdc/types/reflection/image.h +++ b/src/shdc/types/reflection/image.h @@ -8,7 +8,7 @@ namespace shdc::refl { struct Image { - static const int Num = 12; // must be identical with SG_MAX_SHADERSTAGE_IMAGES + static const int Num = 16; // must be identical with SG_MAX_IMAGE_BINDSLOTS ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; std::string name; diff --git a/src/shdc/types/reflection/image_sampler.h b/src/shdc/types/reflection/image_sampler.h index af2cff83..b7ec3913 100644 --- a/src/shdc/types/reflection/image_sampler.h +++ b/src/shdc/types/reflection/image_sampler.h @@ -7,7 +7,7 @@ namespace shdc::refl { // special combined-image-samplers for GLSL output with GL semantics struct ImageSampler { - static const int Num = 12; // must be identical with SG_MAX_SHADERSTAGE_IMAGES + static const int Num = 16; // must be identical with SG_MAX_IMAGE_SAMPLER_PAIRS ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; std::string name; diff --git a/src/shdc/types/reflection/sampler.h b/src/shdc/types/reflection/sampler.h index 938fe560..d5af53c7 100644 --- a/src/shdc/types/reflection/sampler.h +++ b/src/shdc/types/reflection/sampler.h @@ -7,7 +7,7 @@ namespace shdc::refl { struct Sampler { - static const int Num = 12; // must be identical with SG_MAX_SHADERSTAGE_SAMPLERS + static const int Num = 16; // must be identical with SG_MAX_SAMPLER_BINDSLOTS ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; std::string name; diff --git a/src/shdc/types/reflection/storage_buffer.h b/src/shdc/types/reflection/storage_buffer.h index 424964bb..34c99181 100644 --- a/src/shdc/types/reflection/storage_buffer.h +++ b/src/shdc/types/reflection/storage_buffer.h @@ -7,7 +7,7 @@ namespace shdc::refl { struct StorageBuffer { - static const int Num = 8; // must be identical with SG_MAX_SHADERSTAGE_STORAGE_BUFFERS + static const int Num = 8; // must be identical with SG_MAX_STORAGEBUFFER_BINDSLOTS ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; std::string inst_name; diff --git a/src/shdc/types/reflection/uniform_block.h b/src/shdc/types/reflection/uniform_block.h index 28e91d7c..b120cfad 100644 --- a/src/shdc/types/reflection/uniform_block.h +++ b/src/shdc/types/reflection/uniform_block.h @@ -8,7 +8,7 @@ namespace shdc::refl { struct UniformBlock { - static const int Num = 4; // must be identical with SG_MAX_SHADERSTAGE_UBS + static const int Num = 8; // must be identical with SG_MAX_UNIFORMBLOCK_BINDSLOTS ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; std::string inst_name; From 7299ce30d113f8f8004d9fbf27190dfe76415a32 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Fri, 4 Oct 2024 11:32:39 +0200 Subject: [PATCH 05/37] wip rework bindings reflection --- src/shdc/generators/sokolc.cc | 10 +-- src/shdc/generators/sokold.cc | 10 +-- src/shdc/generators/sokoljai.cc | 10 +-- src/shdc/generators/sokolnim.cc | 10 +-- src/shdc/generators/sokolodin.cc | 10 +-- src/shdc/generators/sokolrust.cc | 10 +-- src/shdc/generators/sokolzig.cc | 10 +-- src/shdc/reflection.h | 3 - src/shdc/spirvcross.cc | 97 +++++----------------- src/shdc/types/reflection/bindings.h | 75 +++++++++++++++++ src/shdc/types/reflection/image.h | 1 - src/shdc/types/reflection/image_sampler.h | 1 - src/shdc/types/reflection/sampler.h | 1 - src/shdc/types/reflection/shader_stage.h | 10 +++ src/shdc/types/reflection/storage_buffer.h | 1 - src/shdc/types/reflection/uniform_block.h | 1 - 16 files changed, 142 insertions(+), 118 deletions(-) diff --git a/src/shdc/generators/sokolc.cc b/src/shdc/generators/sokolc.cc index 5c264f7f..f1f57fd0 100644 --- a/src/shdc/generators/sokolc.cc +++ b/src/shdc/generators/sokolc.cc @@ -292,7 +292,7 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < UniformBlock::Num; ub_index++) { + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); @@ -316,7 +316,7 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } } - for (int sbuf_index = 0; sbuf_index < StorageBuffer::Num; sbuf_index++) { + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); @@ -324,7 +324,7 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef l("{}.readonly = {};\n", sbn, sbuf->readonly); } } - for (int img_index = 0; img_index < Image::Num; img_index++) { + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { const Image* img = refl.bindings.find_image_by_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); @@ -334,7 +334,7 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); } } - for (int smp_index = 0; smp_index < Sampler::Num; smp_index++) { + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); @@ -342,7 +342,7 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); } } - for (int img_smp_index = 0; img_smp_index < ImageSampler::Num; img_smp_index++) { + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index 5d227cc4..ddd733f0 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -242,7 +242,7 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < UniformBlock::Num; ub_index++) { + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); @@ -266,7 +266,7 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } } - for (int sbuf_index = 0; sbuf_index < StorageBuffer::Num; sbuf_index++) { + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); @@ -274,7 +274,7 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef l("{}.readonly = {};\n", sbn, sbuf->readonly); } } - for (int img_index = 0; img_index < Image::Num; img_index++) { + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { const Image* img = refl.bindings.find_image_by_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); @@ -284,7 +284,7 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); } } - for (int smp_index = 0; smp_index < Sampler::Num; smp_index++) { + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); @@ -292,7 +292,7 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); } } - for (int img_smp_index = 0; img_smp_index < ImageSampler::Num; img_smp_index++) { + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); diff --git a/src/shdc/generators/sokoljai.cc b/src/shdc/generators/sokoljai.cc index ef920795..eaf1b90e 100644 --- a/src/shdc/generators/sokoljai.cc +++ b/src/shdc/generators/sokoljai.cc @@ -226,7 +226,7 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < UniformBlock::Num; ub_index++) { + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); @@ -250,7 +250,7 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } } - for (int sbuf_index = 0; sbuf_index < StorageBuffer::Num; sbuf_index++) { + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); @@ -258,7 +258,7 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR l("{}.readonly = {};\n", sbn, sbuf->readonly); } } - for (int img_index = 0; img_index < Image::Num; img_index++) { + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { const Image* img = refl.bindings.find_image_by_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); @@ -268,7 +268,7 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); } } - for (int smp_index = 0; smp_index < Sampler::Num; smp_index++) { + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); @@ -276,7 +276,7 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); } } - for (int img_smp_index = 0; img_smp_index < ImageSampler::Num; img_smp_index++) { + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); diff --git a/src/shdc/generators/sokolnim.cc b/src/shdc/generators/sokolnim.cc index 2db7437d..b58aa089 100644 --- a/src/shdc/generators/sokolnim.cc +++ b/src/shdc/generators/sokolnim.cc @@ -309,7 +309,7 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } l("{}.entry = \"{}\"\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < UniformBlock::Num; ub_index++) { + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniformBlocks[{}]", dsn, ub_index); @@ -333,7 +333,7 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } } - for (int sbuf_index = 0; sbuf_index < StorageBuffer::Num; sbuf_index++) { + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storageBuffers[{}]", dsn, sbuf_index); @@ -341,7 +341,7 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR l("{}.readonly = {}\n", sbn, sbuf->readonly); } } - for (int img_index = 0; img_index < Image::Num; img_index++) { + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { const Image* img = refl.bindings.find_image_by_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); @@ -351,7 +351,7 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR l("{}.sampleType = {}\n", in, image_sample_type(img->sample_type)); } } - for (int smp_index = 0; smp_index < Sampler::Num; smp_index++) { + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); @@ -359,7 +359,7 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR l("{}.samplerType = {}\n", sn, sampler_type(smp->type)); } } - for (int img_smp_index = 0; img_smp_index < ImageSampler::Num; img_smp_index++) { + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.imageSamplerPairs[{}]", dsn, img_smp_index); diff --git a/src/shdc/generators/sokolodin.cc b/src/shdc/generators/sokolodin.cc index 70649227..091406d0 100644 --- a/src/shdc/generators/sokolodin.cc +++ b/src/shdc/generators/sokolodin.cc @@ -229,7 +229,7 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } l("{}.entry = \"{}\"\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < UniformBlock::Num; ub_index++) { + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); @@ -253,7 +253,7 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } } - for (int sbuf_index = 0; sbuf_index < StorageBuffer::Num; sbuf_index++) { + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); @@ -261,7 +261,7 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program l("{}.readonly = {}\n", sbn, sbuf->readonly); } } - for (int img_index = 0; img_index < Image::Num; img_index++) { + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { const Image* img = refl.bindings.find_image_by_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); @@ -271,7 +271,7 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program l("{}.sample_type = {}\n", in, image_sample_type(img->sample_type)); } } - for (int smp_index = 0; smp_index < Sampler::Num; smp_index++) { + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); @@ -279,7 +279,7 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program l("{}.sampler_type = {}\n", sn, sampler_type(smp->type)); } } - for (int img_smp_index = 0; img_smp_index < ImageSampler::Num; img_smp_index++) { + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); diff --git a/src/shdc/generators/sokolrust.cc b/src/shdc/generators/sokolrust.cc index ebde6585..aeb51013 100644 --- a/src/shdc/generators/sokolrust.cc +++ b/src/shdc/generators/sokolrust.cc @@ -242,7 +242,7 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } l("{}.entry = c\"{}\".as_ptr();\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < UniformBlock::Num; ub_index++) { + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); @@ -266,7 +266,7 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } } - for (int sbuf_index = 0; sbuf_index < StorageBuffer::Num; sbuf_index++) { + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); @@ -274,7 +274,7 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program l("{}.readonly = {};\n", sbn, sbuf->readonly); } } - for (int img_index = 0; img_index < Image::Num; img_index++) { + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { const Image* img = refl.bindings.find_image_by_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); @@ -284,7 +284,7 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); } } - for (int smp_index = 0; smp_index < Sampler::Num; smp_index++) { + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); @@ -292,7 +292,7 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); } } - for (int img_smp_index = 0; img_smp_index < ImageSampler::Num; img_smp_index++) { + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); diff --git a/src/shdc/generators/sokolzig.cc b/src/shdc/generators/sokolzig.cc index 71971dc1..7cd8673b 100644 --- a/src/shdc/generators/sokolzig.cc +++ b/src/shdc/generators/sokolzig.cc @@ -240,7 +240,7 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < UniformBlock::Num; ub_index++) { + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); @@ -264,7 +264,7 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } } - for (int sbuf_index = 0; sbuf_index < StorageBuffer::Num; sbuf_index++) { + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); @@ -272,7 +272,7 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR l("{}.readonly = {};\n", sbn, sbuf->readonly); } } - for (int img_index = 0; img_index < Image::Num; img_index++) { + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { const Image* img = refl.bindings.find_image_by_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); @@ -282,7 +282,7 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); } } - for (int smp_index = 0; smp_index < Sampler::Num; smp_index++) { + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); @@ -290,7 +290,7 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); } } - for (int img_smp_index = 0; img_smp_index < ImageSampler::Num; img_smp_index++) { + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); diff --git a/src/shdc/reflection.h b/src/shdc/reflection.h index 046985c6..1f49db48 100644 --- a/src/shdc/reflection.h +++ b/src/shdc/reflection.h @@ -24,9 +24,6 @@ struct Reflection { static Reflection build(const Args& args, const Input& inp, const std::array& spirvcross); // parse per-snippet reflection info for a compiled shader source static StageReflection parse_snippet_reflection(const spirv_cross::Compiler& compiler, const Snippet& snippet, ErrMsg& out_error); - -FIXME: add a static helper function which returns binding base by slang, stage and resource type - // print a debug dump to stderr void dump_debug(ErrMsg::Format err_fmt) const; diff --git a/src/shdc/spirvcross.cc b/src/shdc/spirvcross.cc index 14dee5e0..9ed15c2b 100644 --- a/src/shdc/spirvcross.cc +++ b/src/shdc/spirvcross.cc @@ -30,18 +30,17 @@ const SpirvcrossSource* Spirvcross::find_source_by_snippet_index(int snippet_ind return nullptr; } -static void fix_bind_slots(Compiler& compiler, Snippet::Type type, Slang::Enum slang) { +static void fix_bind_slots(Compiler& compiler, Snippet::Type snippet_type, Slang::Enum slang) { // WGSL bindslot fixup is handled elsewhere // Also note that this function can be called with the special Slang::REFLECTION // which guarantees zero-based bindings for each resource type assert(!Slang::is_wgsl(slang)); ShaderResources shader_resources = compiler.get_shader_resources(); - -FIXME: use the new Reflection::binding_base() helper function + ShaderStage::Enum stage = ShaderStage::from_snippet_type(snippet_type); // uniform buffers { - uint32_t binding = 0; + uint32_t binding = Bindings::base_slot(slang, stage, Bindings::Type::UNIFORM_BLOCK); for (const Resource& res: shader_resources.uniform_buffers) { compiler.set_decoration(res.id, spv::DecorationDescriptorSet, 0); compiler.set_decoration(res.id, spv::DecorationBinding, binding++); @@ -50,16 +49,7 @@ FIXME: use the new Reflection::binding_base() helper function // combined image samplers { - uint32_t binding; - if (Slang::is_glsl(slang)) { - // GLSL has a common bind space across shader stages, so make sure - // that bindings can't collide. - // NOTE though that currently that binding isn't used by sokol-gfx - // because image-samplers use name-lookup - binding = Snippet::is_vs(type) ? 0 : ImageSampler::Num; - } else { - binding = 0; - } + uint32_t binding = Bindings::base_slot(slang, stage, Bindings::Type::IMAGE_SAMPLER); for (const Resource& res: shader_resources.sampled_images) { compiler.set_decoration(res.id, spv::DecorationDescriptorSet, 0); compiler.set_decoration(res.id, spv::DecorationBinding, binding++); @@ -68,7 +58,7 @@ FIXME: use the new Reflection::binding_base() helper function // separate images { - uint32_t binding = 0; + uint32_t binding = Bindings::base_slot(slang, stage, Bindings::Type::IMAGE); for (const Resource& res: shader_resources.separate_images) { compiler.set_decoration(res.id, spv::DecorationDescriptorSet, 0); compiler.set_decoration(res.id, spv::DecorationBinding, binding++); @@ -77,7 +67,7 @@ FIXME: use the new Reflection::binding_base() helper function // separate samplers { - uint32_t binding = 0; + uint32_t binding = Bindings::base_slot(slang, stage, Bindings::Type::SAMPLER); for (const Resource& res: shader_resources.separate_samplers) { compiler.set_decoration(res.id, spv::DecorationDescriptorSet, 0); compiler.set_decoration(res.id, spv::DecorationBinding, binding++); @@ -86,22 +76,7 @@ FIXME: use the new Reflection::binding_base() helper function // storage buffers { - uint32_t binding; - if (Slang::is_msl(slang)) { - // in Metal, all buffers have a common bind space per stage, - // bind storage buffers after uniform buffers - binding = UniformBlock::Num; - } else if (Slang::is_hlsl(slang)) { - // in D3D11, textures and storage buffers have a common bind space - // per stage, bind storage buffers after textures - binding = Image::Num; - } else if (Slang::is_glsl(slang)) { - // in GL, the shader stages share a common bind space, need to offset - // fragment bindings - binding = Snippet::is_vs(type) ? 0 : StorageBuffer::Num; - } else { - binding = 0; - } + uint32_t binding = Bindings::base_slot(slang, stage, Bindings::Type::STORAGE_BUFFER); for (const Resource& res: shader_resources.storage_buffers) { compiler.set_decoration(res.id, spv::DecorationDescriptorSet, 0); compiler.set_decoration(res.id, spv::DecorationBinding, binding++); @@ -112,43 +87,16 @@ FIXME: use the new Reflection::binding_base() helper function // This directly patches the descriptor set and bindslot decorators in the input SPIRV // via SPIRVCross helper functions. This patched SPIRV is then used as input to Tint // for the SPIRV-to-WGSL translation. -static void wgsl_patch_bind_slots(Compiler& compiler, Snippet::Type type, std::vector& inout_bytecode) { +static void wgsl_patch_bind_slots(Compiler& compiler, Snippet::Type snippet_type, std::vector& inout_bytecode) { ShaderResources shader_resources = compiler.get_shader_resources(); - - // even though sokol-gfx is flexible now, still use specific - // bind slot ranges here: - // - // - bindgroup 0 for uniform buffer bindings - // - vertex stage bindings start at 0 - // - fragment stage bindings start at UniformBlock::Num (8) - // - bindgroup 1 for all images, samplers and storage buffers - // - vertex stage image bindings start at 0 - // - vertex stage sampler bindings start at Image::Num (16) - // - vertex stage storage buffer bindings start at Image::Num + Sampler::Num (32) - // - fragment stage image bindings start at 64 - // - fragment stage sampler bindings start at 64 + Image::Num (80) - // - fragment stage storage buffer bindings start at 64 + Image::Num + Sampler::Num (96) - -FIXME: use the new Reflection::binding_base() helper function instead - - const uint32_t wgsl_vs_ub_bind_offset = 0; - const uint32_t wgsl_fs_ub_bind_offset = UniformBlock::Num; - const uint32_t wgsl_vs_img_bind_offset = 0; - const uint32_t wgsl_vs_smp_bind_offset = Image::Num; - const uint32_t wgsl_vs_sbuf_bind_offset = Image::Num + Sampler::Num; - const uint32_t wgsl_fs_img_bind_offset = 64; - const uint32_t wgsl_fs_smp_bind_offset = 64 + Image::Num; - const uint32_t wgsl_fs_sbuf_bind_offset = 64 + Image::Num + Sampler::Num; - + const ShaderStage::Enum stage = ShaderStage::from_snippet_type(snippet_type); + const Slang::Enum slang = Slang::WGSL; const uint32_t ub_bindgroup = 0; - const uint32_t res_bindgroup = 1; - uint32_t cur_ub_binding = Snippet::is_vs(type) ? wgsl_vs_ub_bind_offset : wgsl_fs_ub_bind_offset; - uint32_t cur_image_binding = Snippet::is_vs(type) ? wgsl_vs_img_bind_offset : wgsl_fs_img_bind_offset; - uint32_t cur_sampler_binding = Snippet::is_vs(type) ? wgsl_vs_smp_bind_offset : wgsl_fs_smp_bind_offset; - uint32_t cur_sbuf_binding = Snippet::is_vs(type) ? wgsl_vs_sbuf_bind_offset : wgsl_fs_sbuf_bind_offset; + const uint32_t img_smp_sbuf_bindgroup = 1; // uniform buffers { + uint32_t binding = Bindings::base_slot(slang, stage, Bindings::Type::UNIFORM_BLOCK); for (const Resource& res: shader_resources.uniform_buffers) { uint32_t out_offset = 0; if (compiler.get_binary_offset_for_decoration(res.id, spv::DecorationDescriptorSet, out_offset)) { @@ -157,8 +105,7 @@ FIXME: use the new Reflection::binding_base() helper function instead // FIXME handle error } if (compiler.get_binary_offset_for_decoration(res.id, spv::DecorationBinding, out_offset)) { - inout_bytecode[out_offset] = cur_ub_binding; - cur_ub_binding += 1; + inout_bytecode[out_offset] = binding++; } else { // FIXME: handle error } @@ -167,16 +114,16 @@ FIXME: use the new Reflection::binding_base() helper function instead // separate images { + uint32_t binding = Bindings::base_slot(slang, stage, Bindings::Type::IMAGE); for (const Resource& res: shader_resources.separate_images) { uint32_t out_offset = 0; if (compiler.get_binary_offset_for_decoration(res.id, spv::DecorationDescriptorSet, out_offset)) { - inout_bytecode[out_offset] = res_bindgroup; + inout_bytecode[out_offset] = img_smp_sbuf_bindgroup; } else { // FIXME: handle error } if (compiler.get_binary_offset_for_decoration(res.id, spv::DecorationBinding, out_offset)) { - inout_bytecode[out_offset] = cur_image_binding; - cur_image_binding += 1; + inout_bytecode[out_offset] = binding++; } else { // FIXME: handle error } @@ -185,16 +132,16 @@ FIXME: use the new Reflection::binding_base() helper function instead // separate samplers { + uint32_t binding = Bindings::base_slot(slang, stage, Bindings::Type::SAMPLER); for (const Resource& res: shader_resources.separate_samplers) { uint32_t out_offset = 0; if (compiler.get_binary_offset_for_decoration(res.id, spv::DecorationDescriptorSet, out_offset)) { - inout_bytecode[out_offset] = res_bindgroup; + inout_bytecode[out_offset] = img_smp_sbuf_bindgroup; } else { // FIXME: handle error } if (compiler.get_binary_offset_for_decoration(res.id, spv::DecorationBinding, out_offset)) { - inout_bytecode[out_offset] = cur_sampler_binding; - cur_sampler_binding += 1; + inout_bytecode[out_offset] = binding++; } else { // FIXME: handle error } @@ -203,16 +150,16 @@ FIXME: use the new Reflection::binding_base() helper function instead // storage buffers { + uint32_t binding = Bindings::base_slot(slang, stage, Bindings::Type::STORAGE_BUFFER); for (const Resource& res: shader_resources.storage_buffers) { uint32_t out_offset = 0; if (compiler.get_binary_offset_for_decoration(res.id, spv::DecorationDescriptorSet, out_offset)) { - inout_bytecode[out_offset] = res_bindgroup; + inout_bytecode[out_offset] = img_smp_sbuf_bindgroup; } else { // FIXME: handle error } if (compiler.get_binary_offset_for_decoration(res.id, spv::DecorationBinding, out_offset)) { - inout_bytecode[out_offset] = cur_sbuf_binding; - cur_sbuf_binding += 1; + inout_bytecode[out_offset] = binding++; } else { // FIXME: handle error } diff --git a/src/shdc/types/reflection/bindings.h b/src/shdc/types/reflection/bindings.h index fb535747..a2b09db2 100644 --- a/src/shdc/types/reflection/bindings.h +++ b/src/shdc/types/reflection/bindings.h @@ -8,12 +8,35 @@ namespace shdc::refl { struct Bindings { + // keep these in sync with: + // - SG_MAX_UNIFORMBLOCK_BINDSLOTS + // - SG_MAX_IMAGE_BINDSLOTS + // - SG_MAX_SAMPLER_BINDSLOTS + // - SG_MAX_STORAGEBUFFER_BINDSLOTS + // - SG_MAX_IMAGE_SAMPLERS_PAIRS + // + static const int MaxUniformBlocks = 8; + static const int MaxImages = 16; + static const int MaxSamplers = 16; + static const int MaxStorageBuffers = 8; + static const int MaxImageSamplers = 16; + + enum Type { + UNIFORM_BLOCK, + IMAGE, + SAMPLER, + STORAGE_BUFFER, + IMAGE_SAMPLER, + }; + std::vector uniform_blocks; std::vector storage_buffers; std::vector images; std::vector samplers; std::vector image_samplers; + static uint32_t base_slot(Slang::Enum slang, ShaderStage::Enum stage, Type type); + const UniformBlock* find_uniform_block_by_slot(int slot) const; const StorageBuffer* find_storage_buffer_by_slot(int slot) const; const Image* find_image_by_slot(int slot) const; @@ -29,6 +52,58 @@ struct Bindings { void dump_debug(const std::string& indent) const; }; +// returns the 3D API specific base-binding slot for a shader dialect, stage and resource type +// NOTE: the special Slang::REFLECTION always returns zero, this can be used +// to figure out the sokol-gfx bindslots +inline uint32_t Bindings::base_slot(Slang::Enum slang, ShaderStage::Enum stage, Type type) { + int res = 0; + switch (type) { + case Type::UNIFORM_BLOCK: + if (Slang::is_wgsl(slang)) { + res = ShaderStage::is_vs(stage) ? 0 : MaxUniformBlocks; + } + break; + case Type::IMAGE_SAMPLER: + if (Slang::is_glsl(slang)) { + res = ShaderStage::is_vs(stage) ? 0 : MaxImageSamplers; + } + case Type::IMAGE: + if (Slang::is_wgsl(slang)) { + if (ShaderStage::is_fs(stage)) { + res += 64; + } + } + break; + case Type::SAMPLER: + if (Slang::is_wgsl(slang)) { + res = MaxImages; + if (ShaderStage::is_fs(stage)) { + res += 64; + } + } + break; + case Type::STORAGE_BUFFER: + if (Slang::is_msl(slang)) { + res = MaxUniformBlocks; + } else if (Slang::is_hlsl(slang)) { + res = MaxImages; + } else if (Slang::is_glsl(slang)) { + if (ShaderStage::is_fs(stage)) { + res = MaxStorageBuffers; + } + } else if (Slang::is_wgsl(slang)) { + res = MaxImages + MaxSamplers; + if (ShaderStage::is_fs(stage)) { + res += 64; + } + } else if (Slang::is_glsl(slang)) { + + } + break; + } + return res; +} + inline const UniformBlock* Bindings::find_uniform_block_by_slot(int slot) const { for (const UniformBlock& ub: uniform_blocks) { if (ub.slot == slot) { diff --git a/src/shdc/types/reflection/image.h b/src/shdc/types/reflection/image.h index 54ef92e2..d1bb86de 100644 --- a/src/shdc/types/reflection/image.h +++ b/src/shdc/types/reflection/image.h @@ -8,7 +8,6 @@ namespace shdc::refl { struct Image { - static const int Num = 16; // must be identical with SG_MAX_IMAGE_BINDSLOTS ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; std::string name; diff --git a/src/shdc/types/reflection/image_sampler.h b/src/shdc/types/reflection/image_sampler.h index b7ec3913..0728fbde 100644 --- a/src/shdc/types/reflection/image_sampler.h +++ b/src/shdc/types/reflection/image_sampler.h @@ -7,7 +7,6 @@ namespace shdc::refl { // special combined-image-samplers for GLSL output with GL semantics struct ImageSampler { - static const int Num = 16; // must be identical with SG_MAX_IMAGE_SAMPLER_PAIRS ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; std::string name; diff --git a/src/shdc/types/reflection/sampler.h b/src/shdc/types/reflection/sampler.h index d5af53c7..12fb1f34 100644 --- a/src/shdc/types/reflection/sampler.h +++ b/src/shdc/types/reflection/sampler.h @@ -7,7 +7,6 @@ namespace shdc::refl { struct Sampler { - static const int Num = 16; // must be identical with SG_MAX_SAMPLER_BINDSLOTS ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; std::string name; diff --git a/src/shdc/types/reflection/shader_stage.h b/src/shdc/types/reflection/shader_stage.h index 72271429..b67b0342 100644 --- a/src/shdc/types/reflection/shader_stage.h +++ b/src/shdc/types/reflection/shader_stage.h @@ -1,4 +1,5 @@ #pragma once +#include "types/snippet.h" namespace shdc::refl { @@ -12,6 +13,7 @@ struct ShaderStage { }; static const char* to_str(Enum e); static Enum from_index(int idx); + static Enum from_snippet_type(Snippet::Type t); static bool is_vs(Enum e); static bool is_fs(Enum e); }; @@ -24,6 +26,14 @@ inline const char* ShaderStage::to_str(ShaderStage::Enum e) { } } +inline ShaderStage::Enum ShaderStage::from_snippet_type(Snippet::Type t) { + switch (t) { + case Snippet::Type::VS: return ShaderStage::Vertex; + case Snippet::Type::FS: return ShaderStage::Fragment; + default: return ShaderStage::Vertex; + } +} + inline ShaderStage::Enum ShaderStage::from_index(int idx) { assert((idx >= 0) && (idx < Num)); return (ShaderStage::Enum)idx; diff --git a/src/shdc/types/reflection/storage_buffer.h b/src/shdc/types/reflection/storage_buffer.h index 34c99181..82d74502 100644 --- a/src/shdc/types/reflection/storage_buffer.h +++ b/src/shdc/types/reflection/storage_buffer.h @@ -7,7 +7,6 @@ namespace shdc::refl { struct StorageBuffer { - static const int Num = 8; // must be identical with SG_MAX_STORAGEBUFFER_BINDSLOTS ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; std::string inst_name; diff --git a/src/shdc/types/reflection/uniform_block.h b/src/shdc/types/reflection/uniform_block.h index b120cfad..6667a49b 100644 --- a/src/shdc/types/reflection/uniform_block.h +++ b/src/shdc/types/reflection/uniform_block.h @@ -8,7 +8,6 @@ namespace shdc::refl { struct UniformBlock { - static const int Num = 8; // must be identical with SG_MAX_UNIFORMBLOCK_BINDSLOTS ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; std::string inst_name; From b16410563c116b44ab4c8bb4ae23eeb05ebab843 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Fri, 4 Oct 2024 11:56:23 +0200 Subject: [PATCH 06/37] wip add backend specific bind slots to reflection --- src/shdc/types/reflection/image.h | 9 +++++++++ src/shdc/types/reflection/sampler.h | 9 +++++++++ src/shdc/types/reflection/storage_buffer.h | 12 ++++++++++++ src/shdc/types/reflection/uniform_block.h | 9 +++++++++ 4 files changed, 39 insertions(+) diff --git a/src/shdc/types/reflection/image.h b/src/shdc/types/reflection/image.h index d1bb86de..568f2907 100644 --- a/src/shdc/types/reflection/image.h +++ b/src/shdc/types/reflection/image.h @@ -10,6 +10,9 @@ namespace shdc::refl { struct Image { ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; + int hlsl_register_t_n = -1; + int msl_texture_n = -1; + int wgsl_group1_binding_n = -1; std::string name; ImageType::Enum type = ImageType::INVALID; ImageSampleType::Enum sample_type = ImageSampleType::INVALID; @@ -22,6 +25,9 @@ struct Image { inline bool Image::equals(const Image& other) const { return (stage == other.stage) && (slot == other.slot) + && (hlsl_register_t_n == other.hlsl_register_t_n) + && (msl_texture_n == other.msl_texture_n) + && (wgsl_group1_binding_n == other.wgsl_group1_binding_n) && (name == other.name) && (type == other.type) && (sample_type == other.sample_type) @@ -33,6 +39,9 @@ inline void Image::dump_debug(const std::string& indent) const { fmt::print(stderr, "{}-\n", indent); fmt::print(stderr, "{}stage: {}\n", indent2, ShaderStage::to_str(stage)); fmt::print(stderr, "{}slot: {}\n", indent2, slot); + fmt::print(stderr, "{}hlsl_register_t_n: {}\n", indent2, hlsl_register_t_n); + fmt::print(stderr, "{}msl_texture_n: {}\n", indent2, msl_texture_n); + fmt::print(stderr, "{}wgsl_group1_binding_n: {}\n", indent2, wgsl_group1_binding_n); fmt::print(stderr, "{}name: {}\n", indent2, name); fmt::print(stderr, "{}type: {}\n", indent2, ImageType::to_str(type)); fmt::print(stderr, "{}sample_type: {}\n", indent2, ImageSampleType::to_str(sample_type)); diff --git a/src/shdc/types/reflection/sampler.h b/src/shdc/types/reflection/sampler.h index 12fb1f34..3fffeda3 100644 --- a/src/shdc/types/reflection/sampler.h +++ b/src/shdc/types/reflection/sampler.h @@ -9,6 +9,9 @@ namespace shdc::refl { struct Sampler { ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; + int hlsl_register_s_n = -1; + int msl_sampler_n = -1; + int wgsl_group1_binding_n = -1; std::string name; SamplerType::Enum type = SamplerType::INVALID; @@ -19,6 +22,9 @@ struct Sampler { inline bool Sampler::equals(const Sampler& other) const { return (stage == other.stage) && (slot == other.slot) + && (hlsl_register_s_n == other.hlsl_register_s_n) + && (msl_sampler_n == other.msl_sampler_n) + && (wgsl_group1_binding_n == other.wgsl_group1_binding_n) && (name == other.name) && (type == other.type); } @@ -28,6 +34,9 @@ inline void Sampler::dump_debug(const std::string& indent) const { fmt::print(stderr, "{}-\n", indent); fmt::print(stderr, "{}stage: {}\n", indent2, ShaderStage::to_str(stage)); fmt::print(stderr, "{}slot: {}\n", indent2, slot); + fmt::print(stderr, "{}hlsl_register_s_n: {}\n", indent2, hlsl_register_s_n); + fmt::print(stderr, "{}msl_sampler_n: {}\n", indent2, msl_sampler_n); + fmt::print(stderr, "{}wgsl_group1_binding_n: {}\n", indent2, wgsl_group1_binding_n); fmt::print(stderr, "{}name: {}\n", indent2, name); fmt::print(stderr, "{}type: {}\n", indent2, SamplerType::to_str(type)); } diff --git a/src/shdc/types/reflection/storage_buffer.h b/src/shdc/types/reflection/storage_buffer.h index 82d74502..9a5056a7 100644 --- a/src/shdc/types/reflection/storage_buffer.h +++ b/src/shdc/types/reflection/storage_buffer.h @@ -9,6 +9,10 @@ namespace shdc::refl { struct StorageBuffer { ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; + int hlsl_register_t_n = -1; + int msl_buffer_n = -1; + int wgsl_group1_binding_n = -1; + int glsl_binding_n = -1; std::string inst_name; bool readonly; Type struct_info; @@ -20,6 +24,10 @@ struct StorageBuffer { inline bool StorageBuffer::equals(const StorageBuffer& other) const { return (stage == other.stage) && (slot == other.slot) + && (hlsl_register_t_n == other.hlsl_register_t_n) + && (msl_buffer_n == other.msl_buffer_n) + && (wgsl_group1_binding_n == other.wgsl_group1_binding_n) + && (glsl_binding_n == other.glsl_binding_n) && (inst_name == other.inst_name) && (readonly == other.readonly) && (struct_info.equals(other.struct_info)); @@ -30,6 +38,10 @@ inline void StorageBuffer::dump_debug(const std::string& indent) const { fmt::print(stderr, "{}-\n", indent); fmt::print(stderr, "{}stage: {}\n", indent2, ShaderStage::to_str(stage)); fmt::print(stderr, "{}slot: {}\n", indent2, slot); + fmt::print(stderr, "{}hlsl_register_t_n: {}\n", indent2, hlsl_register_t_n); + fmt::print(stderr, "{}msl_buffer_n: {}\n", indent2, msl_buffer_n); + fmt::print(stderr, "{}wgsl_group1_binding_n: {}\n", indent2, wgsl_group1_binding_n); + fmt::print(stderr, "{}glsl_binding_n: {}\n", indent2, glsl_binding_n); fmt::print(stderr, "{}inst_name: {}\n", indent2, inst_name); fmt::print(stderr, "{}readonly: {}\n", indent2, readonly); fmt::print(stderr, "{}struct:\n", indent2); diff --git a/src/shdc/types/reflection/uniform_block.h b/src/shdc/types/reflection/uniform_block.h index 6667a49b..908250c3 100644 --- a/src/shdc/types/reflection/uniform_block.h +++ b/src/shdc/types/reflection/uniform_block.h @@ -10,6 +10,9 @@ namespace shdc::refl { struct UniformBlock { ShaderStage::Enum stage = ShaderStage::Invalid; int slot = -1; + int hlsl_register_b_n = -1; + int msl_buffer_n = -1; + int wgsl_group0_binding_n = -1; std::string inst_name; bool flattened = false; Type struct_info; @@ -21,6 +24,9 @@ struct UniformBlock { inline bool UniformBlock::equals(const UniformBlock& other) const { return (stage == other.stage) && (slot == other.slot) + && (hlsl_register_b_n == other.hlsl_register_b_n) + && (msl_buffer_n == other.msl_buffer_n) + && (wgsl_group0_binding_n == other.wgsl_group0_binding_n) // NOTE: ignore inst_name && (flattened == other.flattened) && struct_info.equals(other.struct_info); @@ -31,6 +37,9 @@ inline void UniformBlock::dump_debug(const std::string& indent) const { fmt::print(stderr, "{}-\n", indent); fmt::print(stderr, "{}stage: {}\n", indent2, ShaderStage::to_str(stage)); fmt::print(stderr, "{}slot: {}\n", indent2, slot); + fmt::print(stderr, "{}hlsl_register_b_n: {}\n", indent2, hlsl_register_b_n); + fmt::print(stderr, "{}msl_buffer_n: {}\n", indent2, msl_buffer_n); + fmt::print(stderr, "{}wgsl_group0_binding_n: {}\n", indent2, wgsl_group0_binding_n); fmt::print(stderr, "{}inst_name: {}\n", indent2, inst_name); fmt::print(stderr, "{}flattened: {}\n", indent2, flattened); fmt::print(stderr, "{}struct:\n", indent2); From 833325c3440f1f4636931e9fe7c2aa7398e7c4b8 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Fri, 4 Oct 2024 12:12:43 +0200 Subject: [PATCH 07/37] reflection: populate 3d api specific bind slots --- src/shdc/reflection.cc | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/shdc/reflection.cc b/src/shdc/reflection.cc index 49b49f83..33aa6e9b 100644 --- a/src/shdc/reflection.cc +++ b/src/shdc/reflection.cc @@ -3,6 +3,7 @@ */ #include "reflection.h" #include "spirvcross.h" +#include "types/reflection/bindings.h" // workaround for Compiler.comparison_ids being protected class UnprotectedCompiler: spirv_cross::Compiler { @@ -246,9 +247,14 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c } // uniform blocks for (const Resource& ub_res: shd_resources.uniform_buffers) { + const int slot = compiler.get_decoration(ub_res.id, spv::DecorationBinding); + const Bindings::Type res_type = Bindings::Type::UNIFORM_BLOCK; UniformBlock refl_ub; refl_ub.stage = refl.stage; - refl_ub.slot = compiler.get_decoration(ub_res.id, spv::DecorationBinding); + refl_ub.slot = slot; + refl_ub.hlsl_register_b_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); + refl_ub.msl_buffer_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); + refl_ub.wgsl_group0_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); refl_ub.inst_name = compiler.get_name(ub_res.id); if (refl_ub.inst_name.empty()) { refl_ub.inst_name = compiler.get_fallback_name(ub_res.id); @@ -264,9 +270,15 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c } // storage buffers for (const Resource& sbuf_res: shd_resources.storage_buffers) { + const int slot = compiler.get_decoration(sbuf_res.id, spv::DecorationBinding); + const Bindings::Type res_type = Bindings::Type::STORAGE_BUFFER; StorageBuffer refl_sbuf; refl_sbuf.stage = refl.stage; - refl_sbuf.slot = compiler.get_decoration(sbuf_res.id, spv::DecorationBinding); + refl_sbuf.slot = slot; + refl_sbuf.hlsl_register_t_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); + refl_sbuf.msl_buffer_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); + refl_sbuf.wgsl_group1_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); + refl_sbuf.glsl_binding_n = slot + Bindings::base_slot(Slang::GLSL430, refl.stage, res_type); refl_sbuf.inst_name = compiler.get_name(sbuf_res.id); refl_sbuf.readonly = compiler.get_buffer_block_flags(sbuf_res.id).get(spv::DecorationNonWritable); if (refl_sbuf.inst_name.empty()) { @@ -281,9 +293,14 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c // (separate) images for (const Resource& img_res: shd_resources.separate_images) { + const int slot = compiler.get_decoration(img_res.id, spv::DecorationBinding); + const Bindings::Type res_type = Bindings::Type::IMAGE; Image refl_img; refl_img.stage = refl.stage; - refl_img.slot = compiler.get_decoration(img_res.id, spv::DecorationBinding); + refl_img.slot = slot; + refl_img.hlsl_register_t_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); + refl_img.msl_texture_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); + refl_img.wgsl_group1_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); refl_img.name = img_res.name; const SPIRType& img_type = compiler.get_type(img_res.type_id); refl_img.type = spirtype_to_image_type(img_type); @@ -297,10 +314,15 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c } // (separate) samplers for (const Resource& smp_res: shd_resources.separate_samplers) { + const int slot = compiler.get_decoration(smp_res.id, spv::DecorationBinding); + const Bindings::Type res_type = Bindings::Type::SAMPLER; const SPIRType& smp_type = compiler.get_type(smp_res.type_id); Sampler refl_smp; refl_smp.stage = refl.stage; - refl_smp.slot = compiler.get_decoration(smp_res.id, spv::DecorationBinding); + refl_smp.slot = slot; + refl_smp.hlsl_register_s_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); + refl_smp.msl_sampler_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); + refl_smp.wgsl_group1_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); refl_smp.name = smp_res.name; // HACK ALERT! if (((UnprotectedCompiler*)&compiler)->is_comparison_sampler(smp_type, smp_res.id)) { From 0c8de7768e1e29476981c3423e1dc02c17a524bc Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Fri, 4 Oct 2024 13:27:41 +0200 Subject: [PATCH 08/37] reflection: generate merged per-program bindings --- src/shdc/reflection.cc | 26 +++++++++++-------- .../types/reflection/program_reflection.h | 2 ++ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/shdc/reflection.cc b/src/shdc/reflection.cc index 33aa6e9b..52837908 100644 --- a/src/shdc/reflection.cc +++ b/src/shdc/reflection.cc @@ -74,10 +74,12 @@ static ErrMsg validate_linking(const Input& inp, const Program& prog, const Prog Reflection Reflection::build(const Args& args, const Input& inp, const std::array& spirvcross_array) { Reflection res; + ErrMsg error; // for each program, just pick the reflection info from the first compiled slang, // the reflection info is the same for each Slang because it has been generated // with the special Slang::REFLECTION, not the actual slang. + std::vector prog_bindings; for (const auto& item: inp.programs) { const Program& prog = item.second; int vs_snippet_index = inp.snippet_map.at(prog.vs_name); @@ -91,6 +93,15 @@ Reflection Reflection::build(const Args& args, const Input& inp, const std::arra prog_refl.name = prog.name; prog_refl.stages[ShaderStage::Vertex] = vs_src->stage_refl; prog_refl.stages[ShaderStage::Fragment] = fs_src->stage_refl; + prog_refl.bindings = merge_bindings({ + vs_src->stage_refl.bindings, + fs_src->stage_refl.bindings, + }, error); + if (error.valid()) { + res.error = inp.error(0, error.msg); + return res; + } + prog_bindings.push_back(prog_refl.bindings); // check that the outputs of the vertex stage match the input stage res.error = validate_linking(inp, prog, prog_refl); @@ -102,24 +113,17 @@ Reflection Reflection::build(const Args& args, const Input& inp, const std::arra // create a set of vertex shader inputs with removed duplicates // (or error out if the are attribute conflicts) - ErrMsg error; res.unique_vs_inputs = merge_vs_inputs(res.progs, error); if (error.valid()) { res.error = inp.error(0, error.msg); return res; } - // create a merged set of resource bindings - std::vector snippet_bindings; - for (int i = 0; i < Slang::Num; i++) { - Slang::Enum slang = Slang::from_index(i); - if (args.slang & Slang::bit(slang)) { - for (const SpirvcrossSource& src: spirvcross_array[i].sources) { - snippet_bindings.push_back(src.stage_refl.bindings); - } - } + // create a merged set of resource bindings across all programs + for (const auto& prog_refl: res.progs) { + prog_bindings.push_back(prog_refl.bindings); } - res.bindings = merge_bindings(snippet_bindings, error); + res.bindings = merge_bindings(prog_bindings, error); if (error.valid()) { res.error = inp.error(0, error.msg); } diff --git a/src/shdc/types/reflection/program_reflection.h b/src/shdc/types/reflection/program_reflection.h index 9b8ad3f8..50d41f37 100644 --- a/src/shdc/types/reflection/program_reflection.h +++ b/src/shdc/types/reflection/program_reflection.h @@ -7,6 +7,7 @@ namespace shdc::refl { struct ProgramReflection { std::string name; std::array stages; + Bindings bindings; // merged stage bindings const StageReflection& stage(ShaderStage::Enum s) const; const StageReflection& vs() const; @@ -42,6 +43,7 @@ inline void ProgramReflection::dump_debug(const std::string& indent) const { fmt::print(stderr, "{}-\n", indent); fmt::print(stderr, "{}name: {}\n", indent2, name); fmt::print(stderr, "{}stages:\n", indent2); + bindings.dump_debug(indent2); for (const auto& stage: stages) { stage.dump_debug(indent2); } From 92940f95c5bf24e84ee5eee57ec2ccb6b8372cdf Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Fri, 4 Oct 2024 19:55:56 +0200 Subject: [PATCH 09/37] per program bindslot consts wip --- src/shdc/generators/generator.h | 16 +++++++------- src/shdc/generators/sokolc.cc | 34 +++++++++++++++--------------- src/shdc/generators/sokolc.h | 16 +++++++------- src/shdc/generators/sokold.cc | 36 ++++++++++++++------------------ src/shdc/generators/sokold.h | 16 +++++++------- src/shdc/generators/sokoljai.cc | 32 ++++++++++++++-------------- src/shdc/generators/sokoljai.h | 16 +++++++------- src/shdc/generators/sokolnim.cc | 32 ++++++++++++++-------------- src/shdc/generators/sokolnim.h | 16 +++++++------- src/shdc/generators/sokolodin.cc | 32 ++++++++++++++-------------- src/shdc/generators/sokolodin.h | 16 +++++++------- src/shdc/generators/sokolrust.cc | 32 ++++++++++++++-------------- src/shdc/generators/sokolrust.h | 16 +++++++------- src/shdc/generators/sokolzig.cc | 32 ++++++++++++++-------------- src/shdc/generators/sokolzig.h | 16 +++++++------- 15 files changed, 177 insertions(+), 181 deletions(-) diff --git a/src/shdc/generators/generator.h b/src/shdc/generators/generator.h index aadb7049..949037b2 100644 --- a/src/shdc/generators/generator.h +++ b/src/shdc/generators/generator.h @@ -77,16 +77,16 @@ class Generator { virtual std::string struct_name(const std::string& name) { assert(false && "implement me"); return ""; }; virtual std::string vertex_attr_name(const refl::StageAttr& attr) { assert(false && "implement me"); return ""; }; - virtual std::string image_bind_slot_name(const refl::Image& img) { assert(false && "implement me"); return ""; }; - virtual std::string sampler_bind_slot_name(const refl::Sampler& smp) { assert(false && "implement me"); return ""; }; - virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub) { assert(false && "implement me"); return ""; }; - virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf) { assert(false && "implement me"); return ""; }; + virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img) { assert(false && "implement me"); return ""; }; + virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp) { assert(false && "implement me"); return ""; }; + virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub) { assert(false && "implement me"); return ""; }; + virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf) { assert(false && "implement me"); return ""; }; virtual std::string vertex_attr_definition(const refl::StageAttr& attr) { assert(false && "implement me"); return ""; }; - virtual std::string image_bind_slot_definition(const refl::Image& img) { assert(false && "implement me"); return ""; }; - virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp) { assert(false && "implement me"); return ""; }; - virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub) { assert(false && "implement me"); return ""; }; - virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf) { assert(false && "implement me"); return ""; }; + virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img) { assert(false && "implement me"); return ""; }; + virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp) { assert(false && "implement me"); return ""; }; + virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub) { assert(false && "implement me"); return ""; }; + virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf) { assert(false && "implement me"); return ""; }; struct ShaderStageArrayInfo { public: diff --git a/src/shdc/generators/sokolc.cc b/src/shdc/generators/sokolc.cc index f1f57fd0..c31b36e6 100644 --- a/src/shdc/generators/sokolc.cc +++ b/src/shdc/generators/sokolc.cc @@ -683,43 +683,43 @@ std::string SokolCGenerator::struct_name(const std::string& name) { } std::string SokolCGenerator::vertex_attr_name(const StageAttr& attr) { - return fmt::format("ATTR_{}{}_{}", mod_prefix, attr.snippet_name, attr.name); + return fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name); } -std::string SokolCGenerator::image_bind_slot_name(const Image& img) { - return fmt::format("SLOT_{}{}", mod_prefix, img.name); +std::string SokolCGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { + return fmt::format("IMG_{}_{}", prog_name, img.name); } -std::string SokolCGenerator::sampler_bind_slot_name(const Sampler& smp) { - return fmt::format("SLOT_{}{}", mod_prefix, smp.name); +std::string SokolCGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { + return fmt::format("SMP_{}_{}", prog_name, smp.name); } -std::string SokolCGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return fmt::format("SLOT_{}{}", mod_prefix, ub.struct_info.name); +std::string SokolCGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { + return fmt::format("UB_{}_{}", prog_name, ub.struct_info.name); } -std::string SokolCGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { - return fmt::format("SLOT_{}{}", mod_prefix, sbuf.struct_info.name); +std::string SokolCGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const StorageBuffer& sbuf) { + return fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name); } std::string SokolCGenerator::vertex_attr_definition(const StageAttr& attr) { return fmt::format("#define {} ({})", vertex_attr_name(attr), attr.slot); } -std::string SokolCGenerator::image_bind_slot_definition(const Image& img) { - return fmt::format("#define {} ({})", image_bind_slot_name(img), img.slot); +std::string SokolCGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { + return fmt::format("#define {} ({})", image_bind_slot_name(prog_name, img), img.slot); } -std::string SokolCGenerator::sampler_bind_slot_definition(const Sampler& smp) { - return fmt::format("#define {} ({})", sampler_bind_slot_name(smp), smp.slot); +std::string SokolCGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { + return fmt::format("#define {} ({})", sampler_bind_slot_name(prog_name, smp), smp.slot); } -std::string SokolCGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { - return fmt::format("#define {} ({})", uniform_block_bind_slot_name(ub), ub.slot); +std::string SokolCGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { + return fmt::format("#define {} ({})", uniform_block_bind_slot_name(prog_name, ub), ub.slot); } -std::string SokolCGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { - return fmt::format("#define {} ({})", storage_buffer_bind_slot_name(sbuf), sbuf.slot); +std::string SokolCGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { + return fmt::format("#define {} ({})", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.slot); } } // namespace diff --git a/src/shdc/generators/sokolc.h b/src/shdc/generators/sokolc.h index 2ce8eb8d..8cf146a2 100644 --- a/src/shdc/generators/sokolc.h +++ b/src/shdc/generators/sokolc.h @@ -41,15 +41,15 @@ class SokolCGenerator: public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const refl::Image& img); - virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); private: virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, int pad_to_size); }; diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index ddd733f0..28e2952b 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -437,24 +437,20 @@ std::string SokolDGenerator::vertex_attr_name(const StageAttr& attr) { return pystring::upper(fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name)); } -static std::string slot_name(const std::string& name) { - return pystring::upper(fmt::format("SLOT_{}", name)); +std::string SokolDGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { + return pystring::upper(fmt::format("IMG_{}_{}", prog_name, img.name)); } -std::string SokolDGenerator::image_bind_slot_name(const Image& img) { - return slot_name(img.name); +std::string SokolDGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { + return pystring::upper(fmt::format("SMP_{}_{}", prog_name, smp.name)); } -std::string SokolDGenerator::sampler_bind_slot_name(const Sampler& smp) { - return slot_name(smp.name); +std::string SokolDGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { + return pystring::upper(fmt::format("UB_{}_{}", prog_name, ub.struct_info.name)); } -std::string SokolDGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return slot_name(ub.struct_info.name); -} - -std::string SokolDGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { - return slot_name(sbuf.struct_info.name); +std::string SokolDGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const StorageBuffer& sbuf) { + return pystring::upper(fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name)); } static std::string const_def(const std::string& name, int slot) { @@ -465,20 +461,20 @@ std::string SokolDGenerator::vertex_attr_definition(const StageAttr& attr) { return const_def(vertex_attr_name(attr), attr.slot); } -std::string SokolDGenerator::image_bind_slot_definition(const Image& img) { - return const_def(image_bind_slot_name(img), img.slot); +std::string SokolDGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { + return const_def(image_bind_slot_name(prog_name, img), img.slot); } -std::string SokolDGenerator::sampler_bind_slot_definition(const Sampler& smp) { - return const_def(sampler_bind_slot_name(smp), smp.slot); +std::string SokolDGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { + return const_def(sampler_bind_slot_name(prog_name, smp), smp.slot); } -std::string SokolDGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { - return const_def(uniform_block_bind_slot_name(ub), ub.slot); +std::string SokolDGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { + return const_def(uniform_block_bind_slot_name(prog_name, ub), ub.slot); } -std::string SokolDGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { - return const_def(storage_buffer_bind_slot_name(sbuf), sbuf.slot); +std::string SokolDGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { + return const_def(storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.slot); } } // namespace diff --git a/src/shdc/generators/sokold.h b/src/shdc/generators/sokold.h index f87d10b5..44edf655 100644 --- a/src/shdc/generators/sokold.h +++ b/src/shdc/generators/sokold.h @@ -28,15 +28,15 @@ class SokolDGenerator : public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const refl::Image& img); - virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); private: virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, int alignment, int pad_to_size); }; diff --git a/src/shdc/generators/sokoljai.cc b/src/shdc/generators/sokoljai.cc index eaf1b90e..b6030a2e 100644 --- a/src/shdc/generators/sokoljai.cc +++ b/src/shdc/generators/sokoljai.cc @@ -427,40 +427,40 @@ std::string SokolJaiGenerator::vertex_attr_name(const StageAttr& attr) { return fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name); } -std::string SokolJaiGenerator::image_bind_slot_name(const Image& img) { - return fmt::format("SLOT_{}", img.name); +std::string SokolJaiGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { + return fmt::format("IMG_{}_{}", prog_name, img.name); } -std::string SokolJaiGenerator::sampler_bind_slot_name(const Sampler& smp) { - return fmt::format("SLOT_{}", smp.name); +std::string SokolJaiGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { + return fmt::format("SMP_{}_{}", prog_name, smp.name); } -std::string SokolJaiGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return fmt::format("SLOT_{}", ub.struct_info.name); +std::string SokolJaiGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { + return fmt::format("UB_{}_{}", prog_name, ub.struct_info.name); } -std::string SokolJaiGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { - return fmt::format("SLOT_{}", sbuf.struct_info.name); +std::string SokolJaiGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const StorageBuffer& sbuf) { + return fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name); } std::string SokolJaiGenerator::vertex_attr_definition(const StageAttr& attr) { return fmt::format("{} :: {};", vertex_attr_name(attr), attr.slot); } -std::string SokolJaiGenerator::image_bind_slot_definition(const Image& img) { - return fmt::format("{} :: {};", image_bind_slot_name(img), img.slot); +std::string SokolJaiGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { + return fmt::format("{} :: {};", image_bind_slot_name(prog_name, img), img.slot); } -std::string SokolJaiGenerator::sampler_bind_slot_definition(const Sampler& smp) { - return fmt::format("{} :: {};", sampler_bind_slot_name(smp), smp.slot); +std::string SokolJaiGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { + return fmt::format("{} :: {};", sampler_bind_slot_name(prog_name, smp), smp.slot); } -std::string SokolJaiGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { - return fmt::format("{} :: {};", uniform_block_bind_slot_name(ub), ub.slot); +std::string SokolJaiGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { + return fmt::format("{} :: {};", uniform_block_bind_slot_name(prog_name, ub), ub.slot); } -std::string SokolJaiGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { - return fmt::format("{} :: {};", storage_buffer_bind_slot_name(sbuf), sbuf.slot); +std::string SokolJaiGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { + return fmt::format("{} :: {};", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.slot); } } // namespace diff --git a/src/shdc/generators/sokoljai.h b/src/shdc/generators/sokoljai.h index 8de4c3e6..a33c857e 100644 --- a/src/shdc/generators/sokoljai.h +++ b/src/shdc/generators/sokoljai.h @@ -28,15 +28,15 @@ class SokolJaiGenerator: public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const refl::Image& img); - virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); private: virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, int pad_to_size); }; diff --git a/src/shdc/generators/sokolnim.cc b/src/shdc/generators/sokolnim.cc index b58aa089..e30348b5 100644 --- a/src/shdc/generators/sokolnim.cc +++ b/src/shdc/generators/sokolnim.cc @@ -510,40 +510,40 @@ std::string SokolNimGenerator::vertex_attr_name(const StageAttr& attr) { return to_camel_case(fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name)); } -std::string SokolNimGenerator::image_bind_slot_name(const Image& img) { - return to_camel_case(fmt::format("SLOT_{}", img.name)); +std::string SokolNimGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { + return to_camel_case(fmt::format("IMG_{}_{}", prog_name, img.name)); } -std::string SokolNimGenerator::sampler_bind_slot_name(const Sampler& smp) { - return to_camel_case(fmt::format("SLOT_{}", smp.name)); +std::string SokolNimGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { + return to_camel_case(fmt::format("SMP_{}_{}", prog_name, smp.name)); } -std::string SokolNimGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return to_camel_case(fmt::format("SLOT_{}", ub.struct_info.name)); +std::string SokolNimGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { + return to_camel_case(fmt::format("UB_{}_{}", prog_name, ub.struct_info.name)); } -std::string SokolNimGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { - return to_camel_case(fmt::format("SLOT_{}", sbuf.struct_info.name)); +std::string SokolNimGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const StorageBuffer& sbuf) { + return to_camel_case(fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name)); } std::string SokolNimGenerator::vertex_attr_definition(const StageAttr& attr) { return fmt::format("const {}* = {}", vertex_attr_name(attr), attr.slot); } -std::string SokolNimGenerator::image_bind_slot_definition(const Image& img) { - return fmt::format("const {}* = {}", image_bind_slot_name(img), img.slot); +std::string SokolNimGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { + return fmt::format("const {}* = {}", image_bind_slot_name(prog_name, img), img.slot); } -std::string SokolNimGenerator::sampler_bind_slot_definition(const Sampler& smp) { - return fmt::format("const {}* = {}", sampler_bind_slot_name(smp), smp.slot); +std::string SokolNimGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { + return fmt::format("const {}* = {}", sampler_bind_slot_name(prog_name, smp), smp.slot); } -std::string SokolNimGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { - return fmt::format("const {}* = {}", uniform_block_bind_slot_name(ub), ub.slot); +std::string SokolNimGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { + return fmt::format("const {}* = {}", uniform_block_bind_slot_name(prog_name, ub), ub.slot); } -std::string SokolNimGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { - return fmt::format("const {}* = {}", storage_buffer_bind_slot_name(sbuf), sbuf.slot); +std::string SokolNimGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { + return fmt::format("const {}* = {}", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.slot); } } // namespace diff --git a/src/shdc/generators/sokolnim.h b/src/shdc/generators/sokolnim.h index 3a5c39b6..cbcaf5dd 100644 --- a/src/shdc/generators/sokolnim.h +++ b/src/shdc/generators/sokolnim.h @@ -30,15 +30,15 @@ class SokolNimGenerator: public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const refl::Image& img); - virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); private: virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, const std::string& name, int alignment, int pad_to_size); virtual void recurse_unfold_structs(const GenInput& gen, const refl::Type& struc, const std::string& name, int alignment, int pad_to_size); diff --git a/src/shdc/generators/sokolodin.cc b/src/shdc/generators/sokolodin.cc index 091406d0..6a9b4c24 100644 --- a/src/shdc/generators/sokolodin.cc +++ b/src/shdc/generators/sokolodin.cc @@ -430,40 +430,40 @@ std::string SokolOdinGenerator::vertex_attr_name(const StageAttr& attr) { return fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name); } -std::string SokolOdinGenerator::image_bind_slot_name(const Image& img) { - return fmt::format("SLOT_{}", img.name); +std::string SokolOdinGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { + return fmt::format("IMG_{}_{}", prog_name, img.name); } -std::string SokolOdinGenerator::sampler_bind_slot_name(const Sampler& smp) { - return fmt::format("SLOT_{}", smp.name); +std::string SokolOdinGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { + return fmt::format("SMP_{}_{}", prog_name, smp.name); } -std::string SokolOdinGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return fmt::format("SLOT_{}", ub.struct_info.name); +std::string SokolOdinGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { + return fmt::format("UB_{}_{}", prog_name, ub.struct_info.name); } -std::string SokolOdinGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { - return fmt::format("SLOT_{}", sbuf.struct_info.name); +std::string SokolOdinGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const StorageBuffer& sbuf) { + return fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name); } std::string SokolOdinGenerator::vertex_attr_definition(const StageAttr& attr) { return fmt::format("{} :: {}", vertex_attr_name(attr), attr.slot); } -std::string SokolOdinGenerator::image_bind_slot_definition(const Image& img) { - return fmt::format("{} :: {}", image_bind_slot_name(img), img.slot); +std::string SokolOdinGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { + return fmt::format("{} :: {}", image_bind_slot_name(prog_name, img), img.slot); } -std::string SokolOdinGenerator::sampler_bind_slot_definition(const Sampler& smp) { - return fmt::format("{} :: {}", sampler_bind_slot_name(smp), smp.slot); +std::string SokolOdinGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { + return fmt::format("{} :: {}", sampler_bind_slot_name(prog_name, smp), smp.slot); } -std::string SokolOdinGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { - return fmt::format("{} :: {}", uniform_block_bind_slot_name(ub), ub.slot); +std::string SokolOdinGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { + return fmt::format("{} :: {}", uniform_block_bind_slot_name(prog_name, ub), ub.slot); } -std::string SokolOdinGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { - return fmt::format("{} :: {}", storage_buffer_bind_slot_name(sbuf), sbuf.slot); +std::string SokolOdinGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { + return fmt::format("{} :: {}", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.slot); } } // namespace diff --git a/src/shdc/generators/sokolodin.h b/src/shdc/generators/sokolodin.h index 40830423..df9c8166 100644 --- a/src/shdc/generators/sokolodin.h +++ b/src/shdc/generators/sokolodin.h @@ -28,15 +28,15 @@ class SokolOdinGenerator: public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const refl::Image& img); - virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); private: virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, int pad_to_size); }; diff --git a/src/shdc/generators/sokolrust.cc b/src/shdc/generators/sokolrust.cc index aeb51013..de18cc91 100644 --- a/src/shdc/generators/sokolrust.cc +++ b/src/shdc/generators/sokolrust.cc @@ -444,40 +444,40 @@ std::string SokolRustGenerator::vertex_attr_name(const StageAttr& attr) { return pystring::upper(fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name)); } -std::string SokolRustGenerator::image_bind_slot_name(const Image& img) { - return pystring::upper(fmt::format("SLOT_{}", img.name)); +std::string SokolRustGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { + return pystring::upper(fmt::format("IMG_{}_{}", prog_name, img.name)); } -std::string SokolRustGenerator::sampler_bind_slot_name(const Sampler& smp) { - return pystring::upper(fmt::format("SLOT_{}", smp.name)); +std::string SokolRustGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { + return pystring::upper(fmt::format("SMP_{}_{}", prog_name, smp.name)); } -std::string SokolRustGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return pystring::upper(fmt::format("SLOT_{}", ub.struct_info.name)); +std::string SokolRustGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { + return pystring::upper(fmt::format("UB_{}_{}", prog_name, ub.struct_info.name)); } -std::string SokolRustGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { - return pystring::upper(fmt::format("SLOT_{}", sbuf.struct_info.name)); +std::string SokolRustGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const StorageBuffer& sbuf) { + return pystring::upper(fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name)); } std::string SokolRustGenerator::vertex_attr_definition(const StageAttr& attr) { return fmt::format("pub const {}: usize = {};", vertex_attr_name(attr), attr.slot); } -std::string SokolRustGenerator::image_bind_slot_definition(const Image& img) { - return fmt::format("pub const {}: usize = {};", image_bind_slot_name(img), img.slot); +std::string SokolRustGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { + return fmt::format("pub const {}: usize = {};", image_bind_slot_name(prog_name, img), img.slot); } -std::string SokolRustGenerator::sampler_bind_slot_definition(const Sampler& smp) { - return fmt::format("pub const {}: usize = {};", sampler_bind_slot_name(smp), smp.slot); +std::string SokolRustGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { + return fmt::format("pub const {}: usize = {};", sampler_bind_slot_name(prog_name, smp), smp.slot); } -std::string SokolRustGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { - return fmt::format("pub const {}: usize = {};", uniform_block_bind_slot_name(ub), ub.slot); +std::string SokolRustGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { + return fmt::format("pub const {}: usize = {};", uniform_block_bind_slot_name(prog_name, ub), ub.slot); } -std::string SokolRustGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { - return fmt::format("pub const {}: usize = {};", storage_buffer_bind_slot_name(sbuf), sbuf.slot); +std::string SokolRustGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { + return fmt::format("pub const {}: usize = {};", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.slot); } } // namespace diff --git a/src/shdc/generators/sokolrust.h b/src/shdc/generators/sokolrust.h index 497507ad..eba06e8d 100644 --- a/src/shdc/generators/sokolrust.h +++ b/src/shdc/generators/sokolrust.h @@ -28,15 +28,15 @@ class SokolRustGenerator: public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const refl::Image& img); - virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); private: void recurse_unfold_structs(const GenInput& gen, const refl::Type& struc, const std::string& name, int alignment, int pad_to_size); virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, const std::string& name, int pad_to_size); diff --git a/src/shdc/generators/sokolzig.cc b/src/shdc/generators/sokolzig.cc index 7cd8673b..0ae70aa2 100644 --- a/src/shdc/generators/sokolzig.cc +++ b/src/shdc/generators/sokolzig.cc @@ -442,40 +442,40 @@ std::string SokolZigGenerator::vertex_attr_name(const StageAttr& attr) { return fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name); } -std::string SokolZigGenerator::image_bind_slot_name(const Image& img) { - return fmt::format("SLOT_{}", img.name); +std::string SokolZigGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { + return fmt::format("IMG_{}_{}", prog_name, img.name); } -std::string SokolZigGenerator::sampler_bind_slot_name(const Sampler& smp) { - return fmt::format("SLOT_{}", smp.name); +std::string SokolZigGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { + return fmt::format("SMP_{}_{}", prog_name, smp.name); } -std::string SokolZigGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return fmt::format("SLOT_{}", ub.struct_info.name); +std::string SokolZigGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { + return fmt::format("UB_{}_{}", prog_name, ub.struct_info.name); } -std::string SokolZigGenerator::storage_buffer_bind_slot_name(const refl::StorageBuffer& sb) { - return fmt::format("SLOT_{}", sb.struct_info.name); +std::string SokolZigGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sb) { + return fmt::format("SBUF_{}_{}", prog_name, sb.struct_info.name); } std::string SokolZigGenerator::vertex_attr_definition(const StageAttr& attr) { return fmt::format("pub const {} = {};", vertex_attr_name(attr), attr.slot); } -std::string SokolZigGenerator::image_bind_slot_definition(const Image& img) { - return fmt::format("pub const {} = {};", image_bind_slot_name(img), img.slot); +std::string SokolZigGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { + return fmt::format("pub const {} = {};", image_bind_slot_name(prog_name, img), img.slot); } -std::string SokolZigGenerator::sampler_bind_slot_definition(const Sampler& smp) { - return fmt::format("pub const {} = {};", sampler_bind_slot_name(smp), smp.slot); +std::string SokolZigGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { + return fmt::format("pub const {} = {};", sampler_bind_slot_name(prog_name, smp), smp.slot); } -std::string SokolZigGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { - return fmt::format("pub const {} = {};", uniform_block_bind_slot_name(ub), ub.slot); +std::string SokolZigGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { + return fmt::format("pub const {} = {};", uniform_block_bind_slot_name(prog_name, ub), ub.slot); } -std::string SokolZigGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sb) { - return fmt::format("pub const {} = {};", storage_buffer_bind_slot_name(sb), sb.slot); +std::string SokolZigGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sb) { + return fmt::format("pub const {} = {};", storage_buffer_bind_slot_name(prog_name, sb), sb.slot); } void SokolZigGenerator::gen_attr_slot_refl_func(const GenInput& gen, const ProgramReflection& prog) { diff --git a/src/shdc/generators/sokolzig.h b/src/shdc/generators/sokolzig.h index ad60e7d8..98ae400d 100644 --- a/src/shdc/generators/sokolzig.h +++ b/src/shdc/generators/sokolzig.h @@ -36,15 +36,15 @@ class SokolZigGenerator: public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const refl::Image& img); - virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); private: virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, int alignment, int pad_to_size); }; From a8ccb3cc64f1445435616adb691a5d52dfe3f229 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 6 Oct 2024 13:53:07 +0200 Subject: [PATCH 10/37] wip reflection: rename slot => sokol_slot, generate per program bindslot info --- src/shdc/generators/generator.cc | 60 ++++++++++------------ src/shdc/generators/generator.h | 5 +- src/shdc/generators/sokolc.cc | 44 ++++++++-------- src/shdc/generators/sokold.cc | 22 ++++---- src/shdc/generators/sokoljai.cc | 22 ++++---- src/shdc/generators/sokolnim.cc | 22 ++++---- src/shdc/generators/sokolodin.cc | 22 ++++---- src/shdc/generators/sokolrust.cc | 22 ++++---- src/shdc/generators/sokolzig.cc | 44 ++++++++-------- src/shdc/generators/yaml.cc | 10 ++-- src/shdc/reflection.cc | 11 ++-- src/shdc/types/reflection/bindings.h | 30 +++++------ src/shdc/types/reflection/image.h | 6 +-- src/shdc/types/reflection/image_sampler.h | 6 +-- src/shdc/types/reflection/sampler.h | 6 +-- src/shdc/types/reflection/storage_buffer.h | 6 +-- src/shdc/types/reflection/uniform_block.h | 6 +-- 17 files changed, 170 insertions(+), 174 deletions(-) diff --git a/src/shdc/generators/generator.cc b/src/shdc/generators/generator.cc index c18cd7d2..cfbc2e35 100644 --- a/src/shdc/generators/generator.cc +++ b/src/shdc/generators/generator.cc @@ -77,8 +77,7 @@ void Generator::gen_header(const GenInput& gen) { for (const ProgramReflection& prog: gen.refl.progs) { cbl_open("Shader program: '{}':\n", prog.name); cbl("Get shader desc: {}", get_shader_desc_help(prog.name)); - gen_vertex_shader_info(gen, prog); - gen_fragment_shader_info(gen, prog); + gen_program_info(gen, prog); cbl_close(); } cbl_end(); @@ -89,8 +88,9 @@ void Generator::gen_prerequisites(const GenInput& gen) { // empty } -void Generator::gen_vertex_shader_info(const GenInput& gen, const ProgramReflection& prog) { - cbl_open("Vertex shader: {}\n", prog.vs_name()); +void Generator::gen_program_info(const GenInput& gen, const ProgramReflection& prog) { + cbl_open("Vertex Shader: {}\n", prog.vs_name()); + cbl_open("Fragment Shader: {}\n", prog.fs_name()); cbl_open("Attributes:\n"); for (const StageAttr& attr: prog.vs().inputs) { if (attr.slot >= 0) { @@ -98,44 +98,38 @@ void Generator::gen_vertex_shader_info(const GenInput& gen, const ProgramReflect } } cbl_close(); - gen_bindings_info(gen, prog.vs().bindings); + gen_bindings_info(gen, prog); cbl_close(); } -void Generator::gen_fragment_shader_info(const GenInput& gen, const ProgramReflection& prog) { - cbl_open("Fragment shader: {}\n", prog.fs_name()); - gen_bindings_info(gen, prog.fs().bindings); - cbl_close(); -} - -void Generator::gen_bindings_info(const GenInput& gen, const Bindings& bindings) { - for (const UniformBlock& ub: bindings.uniform_blocks) { +void Generator::gen_bindings_info(const GenInput& gen, const ProgramReflection& prog) { + for (const UniformBlock& ub: prog.bindings.uniform_blocks) { cbl_open("Uniform block '{}':\n", ub.struct_info.name); cbl("{} struct: {}\n", lang_name(), struct_name(ub.struct_info.name)); - cbl("Bind slot: {} => {}\n", uniform_block_bind_slot_name(ub), ub.slot); + cbl("Bind slot: {} => {}\n", uniform_block_bind_slot_name(prog.name, ub), ub.sokol_slot); cbl_close(); } - for (const StorageBuffer& sbuf: bindings.storage_buffers) { + for (const StorageBuffer& sbuf: prog.bindings.storage_buffers) { cbl_open("Storage buffer '{}':\n", sbuf.struct_info.name); cbl("{} struct: {}\n", lang_name(), struct_name(sbuf.struct_info.name)); - cbl("Bind slot: {} => {}\n", storage_buffer_bind_slot_name(sbuf), sbuf.slot); + cbl("Bind slot: {} => {}\n", storage_buffer_bind_slot_name(prog.name, sbuf), sbuf.sokol_slot); cbl_close(); } - for (const Image& img: bindings.images) { + for (const Image& img: prog.bindings.images) { cbl_open("Image '{}':\n", img.name); cbl("Image type: {}\n", image_type(img.type)); cbl("Sample type: {}\n", image_sample_type(img.sample_type)); cbl("Multisampled: {}\n", img.multisampled); - cbl("Bind slot: {} => {}\n", image_bind_slot_name(img), img.slot); + cbl("Bind slot: {} => {}\n", image_bind_slot_name(prog.name, img), img.sokol_slot); cbl_close(); } - for (const Sampler& smp: bindings.samplers) { + for (const Sampler& smp: prog.bindings.samplers) { cbl_open("Sampler '{}':\n", smp.name); cbl("Type: {}\n", sampler_type(smp.type)); - cbl("Bind slot: {} => {}\n", sampler_bind_slot_name(smp), smp.slot); + cbl("Bind slot: {} => {}\n", sampler_bind_slot_name(prog.name, smp), smp.sokol_slot); cbl_close(); } - for (const ImageSampler& img_smp: bindings.image_samplers) { + for (const ImageSampler& img_smp: prog.bindings.image_samplers) { cbl_open("Image Sampler Pair '{}':\n", img_smp.name); cbl("Image: {}\n", img_smp.image_name); cbl("Sampler: {}\n", img_smp.sampler_name); @@ -152,17 +146,19 @@ void Generator::gen_vertex_attr_consts(const GenInput& gen) { } void Generator::gen_bind_slot_consts(const GenInput& gen) { - for (const UniformBlock& ub: gen.refl.bindings.uniform_blocks) { - l("{}\n", uniform_block_bind_slot_definition(ub)); - } - for (const StorageBuffer& sbuf: gen.refl.bindings.storage_buffers) { - l("{}\n", storage_buffer_bind_slot_definition(sbuf)); - } - for (const Image& img: gen.refl.bindings.images) { - l("{}\n", image_bind_slot_definition(img)); - } - for (const Sampler& smp: gen.refl.bindings.samplers) { - l("{}\n", sampler_bind_slot_definition(smp)); + for (const ProgramReflection& prog: gen.refl.progs) { + for (const UniformBlock& ub: prog.bindings.uniform_blocks) { + l("{}\n", uniform_block_bind_slot_definition(prog.name, ub)); + } + for (const StorageBuffer& sbuf: prog.bindings.storage_buffers) { + l("{}\n", storage_buffer_bind_slot_definition(prog.name, sbuf)); + } + for (const Image& img: prog.bindings.images) { + l("{}\n", image_bind_slot_definition(prog.name, img)); + } + for (const Sampler& smp: prog.bindings.samplers) { + l("{}\n", sampler_bind_slot_definition(prog.name, smp)); + } } } diff --git a/src/shdc/generators/generator.h b/src/shdc/generators/generator.h index 949037b2..5aab9d58 100644 --- a/src/shdc/generators/generator.h +++ b/src/shdc/generators/generator.h @@ -30,9 +30,8 @@ class Generator { virtual ErrMsg end(const GenInput& gen); // called by gen_header() - virtual void gen_vertex_shader_info(const GenInput& gen, const refl::ProgramReflection& prog); - virtual void gen_fragment_shader_info(const GenInput& gen, const refl::ProgramReflection& prog); - virtual void gen_bindings_info(const GenInput& gen, const refl::Bindings& bindings); + virtual void gen_program_info(const GenInput& gen, const refl::ProgramReflection& prog); + virtual void gen_bindings_info(const GenInput& gen, const refl::ProgramReflection& prog); // called by gen_uniform_block_decls() virtual void gen_uniform_block_decl(const GenInput& gen, const refl::UniformBlock& ub) { assert(false && "implement me"); }; diff --git a/src/shdc/generators/sokolc.cc b/src/shdc/generators/sokolc.cc index c31b36e6..eef04d7a 100644 --- a/src/shdc/generators/sokolc.cc +++ b/src/shdc/generators/sokolc.cc @@ -293,7 +293,7 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); + const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); @@ -317,7 +317,7 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); + const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); l("{}.used = true;\n", sbn); @@ -325,7 +325,7 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_slot(img_index); + const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); l("{}.used = true;\n", in); @@ -335,7 +335,7 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); + const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); l("{}.used = true;\n", sn); @@ -343,12 +343,12 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); + const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); l("{}.used = true;\n", isn); - l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->slot); - l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->slot); + l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); if (Slang::is_glsl(slang)) { l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); } @@ -389,9 +389,9 @@ void SokolCGenerator::gen_image_slot_refl_func(const GenInput& gen, const Progra if (!refl.bindings.images.empty()) { l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); for (const Image& img: refl.bindings.images) { - if (img.slot >= 0) { + if (img.sokol_slot >= 0) { l_open("if (0 == strcmp(img_name, \"{}\")) {{\n", img.name); - l("return {};\n", img.slot); + l("return {};\n", img.sokol_slot); l_close("}}\n"); } } @@ -409,9 +409,9 @@ void SokolCGenerator::gen_sampler_slot_refl_func(const GenInput& gen, const Prog if (!refl.bindings.samplers.empty()) { l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); for (const Sampler& smp: refl.bindings.samplers) { - if (smp.slot >= 0) { + if (smp.sokol_slot >= 0) { l_open("if (0 == strcmp(smp_name, \"{}\")) {{\n", smp.name); - l("return {};\n", smp.slot); + l("return {};\n", smp.sokol_slot); l_close("}}\n"); } } @@ -429,9 +429,9 @@ void SokolCGenerator::gen_uniform_block_slot_refl_func(const GenInput& gen, cons if (!refl.bindings.uniform_blocks.empty()) { l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.slot >= 0) { + if (ub.sokol_slot >= 0) { l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); - l("return {};\n", ub.slot); + l("return {};\n", ub.sokol_slot); l_close("}}\n"); } } @@ -449,7 +449,7 @@ void SokolCGenerator::gen_uniform_block_size_refl_func(const GenInput& gen, cons if (!refl.bindings.uniform_blocks.empty()) { l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.slot >= 0) { + if (ub.sokol_slot >= 0) { l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); l("return sizeof({});\n", struct_name(ub.struct_info.name)); l_close("}}\n"); @@ -469,9 +469,9 @@ void SokolCGenerator::gen_storage_buffer_slot_refl_func(const GenInput& gen, con if (!refl.bindings.storage_buffers.empty()) { l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); for (const StorageBuffer& sbuf: refl.bindings.storage_buffers) { - if (sbuf.slot >= 0) { + if (sbuf.sokol_slot >= 0) { l_open("if (0 == strcmp(sbuf_name, \"{}\")) {{\n", sbuf.struct_info.name); - l("return {};\n", sbuf.slot); + l("return {};\n", sbuf.sokol_slot); l_close("}}\n"); } } @@ -489,7 +489,7 @@ void SokolCGenerator::gen_uniform_offset_refl_func(const GenInput& gen, const Pr if (!refl.bindings.uniform_blocks.empty()) { l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.slot >= 0) { + if (ub.sokol_slot >= 0) { l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); for (const Type& u: ub.struct_info.struct_items) { l_open("if (0 == strcmp(u_name, \"{}\")) {{\n", u.name); @@ -518,7 +518,7 @@ void SokolCGenerator::gen_uniform_desc_refl_func(const GenInput& gen, const Prog if (!refl.bindings.uniform_blocks.empty()) { l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.slot >= 0) { + if (ub.sokol_slot >= 0) { l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); for (const Type& u: ub.struct_info.struct_items) { l_open("if (0 == strcmp(u_name, \"{}\")) {{\n", u.name); @@ -707,19 +707,19 @@ std::string SokolCGenerator::vertex_attr_definition(const StageAttr& attr) { } std::string SokolCGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return fmt::format("#define {} ({})", image_bind_slot_name(prog_name, img), img.slot); + return fmt::format("#define {} ({})", image_bind_slot_name(prog_name, img), img.sokol_slot); } std::string SokolCGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return fmt::format("#define {} ({})", sampler_bind_slot_name(prog_name, smp), smp.slot); + return fmt::format("#define {} ({})", sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); } std::string SokolCGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("#define {} ({})", uniform_block_bind_slot_name(prog_name, ub), ub.slot); + return fmt::format("#define {} ({})", uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); } std::string SokolCGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("#define {} ({})", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.slot); + return fmt::format("#define {} ({})", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.sokol_slot); } } // namespace diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index 28e2952b..e8a63199 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -243,7 +243,7 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); + const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); @@ -267,7 +267,7 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); + const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); l("{}.used = true;\n", sbn); @@ -275,7 +275,7 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_slot(img_index); + const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); l("{}.used = true;\n", in); @@ -285,7 +285,7 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); + const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); l("{}.used = true;\n", sn); @@ -293,12 +293,12 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); + const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); l("{}.used = true;\n", isn); - l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->slot); - l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->slot); + l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); if (Slang::is_glsl(slang)) { l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); } @@ -462,19 +462,19 @@ std::string SokolDGenerator::vertex_attr_definition(const StageAttr& attr) { } std::string SokolDGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return const_def(image_bind_slot_name(prog_name, img), img.slot); + return const_def(image_bind_slot_name(prog_name, img), img.sokol_slot); } std::string SokolDGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return const_def(sampler_bind_slot_name(prog_name, smp), smp.slot); + return const_def(sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); } std::string SokolDGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return const_def(uniform_block_bind_slot_name(prog_name, ub), ub.slot); + return const_def(uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); } std::string SokolDGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { - return const_def(storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.slot); + return const_def(storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.sokol_slot); } } // namespace diff --git a/src/shdc/generators/sokoljai.cc b/src/shdc/generators/sokoljai.cc index b6030a2e..3f872499 100644 --- a/src/shdc/generators/sokoljai.cc +++ b/src/shdc/generators/sokoljai.cc @@ -227,7 +227,7 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); + const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); @@ -251,7 +251,7 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); + const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); l("{}.used = true;\n", sbn); @@ -259,7 +259,7 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_slot(img_index); + const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); l("{}.used = true;\n", in); @@ -269,7 +269,7 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); + const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); l("{}.used = true;\n", sn); @@ -277,12 +277,12 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); + const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); l("{}.used = true;\n", isn); - l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->slot); - l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->slot); + l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); if (Slang::is_glsl(slang)) { l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); } @@ -448,19 +448,19 @@ std::string SokolJaiGenerator::vertex_attr_definition(const StageAttr& attr) { } std::string SokolJaiGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return fmt::format("{} :: {};", image_bind_slot_name(prog_name, img), img.slot); + return fmt::format("{} :: {};", image_bind_slot_name(prog_name, img), img.sokol_slot); } std::string SokolJaiGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return fmt::format("{} :: {};", sampler_bind_slot_name(prog_name, smp), smp.slot); + return fmt::format("{} :: {};", sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); } std::string SokolJaiGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("{} :: {};", uniform_block_bind_slot_name(prog_name, ub), ub.slot); + return fmt::format("{} :: {};", uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); } std::string SokolJaiGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("{} :: {};", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.slot); + return fmt::format("{} :: {};", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.sokol_slot); } } // namespace diff --git a/src/shdc/generators/sokolnim.cc b/src/shdc/generators/sokolnim.cc index e30348b5..e1e092b9 100644 --- a/src/shdc/generators/sokolnim.cc +++ b/src/shdc/generators/sokolnim.cc @@ -310,7 +310,7 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } l("{}.entry = \"{}\"\n", dsn, refl.entry_point_by_slang(slang)); for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); + const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniformBlocks[{}]", dsn, ub_index); l("{}.size = {}\n", ubn, roundup(ub->struct_info.size, 16)); @@ -334,7 +334,7 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); + const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storageBuffers[{}]", dsn, sbuf_index); l("{}.used = true\n", sbn); @@ -342,7 +342,7 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_slot(img_index); + const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); l("{}.used = true\n", in); @@ -352,7 +352,7 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); + const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); l("{}.used = true\n", sn); @@ -360,12 +360,12 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); + const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.imageSamplerPairs[{}]", dsn, img_smp_index); l("{}.used = true\n", isn); - l("{}.imageSlot = {}\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->slot); - l("{}.samplerSlot = {}\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->slot); + l("{}.imageSlot = {}\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.samplerSlot = {}\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); if (Slang::is_glsl(slang)) { l("{}.glslName = \"{}\"\n", isn, img_smp->name); } @@ -531,19 +531,19 @@ std::string SokolNimGenerator::vertex_attr_definition(const StageAttr& attr) { } std::string SokolNimGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return fmt::format("const {}* = {}", image_bind_slot_name(prog_name, img), img.slot); + return fmt::format("const {}* = {}", image_bind_slot_name(prog_name, img), img.sokol_slot); } std::string SokolNimGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return fmt::format("const {}* = {}", sampler_bind_slot_name(prog_name, smp), smp.slot); + return fmt::format("const {}* = {}", sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); } std::string SokolNimGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("const {}* = {}", uniform_block_bind_slot_name(prog_name, ub), ub.slot); + return fmt::format("const {}* = {}", uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); } std::string SokolNimGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("const {}* = {}", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.slot); + return fmt::format("const {}* = {}", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.sokol_slot); } } // namespace diff --git a/src/shdc/generators/sokolodin.cc b/src/shdc/generators/sokolodin.cc index 6a9b4c24..4a407a69 100644 --- a/src/shdc/generators/sokolodin.cc +++ b/src/shdc/generators/sokolodin.cc @@ -230,7 +230,7 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program } l("{}.entry = \"{}\"\n", dsn, refl.entry_point_by_slang(slang)); for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); + const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); l("{}.size = {}\n", ubn, roundup(ub->struct_info.size, 16)); @@ -254,7 +254,7 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); + const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); l("{}.used = true\n", sbn); @@ -262,7 +262,7 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_slot(img_index); + const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); l("{}.used = true\n", in); @@ -272,7 +272,7 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); + const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); l("{}.used = true\n", sn); @@ -280,12 +280,12 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); + const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); l("{}.used = true\n", isn); - l("{}.image_slot = {}\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->slot); - l("{}.sampler_slot = {}\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->slot); + l("{}.image_slot = {}\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.sampler_slot = {}\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); if (Slang::is_glsl(slang)) { l("{}.glsl_name = \"{}\"\n", isn, img_smp->name); } @@ -451,19 +451,19 @@ std::string SokolOdinGenerator::vertex_attr_definition(const StageAttr& attr) { } std::string SokolOdinGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return fmt::format("{} :: {}", image_bind_slot_name(prog_name, img), img.slot); + return fmt::format("{} :: {}", image_bind_slot_name(prog_name, img), img.sokol_slot); } std::string SokolOdinGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return fmt::format("{} :: {}", sampler_bind_slot_name(prog_name, smp), smp.slot); + return fmt::format("{} :: {}", sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); } std::string SokolOdinGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("{} :: {}", uniform_block_bind_slot_name(prog_name, ub), ub.slot); + return fmt::format("{} :: {}", uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); } std::string SokolOdinGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("{} :: {}", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.slot); + return fmt::format("{} :: {}", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.sokol_slot); } } // namespace diff --git a/src/shdc/generators/sokolrust.cc b/src/shdc/generators/sokolrust.cc index de18cc91..d4e29a56 100644 --- a/src/shdc/generators/sokolrust.cc +++ b/src/shdc/generators/sokolrust.cc @@ -243,7 +243,7 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program } l("{}.entry = c\"{}\".as_ptr();\n", dsn, refl.entry_point_by_slang(slang)); for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); + const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); @@ -267,7 +267,7 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); + const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); l("{}.used = true;\n", sbn); @@ -275,7 +275,7 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_slot(img_index); + const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); l("{}.used = true;\n", in); @@ -285,7 +285,7 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); + const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); l("{}.used = true;\n", sn); @@ -293,12 +293,12 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); + const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); l("{}.used = true;\n", isn); - l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->slot); - l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->slot); + l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); if (Slang::is_glsl(slang)) { l("{}.glsl_name = c\"{}\".as_ptr();\n", isn, img_smp->name); } @@ -465,19 +465,19 @@ std::string SokolRustGenerator::vertex_attr_definition(const StageAttr& attr) { } std::string SokolRustGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return fmt::format("pub const {}: usize = {};", image_bind_slot_name(prog_name, img), img.slot); + return fmt::format("pub const {}: usize = {};", image_bind_slot_name(prog_name, img), img.sokol_slot); } std::string SokolRustGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return fmt::format("pub const {}: usize = {};", sampler_bind_slot_name(prog_name, smp), smp.slot); + return fmt::format("pub const {}: usize = {};", sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); } std::string SokolRustGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("pub const {}: usize = {};", uniform_block_bind_slot_name(prog_name, ub), ub.slot); + return fmt::format("pub const {}: usize = {};", uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); } std::string SokolRustGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("pub const {}: usize = {};", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.slot); + return fmt::format("pub const {}: usize = {};", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.sokol_slot); } } // namespace diff --git a/src/shdc/generators/sokolzig.cc b/src/shdc/generators/sokolzig.cc index 0ae70aa2..d5b12a59 100644 --- a/src/shdc/generators/sokolzig.cc +++ b/src/shdc/generators/sokolzig.cc @@ -241,7 +241,7 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_slot(ub_index); + const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); if (ub) { const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); @@ -265,7 +265,7 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_slot(sbuf_index); + const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); if (sbuf) { const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); l("{}.used = true;\n", sbn); @@ -273,7 +273,7 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_slot(img_index); + const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); if (img) { const std::string in = fmt::format("{}.images[{}]", dsn, img_index); l("{}.used = true;\n", in); @@ -283,7 +283,7 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_slot(smp_index); + const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); if (smp) { const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); l("{}.used = true;\n", sn); @@ -291,12 +291,12 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_slot(img_smp_index); + const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); if (img_smp) { const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); l("{}.used = true;\n", isn); - l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->slot); - l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->slot); + l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); if (Slang::is_glsl(slang)) { l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); } @@ -463,19 +463,19 @@ std::string SokolZigGenerator::vertex_attr_definition(const StageAttr& attr) { } std::string SokolZigGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return fmt::format("pub const {} = {};", image_bind_slot_name(prog_name, img), img.slot); + return fmt::format("pub const {} = {};", image_bind_slot_name(prog_name, img), img.sokol_slot); } std::string SokolZigGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return fmt::format("pub const {} = {};", sampler_bind_slot_name(prog_name, smp), smp.slot); + return fmt::format("pub const {} = {};", sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); } std::string SokolZigGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("pub const {} = {};", uniform_block_bind_slot_name(prog_name, ub), ub.slot); + return fmt::format("pub const {} = {};", uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); } std::string SokolZigGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sb) { - return fmt::format("pub const {} = {};", storage_buffer_bind_slot_name(prog_name, sb), sb.slot); + return fmt::format("pub const {} = {};", storage_buffer_bind_slot_name(prog_name, sb), sb.sokol_slot); } void SokolZigGenerator::gen_attr_slot_refl_func(const GenInput& gen, const ProgramReflection& prog) { @@ -503,9 +503,9 @@ void SokolZigGenerator::gen_image_slot_refl_func(const GenInput& gen, const Prog l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); wrote_stage = true; for (const Image& img: refl.bindings.images) { - if (img.slot >= 0) { + if (img.sokol_slot >= 0) { l_open("if (std.mem.eql(u8, img_name, \"{}\")) {{\n", img.name); - l("return {};\n", img.slot); + l("return {};\n", img.sokol_slot); l_close("}}\n"); wrote_image = true; } @@ -528,9 +528,9 @@ void SokolZigGenerator::gen_sampler_slot_refl_func(const GenInput& gen, const Pr l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); wrote_stage = true; for (const Sampler& smp: refl.bindings.samplers) { - if (smp.slot >= 0) { + if (smp.sokol_slot >= 0) { l_open("if (std.mem.eql(u8, smp_name, \"{}\")) {{\n", smp.name); - l("return {};\n", smp.slot); + l("return {};\n", smp.sokol_slot); l_close("}}\n"); wrote_smp = true; } @@ -553,9 +553,9 @@ void SokolZigGenerator::gen_uniform_block_slot_refl_func(const GenInput& gen, co l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); wrote_stage = true; for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.slot >= 0) { + if (ub.sokol_slot >= 0) { l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.struct_info.name); - l("return {};\n", ub.slot); + l("return {};\n", ub.sokol_slot); l_close("}}\n"); wrote_ub_name = true; } @@ -578,7 +578,7 @@ void SokolZigGenerator::gen_uniform_block_size_refl_func(const GenInput& gen, co l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); wrote_stage = true; for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.slot >= 0) { + if (ub.sokol_slot >= 0) { l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.struct_info.name); l("return @sizeOf({});\n", struct_name(ub.struct_info.name)); l_close("}}\n"); @@ -603,9 +603,9 @@ void SokolZigGenerator::gen_storage_buffer_slot_refl_func(const GenInput& gen, c l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); wrote_stage = true; for (const StorageBuffer& sbuf: refl.bindings.storage_buffers) { - if (sbuf.slot >= 0) { + if (sbuf.sokol_slot >= 0) { l_open("if (std.mem.eql(u8, sbuf_name, \"{}\")) {{\n", sbuf.struct_info.name); - l("return {};\n", sbuf.slot); + l("return {};\n", sbuf.sokol_slot); l_close("}}\n"); wrote_sbuf_name = true; } @@ -629,7 +629,7 @@ void SokolZigGenerator::gen_uniform_offset_refl_func(const GenInput& gen, const l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); wrote_stage = true; for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.slot >= 0) { + if (ub.sokol_slot >= 0) { l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.struct_info.name); wrote_ub_name = true; for (const Type& u: ub.struct_info.struct_items) { @@ -662,7 +662,7 @@ void SokolZigGenerator::gen_uniform_desc_refl_func(const GenInput& gen, const Pr l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); wrote_stage = true; for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.slot >= 0) { + if (ub.sokol_slot >= 0) { l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.struct_info.name); wrote_ub_name = true; for (const Type& u: ub.struct_info.struct_items) { diff --git a/src/shdc/generators/yaml.cc b/src/shdc/generators/yaml.cc index 2ae45590..d17c4135 100644 --- a/src/shdc/generators/yaml.cc +++ b/src/shdc/generators/yaml.cc @@ -124,7 +124,7 @@ void YamlGenerator::gen_attr(const StageAttr& att) { void YamlGenerator::gen_uniform_block(const GenInput& gen, const UniformBlock& ub) { l_open("-\n"); - l("slot: {}\n", ub.slot); + l("slot: {}\n", ub.sokol_slot); l("size: {}\n", roundup(ub.struct_info.size, 16)); l("struct_name: {}\n", ub.struct_info.name); l("inst_name: {}\n", ub.inst_name); @@ -169,7 +169,7 @@ void YamlGenerator::gen_uniform_block_refl(const UniformBlock& ub) { void YamlGenerator::gen_storage_buffer(const StorageBuffer& sbuf) { const auto& item = sbuf.struct_info.struct_items[0]; l_open("-\n"); - l("slot: {}\n", sbuf.slot); + l("slot: {}\n", sbuf.sokol_slot); l("size: {}\n", sbuf.struct_info.size); l("align: {}\n", sbuf.struct_info.align); l("struct_name: {}\n", sbuf.struct_info.name); @@ -181,7 +181,7 @@ void YamlGenerator::gen_storage_buffer(const StorageBuffer& sbuf) { void YamlGenerator::gen_image(const Image& image) { l_open("-\n"); - l("slot: {}\n", image.slot); + l("slot: {}\n", image.sokol_slot); l("name: {}\n", image.name); l("multisampled: {}\n", image.multisampled); l("type: {}\n", image_type(image.type)); @@ -191,7 +191,7 @@ void YamlGenerator::gen_image(const Image& image) { void YamlGenerator::gen_sampler(const Sampler& sampler) { l_open("-\n"); - l("slot: {}\n", sampler.slot); + l("slot: {}\n", sampler.sokol_slot); l("name: {}\n", sampler.name); l("sampler_type: {}\n", sampler_type(sampler.type)); l_close(); @@ -199,7 +199,7 @@ void YamlGenerator::gen_sampler(const Sampler& sampler) { void YamlGenerator::gen_image_sampler(const ImageSampler& image_sampler) { l_open("-\n"); - l("slot: {}\n", image_sampler.slot); + l("slot: {}\n", image_sampler.sokol_slot); l("name: {}\n", image_sampler.name); l("image_name: {}\n", image_sampler.image_name); l("sampler_name: {}\n", image_sampler.sampler_name); diff --git a/src/shdc/reflection.cc b/src/shdc/reflection.cc index 52837908..dd55bb7f 100644 --- a/src/shdc/reflection.cc +++ b/src/shdc/reflection.cc @@ -120,6 +120,7 @@ Reflection Reflection::build(const Args& args, const Input& inp, const std::arra } // create a merged set of resource bindings across all programs + // NOTE: these are only used to de-duplicate struct declarations for (const auto& prog_refl: res.progs) { prog_bindings.push_back(prog_refl.bindings); } @@ -255,7 +256,7 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c const Bindings::Type res_type = Bindings::Type::UNIFORM_BLOCK; UniformBlock refl_ub; refl_ub.stage = refl.stage; - refl_ub.slot = slot; + refl_ub.sokol_slot = slot; refl_ub.hlsl_register_b_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); refl_ub.msl_buffer_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); refl_ub.wgsl_group0_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); @@ -278,7 +279,7 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c const Bindings::Type res_type = Bindings::Type::STORAGE_BUFFER; StorageBuffer refl_sbuf; refl_sbuf.stage = refl.stage; - refl_sbuf.slot = slot; + refl_sbuf.sokol_slot = slot; refl_sbuf.hlsl_register_t_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); refl_sbuf.msl_buffer_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); refl_sbuf.wgsl_group1_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); @@ -301,7 +302,7 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c const Bindings::Type res_type = Bindings::Type::IMAGE; Image refl_img; refl_img.stage = refl.stage; - refl_img.slot = slot; + refl_img.sokol_slot = slot; refl_img.hlsl_register_t_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); refl_img.msl_texture_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); refl_img.wgsl_group1_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); @@ -323,7 +324,7 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c const SPIRType& smp_type = compiler.get_type(smp_res.type_id); Sampler refl_smp; refl_smp.stage = refl.stage; - refl_smp.slot = slot; + refl_smp.sokol_slot = slot; refl_smp.hlsl_register_s_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); refl_smp.msl_sampler_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); refl_smp.wgsl_group1_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); @@ -340,7 +341,7 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c for (auto& img_smp_res: compiler.get_combined_image_samplers()) { ImageSampler refl_img_smp; refl_img_smp.stage = refl.stage; - refl_img_smp.slot = compiler.get_decoration(img_smp_res.combined_id, spv::DecorationBinding); + refl_img_smp.sokol_slot = compiler.get_decoration(img_smp_res.combined_id, spv::DecorationBinding); refl_img_smp.name = compiler.get_name(img_smp_res.combined_id); refl_img_smp.image_name = compiler.get_name(img_smp_res.image_id); refl_img_smp.sampler_name = compiler.get_name(img_smp_res.sampler_id); diff --git a/src/shdc/types/reflection/bindings.h b/src/shdc/types/reflection/bindings.h index a2b09db2..0ea7d81b 100644 --- a/src/shdc/types/reflection/bindings.h +++ b/src/shdc/types/reflection/bindings.h @@ -37,11 +37,11 @@ struct Bindings { static uint32_t base_slot(Slang::Enum slang, ShaderStage::Enum stage, Type type); - const UniformBlock* find_uniform_block_by_slot(int slot) const; - const StorageBuffer* find_storage_buffer_by_slot(int slot) const; - const Image* find_image_by_slot(int slot) const; - const Sampler* find_sampler_by_slot(int slot) const; - const ImageSampler* find_image_sampler_by_slot(int slot) const; + const UniformBlock* find_uniform_block_by_sokol_slot(int slot) const; + const StorageBuffer* find_storage_buffer_by_sokol_slot(int slot) const; + const Image* find_image_by_sokol_slot(int slot) const; + const Sampler* find_sampler_by_sokol_slot(int slot) const; + const ImageSampler* find_image_sampler_by_sokol_slot(int slot) const; const UniformBlock* find_uniform_block_by_name(const std::string& name) const; const StorageBuffer* find_storage_buffer_by_name(const std::string& name) const; @@ -104,45 +104,45 @@ inline uint32_t Bindings::base_slot(Slang::Enum slang, ShaderStage::Enum stage, return res; } -inline const UniformBlock* Bindings::find_uniform_block_by_slot(int slot) const { +inline const UniformBlock* Bindings::find_uniform_block_by_sokol_slot(int slot) const { for (const UniformBlock& ub: uniform_blocks) { - if (ub.slot == slot) { + if (ub.sokol_slot == slot) { return &ub; } } return nullptr; } -inline const StorageBuffer* Bindings::find_storage_buffer_by_slot(int slot) const { +inline const StorageBuffer* Bindings::find_storage_buffer_by_sokol_slot(int slot) const { for (const StorageBuffer& sbuf: storage_buffers) { - if (sbuf.slot == slot) { + if (sbuf.sokol_slot == slot) { return &sbuf; } } return nullptr; } -inline const Image* Bindings::find_image_by_slot(int slot) const { +inline const Image* Bindings::find_image_by_sokol_slot(int slot) const { for (const Image& img: images) { - if (img.slot == slot) { + if (img.sokol_slot == slot) { return &img; } } return nullptr; } -inline const Sampler* Bindings::find_sampler_by_slot(int slot) const { +inline const Sampler* Bindings::find_sampler_by_sokol_slot(int slot) const { for (const Sampler& smp: samplers) { - if (smp.slot == slot) { + if (smp.sokol_slot == slot) { return &smp; } } return nullptr; } -inline const ImageSampler* Bindings::find_image_sampler_by_slot(int slot) const { +inline const ImageSampler* Bindings::find_image_sampler_by_sokol_slot(int slot) const { for (const ImageSampler& img_smp: image_samplers) { - if (img_smp.slot == slot) { + if (img_smp.sokol_slot == slot) { return &img_smp; } } diff --git a/src/shdc/types/reflection/image.h b/src/shdc/types/reflection/image.h index 568f2907..c6065f22 100644 --- a/src/shdc/types/reflection/image.h +++ b/src/shdc/types/reflection/image.h @@ -9,7 +9,7 @@ namespace shdc::refl { struct Image { ShaderStage::Enum stage = ShaderStage::Invalid; - int slot = -1; + int sokol_slot = -1; int hlsl_register_t_n = -1; int msl_texture_n = -1; int wgsl_group1_binding_n = -1; @@ -24,7 +24,7 @@ struct Image { inline bool Image::equals(const Image& other) const { return (stage == other.stage) - && (slot == other.slot) + && (sokol_slot == other.sokol_slot) && (hlsl_register_t_n == other.hlsl_register_t_n) && (msl_texture_n == other.msl_texture_n) && (wgsl_group1_binding_n == other.wgsl_group1_binding_n) @@ -38,7 +38,7 @@ inline void Image::dump_debug(const std::string& indent) const { const std::string indent2 = indent + " "; fmt::print(stderr, "{}-\n", indent); fmt::print(stderr, "{}stage: {}\n", indent2, ShaderStage::to_str(stage)); - fmt::print(stderr, "{}slot: {}\n", indent2, slot); + fmt::print(stderr, "{}sokol_slot: {}\n", indent2, sokol_slot); fmt::print(stderr, "{}hlsl_register_t_n: {}\n", indent2, hlsl_register_t_n); fmt::print(stderr, "{}msl_texture_n: {}\n", indent2, msl_texture_n); fmt::print(stderr, "{}wgsl_group1_binding_n: {}\n", indent2, wgsl_group1_binding_n); diff --git a/src/shdc/types/reflection/image_sampler.h b/src/shdc/types/reflection/image_sampler.h index 0728fbde..608b3343 100644 --- a/src/shdc/types/reflection/image_sampler.h +++ b/src/shdc/types/reflection/image_sampler.h @@ -8,7 +8,7 @@ namespace shdc::refl { // special combined-image-samplers for GLSL output with GL semantics struct ImageSampler { ShaderStage::Enum stage = ShaderStage::Invalid; - int slot = -1; + int sokol_slot = -1; std::string name; std::string image_name; std::string sampler_name; @@ -19,7 +19,7 @@ struct ImageSampler { inline bool ImageSampler::equals(const ImageSampler& other) const { return (stage == other.stage) - && (slot == other.slot) + && (sokol_slot == other.sokol_slot) && (name == other.name) && (image_name == other.image_name) && (sampler_name == other.sampler_name); @@ -29,7 +29,7 @@ inline void ImageSampler::dump_debug(const std::string& indent) const { const std::string indent2 = indent + " "; fmt::print(stderr, "{}-\n", indent); fmt::print(stderr, "{}stage: {}\n", indent2, ShaderStage::to_str(stage)); - fmt::print(stderr, "{}slot: {}\n", indent2, slot); + fmt::print(stderr, "{}sokol_slot: {}\n", indent2, sokol_slot); fmt::print(stderr, "{}name: {}\n", indent2, name); fmt::print(stderr, "{}image_name: {}\n", indent2, image_name); fmt::print(stderr, "{}sampler_name: {}\n", indent2, sampler_name); diff --git a/src/shdc/types/reflection/sampler.h b/src/shdc/types/reflection/sampler.h index 3fffeda3..4ba1159f 100644 --- a/src/shdc/types/reflection/sampler.h +++ b/src/shdc/types/reflection/sampler.h @@ -8,7 +8,7 @@ namespace shdc::refl { struct Sampler { ShaderStage::Enum stage = ShaderStage::Invalid; - int slot = -1; + int sokol_slot = -1; int hlsl_register_s_n = -1; int msl_sampler_n = -1; int wgsl_group1_binding_n = -1; @@ -21,7 +21,7 @@ struct Sampler { inline bool Sampler::equals(const Sampler& other) const { return (stage == other.stage) - && (slot == other.slot) + && (sokol_slot == other.sokol_slot) && (hlsl_register_s_n == other.hlsl_register_s_n) && (msl_sampler_n == other.msl_sampler_n) && (wgsl_group1_binding_n == other.wgsl_group1_binding_n) @@ -33,7 +33,7 @@ inline void Sampler::dump_debug(const std::string& indent) const { const std::string indent2 = indent + " "; fmt::print(stderr, "{}-\n", indent); fmt::print(stderr, "{}stage: {}\n", indent2, ShaderStage::to_str(stage)); - fmt::print(stderr, "{}slot: {}\n", indent2, slot); + fmt::print(stderr, "{}sokol_slot: {}\n", indent2, sokol_slot); fmt::print(stderr, "{}hlsl_register_s_n: {}\n", indent2, hlsl_register_s_n); fmt::print(stderr, "{}msl_sampler_n: {}\n", indent2, msl_sampler_n); fmt::print(stderr, "{}wgsl_group1_binding_n: {}\n", indent2, wgsl_group1_binding_n); diff --git a/src/shdc/types/reflection/storage_buffer.h b/src/shdc/types/reflection/storage_buffer.h index 9a5056a7..858290b0 100644 --- a/src/shdc/types/reflection/storage_buffer.h +++ b/src/shdc/types/reflection/storage_buffer.h @@ -8,7 +8,7 @@ namespace shdc::refl { struct StorageBuffer { ShaderStage::Enum stage = ShaderStage::Invalid; - int slot = -1; + int sokol_slot = -1; int hlsl_register_t_n = -1; int msl_buffer_n = -1; int wgsl_group1_binding_n = -1; @@ -23,7 +23,7 @@ struct StorageBuffer { inline bool StorageBuffer::equals(const StorageBuffer& other) const { return (stage == other.stage) - && (slot == other.slot) + && (sokol_slot == other.sokol_slot) && (hlsl_register_t_n == other.hlsl_register_t_n) && (msl_buffer_n == other.msl_buffer_n) && (wgsl_group1_binding_n == other.wgsl_group1_binding_n) @@ -37,7 +37,7 @@ inline void StorageBuffer::dump_debug(const std::string& indent) const { const std::string indent2 = indent + " "; fmt::print(stderr, "{}-\n", indent); fmt::print(stderr, "{}stage: {}\n", indent2, ShaderStage::to_str(stage)); - fmt::print(stderr, "{}slot: {}\n", indent2, slot); + fmt::print(stderr, "{}sokol_slot: {}\n", indent2, sokol_slot); fmt::print(stderr, "{}hlsl_register_t_n: {}\n", indent2, hlsl_register_t_n); fmt::print(stderr, "{}msl_buffer_n: {}\n", indent2, msl_buffer_n); fmt::print(stderr, "{}wgsl_group1_binding_n: {}\n", indent2, wgsl_group1_binding_n); diff --git a/src/shdc/types/reflection/uniform_block.h b/src/shdc/types/reflection/uniform_block.h index 908250c3..5426a35f 100644 --- a/src/shdc/types/reflection/uniform_block.h +++ b/src/shdc/types/reflection/uniform_block.h @@ -9,7 +9,7 @@ namespace shdc::refl { struct UniformBlock { ShaderStage::Enum stage = ShaderStage::Invalid; - int slot = -1; + int sokol_slot = -1; int hlsl_register_b_n = -1; int msl_buffer_n = -1; int wgsl_group0_binding_n = -1; @@ -23,7 +23,7 @@ struct UniformBlock { inline bool UniformBlock::equals(const UniformBlock& other) const { return (stage == other.stage) - && (slot == other.slot) + && (sokol_slot == other.sokol_slot) && (hlsl_register_b_n == other.hlsl_register_b_n) && (msl_buffer_n == other.msl_buffer_n) && (wgsl_group0_binding_n == other.wgsl_group0_binding_n) @@ -36,7 +36,7 @@ inline void UniformBlock::dump_debug(const std::string& indent) const { const std::string indent2 = indent + " "; fmt::print(stderr, "{}-\n", indent); fmt::print(stderr, "{}stage: {}\n", indent2, ShaderStage::to_str(stage)); - fmt::print(stderr, "{}slot: {}\n", indent2, slot); + fmt::print(stderr, "{}sokol_slot: {}\n", indent2, sokol_slot); fmt::print(stderr, "{}hlsl_register_b_n: {}\n", indent2, hlsl_register_b_n); fmt::print(stderr, "{}msl_buffer_n: {}\n", indent2, msl_buffer_n); fmt::print(stderr, "{}wgsl_group0_binding_n: {}\n", indent2, wgsl_group0_binding_n); From 60d9ba76bf607ceac9d46a3ac730fc816c5d5ba4 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 6 Oct 2024 15:50:37 +0200 Subject: [PATCH 11/37] new bindings codegen wip --- src/shdc/generators/bare.cc | 2 +- src/shdc/generators/generator.cc | 6 +- src/shdc/generators/generator.h | 2 + src/shdc/generators/sokolc.cc | 312 +++++++++---------- src/shdc/generators/sokolc.h | 1 + src/shdc/generators/sokold.cc | 2 +- src/shdc/generators/sokoljai.cc | 2 +- src/shdc/generators/sokolnim.cc | 2 +- src/shdc/generators/sokolodin.cc | 2 +- src/shdc/generators/sokolrust.cc | 2 +- src/shdc/generators/sokolzig.cc | 16 +- src/shdc/generators/yaml.cc | 4 +- src/shdc/reflection.cc | 6 +- src/shdc/spirvcross.cc | 4 +- src/shdc/types/reflection/image.h | 4 - src/shdc/types/reflection/image_sampler.h | 1 - src/shdc/types/reflection/sampler.h | 4 - src/shdc/types/reflection/stage_reflection.h | 3 +- src/shdc/types/reflection/storage_buffer.h | 5 - src/shdc/types/reflection/uniform_block.h | 4 - 20 files changed, 184 insertions(+), 200 deletions(-) diff --git a/src/shdc/generators/bare.cc b/src/shdc/generators/bare.cc index 5318e883..bbce1abd 100644 --- a/src/shdc/generators/bare.cc +++ b/src/shdc/generators/bare.cc @@ -51,7 +51,7 @@ ErrMsg BareGenerator::generate(const GenInput& gen) { const StageReflection& refl = prog.stages[stage_index]; const SpirvcrossSource* src = spirvcross.find_source_by_snippet_index(refl.snippet_index); const BytecodeBlob* blob = bytecode.find_blob_by_snippet_index(refl.snippet_index); - const std::string file_path = shader_file_path(gen, prog.name, refl.stage_name, slang, blob != nullptr); + const std::string file_path = shader_file_path(gen, prog.name, ShaderStage::to_str(refl.stage), slang, blob != nullptr); err = write_file(file_path, src, blob); if (err.valid()) { return err; diff --git a/src/shdc/generators/generator.cc b/src/shdc/generators/generator.cc index cfbc2e35..62792552 100644 --- a/src/shdc/generators/generator.cc +++ b/src/shdc/generators/generator.cc @@ -35,6 +35,7 @@ ErrMsg Generator::generate(const GenInput& gen) { Generator::ShaderStageArrayInfo Generator::shader_stage_array_info(const GenInput& gen, const ProgramReflection& prog, ShaderStage::Enum stage, Slang::Enum slang) { ShaderStageArrayInfo info; + info.stage = stage; const BytecodeBlob* bytecode_blob = gen.bytecode[slang].find_blob_by_snippet_index(prog.stage(stage).snippet_index); if (bytecode_blob) { info.has_bytecode = true; @@ -89,8 +90,8 @@ void Generator::gen_prerequisites(const GenInput& gen) { } void Generator::gen_program_info(const GenInput& gen, const ProgramReflection& prog) { - cbl_open("Vertex Shader: {}\n", prog.vs_name()); - cbl_open("Fragment Shader: {}\n", prog.fs_name()); + cbl("Vertex Shader: {}\n", prog.vs_name()); + cbl("Fragment Shader: {}\n", prog.fs_name()); cbl_open("Attributes:\n"); for (const StageAttr& attr: prog.vs().inputs) { if (attr.slot >= 0) { @@ -99,7 +100,6 @@ void Generator::gen_program_info(const GenInput& gen, const ProgramReflection& p } cbl_close(); gen_bindings_info(gen, prog); - cbl_close(); } void Generator::gen_bindings_info(const GenInput& gen, const ProgramReflection& prog) { diff --git a/src/shdc/generators/generator.h b/src/shdc/generators/generator.h index 5aab9d58..87e72e4d 100644 --- a/src/shdc/generators/generator.h +++ b/src/shdc/generators/generator.h @@ -67,6 +67,7 @@ class Generator { virtual std::string shader_bytecode_array_name(const std::string& snippet_name, Slang::Enum slang) { assert(false && "implement me"); return ""; }; virtual std::string shader_source_array_name(const std::string& snippet_name, Slang::Enum slang) { assert(false && "implement me"); return ""; }; + virtual std::string shader_stage(refl::ShaderStage::Enum e) { assert(false && "implement me"); return ""; }; virtual std::string uniform_type(refl::Type::Enum e) { assert(false && "implement me"); return ""; }; virtual std::string flattened_uniform_type(refl::Type::Enum e) { assert(false && "implement me"); return ""; }; virtual std::string image_type(refl::ImageType::Enum e) { assert(false && "implement me"); return ""; }; @@ -89,6 +90,7 @@ class Generator { struct ShaderStageArrayInfo { public: + refl::ShaderStage::Enum stage = refl::ShaderStage::Enum::Invalid; bool has_bytecode = false; size_t bytecode_array_size = 0; std::string bytecode_array_name; diff --git a/src/shdc/generators/sokolc.cc b/src/shdc/generators/sokolc.cc index eef04d7a..3d0edbda 100644 --- a/src/shdc/generators/sokolc.cc +++ b/src/shdc/generators/sokolc.cc @@ -261,21 +261,10 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef l("static bool valid;\n"); l_open("if (!valid) {{\n"); l("valid = true;\n"); - for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { - const StageAttr& attr = prog.vs().inputs[attr_index]; - if (attr.slot >= 0) { - if (Slang::is_glsl(slang)) { - l("desc.attrs[{}].name = \"{}\";\n", attr_index, attr.name); - } else if (Slang::is_hlsl(slang)) { - l("desc.attrs[{}].sem_name = \"{}\";\n", attr_index, attr.sem_name); - l("desc.attrs[{}].sem_index = {};\n", attr_index, attr.sem_index); - } - } - } for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("desc.{}", pystring::lower(refl.stage_name)); + const std::string dsn = fmt::format("desc.{}", info.stage == ShaderStage::Vertex ? "vertex_func" : "fragment_func"); if (info.has_bytecode) { l("{}.bytecode.ptr = {};\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {};\n", dsn, info.bytecode_array_size); @@ -292,66 +281,108 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); - if (ub) { - const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); - l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); - l("{}.layout = SG_UNIFORMLAYOUT_STD140;\n", ubn); - if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { - if (ub->flattened) { - l("{}.uniforms[0].name = \"{}\";\n", ubn, ub->struct_info.name); - // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) - l("{}.uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); - l("{}.uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); - } else { - for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { - const Type& u = ub->struct_info.struct_items[u_index]; - const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); - l("{}.name = \"{}.{}\";\n", un, ub->inst_name, u.name); - l("{}.type = {};\n", un, uniform_type(u.type)); - l("{}.array_count = {};\n", un, u.array_count); - } + } + for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { + const StageAttr& attr = prog.vs().inputs[attr_index]; + if (attr.slot >= 0) { + if (Slang::is_glsl(slang)) { + l("desc.attrs[{}].glsl_name = \"{}\";\n", attr_index, attr.name); + } else if (Slang::is_hlsl(slang)) { + l("desc.attrs[{}].hlsl_sem_name = \"{}\";\n", attr_index, attr.sem_name); + l("desc.attrs[{}].hlsl_sem_index = {};\n", attr_index, attr.sem_index); + } + } + } + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { + const UniformBlock* ub = prog.bindings.find_uniform_block_by_sokol_slot(ub_index); + if (ub) { + const std::string ubn = fmt::format("desc.uniform_blocks[{}]", ub_index); + l("{}.stage = {};\n", ubn, shader_stage(ub->stage)); + l("{}.layout = SG_UNIFORMLAYOUT_STD140;\n", ubn); + l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_b_n = {};\n", ubn, ub->hlsl_register_b_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_buffer_n = {};\n", ubn, ub->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group0_binding_n = {};\n", ubn, ub->wgsl_group0_binding_n); + } else if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { + if (ub->flattened) { + // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) + l("{}.uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); + l("{}.uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); + l("{}.uniforms[0].glsl_name = \"{}\";\n", ubn, ub->struct_info.name); + } else { + for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { + const Type& u = ub->struct_info.struct_items[u_index]; + const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); + l("{}.type = {};\n", un, uniform_type(u.type)); + l("{}.offset = {};\n", un, u.offset); + l("{}.array_count = {};\n", un, u.array_count); + l("{}.glsl_name = \"{}.{}\";\n", un, ub->inst_name, u.name); } } } } - for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); - if (sbuf) { - const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); - l("{}.used = true;\n", sbn); - l("{}.readonly = {};\n", sbn, sbuf->readonly); + } + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { + const StorageBuffer* sbuf = prog.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); + if (sbuf) { + const std::string& sbn = fmt::format("desc.storage_buffers[{}]", sbuf_index); + l("{}.stage = {};\n", sbn, shader_stage(sbuf->stage)); + l("{}.readonly = {};\n", sbn, sbuf->readonly); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_t_n = {};\n", sbn, sbuf->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_buffer_n = {};\n", sbn, sbuf->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", sbn, sbuf->wgsl_group1_binding_n); + } else if (Slang::is_glsl(slang)) { + l("{}.glsl_binding_n = {};\n", sbn, sbuf->glsl_binding_n); } } - for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); - if (img) { - const std::string in = fmt::format("{}.images[{}]", dsn, img_index); - l("{}.used = true;\n", in); - l("{}.multisampled = {};\n", in, img->multisampled ? "true" : "false"); - l("{}.image_type = {};\n", in, image_type(img->type)); - l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); + } + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { + const Image* img = prog.bindings.find_image_by_sokol_slot(img_index); + if (img) { + const std::string in = fmt::format("desc.images[{}]", img_index); + l("{}.stage = {};\n", in, shader_stage(img->stage)); + l("{}.image_type = {};\n", in, image_type(img->type)); + l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); + l("{}.multisampled = {};\n", in, img->multisampled ? "true" : "false"); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_t_n = {};\n", in, img->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_texture_n = {};\n", in, img->msl_texture_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {}\n", in, img->wgsl_group1_binding_n); } } - for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); - if (smp) { - const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); - l("{}.used = true;\n", sn); - l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); + } + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { + const Sampler* smp = prog.bindings.find_sampler_by_sokol_slot(smp_index); + if (smp) { + const std::string sn = fmt::format("desc.samplers[{}]", smp_index); + l("{}.stage = {};\n", sn, shader_stage(smp->stage)); + l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_s_n = {};\n", sn, smp->hlsl_register_s_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_sampler_n = {};\n", sn, smp->msl_sampler_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", sn, smp->wgsl_group1_binding_n); } } - for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); - if (img_smp) { - const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); - l("{}.used = true;\n", isn); - l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); - l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); - if (Slang::is_glsl(slang)) { - l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); - } + } + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { + const ImageSampler* img_smp = prog.bindings.find_image_sampler_by_sokol_slot(img_smp_index); + if (img_smp) { + const std::string isn = fmt::format("desc.image_sampler_pairs[{}]", img_smp_index); + l("{}.stage = {};\n", isn, shader_stage(img_smp->stage)); + l("{}.image_slot = {};\n", isn, prog.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.sampler_slot = {};\n", isn, prog.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); + if (Slang::is_glsl(slang)) { + l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); } } } @@ -383,18 +414,12 @@ void SokolCGenerator::gen_attr_slot_refl_func(const GenInput& gen, const Program } void SokolCGenerator::gen_image_slot_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("{}int {}{}_image_slot(sg_shader_stage stage, const char* img_name) {{\n", func_prefix, mod_prefix, prog.name); - l("(void)stage; (void)img_name;\n"); - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.images.empty()) { - l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); - for (const Image& img: refl.bindings.images) { - if (img.sokol_slot >= 0) { - l_open("if (0 == strcmp(img_name, \"{}\")) {{\n", img.name); - l("return {};\n", img.sokol_slot); - l_close("}}\n"); - } - } + l_open("{}int {}{}_image_slot(const char* img_name) {{\n", func_prefix, mod_prefix, prog.name); + l("(void)img_name;\n"); + for (const Image& img: prog.bindings.images) { + if (img.sokol_slot >= 0) { + l_open("if (0 == strcmp(img_name, \"{}\")) {{\n", img.name); + l("return {};\n", img.sokol_slot); l_close("}}\n"); } } @@ -403,18 +428,12 @@ void SokolCGenerator::gen_image_slot_refl_func(const GenInput& gen, const Progra } void SokolCGenerator::gen_sampler_slot_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("{}int {}{}_sampler_slot(sg_shader_stage stage, const char* smp_name) {{\n", func_prefix, mod_prefix, prog.name); - l("(void)stage; (void)smp_name;\n"); - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.samplers.empty()) { - l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); - for (const Sampler& smp: refl.bindings.samplers) { - if (smp.sokol_slot >= 0) { - l_open("if (0 == strcmp(smp_name, \"{}\")) {{\n", smp.name); - l("return {};\n", smp.sokol_slot); - l_close("}}\n"); - } - } + l_open("{}int {}{}_sampler_slot(const char* smp_name) {{\n", func_prefix, mod_prefix, prog.name); + l("(void)smp_name;\n"); + for (const Sampler& smp: prog.bindings.samplers) { + if (smp.sokol_slot >= 0) { + l_open("if (0 == strcmp(smp_name, \"{}\")) {{\n", smp.name); + l("return {};\n", smp.sokol_slot); l_close("}}\n"); } } @@ -423,18 +442,12 @@ void SokolCGenerator::gen_sampler_slot_refl_func(const GenInput& gen, const Prog } void SokolCGenerator::gen_uniform_block_slot_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("{}int {}{}_uniformblock_slot(sg_shader_stage stage, const char* ub_name) {{\n", func_prefix, mod_prefix, prog.name); - l("(void)stage; (void)ub_name;\n"); - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.uniform_blocks.empty()) { - l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); - for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.sokol_slot >= 0) { - l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); - l("return {};\n", ub.sokol_slot); - l_close("}}\n"); - } - } + l_open("{}int {}{}_uniformblock_slot(const char* ub_name) {{\n", func_prefix, mod_prefix, prog.name); + l("(void)ub_name;\n"); + for (const UniformBlock& ub: prog.bindings.uniform_blocks) { + if (ub.sokol_slot >= 0) { + l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); + l("return {};\n", ub.sokol_slot); l_close("}}\n"); } } @@ -443,18 +456,12 @@ void SokolCGenerator::gen_uniform_block_slot_refl_func(const GenInput& gen, cons } void SokolCGenerator::gen_uniform_block_size_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("{}size_t {}{}_uniformblock_size(sg_shader_stage stage, const char* ub_name) {{\n", func_prefix, mod_prefix, prog.name); - l("(void)stage; (void)ub_name;\n"); - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.uniform_blocks.empty()) { - l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); - for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.sokol_slot >= 0) { - l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); - l("return sizeof({});\n", struct_name(ub.struct_info.name)); - l_close("}}\n"); - } - } + l_open("{}size_t {}{}_uniformblock_size(const char* ub_name) {{\n", func_prefix, mod_prefix, prog.name); + l("(void)ub_name;\n"); + for (const UniformBlock& ub: prog.bindings.uniform_blocks) { + if (ub.sokol_slot >= 0) { + l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); + l("return sizeof({});\n", struct_name(ub.struct_info.name)); l_close("}}\n"); } } @@ -463,18 +470,12 @@ void SokolCGenerator::gen_uniform_block_size_refl_func(const GenInput& gen, cons } void SokolCGenerator::gen_storage_buffer_slot_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("{}int {}{}_storagebuffer_slot(sg_shader_stage stage, const char* sbuf_name) {{\n", func_prefix, mod_prefix, prog.name); - l("(void)stage; (void)sbuf_name;\n"); - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.storage_buffers.empty()) { - l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); - for (const StorageBuffer& sbuf: refl.bindings.storage_buffers) { - if (sbuf.sokol_slot >= 0) { - l_open("if (0 == strcmp(sbuf_name, \"{}\")) {{\n", sbuf.struct_info.name); - l("return {};\n", sbuf.sokol_slot); - l_close("}}\n"); - } - } + l_open("{}int {}{}_storagebuffer_slot(const char* sbuf_name) {{\n", func_prefix, mod_prefix, prog.name); + l("(void)sbuf_name;\n"); + for (const StorageBuffer& sbuf: prog.bindings.storage_buffers) { + if (sbuf.sokol_slot >= 0) { + l_open("if (0 == strcmp(sbuf_name, \"{}\")) {{\n", sbuf.struct_info.name); + l("return {};\n", sbuf.sokol_slot); l_close("}}\n"); } } @@ -483,21 +484,15 @@ void SokolCGenerator::gen_storage_buffer_slot_refl_func(const GenInput& gen, con } void SokolCGenerator::gen_uniform_offset_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("{}int {}{}_uniform_offset(sg_shader_stage stage, const char* ub_name, const char* u_name) {{\n", func_prefix, mod_prefix, prog.name); - l("(void)stage; (void)ub_name; (void)u_name;\n"); - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.uniform_blocks.empty()) { - l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); - for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.sokol_slot >= 0) { - l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); - for (const Type& u: ub.struct_info.struct_items) { - l_open("if (0 == strcmp(u_name, \"{}\")) {{\n", u.name); - l("return {};\n", u.offset); - l_close("}}\n"); - } - l_close("}}\n"); - } + l_open("{}int {}{}_uniform_offset(const char* ub_name, const char* u_name) {{\n", func_prefix, mod_prefix, prog.name); + l("(void)ub_name; (void)u_name;\n"); + for (const UniformBlock& ub: prog.bindings.uniform_blocks) { + if (ub.sokol_slot >= 0) { + l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); + for (const Type& u: ub.struct_info.struct_items) { + l_open("if (0 == strcmp(u_name, \"{}\")) {{\n", u.name); + l("return {};\n", u.offset); + l_close("}}\n"); } l_close("}}\n"); } @@ -507,29 +502,24 @@ void SokolCGenerator::gen_uniform_offset_refl_func(const GenInput& gen, const Pr } void SokolCGenerator::gen_uniform_desc_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("{}sg_shader_uniform_desc {}{}_uniform_desc(sg_shader_stage stage, const char* ub_name, const char* u_name) {{\n", func_prefix, mod_prefix, prog.name); - l("(void)stage; (void)ub_name; (void)u_name;\n"); + l_open("{}sg_glsl_shader_uniform {}{}_uniform_desc(const char* ub_name, const char* u_name) {{\n", func_prefix, mod_prefix, prog.name); + l("(void)ub_name; (void)u_name;\n"); l("#if defined(__cplusplus)\n"); - l("sg_shader_uniform_desc desc = {{}};\n"); + l("sg_glsl_shader_uniform res = {{}};\n"); l("#else\n"); - l("sg_shader_uniform_desc desc = {{0}};\n"); + l("sg_glsl_shader_uniform res = {{0}};\n"); l("#endif\n"); - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.uniform_blocks.empty()) { - l_open("if (SG_SHADERSTAGE_{} == stage) {{\n", pystring::upper(refl.stage_name)); - for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.sokol_slot >= 0) { - l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); - for (const Type& u: ub.struct_info.struct_items) { - l_open("if (0 == strcmp(u_name, \"{}\")) {{\n", u.name); - l("desc.name = \"{}\";\n", u.name); - l("desc.type = {};\n", uniform_type(u.type)); - l("desc.array_count = {};\n", u.array_count); - l("return desc;\n"); - l_close("}}\n"); - } - l_close("}}\n"); - } + for (const UniformBlock& ub: prog.bindings.uniform_blocks) { + if (ub.sokol_slot >= 0) { + l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); + for (const Type& u: ub.struct_info.struct_items) { + l_open("if (0 == strcmp(u_name, \"{}\")) {{\n", u.name); + l("res.type = {};\n", uniform_type(u.type)); + l("res.offset = {};\n", u.offset); + l("res.array_count = {};\n", u.array_count); + l("res.glsl_name = \"{}\";\n", u.name); + l("return res;\n"); + l_close("}}\n"); } l_close("}}\n"); } @@ -592,6 +582,14 @@ std::string SokolCGenerator::get_shader_desc_help(const std::string& prog_name) return fmt::format("{}{}_shader_desc(sg_query_backend());\n", mod_prefix, prog_name); } +std::string SokolCGenerator::shader_stage(ShaderStage::Enum e) { + switch (e) { + case ShaderStage::Vertex: return "SG_SHADERSTAGE_VERTEX"; + case ShaderStage::Fragment: return "SG_SHADERSTAGE_FRAGMENT"; + default: return "INVALID"; + } +} + std::string SokolCGenerator::uniform_type(Type::Enum e) { switch (e) { case Type::Float: return "SG_UNIFORMTYPE_FLOAT"; diff --git a/src/shdc/generators/sokolc.h b/src/shdc/generators/sokolc.h index 8cf146a2..8e53abbb 100644 --- a/src/shdc/generators/sokolc.h +++ b/src/shdc/generators/sokolc.h @@ -33,6 +33,7 @@ class SokolCGenerator: public Generator { virtual std::string shader_bytecode_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string shader_source_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string get_shader_desc_help(const std::string& prog_name); + virtual std::string shader_stage(refl::ShaderStage::Enum e); virtual std::string uniform_type(refl::Type::Enum e); virtual std::string flattened_uniform_type(refl::Type::Enum e); virtual std::string image_type(refl::ImageType::Enum e); diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index e8a63199..bde8f036 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -225,7 +225,7 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("desc.{}", pystring::lower(refl.stage_name)); + const std::string dsn = fmt::format("desc.{}", pystring::lower(ShaderStage::to_str(refl.stage))); if (info.has_bytecode) { l("{}.bytecode.ptr = {}.ptr;\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {};\n", dsn, info.bytecode_array_size); diff --git a/src/shdc/generators/sokoljai.cc b/src/shdc/generators/sokoljai.cc index 3f872499..1b84426c 100644 --- a/src/shdc/generators/sokoljai.cc +++ b/src/shdc/generators/sokoljai.cc @@ -209,7 +209,7 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("desc.{}", pystring::lower(refl.stage_name)); + const std::string dsn = fmt::format("desc.{}", pystring::lower(ShaderStage::to_str(refl.stage))); if (info.has_bytecode) { l("{}.bytecode.ptr = *{};\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {};\n", dsn, info.bytecode_array_size); diff --git a/src/shdc/generators/sokolnim.cc b/src/shdc/generators/sokolnim.cc index e1e092b9..c7844f6f 100644 --- a/src/shdc/generators/sokolnim.cc +++ b/src/shdc/generators/sokolnim.cc @@ -292,7 +292,7 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("result.{}", pystring::lower(refl.stage_name)); + const std::string dsn = fmt::format("result.{}", pystring::lower(ShaderStage::to_str(refl.stage))); if (info.has_bytecode) { l("{}.bytecode.ptr = {}\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {}\n", dsn, info.bytecode_array_size); diff --git a/src/shdc/generators/sokolodin.cc b/src/shdc/generators/sokolodin.cc index 4a407a69..442e1e8f 100644 --- a/src/shdc/generators/sokolodin.cc +++ b/src/shdc/generators/sokolodin.cc @@ -212,7 +212,7 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("desc.{}", pystring::lower(refl.stage_name)); + const std::string dsn = fmt::format("desc.{}", pystring::lower(ShaderStage::to_str(refl.stage))); if (info.has_bytecode) { l("{}.bytecode.ptr = &{}\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {}\n", dsn, info.bytecode_array_size); diff --git a/src/shdc/generators/sokolrust.cc b/src/shdc/generators/sokolrust.cc index d4e29a56..be5a344c 100644 --- a/src/shdc/generators/sokolrust.cc +++ b/src/shdc/generators/sokolrust.cc @@ -225,7 +225,7 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("desc.{}", pystring::lower(refl.stage_name)); + const std::string dsn = fmt::format("desc.{}", pystring::lower(ShaderStage::to_str(refl.stage))); if (info.has_bytecode) { l("{}.bytecode.ptr = &{} as *const _ as *const _;\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {};\n", dsn, info.bytecode_array_size); diff --git a/src/shdc/generators/sokolzig.cc b/src/shdc/generators/sokolzig.cc index d5b12a59..2d457142 100644 --- a/src/shdc/generators/sokolzig.cc +++ b/src/shdc/generators/sokolzig.cc @@ -223,7 +223,7 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("desc.{}", pystring::lower(refl.stage_name)); + const std::string dsn = fmt::format("desc.{}", pystring::lower(ShaderStage::to_str(refl.stage))); if (info.has_bytecode) { l("{}.bytecode.ptr = &{};\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {};\n", dsn, info.bytecode_array_size); @@ -500,7 +500,7 @@ void SokolZigGenerator::gen_image_slot_refl_func(const GenInput& gen, const Prog bool wrote_image = false; for (const StageReflection& refl: prog.stages) { if (!refl.bindings.images.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); + l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); wrote_stage = true; for (const Image& img: refl.bindings.images) { if (img.sokol_slot >= 0) { @@ -525,7 +525,7 @@ void SokolZigGenerator::gen_sampler_slot_refl_func(const GenInput& gen, const Pr bool wrote_smp = false; for (const StageReflection& refl: prog.stages) { if (!refl.bindings.samplers.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); + l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); wrote_stage = true; for (const Sampler& smp: refl.bindings.samplers) { if (smp.sokol_slot >= 0) { @@ -550,7 +550,7 @@ void SokolZigGenerator::gen_uniform_block_slot_refl_func(const GenInput& gen, co bool wrote_ub_name = false; for (const StageReflection& refl: prog.stages) { if (!refl.bindings.uniform_blocks.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); + l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); wrote_stage = true; for (const UniformBlock& ub: refl.bindings.uniform_blocks) { if (ub.sokol_slot >= 0) { @@ -575,7 +575,7 @@ void SokolZigGenerator::gen_uniform_block_size_refl_func(const GenInput& gen, co bool wrote_ub_name = false; for (const StageReflection& refl: prog.stages) { if (!refl.bindings.uniform_blocks.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); + l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); wrote_stage = true; for (const UniformBlock& ub: refl.bindings.uniform_blocks) { if (ub.sokol_slot >= 0) { @@ -600,7 +600,7 @@ void SokolZigGenerator::gen_storage_buffer_slot_refl_func(const GenInput& gen, c bool wrote_sbuf_name = false; for (const StageReflection& refl: prog.stages) { if (!refl.bindings.storage_buffers.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); + l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); wrote_stage = true; for (const StorageBuffer& sbuf: refl.bindings.storage_buffers) { if (sbuf.sokol_slot >= 0) { @@ -626,7 +626,7 @@ void SokolZigGenerator::gen_uniform_offset_refl_func(const GenInput& gen, const bool wrote_u_name = false; for (const StageReflection& refl: prog.stages) { if (!refl.bindings.uniform_blocks.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); + l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); wrote_stage = true; for (const UniformBlock& ub: refl.bindings.uniform_blocks) { if (ub.sokol_slot >= 0) { @@ -659,7 +659,7 @@ void SokolZigGenerator::gen_uniform_desc_refl_func(const GenInput& gen, const Pr for (const StageReflection& refl: prog.stages) { if (!refl.bindings.uniform_blocks.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(refl.stage_name)); + l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); wrote_stage = true; for (const UniformBlock& ub: refl.bindings.uniform_blocks) { if (ub.sokol_slot >= 0) { diff --git a/src/shdc/generators/yaml.cc b/src/shdc/generators/yaml.cc index d17c4135..9813e21a 100644 --- a/src/shdc/generators/yaml.cc +++ b/src/shdc/generators/yaml.cc @@ -37,8 +37,8 @@ ErrMsg YamlGenerator::generate(const GenInput& gen) { const StageReflection& refl = prog.stages[stage_index]; const SpirvcrossSource* src = spirvcross.find_source_by_snippet_index(refl.snippet_index); const BytecodeBlob* blob = bytecode.find_blob_by_snippet_index(refl.snippet_index); - const std::string file_path = shader_file_path(gen, prog.name, refl.stage_name, slang, blob != nullptr); - l_open("{}:\n", pystring::lower(refl.stage_name)); + const std::string file_path = shader_file_path(gen, prog.name, ShaderStage::to_str(refl.stage), slang, blob != nullptr); + l_open("{}:\n", pystring::lower(ShaderStage::to_str(refl.stage))); l("path: {}\n", file_path); l("is_binary: {}\n", blob != nullptr); l("entry_point: {}\n", refl.entry_point_by_slang(slang)); diff --git a/src/shdc/reflection.cc b/src/shdc/reflection.cc index dd55bb7f..c3a8baf9 100644 --- a/src/shdc/reflection.cc +++ b/src/shdc/reflection.cc @@ -217,7 +217,6 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c case spv::ExecutionModelFragment: refl.stage = ShaderStage::Fragment; break; default: refl.stage = ShaderStage::Invalid; break; } - refl.stage_name = ShaderStage::to_str(refl.stage); // find entry point const auto entry_points = compiler.get_entry_points_and_stages(); @@ -411,6 +410,7 @@ Bindings Reflection::merge_bindings(const std::vector& in_bindings, Er } } else { out_bindings.uniform_blocks.push_back(ub); + out_bindings.uniform_blocks.back().sokol_slot = (int)out_bindings.uniform_blocks.size() - 1; } } @@ -425,6 +425,7 @@ Bindings Reflection::merge_bindings(const std::vector& in_bindings, Er } } else { out_bindings.storage_buffers.push_back(sbuf); + out_bindings.storage_buffers.back().sokol_slot = (int)out_bindings.storage_buffers.size() - 1; } } @@ -439,6 +440,7 @@ Bindings Reflection::merge_bindings(const std::vector& in_bindings, Er } } else { out_bindings.images.push_back(img); + out_bindings.images.back().sokol_slot = (int)out_bindings.images.size() - 1; } } @@ -453,6 +455,7 @@ Bindings Reflection::merge_bindings(const std::vector& in_bindings, Er } } else { out_bindings.samplers.push_back(smp); + out_bindings.samplers.back().sokol_slot = (int)out_bindings.samplers.size() - 1; } } @@ -467,6 +470,7 @@ Bindings Reflection::merge_bindings(const std::vector& in_bindings, Er } } else { out_bindings.image_samplers.push_back(img_smp); + out_bindings.image_samplers.back().sokol_slot = (int)out_bindings.image_samplers.size() - 1; } } } diff --git a/src/shdc/spirvcross.cc b/src/shdc/spirvcross.cc index 9ed15c2b..dcf7855d 100644 --- a/src/shdc/spirvcross.cc +++ b/src/shdc/spirvcross.cc @@ -31,10 +31,8 @@ const SpirvcrossSource* Spirvcross::find_source_by_snippet_index(int snippet_ind } static void fix_bind_slots(Compiler& compiler, Snippet::Type snippet_type, Slang::Enum slang) { - // WGSL bindslot fixup is handled elsewhere - // Also note that this function can be called with the special Slang::REFLECTION + // NOTE: this function can be called with the special Slang::REFLECTION // which guarantees zero-based bindings for each resource type - assert(!Slang::is_wgsl(slang)); ShaderResources shader_resources = compiler.get_shader_resources(); ShaderStage::Enum stage = ShaderStage::from_snippet_type(snippet_type); diff --git a/src/shdc/types/reflection/image.h b/src/shdc/types/reflection/image.h index c6065f22..f50e3998 100644 --- a/src/shdc/types/reflection/image.h +++ b/src/shdc/types/reflection/image.h @@ -24,10 +24,6 @@ struct Image { inline bool Image::equals(const Image& other) const { return (stage == other.stage) - && (sokol_slot == other.sokol_slot) - && (hlsl_register_t_n == other.hlsl_register_t_n) - && (msl_texture_n == other.msl_texture_n) - && (wgsl_group1_binding_n == other.wgsl_group1_binding_n) && (name == other.name) && (type == other.type) && (sample_type == other.sample_type) diff --git a/src/shdc/types/reflection/image_sampler.h b/src/shdc/types/reflection/image_sampler.h index 608b3343..0068c71b 100644 --- a/src/shdc/types/reflection/image_sampler.h +++ b/src/shdc/types/reflection/image_sampler.h @@ -19,7 +19,6 @@ struct ImageSampler { inline bool ImageSampler::equals(const ImageSampler& other) const { return (stage == other.stage) - && (sokol_slot == other.sokol_slot) && (name == other.name) && (image_name == other.image_name) && (sampler_name == other.sampler_name); diff --git a/src/shdc/types/reflection/sampler.h b/src/shdc/types/reflection/sampler.h index 4ba1159f..8875ce67 100644 --- a/src/shdc/types/reflection/sampler.h +++ b/src/shdc/types/reflection/sampler.h @@ -21,10 +21,6 @@ struct Sampler { inline bool Sampler::equals(const Sampler& other) const { return (stage == other.stage) - && (sokol_slot == other.sokol_slot) - && (hlsl_register_s_n == other.hlsl_register_s_n) - && (msl_sampler_n == other.msl_sampler_n) - && (wgsl_group1_binding_n == other.wgsl_group1_binding_n) && (name == other.name) && (type == other.type); } diff --git a/src/shdc/types/reflection/stage_reflection.h b/src/shdc/types/reflection/stage_reflection.h index e46fd505..06b0a812 100644 --- a/src/shdc/types/reflection/stage_reflection.h +++ b/src/shdc/types/reflection/stage_reflection.h @@ -12,7 +12,6 @@ struct StageReflection { int snippet_index = -1; std::string snippet_name; ShaderStage::Enum stage = ShaderStage::Invalid; - std::string stage_name; // same as ShaderStage::to_str(stage) std::string entry_point; std::array inputs; // index == attribute slot std::array outputs; // index == attribute slot @@ -33,7 +32,7 @@ inline std::string StageReflection::entry_point_by_slang(Slang::Enum slang) cons inline void StageReflection::dump_debug(const std::string& indent) const { const std::string indent2 = indent + " "; fmt::print(stderr, "{}-\n", indent); - fmt::print(stderr, "{}name: {}\n", indent2, stage_name); + fmt::print(stderr, "{}stage: {}\n", indent2, ShaderStage::to_str(stage)); fmt::print(stderr, "{}snippet_index: {}\n", indent2, snippet_index); fmt::print(stderr, "{}snippet_name: {}\n", indent2, snippet_name); fmt::print(stderr, "{}entry_point: {}\n", indent2, entry_point); diff --git a/src/shdc/types/reflection/storage_buffer.h b/src/shdc/types/reflection/storage_buffer.h index 858290b0..18a90396 100644 --- a/src/shdc/types/reflection/storage_buffer.h +++ b/src/shdc/types/reflection/storage_buffer.h @@ -23,11 +23,6 @@ struct StorageBuffer { inline bool StorageBuffer::equals(const StorageBuffer& other) const { return (stage == other.stage) - && (sokol_slot == other.sokol_slot) - && (hlsl_register_t_n == other.hlsl_register_t_n) - && (msl_buffer_n == other.msl_buffer_n) - && (wgsl_group1_binding_n == other.wgsl_group1_binding_n) - && (glsl_binding_n == other.glsl_binding_n) && (inst_name == other.inst_name) && (readonly == other.readonly) && (struct_info.equals(other.struct_info)); diff --git a/src/shdc/types/reflection/uniform_block.h b/src/shdc/types/reflection/uniform_block.h index 5426a35f..34f28995 100644 --- a/src/shdc/types/reflection/uniform_block.h +++ b/src/shdc/types/reflection/uniform_block.h @@ -23,10 +23,6 @@ struct UniformBlock { inline bool UniformBlock::equals(const UniformBlock& other) const { return (stage == other.stage) - && (sokol_slot == other.sokol_slot) - && (hlsl_register_b_n == other.hlsl_register_b_n) - && (msl_buffer_n == other.msl_buffer_n) - && (wgsl_group0_binding_n == other.wgsl_group0_binding_n) // NOTE: ignore inst_name && (flattened == other.flattened) && struct_info.equals(other.struct_info); From a82e7165693856276b0854023b4718285ee28bb7 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 6 Oct 2024 17:40:47 +0200 Subject: [PATCH 12/37] write per-program vertex attribute constants --- src/shdc/generators/generator.cc | 10 +++--- src/shdc/generators/generator.h | 4 +-- src/shdc/generators/sokolc.cc | 8 ++--- src/shdc/generators/sokolc.h | 4 +-- src/shdc/generators/sokold.cc | 8 ++--- src/shdc/generators/sokold.h | 6 ++-- src/shdc/generators/sokoljai.cc | 8 ++--- src/shdc/generators/sokoljai.h | 4 +-- src/shdc/generators/sokolnim.cc | 8 ++--- src/shdc/generators/sokolnim.h | 4 +-- src/shdc/generators/sokolodin.cc | 8 ++--- src/shdc/generators/sokolodin.h | 4 +-- src/shdc/generators/sokolrust.cc | 8 ++--- src/shdc/generators/sokolrust.h | 4 +-- src/shdc/generators/sokolzig.cc | 8 ++--- src/shdc/generators/sokolzig.h | 4 +-- src/shdc/reflection.cc | 43 +------------------------- src/shdc/reflection.h | 3 -- src/shdc/types/reflection/stage_attr.h | 22 ++++--------- 19 files changed, 58 insertions(+), 110 deletions(-) diff --git a/src/shdc/generators/generator.cc b/src/shdc/generators/generator.cc index 62792552..3612c006 100644 --- a/src/shdc/generators/generator.cc +++ b/src/shdc/generators/generator.cc @@ -95,7 +95,7 @@ void Generator::gen_program_info(const GenInput& gen, const ProgramReflection& p cbl_open("Attributes:\n"); for (const StageAttr& attr: prog.vs().inputs) { if (attr.slot >= 0) { - cbl("{} => {}\n", vertex_attr_name(attr), attr.slot); + cbl("{} => {}\n", vertex_attr_name(prog.name, attr), attr.slot); } } cbl_close(); @@ -138,9 +138,11 @@ void Generator::gen_bindings_info(const GenInput& gen, const ProgramReflection& } void Generator::gen_vertex_attr_consts(const GenInput& gen) { - for (const StageAttr& attr: gen.refl.unique_vs_inputs) { - if (attr.slot >= 0) { - l("{}\n", vertex_attr_definition(attr)); + for (const ProgramReflection& prog: gen.refl.progs) { + for (const StageAttr& attr: prog.vs().inputs) { + if (attr.slot >= 0) { + l("{}\n", vertex_attr_definition(prog.name, attr)); + } } } } diff --git a/src/shdc/generators/generator.h b/src/shdc/generators/generator.h index 87e72e4d..0e6c3d93 100644 --- a/src/shdc/generators/generator.h +++ b/src/shdc/generators/generator.h @@ -76,13 +76,13 @@ class Generator { virtual std::string backend(Slang::Enum e) { assert(false && "implement me"); return ""; }; virtual std::string struct_name(const std::string& name) { assert(false && "implement me"); return ""; }; - virtual std::string vertex_attr_name(const refl::StageAttr& attr) { assert(false && "implement me"); return ""; }; + virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr) { assert(false && "implement me"); return ""; }; virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img) { assert(false && "implement me"); return ""; }; virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp) { assert(false && "implement me"); return ""; }; virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub) { assert(false && "implement me"); return ""; }; virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf) { assert(false && "implement me"); return ""; }; - virtual std::string vertex_attr_definition(const refl::StageAttr& attr) { assert(false && "implement me"); return ""; }; + virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr) { assert(false && "implement me"); return ""; }; virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img) { assert(false && "implement me"); return ""; }; virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp) { assert(false && "implement me"); return ""; }; virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub) { assert(false && "implement me"); return ""; }; diff --git a/src/shdc/generators/sokolc.cc b/src/shdc/generators/sokolc.cc index 3d0edbda..130c8778 100644 --- a/src/shdc/generators/sokolc.cc +++ b/src/shdc/generators/sokolc.cc @@ -680,8 +680,8 @@ std::string SokolCGenerator::struct_name(const std::string& name) { return fmt::format("{}{}_t", mod_prefix, name); } -std::string SokolCGenerator::vertex_attr_name(const StageAttr& attr) { - return fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name); +std::string SokolCGenerator::vertex_attr_name(const std::string& prog_name, const StageAttr& attr) { + return fmt::format("ATTR_{}_{}", prog_name, attr.name); } std::string SokolCGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { @@ -700,8 +700,8 @@ std::string SokolCGenerator::storage_buffer_bind_slot_name(const std::string& pr return fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name); } -std::string SokolCGenerator::vertex_attr_definition(const StageAttr& attr) { - return fmt::format("#define {} ({})", vertex_attr_name(attr), attr.slot); +std::string SokolCGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { + return fmt::format("#define {} ({})", vertex_attr_name(prog_name, attr), attr.slot); } std::string SokolCGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { diff --git a/src/shdc/generators/sokolc.h b/src/shdc/generators/sokolc.h index 8e53abbb..8ca29e13 100644 --- a/src/shdc/generators/sokolc.h +++ b/src/shdc/generators/sokolc.h @@ -41,12 +41,12 @@ class SokolCGenerator: public Generator { virtual std::string sampler_type(refl::SamplerType::Enum e); virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); - virtual std::string vertex_attr_name(const refl::StageAttr& attr); + virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); - virtual std::string vertex_attr_definition(const refl::StageAttr& attr); + virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index bde8f036..ee3c2c1a 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -433,8 +433,8 @@ std::string SokolDGenerator::struct_name(const std::string& name) { return to_pascal_case(name); } -std::string SokolDGenerator::vertex_attr_name(const StageAttr& attr) { - return pystring::upper(fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name)); +std::string SokolDGenerator::vertex_attr_name(const std::string& prog_name, const StageAttr& attr) { + return pystring::upper(fmt::format("ATTR_{}_{}", prog_name, attr.name)); } std::string SokolDGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { @@ -457,8 +457,8 @@ static std::string const_def(const std::string& name, int slot) { return fmt::format("enum {} = {};", name, slot); } -std::string SokolDGenerator::vertex_attr_definition(const StageAttr& attr) { - return const_def(vertex_attr_name(attr), attr.slot); +std::string SokolDGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { + return const_def(vertex_attr_name(prog_name, attr), attr.slot); } std::string SokolDGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { diff --git a/src/shdc/generators/sokold.h b/src/shdc/generators/sokold.h index 44edf655..8a194a48 100644 --- a/src/shdc/generators/sokold.h +++ b/src/shdc/generators/sokold.h @@ -27,12 +27,12 @@ class SokolDGenerator : public Generator { virtual std::string sampler_type(refl::SamplerType::Enum e); virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); - virtual std::string vertex_attr_name(const refl::StageAttr& attr); + virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); - virtual std::string vertex_attr_definition(const refl::StageAttr& attr); + virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); @@ -41,4 +41,4 @@ class SokolDGenerator : public Generator { virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, int alignment, int pad_to_size); }; -} // namespace \ No newline at end of file +} // namespace diff --git a/src/shdc/generators/sokoljai.cc b/src/shdc/generators/sokoljai.cc index 1b84426c..2fb3180b 100644 --- a/src/shdc/generators/sokoljai.cc +++ b/src/shdc/generators/sokoljai.cc @@ -423,8 +423,8 @@ std::string SokolJaiGenerator::struct_name(const std::string& name) { return to_ada_case(name); } -std::string SokolJaiGenerator::vertex_attr_name(const StageAttr& attr) { - return fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name); +std::string SokolJaiGenerator::vertex_attr_name(const std::string& prog_name, const StageAttr& attr) { + return fmt::format("ATTR_{}_{}", prog_name, attr.name); } std::string SokolJaiGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { @@ -443,8 +443,8 @@ std::string SokolJaiGenerator::storage_buffer_bind_slot_name(const std::string& return fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name); } -std::string SokolJaiGenerator::vertex_attr_definition(const StageAttr& attr) { - return fmt::format("{} :: {};", vertex_attr_name(attr), attr.slot); +std::string SokolJaiGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { + return fmt::format("{} :: {};", vertex_attr_name(prog_name, attr), attr.slot); } std::string SokolJaiGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { diff --git a/src/shdc/generators/sokoljai.h b/src/shdc/generators/sokoljai.h index a33c857e..b41ff092 100644 --- a/src/shdc/generators/sokoljai.h +++ b/src/shdc/generators/sokoljai.h @@ -27,12 +27,12 @@ class SokolJaiGenerator: public Generator { virtual std::string sampler_type(refl::SamplerType::Enum e); virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); - virtual std::string vertex_attr_name(const refl::StageAttr& attr); + virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); - virtual std::string vertex_attr_definition(const refl::StageAttr& attr); + virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); diff --git a/src/shdc/generators/sokolnim.cc b/src/shdc/generators/sokolnim.cc index c7844f6f..a51356be 100644 --- a/src/shdc/generators/sokolnim.cc +++ b/src/shdc/generators/sokolnim.cc @@ -506,8 +506,8 @@ std::string SokolNimGenerator::struct_name(const std::string& name) { return to_pascal_case(name); } -std::string SokolNimGenerator::vertex_attr_name(const StageAttr& attr) { - return to_camel_case(fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name)); +std::string SokolNimGenerator::vertex_attr_name(const std::string& prog_name, const StageAttr& attr) { + return to_camel_case(fmt::format("ATTR_{}_{}", prog_name, attr.name)); } std::string SokolNimGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { @@ -526,8 +526,8 @@ std::string SokolNimGenerator::storage_buffer_bind_slot_name(const std::string& return to_camel_case(fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name)); } -std::string SokolNimGenerator::vertex_attr_definition(const StageAttr& attr) { - return fmt::format("const {}* = {}", vertex_attr_name(attr), attr.slot); +std::string SokolNimGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { + return fmt::format("const {}* = {}", vertex_attr_name(prog_name, attr), attr.slot); } std::string SokolNimGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { diff --git a/src/shdc/generators/sokolnim.h b/src/shdc/generators/sokolnim.h index cbcaf5dd..874c02a7 100644 --- a/src/shdc/generators/sokolnim.h +++ b/src/shdc/generators/sokolnim.h @@ -29,12 +29,12 @@ class SokolNimGenerator: public Generator { virtual std::string sampler_type(refl::SamplerType::Enum e); virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); - virtual std::string vertex_attr_name(const refl::StageAttr& attr); + virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); - virtual std::string vertex_attr_definition(const refl::StageAttr& attr); + virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); diff --git a/src/shdc/generators/sokolodin.cc b/src/shdc/generators/sokolodin.cc index 442e1e8f..a0518a35 100644 --- a/src/shdc/generators/sokolodin.cc +++ b/src/shdc/generators/sokolodin.cc @@ -426,8 +426,8 @@ std::string SokolOdinGenerator::struct_name(const std::string& name) { return to_ada_case(name); } -std::string SokolOdinGenerator::vertex_attr_name(const StageAttr& attr) { - return fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name); +std::string SokolOdinGenerator::vertex_attr_name(const std::string& prog_name, const StageAttr& attr) { + return fmt::format("ATTR_{}_{}", prog_name, attr.name); } std::string SokolOdinGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { @@ -446,8 +446,8 @@ std::string SokolOdinGenerator::storage_buffer_bind_slot_name(const std::string& return fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name); } -std::string SokolOdinGenerator::vertex_attr_definition(const StageAttr& attr) { - return fmt::format("{} :: {}", vertex_attr_name(attr), attr.slot); +std::string SokolOdinGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { + return fmt::format("{} :: {}", vertex_attr_name(prog_name, attr), attr.slot); } std::string SokolOdinGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { diff --git a/src/shdc/generators/sokolodin.h b/src/shdc/generators/sokolodin.h index df9c8166..b9fa9a94 100644 --- a/src/shdc/generators/sokolodin.h +++ b/src/shdc/generators/sokolodin.h @@ -27,12 +27,12 @@ class SokolOdinGenerator: public Generator { virtual std::string sampler_type(refl::SamplerType::Enum e); virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); - virtual std::string vertex_attr_name(const refl::StageAttr& attr); + virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); - virtual std::string vertex_attr_definition(const refl::StageAttr& attr); + virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); diff --git a/src/shdc/generators/sokolrust.cc b/src/shdc/generators/sokolrust.cc index be5a344c..4c6236d8 100644 --- a/src/shdc/generators/sokolrust.cc +++ b/src/shdc/generators/sokolrust.cc @@ -440,8 +440,8 @@ std::string SokolRustGenerator::struct_name(const std::string& name) { return to_pascal_case(name); } -std::string SokolRustGenerator::vertex_attr_name(const StageAttr& attr) { - return pystring::upper(fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name)); +std::string SokolRustGenerator::vertex_attr_name(const std::string& prog_name, const StageAttr& attr) { + return pystring::upper(fmt::format("ATTR_{}_{}", prog_name, attr.name)); } std::string SokolRustGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { @@ -460,8 +460,8 @@ std::string SokolRustGenerator::storage_buffer_bind_slot_name(const std::string& return pystring::upper(fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name)); } -std::string SokolRustGenerator::vertex_attr_definition(const StageAttr& attr) { - return fmt::format("pub const {}: usize = {};", vertex_attr_name(attr), attr.slot); +std::string SokolRustGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { + return fmt::format("pub const {}: usize = {};", vertex_attr_name(prog_name, attr), attr.slot); } std::string SokolRustGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { diff --git a/src/shdc/generators/sokolrust.h b/src/shdc/generators/sokolrust.h index eba06e8d..6c79dba2 100644 --- a/src/shdc/generators/sokolrust.h +++ b/src/shdc/generators/sokolrust.h @@ -27,12 +27,12 @@ class SokolRustGenerator: public Generator { virtual std::string sampler_type(refl::SamplerType::Enum e); virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); - virtual std::string vertex_attr_name(const refl::StageAttr& attr); + virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); - virtual std::string vertex_attr_definition(const refl::StageAttr& attr); + virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); diff --git a/src/shdc/generators/sokolzig.cc b/src/shdc/generators/sokolzig.cc index 2d457142..8864be3f 100644 --- a/src/shdc/generators/sokolzig.cc +++ b/src/shdc/generators/sokolzig.cc @@ -438,8 +438,8 @@ std::string SokolZigGenerator::struct_name(const std::string& name) { return to_pascal_case(name); } -std::string SokolZigGenerator::vertex_attr_name(const StageAttr& attr) { - return fmt::format("ATTR_{}_{}", attr.snippet_name, attr.name); +std::string SokolZigGenerator::vertex_attr_name(const std::string& prog_name, const StageAttr& attr) { + return fmt::format("ATTR_{}_{}", prog_name, attr.name); } std::string SokolZigGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { @@ -458,8 +458,8 @@ std::string SokolZigGenerator::storage_buffer_bind_slot_name(const std::string& return fmt::format("SBUF_{}_{}", prog_name, sb.struct_info.name); } -std::string SokolZigGenerator::vertex_attr_definition(const StageAttr& attr) { - return fmt::format("pub const {} = {};", vertex_attr_name(attr), attr.slot); +std::string SokolZigGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { + return fmt::format("pub const {} = {};", vertex_attr_name(prog_name, attr), attr.slot); } std::string SokolZigGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { diff --git a/src/shdc/generators/sokolzig.h b/src/shdc/generators/sokolzig.h index 98ae400d..0788b878 100644 --- a/src/shdc/generators/sokolzig.h +++ b/src/shdc/generators/sokolzig.h @@ -35,12 +35,12 @@ class SokolZigGenerator: public Generator { virtual std::string sampler_type(refl::SamplerType::Enum e); virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); - virtual std::string vertex_attr_name(const refl::StageAttr& attr); + virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); - virtual std::string vertex_attr_definition(const refl::StageAttr& attr); + virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); diff --git a/src/shdc/reflection.cc b/src/shdc/reflection.cc index c3a8baf9..b204a22f 100644 --- a/src/shdc/reflection.cc +++ b/src/shdc/reflection.cc @@ -59,7 +59,7 @@ static ErrMsg validate_linking(const Input& inp, const Program& prog, const Prog const StageAttr& vs_out = prog_refl.vs().outputs[slot]; const StageAttr& fs_inp = prog_refl.fs().inputs[slot]; // ignore snippet-name for equality check - if (!vs_out.equals(fs_inp, false)) { + if (!vs_out.equals(fs_inp)) { return inp.error(prog.line_index, fmt::format("outputs of vs '{}' don't match inputs of fs '{}' for attr #{} (vs={},fs={})\n", prog_refl.vs_name(), @@ -111,14 +111,6 @@ Reflection Reflection::build(const Args& args, const Input& inp, const std::arra res.progs.push_back(prog_refl); } - // create a set of vertex shader inputs with removed duplicates - // (or error out if the are attribute conflicts) - res.unique_vs_inputs = merge_vs_inputs(res.progs, error); - if (error.valid()) { - res.error = inp.error(0, error.msg); - return res; - } - // create a merged set of resource bindings across all programs // NOTE: these are only used to de-duplicate struct declarations for (const auto& prog_refl: res.progs) { @@ -233,7 +225,6 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c refl_attr.name = res_attr.name; refl_attr.sem_name = "TEXCOORD"; refl_attr.sem_index = refl_attr.slot; - refl_attr.snippet_name = snippet.name; refl_attr.type_info = get_type_for_attribute(compiler, res_attr); refl.inputs[refl_attr.slot] = refl_attr; @@ -244,7 +235,6 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c refl_attr.name = res_attr.name; refl_attr.sem_name = "TEXCOORD"; refl_attr.sem_index = refl_attr.slot; - refl_attr.snippet_name = snippet.name; refl_attr.type_info = get_type_for_attribute(compiler, res_attr); refl.outputs[refl_attr.slot] = refl_attr; @@ -363,37 +353,6 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c return refl; } -const StageAttr* find_attr_by_name(const std::vector& attrs, const std::string& snippet_name, const std::string& attr_name) { - for (const StageAttr& attr: attrs) { - if ((attr.name == attr_name) && (attr.snippet_name == snippet_name)) { - return &attr; - } - } - return nullptr; -} - -std::vector Reflection::merge_vs_inputs(const std::vector& progs, ErrMsg& out_error) { - std::vector out_attrs; - out_error = ErrMsg(); - for (const ProgramReflection& prog: progs) { - for (const StageAttr& attr: prog.vs().inputs) { - if (attr.slot != -1) { - const StageAttr* other_attr = find_attr_by_name(out_attrs, attr.snippet_name, attr.name); - if (other_attr) { - // take snippet-name into account for equality check - if (!attr.equals(*other_attr, true)) { - out_error = ErrMsg::error(fmt::format("conflicting vertex shader attributes found for '{}/{}'", attr.snippet_name, attr.name)); - return std::vector{}; - } - } else { - out_attrs.push_back(attr); - } - } - } - } - return out_attrs; -} - Bindings Reflection::merge_bindings(const std::vector& in_bindings, ErrMsg& out_error) { Bindings out_bindings; out_error = ErrMsg(); diff --git a/src/shdc/reflection.h b/src/shdc/reflection.h index 1f49db48..a0c891b5 100644 --- a/src/shdc/reflection.h +++ b/src/shdc/reflection.h @@ -16,7 +16,6 @@ namespace shdc::refl { struct Reflection { std::vector progs; - std::vector unique_vs_inputs; Bindings bindings; ErrMsg error; @@ -28,8 +27,6 @@ struct Reflection { void dump_debug(ErrMsg::Format err_fmt) const; private: - // create a set of unique vertex shader inputs across all programs - static std::vector merge_vs_inputs(const std::vector& progs, ErrMsg& out_error); // create a set of unique resource bindings from shader snippet input bindings static Bindings merge_bindings(const std::vector& in_bindings, ErrMsg& out_error); // parse a struct diff --git a/src/shdc/types/reflection/stage_attr.h b/src/shdc/types/reflection/stage_attr.h index 95730206..418824f9 100644 --- a/src/shdc/types/reflection/stage_attr.h +++ b/src/shdc/types/reflection/stage_attr.h @@ -10,26 +10,17 @@ struct StageAttr { std::string name; std::string sem_name; int sem_index = 0; - std::string snippet_name; Type type_info; - bool equals(const StageAttr& rhs, bool with_snippet_name) const; + bool equals(const StageAttr& rhs) const; void dump_debug(const std::string& indent) const; }; -inline bool StageAttr::equals(const StageAttr& rhs, bool with_snippet_name) const { - if (with_snippet_name) { - return (slot == rhs.slot) && - (name == rhs.name) && - (sem_name == rhs.sem_name) && - (sem_index == rhs.sem_index) && - (snippet_name == rhs.snippet_name); - } else { - return (slot == rhs.slot) && - (name == rhs.name) && - (sem_name == rhs.sem_name) && - (sem_index == rhs.sem_index); - } +inline bool StageAttr::equals(const StageAttr& rhs) const { + return (slot == rhs.slot) && + (name == rhs.name) && + (sem_name == rhs.sem_name) && + (sem_index == rhs.sem_index); } inline void StageAttr::dump_debug(const std::string& indent) const { @@ -39,7 +30,6 @@ inline void StageAttr::dump_debug(const std::string& indent) const { fmt::print(stderr, "{}name: {}\n", indent2, name); fmt::print(stderr, "{}sem_name: {}\n", indent2, sem_name); fmt::print(stderr, "{}sem_index: {}\n", indent2, sem_index); - fmt::print(stderr, "{}snippet_name: {}\n", indent2, snippet_name); } } // namespace From 5e4207606669eb6175b64f7346e749d89dab35fe Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 7 Oct 2024 16:56:04 +0200 Subject: [PATCH 13/37] define sokol bindings via layout(binding=n) instead of custom tag --- src/shdc/generators/generator.cc | 48 +++++++------- src/shdc/generators/generator.h | 18 +++--- src/shdc/generators/sokolc.cc | 32 +++++----- src/shdc/generators/sokolc.h | 16 ++--- src/shdc/generators/sokold.cc | 32 +++++----- src/shdc/generators/sokold.h | 16 ++--- src/shdc/generators/sokoljai.cc | 32 +++++----- src/shdc/generators/sokoljai.h | 16 ++--- src/shdc/generators/sokolnim.cc | 32 +++++----- src/shdc/generators/sokolnim.h | 16 ++--- src/shdc/generators/sokolodin.cc | 32 +++++----- src/shdc/generators/sokolodin.h | 16 ++--- src/shdc/generators/sokolrust.cc | 32 +++++----- src/shdc/generators/sokolrust.h | 16 ++--- src/shdc/generators/sokolzig.cc | 32 +++++----- src/shdc/generators/sokolzig.h | 16 ++--- src/shdc/input.cc | 93 +++++++++++++++++++--------- src/shdc/input.h | 14 +++++ src/shdc/main.cc | 4 +- src/shdc/reflection.cc | 42 ++++++++----- src/shdc/reflection.h | 2 +- src/shdc/spirv.cc | 81 +++++++++++++++++++++--- src/shdc/spirv.h | 2 +- src/shdc/spirvcross.cc | 14 ++--- src/shdc/types/reflection/bindings.h | 10 +-- src/shdc/types/snippet.h | 22 ------- 26 files changed, 394 insertions(+), 292 deletions(-) diff --git a/src/shdc/generators/generator.cc b/src/shdc/generators/generator.cc index 3612c006..6678e085 100644 --- a/src/shdc/generators/generator.cc +++ b/src/shdc/generators/generator.cc @@ -81,6 +81,9 @@ void Generator::gen_header(const GenInput& gen) { gen_program_info(gen, prog); cbl_close(); } + cbl_open("Bindings:\n"); + gen_bindings_info(gen); + cbl_close(); cbl_end(); } @@ -99,37 +102,36 @@ void Generator::gen_program_info(const GenInput& gen, const ProgramReflection& p } } cbl_close(); - gen_bindings_info(gen, prog); } -void Generator::gen_bindings_info(const GenInput& gen, const ProgramReflection& prog) { - for (const UniformBlock& ub: prog.bindings.uniform_blocks) { +void Generator::gen_bindings_info(const GenInput& gen) { + for (const UniformBlock& ub: gen.refl.bindings.uniform_blocks) { cbl_open("Uniform block '{}':\n", ub.struct_info.name); cbl("{} struct: {}\n", lang_name(), struct_name(ub.struct_info.name)); - cbl("Bind slot: {} => {}\n", uniform_block_bind_slot_name(prog.name, ub), ub.sokol_slot); + cbl("Bind slot: {} => {}\n", uniform_block_bind_slot_name(ub), ub.sokol_slot); cbl_close(); } - for (const StorageBuffer& sbuf: prog.bindings.storage_buffers) { + for (const StorageBuffer& sbuf: gen.refl.bindings.storage_buffers) { cbl_open("Storage buffer '{}':\n", sbuf.struct_info.name); cbl("{} struct: {}\n", lang_name(), struct_name(sbuf.struct_info.name)); - cbl("Bind slot: {} => {}\n", storage_buffer_bind_slot_name(prog.name, sbuf), sbuf.sokol_slot); + cbl("Bind slot: {} => {}\n", storage_buffer_bind_slot_name(sbuf), sbuf.sokol_slot); cbl_close(); } - for (const Image& img: prog.bindings.images) { + for (const Image& img: gen.refl.bindings.images) { cbl_open("Image '{}':\n", img.name); cbl("Image type: {}\n", image_type(img.type)); cbl("Sample type: {}\n", image_sample_type(img.sample_type)); cbl("Multisampled: {}\n", img.multisampled); - cbl("Bind slot: {} => {}\n", image_bind_slot_name(prog.name, img), img.sokol_slot); + cbl("Bind slot: {} => {}\n", image_bind_slot_name(img), img.sokol_slot); cbl_close(); } - for (const Sampler& smp: prog.bindings.samplers) { + for (const Sampler& smp: gen.refl.bindings.samplers) { cbl_open("Sampler '{}':\n", smp.name); cbl("Type: {}\n", sampler_type(smp.type)); - cbl("Bind slot: {} => {}\n", sampler_bind_slot_name(prog.name, smp), smp.sokol_slot); + cbl("Bind slot: {} => {}\n", sampler_bind_slot_name(smp), smp.sokol_slot); cbl_close(); } - for (const ImageSampler& img_smp: prog.bindings.image_samplers) { + for (const ImageSampler& img_smp: gen.refl.bindings.image_samplers) { cbl_open("Image Sampler Pair '{}':\n", img_smp.name); cbl("Image: {}\n", img_smp.image_name); cbl("Sampler: {}\n", img_smp.sampler_name); @@ -148,19 +150,17 @@ void Generator::gen_vertex_attr_consts(const GenInput& gen) { } void Generator::gen_bind_slot_consts(const GenInput& gen) { - for (const ProgramReflection& prog: gen.refl.progs) { - for (const UniformBlock& ub: prog.bindings.uniform_blocks) { - l("{}\n", uniform_block_bind_slot_definition(prog.name, ub)); - } - for (const StorageBuffer& sbuf: prog.bindings.storage_buffers) { - l("{}\n", storage_buffer_bind_slot_definition(prog.name, sbuf)); - } - for (const Image& img: prog.bindings.images) { - l("{}\n", image_bind_slot_definition(prog.name, img)); - } - for (const Sampler& smp: prog.bindings.samplers) { - l("{}\n", sampler_bind_slot_definition(prog.name, smp)); - } + for (const UniformBlock& ub: gen.refl.bindings.uniform_blocks) { + l("{}\n", uniform_block_bind_slot_definition(ub)); + } + for (const StorageBuffer& sbuf: gen.refl.bindings.storage_buffers) { + l("{}\n", storage_buffer_bind_slot_definition(sbuf)); + } + for (const Image& img: gen.refl.bindings.images) { + l("{}\n", image_bind_slot_definition(img)); + } + for (const Sampler& smp: gen.refl.bindings.samplers) { + l("{}\n", sampler_bind_slot_definition(smp)); } } diff --git a/src/shdc/generators/generator.h b/src/shdc/generators/generator.h index 0e6c3d93..7995eac9 100644 --- a/src/shdc/generators/generator.h +++ b/src/shdc/generators/generator.h @@ -31,7 +31,7 @@ class Generator { // called by gen_header() virtual void gen_program_info(const GenInput& gen, const refl::ProgramReflection& prog); - virtual void gen_bindings_info(const GenInput& gen, const refl::ProgramReflection& prog); + virtual void gen_bindings_info(const GenInput& gen); // called by gen_uniform_block_decls() virtual void gen_uniform_block_decl(const GenInput& gen, const refl::UniformBlock& ub) { assert(false && "implement me"); }; @@ -77,16 +77,16 @@ class Generator { virtual std::string struct_name(const std::string& name) { assert(false && "implement me"); return ""; }; virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr) { assert(false && "implement me"); return ""; }; - virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img) { assert(false && "implement me"); return ""; }; - virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp) { assert(false && "implement me"); return ""; }; - virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub) { assert(false && "implement me"); return ""; }; - virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf) { assert(false && "implement me"); return ""; }; + virtual std::string image_bind_slot_name(const refl::Image& img) { assert(false && "implement me"); return ""; }; + virtual std::string sampler_bind_slot_name(const refl::Sampler& smp) { assert(false && "implement me"); return ""; }; + virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub) { assert(false && "implement me"); return ""; }; + virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf) { assert(false && "implement me"); return ""; }; virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr) { assert(false && "implement me"); return ""; }; - virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img) { assert(false && "implement me"); return ""; }; - virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp) { assert(false && "implement me"); return ""; }; - virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub) { assert(false && "implement me"); return ""; }; - virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf) { assert(false && "implement me"); return ""; }; + virtual std::string image_bind_slot_definition(const refl::Image& img) { assert(false && "implement me"); return ""; }; + virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp) { assert(false && "implement me"); return ""; }; + virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub) { assert(false && "implement me"); return ""; }; + virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf) { assert(false && "implement me"); return ""; }; struct ShaderStageArrayInfo { public: diff --git a/src/shdc/generators/sokolc.cc b/src/shdc/generators/sokolc.cc index 130c8778..29880955 100644 --- a/src/shdc/generators/sokolc.cc +++ b/src/shdc/generators/sokolc.cc @@ -684,40 +684,40 @@ std::string SokolCGenerator::vertex_attr_name(const std::string& prog_name, cons return fmt::format("ATTR_{}_{}", prog_name, attr.name); } -std::string SokolCGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { - return fmt::format("IMG_{}_{}", prog_name, img.name); +std::string SokolCGenerator::image_bind_slot_name(const Image& img) { + return fmt::format("IMG_{}", img.name); } -std::string SokolCGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { - return fmt::format("SMP_{}_{}", prog_name, smp.name); +std::string SokolCGenerator::sampler_bind_slot_name(const Sampler& smp) { + return fmt::format("SMP_{}", smp.name); } -std::string SokolCGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("UB_{}_{}", prog_name, ub.struct_info.name); +std::string SokolCGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { + return fmt::format("UB_{}", ub.struct_info.name); } -std::string SokolCGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name); +std::string SokolCGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { + return fmt::format("SBUF_{}", sbuf.struct_info.name); } std::string SokolCGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { return fmt::format("#define {} ({})", vertex_attr_name(prog_name, attr), attr.slot); } -std::string SokolCGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return fmt::format("#define {} ({})", image_bind_slot_name(prog_name, img), img.sokol_slot); +std::string SokolCGenerator::image_bind_slot_definition(const Image& img) { + return fmt::format("#define {} ({})", image_bind_slot_name(img), img.sokol_slot); } -std::string SokolCGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return fmt::format("#define {} ({})", sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); +std::string SokolCGenerator::sampler_bind_slot_definition(const Sampler& smp) { + return fmt::format("#define {} ({})", sampler_bind_slot_name(smp), smp.sokol_slot); } -std::string SokolCGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("#define {} ({})", uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); +std::string SokolCGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { + return fmt::format("#define {} ({})", uniform_block_bind_slot_name(ub), ub.sokol_slot); } -std::string SokolCGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("#define {} ({})", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.sokol_slot); +std::string SokolCGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { + return fmt::format("#define {} ({})", storage_buffer_bind_slot_name(sbuf), sbuf.sokol_slot); } } // namespace diff --git a/src/shdc/generators/sokolc.h b/src/shdc/generators/sokolc.h index 8ca29e13..d34944c0 100644 --- a/src/shdc/generators/sokolc.h +++ b/src/shdc/generators/sokolc.h @@ -42,15 +42,15 @@ class SokolCGenerator: public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const refl::Image& img); + virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); private: virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, int pad_to_size); }; diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index ee3c2c1a..7051b306 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -437,20 +437,20 @@ std::string SokolDGenerator::vertex_attr_name(const std::string& prog_name, cons return pystring::upper(fmt::format("ATTR_{}_{}", prog_name, attr.name)); } -std::string SokolDGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { - return pystring::upper(fmt::format("IMG_{}_{}", prog_name, img.name)); +std::string SokolDGenerator::image_bind_slot_name(const Image& img) { + return pystring::upper(fmt::format("IMG_{}", img.name)); } -std::string SokolDGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { - return pystring::upper(fmt::format("SMP_{}_{}", prog_name, smp.name)); +std::string SokolDGenerator::sampler_bind_slot_name(const Sampler& smp) { + return pystring::upper(fmt::format("SMP_{}", smp.name)); } -std::string SokolDGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { - return pystring::upper(fmt::format("UB_{}_{}", prog_name, ub.struct_info.name)); +std::string SokolDGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { + return pystring::upper(fmt::format("UB_{}", ub.struct_info.name)); } -std::string SokolDGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const StorageBuffer& sbuf) { - return pystring::upper(fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name)); +std::string SokolDGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { + return pystring::upper(fmt::format("SBUF_{}", sbuf.struct_info.name)); } static std::string const_def(const std::string& name, int slot) { @@ -461,20 +461,20 @@ std::string SokolDGenerator::vertex_attr_definition(const std::string& prog_name return const_def(vertex_attr_name(prog_name, attr), attr.slot); } -std::string SokolDGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return const_def(image_bind_slot_name(prog_name, img), img.sokol_slot); +std::string SokolDGenerator::image_bind_slot_definition(const Image& img) { + return const_def(image_bind_slot_name(img), img.sokol_slot); } -std::string SokolDGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return const_def(sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); +std::string SokolDGenerator::sampler_bind_slot_definition(const Sampler& smp) { + return const_def(sampler_bind_slot_name(smp), smp.sokol_slot); } -std::string SokolDGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return const_def(uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); +std::string SokolDGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { + return const_def(uniform_block_bind_slot_name(ub), ub.sokol_slot); } -std::string SokolDGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { - return const_def(storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.sokol_slot); +std::string SokolDGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { + return const_def(storage_buffer_bind_slot_name(sbuf), sbuf.sokol_slot); } } // namespace diff --git a/src/shdc/generators/sokold.h b/src/shdc/generators/sokold.h index 8a194a48..400e5a73 100644 --- a/src/shdc/generators/sokold.h +++ b/src/shdc/generators/sokold.h @@ -28,15 +28,15 @@ class SokolDGenerator : public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const refl::Image& img); + virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); private: virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, int alignment, int pad_to_size); }; diff --git a/src/shdc/generators/sokoljai.cc b/src/shdc/generators/sokoljai.cc index 2fb3180b..c741cf0e 100644 --- a/src/shdc/generators/sokoljai.cc +++ b/src/shdc/generators/sokoljai.cc @@ -427,40 +427,40 @@ std::string SokolJaiGenerator::vertex_attr_name(const std::string& prog_name, co return fmt::format("ATTR_{}_{}", prog_name, attr.name); } -std::string SokolJaiGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { - return fmt::format("IMG_{}_{}", prog_name, img.name); +std::string SokolJaiGenerator::image_bind_slot_name(const Image& img) { + return fmt::format("IMG_{}", img.name); } -std::string SokolJaiGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { - return fmt::format("SMP_{}_{}", prog_name, smp.name); +std::string SokolJaiGenerator::sampler_bind_slot_name(const Sampler& smp) { + return fmt::format("SMP_{}", smp.name); } -std::string SokolJaiGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("UB_{}_{}", prog_name, ub.struct_info.name); +std::string SokolJaiGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { + return fmt::format("UB_{}", ub.struct_info.name); } -std::string SokolJaiGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name); +std::string SokolJaiGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { + return fmt::format("SBUF_{}", sbuf.struct_info.name); } std::string SokolJaiGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { return fmt::format("{} :: {};", vertex_attr_name(prog_name, attr), attr.slot); } -std::string SokolJaiGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return fmt::format("{} :: {};", image_bind_slot_name(prog_name, img), img.sokol_slot); +std::string SokolJaiGenerator::image_bind_slot_definition(const Image& img) { + return fmt::format("{} :: {};", image_bind_slot_name(img), img.sokol_slot); } -std::string SokolJaiGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return fmt::format("{} :: {};", sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); +std::string SokolJaiGenerator::sampler_bind_slot_definition(const Sampler& smp) { + return fmt::format("{} :: {};", sampler_bind_slot_name(smp), smp.sokol_slot); } -std::string SokolJaiGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("{} :: {};", uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); +std::string SokolJaiGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { + return fmt::format("{} :: {};", uniform_block_bind_slot_name(ub), ub.sokol_slot); } -std::string SokolJaiGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("{} :: {};", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.sokol_slot); +std::string SokolJaiGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { + return fmt::format("{} :: {};", storage_buffer_bind_slot_name(sbuf), sbuf.sokol_slot); } } // namespace diff --git a/src/shdc/generators/sokoljai.h b/src/shdc/generators/sokoljai.h index b41ff092..5f5736f8 100644 --- a/src/shdc/generators/sokoljai.h +++ b/src/shdc/generators/sokoljai.h @@ -28,15 +28,15 @@ class SokolJaiGenerator: public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const refl::Image& img); + virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); private: virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, int pad_to_size); }; diff --git a/src/shdc/generators/sokolnim.cc b/src/shdc/generators/sokolnim.cc index a51356be..8a188c63 100644 --- a/src/shdc/generators/sokolnim.cc +++ b/src/shdc/generators/sokolnim.cc @@ -510,40 +510,40 @@ std::string SokolNimGenerator::vertex_attr_name(const std::string& prog_name, co return to_camel_case(fmt::format("ATTR_{}_{}", prog_name, attr.name)); } -std::string SokolNimGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { - return to_camel_case(fmt::format("IMG_{}_{}", prog_name, img.name)); +std::string SokolNimGenerator::image_bind_slot_name(const Image& img) { + return to_camel_case(fmt::format("IMG_{}", img.name)); } -std::string SokolNimGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { - return to_camel_case(fmt::format("SMP_{}_{}", prog_name, smp.name)); +std::string SokolNimGenerator::sampler_bind_slot_name(const Sampler& smp) { + return to_camel_case(fmt::format("SMP_{}", smp.name)); } -std::string SokolNimGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { - return to_camel_case(fmt::format("UB_{}_{}", prog_name, ub.struct_info.name)); +std::string SokolNimGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { + return to_camel_case(fmt::format("UB_{}", ub.struct_info.name)); } -std::string SokolNimGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const StorageBuffer& sbuf) { - return to_camel_case(fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name)); +std::string SokolNimGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { + return to_camel_case(fmt::format("SBUF_{}", sbuf.struct_info.name)); } std::string SokolNimGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { return fmt::format("const {}* = {}", vertex_attr_name(prog_name, attr), attr.slot); } -std::string SokolNimGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return fmt::format("const {}* = {}", image_bind_slot_name(prog_name, img), img.sokol_slot); +std::string SokolNimGenerator::image_bind_slot_definition(const Image& img) { + return fmt::format("const {}* = {}", image_bind_slot_name(img), img.sokol_slot); } -std::string SokolNimGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return fmt::format("const {}* = {}", sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); +std::string SokolNimGenerator::sampler_bind_slot_definition(const Sampler& smp) { + return fmt::format("const {}* = {}", sampler_bind_slot_name(smp), smp.sokol_slot); } -std::string SokolNimGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("const {}* = {}", uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); +std::string SokolNimGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { + return fmt::format("const {}* = {}", uniform_block_bind_slot_name(ub), ub.sokol_slot); } -std::string SokolNimGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("const {}* = {}", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.sokol_slot); +std::string SokolNimGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { + return fmt::format("const {}* = {}", storage_buffer_bind_slot_name(sbuf), sbuf.sokol_slot); } } // namespace diff --git a/src/shdc/generators/sokolnim.h b/src/shdc/generators/sokolnim.h index 874c02a7..db3ece29 100644 --- a/src/shdc/generators/sokolnim.h +++ b/src/shdc/generators/sokolnim.h @@ -30,15 +30,15 @@ class SokolNimGenerator: public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const refl::Image& img); + virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); private: virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, const std::string& name, int alignment, int pad_to_size); virtual void recurse_unfold_structs(const GenInput& gen, const refl::Type& struc, const std::string& name, int alignment, int pad_to_size); diff --git a/src/shdc/generators/sokolodin.cc b/src/shdc/generators/sokolodin.cc index a0518a35..019e6476 100644 --- a/src/shdc/generators/sokolodin.cc +++ b/src/shdc/generators/sokolodin.cc @@ -430,40 +430,40 @@ std::string SokolOdinGenerator::vertex_attr_name(const std::string& prog_name, c return fmt::format("ATTR_{}_{}", prog_name, attr.name); } -std::string SokolOdinGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { - return fmt::format("IMG_{}_{}", prog_name, img.name); +std::string SokolOdinGenerator::image_bind_slot_name(const Image& img) { + return fmt::format("IMG_{}", img.name); } -std::string SokolOdinGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { - return fmt::format("SMP_{}_{}", prog_name, smp.name); +std::string SokolOdinGenerator::sampler_bind_slot_name(const Sampler& smp) { + return fmt::format("SMP_{}", smp.name); } -std::string SokolOdinGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("UB_{}_{}", prog_name, ub.struct_info.name); +std::string SokolOdinGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { + return fmt::format("UB_{}", ub.struct_info.name); } -std::string SokolOdinGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name); +std::string SokolOdinGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { + return fmt::format("SBUF_{}", sbuf.struct_info.name); } std::string SokolOdinGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { return fmt::format("{} :: {}", vertex_attr_name(prog_name, attr), attr.slot); } -std::string SokolOdinGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return fmt::format("{} :: {}", image_bind_slot_name(prog_name, img), img.sokol_slot); +std::string SokolOdinGenerator::image_bind_slot_definition(const Image& img) { + return fmt::format("{} :: {}", image_bind_slot_name(img), img.sokol_slot); } -std::string SokolOdinGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return fmt::format("{} :: {}", sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); +std::string SokolOdinGenerator::sampler_bind_slot_definition(const Sampler& smp) { + return fmt::format("{} :: {}", sampler_bind_slot_name(smp), smp.sokol_slot); } -std::string SokolOdinGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("{} :: {}", uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); +std::string SokolOdinGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { + return fmt::format("{} :: {}", uniform_block_bind_slot_name(ub), ub.sokol_slot); } -std::string SokolOdinGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("{} :: {}", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.sokol_slot); +std::string SokolOdinGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { + return fmt::format("{} :: {}", storage_buffer_bind_slot_name(sbuf), sbuf.sokol_slot); } } // namespace diff --git a/src/shdc/generators/sokolodin.h b/src/shdc/generators/sokolodin.h index b9fa9a94..e44687a6 100644 --- a/src/shdc/generators/sokolodin.h +++ b/src/shdc/generators/sokolodin.h @@ -28,15 +28,15 @@ class SokolOdinGenerator: public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const refl::Image& img); + virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); private: virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, int pad_to_size); }; diff --git a/src/shdc/generators/sokolrust.cc b/src/shdc/generators/sokolrust.cc index 4c6236d8..04c1ffca 100644 --- a/src/shdc/generators/sokolrust.cc +++ b/src/shdc/generators/sokolrust.cc @@ -444,40 +444,40 @@ std::string SokolRustGenerator::vertex_attr_name(const std::string& prog_name, c return pystring::upper(fmt::format("ATTR_{}_{}", prog_name, attr.name)); } -std::string SokolRustGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { - return pystring::upper(fmt::format("IMG_{}_{}", prog_name, img.name)); +std::string SokolRustGenerator::image_bind_slot_name(const Image& img) { + return pystring::upper(fmt::format("IMG_{}", img.name)); } -std::string SokolRustGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { - return pystring::upper(fmt::format("SMP_{}_{}", prog_name, smp.name)); +std::string SokolRustGenerator::sampler_bind_slot_name(const Sampler& smp) { + return pystring::upper(fmt::format("SMP_{}", smp.name)); } -std::string SokolRustGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { - return pystring::upper(fmt::format("UB_{}_{}", prog_name, ub.struct_info.name)); +std::string SokolRustGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { + return pystring::upper(fmt::format("UB_{}", ub.struct_info.name)); } -std::string SokolRustGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const StorageBuffer& sbuf) { - return pystring::upper(fmt::format("SBUF_{}_{}", prog_name, sbuf.struct_info.name)); +std::string SokolRustGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { + return pystring::upper(fmt::format("SBUF_{}", sbuf.struct_info.name)); } std::string SokolRustGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { return fmt::format("pub const {}: usize = {};", vertex_attr_name(prog_name, attr), attr.slot); } -std::string SokolRustGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return fmt::format("pub const {}: usize = {};", image_bind_slot_name(prog_name, img), img.sokol_slot); +std::string SokolRustGenerator::image_bind_slot_definition(const Image& img) { + return fmt::format("pub const {}: usize = {};", image_bind_slot_name(img), img.sokol_slot); } -std::string SokolRustGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return fmt::format("pub const {}: usize = {};", sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); +std::string SokolRustGenerator::sampler_bind_slot_definition(const Sampler& smp) { + return fmt::format("pub const {}: usize = {};", sampler_bind_slot_name(smp), smp.sokol_slot); } -std::string SokolRustGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("pub const {}: usize = {};", uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); +std::string SokolRustGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { + return fmt::format("pub const {}: usize = {};", uniform_block_bind_slot_name(ub), ub.sokol_slot); } -std::string SokolRustGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sbuf) { - return fmt::format("pub const {}: usize = {};", storage_buffer_bind_slot_name(prog_name, sbuf), sbuf.sokol_slot); +std::string SokolRustGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { + return fmt::format("pub const {}: usize = {};", storage_buffer_bind_slot_name(sbuf), sbuf.sokol_slot); } } // namespace diff --git a/src/shdc/generators/sokolrust.h b/src/shdc/generators/sokolrust.h index 6c79dba2..cde29685 100644 --- a/src/shdc/generators/sokolrust.h +++ b/src/shdc/generators/sokolrust.h @@ -28,15 +28,15 @@ class SokolRustGenerator: public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const refl::Image& img); + virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); private: void recurse_unfold_structs(const GenInput& gen, const refl::Type& struc, const std::string& name, int alignment, int pad_to_size); virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, const std::string& name, int pad_to_size); diff --git a/src/shdc/generators/sokolzig.cc b/src/shdc/generators/sokolzig.cc index 8864be3f..3825b3d7 100644 --- a/src/shdc/generators/sokolzig.cc +++ b/src/shdc/generators/sokolzig.cc @@ -442,40 +442,40 @@ std::string SokolZigGenerator::vertex_attr_name(const std::string& prog_name, co return fmt::format("ATTR_{}_{}", prog_name, attr.name); } -std::string SokolZigGenerator::image_bind_slot_name(const std::string& prog_name, const Image& img) { - return fmt::format("IMG_{}_{}", prog_name, img.name); +std::string SokolZigGenerator::image_bind_slot_name(const Image& img) { + return fmt::format("IMG_{}", img.name); } -std::string SokolZigGenerator::sampler_bind_slot_name(const std::string& prog_name, const Sampler& smp) { - return fmt::format("SMP_{}_{}", prog_name, smp.name); +std::string SokolZigGenerator::sampler_bind_slot_name(const Sampler& smp) { + return fmt::format("SMP_{}", smp.name); } -std::string SokolZigGenerator::uniform_block_bind_slot_name(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("UB_{}_{}", prog_name, ub.struct_info.name); +std::string SokolZigGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { + return fmt::format("UB_{}", ub.struct_info.name); } -std::string SokolZigGenerator::storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sb) { - return fmt::format("SBUF_{}_{}", prog_name, sb.struct_info.name); +std::string SokolZigGenerator::storage_buffer_bind_slot_name(const refl::StorageBuffer& sb) { + return fmt::format("SBUF_{}", sb.struct_info.name); } std::string SokolZigGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { return fmt::format("pub const {} = {};", vertex_attr_name(prog_name, attr), attr.slot); } -std::string SokolZigGenerator::image_bind_slot_definition(const std::string& prog_name, const Image& img) { - return fmt::format("pub const {} = {};", image_bind_slot_name(prog_name, img), img.sokol_slot); +std::string SokolZigGenerator::image_bind_slot_definition(const Image& img) { + return fmt::format("pub const {} = {};", image_bind_slot_name(img), img.sokol_slot); } -std::string SokolZigGenerator::sampler_bind_slot_definition(const std::string& prog_name, const Sampler& smp) { - return fmt::format("pub const {} = {};", sampler_bind_slot_name(prog_name, smp), smp.sokol_slot); +std::string SokolZigGenerator::sampler_bind_slot_definition(const Sampler& smp) { + return fmt::format("pub const {} = {};", sampler_bind_slot_name(smp), smp.sokol_slot); } -std::string SokolZigGenerator::uniform_block_bind_slot_definition(const std::string& prog_name, const UniformBlock& ub) { - return fmt::format("pub const {} = {};", uniform_block_bind_slot_name(prog_name, ub), ub.sokol_slot); +std::string SokolZigGenerator::uniform_block_bind_slot_definition(const UniformBlock& ub) { + return fmt::format("pub const {} = {};", uniform_block_bind_slot_name(ub), ub.sokol_slot); } -std::string SokolZigGenerator::storage_buffer_bind_slot_definition(const std::string& prog_name, const StorageBuffer& sb) { - return fmt::format("pub const {} = {};", storage_buffer_bind_slot_name(prog_name, sb), sb.sokol_slot); +std::string SokolZigGenerator::storage_buffer_bind_slot_definition(const StorageBuffer& sb) { + return fmt::format("pub const {} = {};", storage_buffer_bind_slot_name(sb), sb.sokol_slot); } void SokolZigGenerator::gen_attr_slot_refl_func(const GenInput& gen, const ProgramReflection& prog) { diff --git a/src/shdc/generators/sokolzig.h b/src/shdc/generators/sokolzig.h index 0788b878..8cbc1936 100644 --- a/src/shdc/generators/sokolzig.h +++ b/src/shdc/generators/sokolzig.h @@ -36,15 +36,15 @@ class SokolZigGenerator: public Generator { virtual std::string backend(Slang::Enum e); virtual std::string struct_name(const std::string& name); virtual std::string vertex_attr_name(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_name(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_name(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_name(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_name(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_name(const refl::Image& img); + virtual std::string sampler_bind_slot_name(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_name(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_name(const refl::StorageBuffer& sbuf); virtual std::string vertex_attr_definition(const std::string& prog_name, const refl::StageAttr& attr); - virtual std::string image_bind_slot_definition(const std::string& prog_name, const refl::Image& img); - virtual std::string sampler_bind_slot_definition(const std::string& prog_name, const refl::Sampler& smp); - virtual std::string uniform_block_bind_slot_definition(const std::string& prog_name, const refl::UniformBlock& ub); - virtual std::string storage_buffer_bind_slot_definition(const std::string& prog_name, const refl::StorageBuffer& sbuf); + virtual std::string image_bind_slot_definition(const refl::Image& img); + virtual std::string sampler_bind_slot_definition(const refl::Sampler& smp); + virtual std::string uniform_block_bind_slot_definition(const refl::UniformBlock& ub); + virtual std::string storage_buffer_bind_slot_definition(const refl::StorageBuffer& sbuf); private: virtual void gen_struct_interior_decl_std430(const GenInput& gen, const refl::Type& struc, int alignment, int pad_to_size); }; diff --git a/src/shdc/input.cc b/src/shdc/input.cc index 774fcddc..0a23eb0c 100644 --- a/src/shdc/input.cc +++ b/src/shdc/input.cc @@ -3,6 +3,7 @@ */ #include "input.h" #include "types/reflection/type.h" +#include "types/reflection/bindings.h" #include "types/option.h" #include #include @@ -14,6 +15,49 @@ namespace shdc { using namespace refl; +static int find_slot(const std::map& map, const std::string& key) { + auto it = map.find(key); + if (it != map.end()) { + return map.at(key); + } else { + return -1; + } +} + +int Input::find_ub_slot(const std::string& name) const { + return find_slot(ub_slots, name); +} + +int Input::find_img_slot(const std::string& name) const { + return find_slot(img_slots, name); +} + +int Input::find_smp_slot(const std::string& name) const { + return find_slot(smp_slots, name); +} + +int Input::find_sbuf_slot(const std::string& name) const { + return find_slot(sbuf_slots, name); +} + +const ImageSampleTypeTag* Input::find_image_sample_type_tag(const std::string& tex_name) const { + auto it = image_sample_type_tags.find(tex_name); + if (it != image_sample_type_tags.end()) { + return &image_sample_type_tags.at(tex_name); + } else { + return nullptr; + } +} + +inline const SamplerTypeTag* Input::find_sampler_type_tag(const std::string& smp_name) const { + auto it = sampler_type_tags.find(smp_name); + if (it != sampler_type_tags.end()) { + return &sampler_type_tags.at(smp_name); + } else { + return nullptr; + } +} + static std::string load_file_into_str(const std::string& path) { FILE* f = fopen(path.c_str(), "rb"); if (!f) { @@ -307,16 +351,12 @@ static bool validate_options_tag(const std::vector& tokens, const S return true; } -static bool validate_image_sample_type_tag(const std::vector& tokens, const Snippet& cur_snippet, int line_index, Input& inp) { - if (tokens.size() < 3) { - inp.out_error = inp.error(line_index, fmt::format("@image_sample_type must have at least 2 arg (@image_sample_type [texture] {})", ImageSampleType::valid_image_sample_types_as_str())); - return false; - } - if ((cur_snippet.type != Snippet::VS) && (cur_snippet.type != Snippet::FS)) { - inp.out_error = inp.error(line_index, "@image_sample_type tag must be inside a @vs or @fs block"); +static bool validate_image_sample_type_tag(const std::vector& tokens, int line_index, Input& inp) { + if (tokens.size() != 3) { + inp.out_error = inp.error(line_index, fmt::format("@image_sample_type must have 2 args (@image_sample_type [texture] {})", ImageSampleType::valid_image_sample_types_as_str())); return false; } - if (nullptr != cur_snippet.lookup_image_sample_type_tag(tokens[1])) { + if (nullptr != inp.find_image_sample_type_tag(tokens[1])) { inp.out_error = inp.error(line_index, "duplicate @image_sample_type (texture name must be unique)"); return false; } @@ -327,16 +367,12 @@ static bool validate_image_sample_type_tag(const std::vector& token return true; } -static bool validate_sampler_type_tag(const std::vector& tokens, const Snippet& cur_snippet, int line_index, Input& inp) { - if (tokens.size() < 3) { - inp.out_error = inp.error(line_index, fmt::format("@sampler_type must have at least 2 arg (@sampler_type [sampler] {})", SamplerType::valid_sampler_types_as_str())); - return false; - } - if ((cur_snippet.type != Snippet::VS) && (cur_snippet.type != Snippet::FS)) { - inp.out_error = inp.error(line_index, "@sampler_type tag must be inside a @vs or @fs block"); +static bool validate_sampler_type_tag(const std::vector& tokens, int line_index, Input& inp) { + if (tokens.size() != 3) { + inp.out_error = inp.error(line_index, fmt::format("@sampler_type must have 2 args (@sampler_type [sampler] {})", SamplerType::valid_sampler_types_as_str())); return false; } - if (nullptr != cur_snippet.lookup_sampler_type_tag(tokens[1])) { + if (nullptr != inp.find_sampler_type_tag(tokens[1])) { inp.out_error = inp.error(line_index, "duplicate @sampler_type (sampler name must be unique)"); return false; } @@ -345,7 +381,6 @@ static bool validate_sampler_type_tag(const std::vector& tokens, co return false; } return true; - } /* This parses the split input line array for custom tags (@vs, @fs, @block, @@ -475,16 +510,16 @@ static bool parse(Input& inp) { inp.programs[tokens[1]] = Program(tokens[1], tokens[2], tokens[3], line_index); add_line = false; } else if (tokens[0] == image_sample_type_tag) { - if (!validate_image_sample_type_tag(tokens, cur_snippet, line_index, inp)) { + if (!validate_image_sample_type_tag(tokens, line_index, inp)) { return false; } - cur_snippet.image_sample_type_tags[tokens[1]] = ImageSampleTypeTag(tokens[1], ImageSampleType::from_str(tokens[2]), line_index); + inp.image_sample_type_tags[tokens[1]] = ImageSampleTypeTag(tokens[1], ImageSampleType::from_str(tokens[2]), line_index); add_line = false; } else if (tokens[0] == sampler_type_tag) { - if (!validate_sampler_type_tag(tokens, cur_snippet, line_index, inp)) { + if (!validate_sampler_type_tag(tokens, line_index, inp)) { return false; } - cur_snippet.sampler_type_tags[tokens[1]] = SamplerTypeTag(tokens[1], SamplerType::from_str(tokens[2]), line_index); + inp.sampler_type_tags[tokens[1]] = SamplerTypeTag(tokens[1], SamplerType::from_str(tokens[2]), line_index); add_line = false; } else if (tokens[0][0] == '@') { inp.out_error = inp.error(line_index, fmt::format("unknown meta tag: {}", tokens[0])); @@ -657,14 +692,6 @@ void Input::dump_debug(ErrMsg::Format err_fmt) const { fmt::print(stderr, " snippet {}:\n", snippet_nr++); fmt::print(stderr, " name: {}\n", snippet.name); fmt::print(stderr, " type: {}\n", Snippet::type_to_str(snippet.type)); - fmt::print(stderr, " image sample type tags:\n"); - for (const auto& [key, val]: snippet.image_sample_type_tags) { - fmt::print(stderr, " {}: {} (line: {})\n", key, ImageSampleType::to_str(val.type), val.line_index); - } - fmt::print(stderr, " sampler type tags:\n"); - for (const auto& [key, val]: snippet.sampler_type_tags) { - fmt::print(stderr, " {}: {} (line: {})\n", key, SamplerType::to_str(val.type), val.line_index); - } fmt::print(stderr, " lines:\n"); int line_nr = 1; for (int line_index : snippet.lines) { @@ -698,6 +725,14 @@ void Input::dump_debug(ErrMsg::Format err_fmt) const { fmt::print(stderr, " fs: {}\n", prog.fs_name); fmt::print(stderr, " line_index: {}\n", prog.line_index); } + fmt::print(stderr, " image sample type tags:\n"); + for (const auto& [key, val]: image_sample_type_tags) { + fmt::print(stderr, " {}: {} (line: {})\n", key, ImageSampleType::to_str(val.type), val.line_index); + } + fmt::print(stderr, " sampler type tags:\n"); + for (const auto& [key, val]: sampler_type_tags) { + fmt::print(stderr, " {}: {} (line: {})\n", key, SamplerType::to_str(val.type), val.line_index); + } fmt::print("\n"); } diff --git a/src/shdc/input.h b/src/shdc/input.h index 51272394..946c7f65 100644 --- a/src/shdc/input.h +++ b/src/shdc/input.h @@ -24,11 +24,25 @@ struct Input { std::map vs_map; // name-index mapping for @vs snippets std::map fs_map; // name-index mapping for @fs snippets std::map programs; // all @program definitions + std::map ub_slots; // uniform block bindslot definitions + std::map img_slots; // image bindslot definitions + std::map smp_slots; // sampler bindslot definitions + std::map sbuf_slots; // storagebuffer bindslot definitions + std::map image_sample_type_tags; + std::map sampler_type_tags; static Input load_and_parse(const std::string& path, const std::string& module_override); ErrMsg error(int line_index, const std::string& msg) const; ErrMsg warning(int line_index, const std::string& msg) const; void dump_debug(ErrMsg::Format err_fmt) const; + // return -1 if not found + int find_ub_slot(const std::string& name) const; + int find_img_slot(const std::string& name) const; + int find_smp_slot(const std::string& name) const; + int find_sbuf_slot(const std::string& name) const; + // return nullptr if not found + const ImageSampleTypeTag* find_image_sample_type_tag(const std::string& tex_name) const; + const SamplerTypeTag* find_sampler_type_tag(const std::string& smp_name) const; }; } // namespace shdc diff --git a/src/shdc/main.cc b/src/shdc/main.cc index 7fa630d6..a813069e 100644 --- a/src/shdc/main.cc +++ b/src/shdc/main.cc @@ -26,7 +26,7 @@ int main(int argc, const char** argv) { } // load the source and parse tagged blocks - const Input inp = Input::load_and_parse(args.input, args.module); + Input inp = Input::load_and_parse(args.input, args.module); if (args.debug_dump) { inp.dump_debug(args.error_format); } @@ -41,7 +41,7 @@ int main(int argc, const char** argv) { for (int i = 0; i < Slang::Num; i++) { Slang::Enum slang = Slang::from_index(i); if (args.slang & Slang::bit(slang)) { - spirv[i] = Spirv::compile_glsl(inp, slang, args.defines); + spirv[i] = Spirv::compile_glsl_and_extract_bindings(inp, slang, args.defines); if (args.debug_dump) { spirv[i].dump_debug(inp, args.error_format); } diff --git a/src/shdc/reflection.cc b/src/shdc/reflection.cc index b204a22f..bd48dc2c 100644 --- a/src/shdc/reflection.cc +++ b/src/shdc/reflection.cc @@ -112,7 +112,6 @@ Reflection Reflection::build(const Args& args, const Input& inp, const std::arra } // create a merged set of resource bindings across all programs - // NOTE: these are only used to de-duplicate struct declarations for (const auto& prog_refl: res.progs) { prog_bindings.push_back(prog_refl.bindings); } @@ -194,7 +193,7 @@ Type get_type_for_attribute(const Compiler& compiler, const Resource& res_attr) return out; } -StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, const Snippet& snippet, ErrMsg& out_error) { +StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, const Snippet& snippet, const Input& inp, ErrMsg& out_error) { out_error = ErrMsg(); StageReflection refl; @@ -245,14 +244,13 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c const Bindings::Type res_type = Bindings::Type::UNIFORM_BLOCK; UniformBlock refl_ub; refl_ub.stage = refl.stage; - refl_ub.sokol_slot = slot; - refl_ub.hlsl_register_b_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); - refl_ub.msl_buffer_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); - refl_ub.wgsl_group0_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); refl_ub.inst_name = compiler.get_name(ub_res.id); if (refl_ub.inst_name.empty()) { refl_ub.inst_name = compiler.get_fallback_name(ub_res.id); } + refl_ub.hlsl_register_b_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); + refl_ub.msl_buffer_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); + refl_ub.wgsl_group0_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); refl_ub.flattened = Spirvcross::can_flatten_uniform_block(compiler, ub_res); refl_ub.struct_info = parse_toplevel_struct(compiler, ub_res, out_error); if (out_error.valid()) { @@ -260,6 +258,11 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c } // uniform blocks always have 16 byte alignment refl_ub.struct_info.align = 16; + refl_ub.sokol_slot = inp.find_ub_slot(refl_ub.struct_info.name); + if (refl_ub.sokol_slot == -1) { + out_error = inp.error(0, fmt::format("no @bindslot definition found for uniformblock '{}'\n", refl_ub.struct_info.name)); + return refl; + } refl.bindings.uniform_blocks.push_back(refl_ub); } // storage buffers @@ -268,7 +271,6 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c const Bindings::Type res_type = Bindings::Type::STORAGE_BUFFER; StorageBuffer refl_sbuf; refl_sbuf.stage = refl.stage; - refl_sbuf.sokol_slot = slot; refl_sbuf.hlsl_register_t_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); refl_sbuf.msl_buffer_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); refl_sbuf.wgsl_group1_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); @@ -282,6 +284,11 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c if (out_error.valid()) { return refl; } + refl_sbuf.sokol_slot = inp.find_sbuf_slot(refl_sbuf.struct_info.name); + if (refl_sbuf.sokol_slot == -1) { + out_error = inp.error(0, fmt::format("no @bindslot definition found for storagebuffer '{}'\n", refl_sbuf.struct_info.name)); + return refl; + } refl.bindings.storage_buffers.push_back(refl_sbuf); } @@ -291,7 +298,6 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c const Bindings::Type res_type = Bindings::Type::IMAGE; Image refl_img; refl_img.stage = refl.stage; - refl_img.sokol_slot = slot; refl_img.hlsl_register_t_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); refl_img.msl_texture_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); refl_img.wgsl_group1_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); @@ -304,6 +310,11 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c refl_img.sample_type = spirtype_to_image_sample_type(compiler.get_type(img_type.image.type)); } refl_img.multisampled = spirtype_to_image_multisampled(img_type); + refl_img.sokol_slot = inp.find_img_slot(refl_img.name); + if (refl_img.sokol_slot == -1) { + out_error = inp.error(0, fmt::format("no @bindslot definition found for image '{}'\n", refl_img.name)); + return refl; + } refl.bindings.images.push_back(refl_img); } // (separate) samplers @@ -313,7 +324,6 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c const SPIRType& smp_type = compiler.get_type(smp_res.type_id); Sampler refl_smp; refl_smp.stage = refl.stage; - refl_smp.sokol_slot = slot; refl_smp.hlsl_register_s_n = slot + Bindings::base_slot(Slang::HLSL5, refl.stage, res_type); refl_smp.msl_sampler_n = slot + Bindings::base_slot(Slang::METAL_SIM, refl.stage, res_type); refl_smp.wgsl_group1_binding_n = slot + Bindings::base_slot(Slang::WGSL, refl.stage, res_type); @@ -324,6 +334,11 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c } else { refl_smp.type = SamplerType::FILTERING; } + refl_smp.sokol_slot = inp.find_smp_slot(refl_smp.name); + if (refl_smp.sokol_slot == -1) { + out_error = inp.error(0, fmt::format("no @bindslot definition found for sampler '{}'\n", refl_smp.name)); + return refl; + } refl.bindings.samplers.push_back(refl_smp); } // combined image samplers @@ -338,14 +353,14 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c } // patch textures with overridden image-sample-types for (auto& img: refl.bindings.images) { - const auto* tag = snippet.lookup_image_sample_type_tag(img.name); + const auto* tag = inp.find_image_sample_type_tag(img.name); if (tag) { img.sample_type = tag->type; } } // patch samplers with overridden sampler-types for (auto& smp: refl.bindings.samplers) { - const auto* tag = snippet.lookup_sampler_type_tag(smp.name); + const auto* tag = inp.find_sampler_type_tag(smp.name); if (tag) { smp.type = tag->type; } @@ -369,7 +384,6 @@ Bindings Reflection::merge_bindings(const std::vector& in_bindings, Er } } else { out_bindings.uniform_blocks.push_back(ub); - out_bindings.uniform_blocks.back().sokol_slot = (int)out_bindings.uniform_blocks.size() - 1; } } @@ -384,7 +398,6 @@ Bindings Reflection::merge_bindings(const std::vector& in_bindings, Er } } else { out_bindings.storage_buffers.push_back(sbuf); - out_bindings.storage_buffers.back().sokol_slot = (int)out_bindings.storage_buffers.size() - 1; } } @@ -399,7 +412,6 @@ Bindings Reflection::merge_bindings(const std::vector& in_bindings, Er } } else { out_bindings.images.push_back(img); - out_bindings.images.back().sokol_slot = (int)out_bindings.images.size() - 1; } } @@ -414,7 +426,6 @@ Bindings Reflection::merge_bindings(const std::vector& in_bindings, Er } } else { out_bindings.samplers.push_back(smp); - out_bindings.samplers.back().sokol_slot = (int)out_bindings.samplers.size() - 1; } } @@ -429,7 +440,6 @@ Bindings Reflection::merge_bindings(const std::vector& in_bindings, Er } } else { out_bindings.image_samplers.push_back(img_smp); - out_bindings.image_samplers.back().sokol_slot = (int)out_bindings.image_samplers.size() - 1; } } } diff --git a/src/shdc/reflection.h b/src/shdc/reflection.h index a0c891b5..85a06c05 100644 --- a/src/shdc/reflection.h +++ b/src/shdc/reflection.h @@ -22,7 +22,7 @@ struct Reflection { // build merged reflection object from per-slang / per-snippet reflections, error will be in .error static Reflection build(const Args& args, const Input& inp, const std::array& spirvcross); // parse per-snippet reflection info for a compiled shader source - static StageReflection parse_snippet_reflection(const spirv_cross::Compiler& compiler, const Snippet& snippet, ErrMsg& out_error); + static StageReflection parse_snippet_reflection(const spirv_cross::Compiler& compiler, const Snippet& snippet, const Input& inp, ErrMsg& out_error); // print a debug dump to stderr void dump_debug(ErrMsg::Format err_fmt) const; diff --git a/src/shdc/spirv.cc b/src/shdc/spirv.cc index c09dd701..3976b51b 100644 --- a/src/shdc/spirv.cc +++ b/src/shdc/spirv.cc @@ -183,7 +183,7 @@ static void spirv_optimize(Slang::Enum slang, std::vector& spirv) { } /* compile a vertex or fragment shader to SPIRV */ -static bool compile(EShLanguage stage, Slang::Enum slang, const MergedSource& source, const Input& inp, int snippet_index, Spirv& out_spirv) { +static bool compile(Input& inp, EShLanguage stage, Slang::Enum slang, const MergedSource& source, int snippet_index, Spirv& out_spirv) { const char* sources[1] = { source.src.c_str() }; const int sourcesLen[1] = { (int) source.src.length() }; const char* sourcesNames[1] = { inp.base_path.c_str() }; @@ -198,11 +198,7 @@ static bool compile(EShLanguage stage, Slang::Enum slang, const MergedSource& so shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100); shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0); shader.setEnvTarget(glslang::EshTargetSpv, glslang::EShTargetSpv_1_0); - // NOTE: where using AutoMapBinding here, but this will just throw all bindings - // into descriptor set null, which is not what we actually want. - // We'll fix up the bindings later before calling SPIRVCross. shader.setAutoMapLocations(true); - shader.setAutoMapBindings(true); bool parse_success = shader.parse(GetDefaultResources(), 100, false, EShMsgDefault); infolog_to_errors(shader.getInfoLog(), inp, snippet_index, linenr_offset, out_spirv.errors); infolog_to_errors(shader.getInfoDebugLog(), inp, snippet_index, linenr_offset, out_spirv.errors); @@ -226,6 +222,58 @@ static bool compile(EShLanguage stage, Slang::Enum slang, const MergedSource& so return false; } + // extract binding information into Input + bool refl_res = program.buildReflection(EShReflectionSeparateBuffers); + if (!refl_res) { + out_spirv.errors.push_back(inp.error(0, "program.buildReflection() failed!")); + } + for (int i = 0; i < program.getNumUniformBlocks(); i++) { + const auto& ub = program.getUniformBlock(i); + const std::string& name = ub.name; + const int slot = inp.find_ub_slot(name); + const int binding = ub.getBinding(); + if (slot == -1) { + inp.ub_slots[name] = binding; + } else if (slot != binding) { + out_spirv.errors.push_back(inp.error(0, fmt::format("binding collision for uniform block '{}' ({} vs {})", name, slot, binding))); + return false; + } + } + for (int i = 0; i < program.getNumBufferBlocks(); i++) { + const auto& sbuf = program.getBufferBlock(i); + const std::string& name = sbuf.name; + const int slot = inp.find_sbuf_slot(name); + const int binding = sbuf.getBinding(); + if (slot == -1) { + inp.sbuf_slots[name] = binding; + } else if (slot != binding) { + out_spirv.errors.push_back(inp.error(0, fmt::format("binding collision for buffer block '{}' ({} vs {})", name, slot, binding))); + return false; + } + } + for (int i = 0; i < program.getNumUniformVariables(); i++) { + const auto& uniform = program.getUniform(i); + const std::string& name = uniform.name; + const int binding = uniform.getBinding(); + if (uniform.getType()->getSampler().sampler) { + const int slot = inp.find_smp_slot(name); + if (slot == -1) { + inp.smp_slots[name] = binding; + } else if (slot != binding) { + out_spirv.errors.push_back(inp.error(0, fmt::format("binding collision for sampler '{}' ({} vs {})", name, slot))); + return false; + } + } else if (uniform.getType()->isTexture()) { + const int slot = inp.find_img_slot(name); + if (slot == -1) { + inp.img_slots[name] = binding; + } else if (slot != binding) { + out_spirv.errors.push_back(inp.error(0, fmt::format("binding collision for image '{}' ({} vs {})", name, slot))); + return false; + } + } + } + // translate intermediate representation to SPIRV const glslang::TIntermediate* im = program.getIntermediate(stage); assert(im); @@ -257,7 +305,7 @@ static bool compile(EShLanguage stage, Slang::Enum slang, const MergedSource& so } // compile all shader-snippets into SPIRV bytecode -Spirv Spirv::compile_glsl(const Input& inp, Slang::Enum slang, const std::vector& defines) { +Spirv Spirv::compile_glsl_and_extract_bindings(Input& inp, Slang::Enum slang, const std::vector& defines) { Spirv out_spirv; // compile shader-snippets @@ -266,14 +314,14 @@ Spirv Spirv::compile_glsl(const Input& inp, Slang::Enum slang, const std::vector if (snippet.type == Snippet::VS) { // vertex shader const MergedSource src = merge_source(inp, snippet, slang, defines); - if (!compile(EShLangVertex, slang, src, inp, snippet_index, out_spirv)) { + if (!compile(inp, EShLangVertex, slang, src, snippet_index, out_spirv)) { // spirv.errors contains error list return out_spirv; } } else if (snippet.type == Snippet::FS) { // fragment shader const MergedSource src = merge_source(inp, snippet, slang, defines); - if (!compile(EShLangFragment, slang, src, inp, snippet_index, out_spirv)) { + if (!compile(inp, EShLangFragment, slang, src, snippet_index, out_spirv)) { // spirv.errors contains error list return out_spirv; } @@ -351,6 +399,23 @@ void Spirv::dump_debug(const Input& inp, ErrMsg::Format err_fmt) const { } fmt::print(stderr, "\n"); } + fmt::print(stderr, " bindings:\n"); + fmt::print(stderr, " uniform blocks:\n"); + for (const auto& item: inp.ub_slots) { + fmt::print(stderr, " {} => {}\n", item.first, item.second); + } + fmt::print(stderr, " images:\n"); + for (const auto& item: inp.img_slots) { + fmt::print(stderr, " {}: {}\n", item.first, item.second); + } + fmt::print(stderr, " samplers:\n"); + for (const auto& item: inp.smp_slots) { + fmt::print(stderr, " {}: {}\n", item.first, item.second); + } + fmt::print(stderr, " storage buffers:\n"); + for (const auto& item: inp.sbuf_slots) { + fmt::print(stderr, " {}: {}\n", item.first, item.second); + } fmt::print(stderr, "\n"); } diff --git a/src/shdc/spirv.h b/src/shdc/spirv.h index 976637be..e289d0e0 100644 --- a/src/shdc/spirv.h +++ b/src/shdc/spirv.h @@ -16,7 +16,7 @@ struct Spirv { static void initialize_spirv_tools(); static void finalize_spirv_tools(); - static Spirv compile_glsl(const Input& inp, Slang::Enum slang, const std::vector& defines); + static Spirv compile_glsl_and_extract_bindings(Input& inp, Slang::Enum slang, const std::vector& defines); bool write_to_file(const Args& args, const Input& inp, Slang::Enum slang); void dump_debug(const Input& inp, ErrMsg::Format err_fmt) const; }; diff --git a/src/shdc/spirvcross.cc b/src/shdc/spirvcross.cc index dcf7855d..a62b038c 100644 --- a/src/shdc/spirvcross.cc +++ b/src/shdc/spirvcross.cc @@ -262,7 +262,7 @@ static void to_combined_image_samplers(CompilerGLSL& compiler) { } } -static StageReflection parse_reflection(const std::vector& bytecode, const Snippet& snippet, ErrMsg& out_error) { +static StageReflection parse_reflection(const Input& inp, const std::vector& bytecode, const Snippet& snippet, ErrMsg& out_error) { // NOTE: do *NOT* use CompilerReflection here, this doesn't generate // the right reflection info for depth textures and comparison samplers CompilerGLSL compiler(bytecode); @@ -283,7 +283,7 @@ static StageReflection parse_reflection(const std::vector& bytecode, c // NOTE: we need to compile here, otherwise the reflection won't be // able to detect depth-textures and comparison-samplers! compiler.compile(); - return Reflection::parse_snippet_reflection(compiler, snippet, out_error); + return Reflection::parse_snippet_reflection(compiler, snippet, inp, out_error); } static SpirvcrossSource to_glsl(const Input& inp, const SpirvBlob& blob, Slang::Enum slang, uint32_t opt_mask, const Snippet& snippet) { @@ -323,7 +323,7 @@ static SpirvcrossSource to_glsl(const Input& inp, const SpirvBlob& blob, Slang:: res.snippet_index = blob.snippet_index; if (!src.empty()) { res.source_code = std::move(src); - res.stage_refl = parse_reflection(blob.bytecode, snippet, res.error); + res.stage_refl = parse_reflection(inp, blob.bytecode, snippet, res.error); } res.valid = !res.error.valid(); return res; @@ -355,7 +355,7 @@ static SpirvcrossSource to_hlsl(const Input& inp, const SpirvBlob& blob, Slang:: res.snippet_index = blob.snippet_index; if (!src.empty()) { res.source_code = std::move(src); - res.stage_refl = parse_reflection(blob.bytecode, snippet, res.error); + res.stage_refl = parse_reflection(inp, blob.bytecode, snippet, res.error); } res.valid = !res.error.valid(); return res; @@ -385,7 +385,7 @@ static SpirvcrossSource to_msl(const Input& inp, const SpirvBlob& blob, Slang::E res.snippet_index = blob.snippet_index; if (!src.empty()) { res.source_code = std::move(src); - res.stage_refl = parse_reflection(blob.bytecode, snippet, res.error); + res.stage_refl = parse_reflection(inp, blob.bytecode, snippet, res.error); } res.valid = !res.error.valid(); return res; @@ -406,7 +406,7 @@ static SpirvcrossSource to_wgsl(const Input& inp, const SpirvBlob& blob, Slang:: tint::writer::wgsl::Result result = tint::writer::wgsl::Generate(&program, wgsl_options); if (result.success) { res.source_code = result.wgsl; - res.stage_refl = parse_reflection(blob.bytecode, snippet, res.error); + res.stage_refl = parse_reflection(inp, blob.bytecode, snippet, res.error); } else { res.error = inp.error(blob.snippet_index, result.error); } @@ -452,7 +452,7 @@ Spirvcross Spirvcross::translate(const Input& inp, const Spirv& spirv, Slang::En const int line_index = snippet.lines[0]; std::string err_msg; if (src.error.valid()) { - err_msg = fmt::format("Failed to cross-compile to {} with:\n{}\n", Slang::to_str(slang), src.error.msg); + err_msg = src.error.msg; } else { err_msg = fmt::format("Failed to cross-compile to {}\n", Slang::to_str(slang)); } diff --git a/src/shdc/types/reflection/bindings.h b/src/shdc/types/reflection/bindings.h index 0ea7d81b..59fd07c0 100644 --- a/src/shdc/types/reflection/bindings.h +++ b/src/shdc/types/reflection/bindings.h @@ -15,11 +15,11 @@ struct Bindings { // - SG_MAX_STORAGEBUFFER_BINDSLOTS // - SG_MAX_IMAGE_SAMPLERS_PAIRS // - static const int MaxUniformBlocks = 8; - static const int MaxImages = 16; - static const int MaxSamplers = 16; - static const int MaxStorageBuffers = 8; - static const int MaxImageSamplers = 16; + inline static const int MaxUniformBlocks = 8; + inline static const int MaxImages = 16; + inline static const int MaxSamplers = 16; + inline static const int MaxStorageBuffers = 8; + inline static const int MaxImageSamplers = 16; enum Type { UNIFORM_BLOCK, diff --git a/src/shdc/types/snippet.h b/src/shdc/types/snippet.h index f4dbb61e..7deff0e6 100644 --- a/src/shdc/types/snippet.h +++ b/src/shdc/types/snippet.h @@ -20,15 +20,11 @@ struct Snippet { int index = -1; Type type = INVALID; std::array options = { }; - std::map image_sample_type_tags; - std::map sampler_type_tags; std::string name; std::vector lines; // resolved zero-based line-indices (including @include_block) Snippet(); Snippet(Type t, const std::string& n); - const ImageSampleTypeTag* lookup_image_sample_type_tag(const std::string& tex_name) const; - const SamplerTypeTag* lookup_sampler_type_tag(const std::string& smp_name) const; static const char* type_to_str(Type t); static bool is_vs(Type t); static bool is_fs(Type t); @@ -38,24 +34,6 @@ inline Snippet::Snippet() { }; inline Snippet::Snippet(Type t, const std::string& n): type(t), name(n) { }; -inline const ImageSampleTypeTag* Snippet::lookup_image_sample_type_tag(const std::string& tex_name) const { - auto it = image_sample_type_tags.find(tex_name); - if (it != image_sample_type_tags.end()) { - return &image_sample_type_tags.at(tex_name); - } else { - return nullptr; - } -} - -inline const SamplerTypeTag* Snippet::lookup_sampler_type_tag(const std::string& smp_name) const { - auto it = sampler_type_tags.find(smp_name); - if (it != sampler_type_tags.end()) { - return &sampler_type_tags.at(smp_name); - } else { - return nullptr; - } -} - inline const char* Snippet::type_to_str(Type t) { switch (t) { case BLOCK: return "block"; From ba11ffd22899e5c036d3055424a585a1e21f7d9e Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 7 Oct 2024 17:08:29 +0200 Subject: [PATCH 14/37] fix error message runtime error --- src/shdc/spirv.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shdc/spirv.cc b/src/shdc/spirv.cc index 3976b51b..7415dcb9 100644 --- a/src/shdc/spirv.cc +++ b/src/shdc/spirv.cc @@ -260,7 +260,7 @@ static bool compile(Input& inp, EShLanguage stage, Slang::Enum slang, const Merg if (slot == -1) { inp.smp_slots[name] = binding; } else if (slot != binding) { - out_spirv.errors.push_back(inp.error(0, fmt::format("binding collision for sampler '{}' ({} vs {})", name, slot))); + out_spirv.errors.push_back(inp.error(0, fmt::format("binding collision for sampler '{}' ({} vs {})", name, slot, binding))); return false; } } else if (uniform.getType()->isTexture()) { @@ -268,7 +268,7 @@ static bool compile(Input& inp, EShLanguage stage, Slang::Enum slang, const Merg if (slot == -1) { inp.img_slots[name] = binding; } else if (slot != binding) { - out_spirv.errors.push_back(inp.error(0, fmt::format("binding collision for image '{}' ({} vs {})", name, slot))); + out_spirv.errors.push_back(inp.error(0, fmt::format("binding collision for image '{}' ({} vs {})", name, slot, binding))); return false; } } From 5688dd140d821178d6c8e21e8b3c9271bf184f9e Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 8 Oct 2024 16:11:33 +0200 Subject: [PATCH 15/37] add sbuftex-sapp.glsl test shader --- test/sapp/sbuftex-sapp.glsl | 50 +++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 test/sapp/sbuftex-sapp.glsl diff --git a/test/sapp/sbuftex-sapp.glsl b/test/sapp/sbuftex-sapp.glsl new file mode 100644 index 00000000..4dcba60e --- /dev/null +++ b/test/sapp/sbuftex-sapp.glsl @@ -0,0 +1,50 @@ +@ctype mat4 hmm_mat4 + +@vs vs +layout(binding=0) uniform vs_params { + mat4 mvp; +}; + +struct sb_vertex { + vec3 pos; + uint idx; + vec2 uv; +}; + +layout(binding=0) readonly buffer vertices { + sb_vertex vtx[]; +}; + +out vec3 uv_idx; + +void main() { + gl_Position = mvp * vec4(vtx[gl_VertexIndex].pos, 1.0); + // need to add a bit of wiggle room here to prevent a precision problem on NVIDIA + // down in the pixel shader + uv_idx = vec3(vtx[gl_VertexIndex].uv, float(vtx[gl_VertexIndex].idx) + 0.5); +} +@end + +@fs fs +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; + +struct sb_color { + vec4 color; +}; + +layout(binding=1) readonly buffer colors { + sb_color clr[]; +}; + +in vec3 uv_idx; +out vec4 frag_color; + +void main() { + uint idx = uint(uv_idx.z); + vec2 uv = uv_idx.xy; + frag_color = vec4(texture(sampler2D(tex,smp), uv).xxx, 1.0) * clr[idx].color; +} +@end + +@program sbuftex vs fs From 68bbfbbb78b5aa9a1a39ef45e9722f620812ba24 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 8 Oct 2024 19:16:47 +0200 Subject: [PATCH 16/37] validate sokol bind slots (range and collisions) --- src/shdc/generators/generator.cc | 8 +- src/shdc/generators/sokolc.cc | 22 ++-- src/shdc/generators/sokold.cc | 8 +- src/shdc/generators/sokoljai.cc | 8 +- src/shdc/generators/sokolnim.cc | 8 +- src/shdc/generators/sokolodin.cc | 8 +- src/shdc/generators/sokolrust.cc | 8 +- src/shdc/generators/sokolzig.cc | 20 ++-- src/shdc/generators/yaml.cc | 6 +- src/shdc/reflection.cc | 120 +++++++++++++++++---- src/shdc/reflection.h | 2 + src/shdc/types/reflection/bindings.h | 4 +- src/shdc/types/reflection/image.h | 1 + src/shdc/types/reflection/image_sampler.h | 1 + src/shdc/types/reflection/sampler.h | 1 + src/shdc/types/reflection/storage_buffer.h | 3 + src/shdc/types/reflection/uniform_block.h | 2 + 17 files changed, 162 insertions(+), 68 deletions(-) diff --git a/src/shdc/generators/generator.cc b/src/shdc/generators/generator.cc index 6678e085..2ebb0d09 100644 --- a/src/shdc/generators/generator.cc +++ b/src/shdc/generators/generator.cc @@ -106,14 +106,14 @@ void Generator::gen_program_info(const GenInput& gen, const ProgramReflection& p void Generator::gen_bindings_info(const GenInput& gen) { for (const UniformBlock& ub: gen.refl.bindings.uniform_blocks) { - cbl_open("Uniform block '{}':\n", ub.struct_info.name); - cbl("{} struct: {}\n", lang_name(), struct_name(ub.struct_info.name)); + cbl_open("Uniform block '{}':\n", ub.name); + cbl("{} struct: {}\n", lang_name(), struct_name(ub.name)); cbl("Bind slot: {} => {}\n", uniform_block_bind_slot_name(ub), ub.sokol_slot); cbl_close(); } for (const StorageBuffer& sbuf: gen.refl.bindings.storage_buffers) { - cbl_open("Storage buffer '{}':\n", sbuf.struct_info.name); - cbl("{} struct: {}\n", lang_name(), struct_name(sbuf.struct_info.name)); + cbl_open("Storage buffer '{}':\n", sbuf.name); + cbl("{} struct: {}\n", lang_name(), struct_name(sbuf.name)); cbl("Bind slot: {} => {}\n", storage_buffer_bind_slot_name(sbuf), sbuf.sokol_slot); cbl_close(); } diff --git a/src/shdc/generators/sokolc.cc b/src/shdc/generators/sokolc.cc index 29880955..6f9b6726 100644 --- a/src/shdc/generators/sokolc.cc +++ b/src/shdc/generators/sokolc.cc @@ -84,7 +84,7 @@ void SokolCGenerator::gen_prerequisites(const GenInput& gen) { void SokolCGenerator::gen_uniform_block_decl(const GenInput &gen, const UniformBlock& ub) { l("#pragma pack(push,1)\n"); int cur_offset = 0; - l_open("SOKOL_SHDC_ALIGN({}) typedef struct {} {{\n", ub.struct_info.align, struct_name(ub.struct_info.name)); + l_open("SOKOL_SHDC_ALIGN({}) typedef struct {} {{\n", ub.struct_info.align, struct_name(ub.name)); for (const Type& uniform: ub.struct_info.struct_items) { int next_offset = uniform.offset; if (next_offset > cur_offset) { @@ -129,7 +129,7 @@ void SokolCGenerator::gen_uniform_block_decl(const GenInput &gen, const UniformB if (cur_offset < round16) { l("uint8_t _pad_{}[{}];\n", cur_offset, round16 - cur_offset); } - l_close("}} {};\n", struct_name(ub.struct_info.name)); + l_close("}} {};\n", struct_name(ub.name)); l("#pragma pack(pop)\n"); } @@ -311,7 +311,7 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) l("{}.uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); l("{}.uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); - l("{}.uniforms[0].glsl_name = \"{}\";\n", ubn, ub->struct_info.name); + l("{}.uniforms[0].glsl_name = \"{}\";\n", ubn, ub->name); } else { for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { const Type& u = ub->struct_info.struct_items[u_index]; @@ -446,7 +446,7 @@ void SokolCGenerator::gen_uniform_block_slot_refl_func(const GenInput& gen, cons l("(void)ub_name;\n"); for (const UniformBlock& ub: prog.bindings.uniform_blocks) { if (ub.sokol_slot >= 0) { - l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); + l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.name); l("return {};\n", ub.sokol_slot); l_close("}}\n"); } @@ -460,8 +460,8 @@ void SokolCGenerator::gen_uniform_block_size_refl_func(const GenInput& gen, cons l("(void)ub_name;\n"); for (const UniformBlock& ub: prog.bindings.uniform_blocks) { if (ub.sokol_slot >= 0) { - l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); - l("return sizeof({});\n", struct_name(ub.struct_info.name)); + l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.name); + l("return sizeof({});\n", struct_name(ub.name)); l_close("}}\n"); } } @@ -474,7 +474,7 @@ void SokolCGenerator::gen_storage_buffer_slot_refl_func(const GenInput& gen, con l("(void)sbuf_name;\n"); for (const StorageBuffer& sbuf: prog.bindings.storage_buffers) { if (sbuf.sokol_slot >= 0) { - l_open("if (0 == strcmp(sbuf_name, \"{}\")) {{\n", sbuf.struct_info.name); + l_open("if (0 == strcmp(sbuf_name, \"{}\")) {{\n", sbuf.name); l("return {};\n", sbuf.sokol_slot); l_close("}}\n"); } @@ -488,7 +488,7 @@ void SokolCGenerator::gen_uniform_offset_refl_func(const GenInput& gen, const Pr l("(void)ub_name; (void)u_name;\n"); for (const UniformBlock& ub: prog.bindings.uniform_blocks) { if (ub.sokol_slot >= 0) { - l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); + l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.name); for (const Type& u: ub.struct_info.struct_items) { l_open("if (0 == strcmp(u_name, \"{}\")) {{\n", u.name); l("return {};\n", u.offset); @@ -511,7 +511,7 @@ void SokolCGenerator::gen_uniform_desc_refl_func(const GenInput& gen, const Prog l("#endif\n"); for (const UniformBlock& ub: prog.bindings.uniform_blocks) { if (ub.sokol_slot >= 0) { - l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.struct_info.name); + l_open("if (0 == strcmp(ub_name, \"{}\")) {{\n", ub.name); for (const Type& u: ub.struct_info.struct_items) { l_open("if (0 == strcmp(u_name, \"{}\")) {{\n", u.name); l("res.type = {};\n", uniform_type(u.type)); @@ -693,11 +693,11 @@ std::string SokolCGenerator::sampler_bind_slot_name(const Sampler& smp) { } std::string SokolCGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return fmt::format("UB_{}", ub.struct_info.name); + return fmt::format("UB_{}", ub.name); } std::string SokolCGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { - return fmt::format("SBUF_{}", sbuf.struct_info.name); + return fmt::format("SBUF_{}", sbuf.name); } std::string SokolCGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index 7051b306..30c4e3d9 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -30,7 +30,7 @@ void SokolDGenerator::gen_prerequisites(const GenInput& gen) { } void SokolDGenerator::gen_uniform_block_decl(const GenInput& gen, const UniformBlock& ub) { - l_open("struct {} {{\n", struct_name(ub.struct_info.name)); + l_open("struct {} {{\n", struct_name(ub.name)); int cur_offset = 0; for (const Type& uniform: ub.struct_info.struct_items) { const int align = (cur_offset == 0) ? ub.struct_info.align : 1; @@ -250,7 +250,7 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef l("{}.layout = sg.UniformLayout.Std140;\n", ubn); if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { if (ub->flattened) { - l("{}.uniforms[0].name = \"{}\";\n", ubn, ub->struct_info.name); + l("{}.uniforms[0].name = \"{}\";\n", ubn, ub->name); // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) l("{}.uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); l("{}.uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); @@ -446,11 +446,11 @@ std::string SokolDGenerator::sampler_bind_slot_name(const Sampler& smp) { } std::string SokolDGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return pystring::upper(fmt::format("UB_{}", ub.struct_info.name)); + return pystring::upper(fmt::format("UB_{}", ub.name)); } std::string SokolDGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { - return pystring::upper(fmt::format("SBUF_{}", sbuf.struct_info.name)); + return pystring::upper(fmt::format("SBUF_{}", sbuf.name)); } static std::string const_def(const std::string& name, int slot) { diff --git a/src/shdc/generators/sokoljai.cc b/src/shdc/generators/sokoljai.cc index c741cf0e..2d5f0ce6 100644 --- a/src/shdc/generators/sokoljai.cc +++ b/src/shdc/generators/sokoljai.cc @@ -26,7 +26,7 @@ void SokolJaiGenerator::gen_prerequisites(const GenInput& gen) { } void SokolJaiGenerator::gen_uniform_block_decl(const GenInput& gen, const UniformBlock& ub) { - l_open("{} :: struct {{\n", struct_name(ub.struct_info.name), ub.struct_info.align); + l_open("{} :: struct {{\n", struct_name(ub.name), ub.struct_info.align); int cur_offset = 0; for (const Type& uniform: ub.struct_info.struct_items) { int next_offset = uniform.offset; @@ -234,7 +234,7 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR l("{}.layout = .STD140;\n", ubn); if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { if (ub->flattened) { - l("{}.uniforms[0].name = \"{}\";\n", ubn, ub->struct_info.name); + l("{}.uniforms[0].name = \"{}\";\n", ubn, ub->name); // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) l("{}.uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); l("{}.uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); @@ -436,11 +436,11 @@ std::string SokolJaiGenerator::sampler_bind_slot_name(const Sampler& smp) { } std::string SokolJaiGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return fmt::format("UB_{}", ub.struct_info.name); + return fmt::format("UB_{}", ub.name); } std::string SokolJaiGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { - return fmt::format("SBUF_{}", sbuf.struct_info.name); + return fmt::format("SBUF_{}", sbuf.name); } std::string SokolJaiGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { diff --git a/src/shdc/generators/sokolnim.cc b/src/shdc/generators/sokolnim.cc index 8a188c63..834a17f5 100644 --- a/src/shdc/generators/sokolnim.cc +++ b/src/shdc/generators/sokolnim.cc @@ -93,7 +93,7 @@ void SokolNimGenerator::gen_prerequisites(const GenInput& gen) { } void SokolNimGenerator::gen_uniform_block_decl(const GenInput& gen, const UniformBlock& ub) { - l_open("type {}* {{.packed.}} = object\n", struct_name(ub.struct_info.name)); + l_open("type {}* {{.packed.}} = object\n", struct_name(ub.name)); int cur_offset = 0; for (const Type& uniform: ub.struct_info.struct_items) { int next_offset = uniform.offset; @@ -317,7 +317,7 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR l("{}.layout = uniformLayoutStd140\n", ubn); if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { if (ub->flattened) { - l("{}.uniforms[0].name = \"{}\"\n", ubn, ub->struct_info.name); + l("{}.uniforms[0].name = \"{}\"\n", ubn, ub->name); // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) l("{}.uniforms[0].type = {}\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); l("{}.uniforms[0].arrayCount = {}\n", ubn, roundup(ub->struct_info.size, 16) / 16); @@ -519,11 +519,11 @@ std::string SokolNimGenerator::sampler_bind_slot_name(const Sampler& smp) { } std::string SokolNimGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return to_camel_case(fmt::format("UB_{}", ub.struct_info.name)); + return to_camel_case(fmt::format("UB_{}", ub.name)); } std::string SokolNimGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { - return to_camel_case(fmt::format("SBUF_{}", sbuf.struct_info.name)); + return to_camel_case(fmt::format("SBUF_{}", sbuf.name)); } std::string SokolNimGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { diff --git a/src/shdc/generators/sokolodin.cc b/src/shdc/generators/sokolodin.cc index 019e6476..207b45bf 100644 --- a/src/shdc/generators/sokolodin.cc +++ b/src/shdc/generators/sokolodin.cc @@ -25,7 +25,7 @@ void SokolOdinGenerator::gen_prerequisites(const GenInput& gen) { } void SokolOdinGenerator::gen_uniform_block_decl(const GenInput& gen, const UniformBlock& ub) { - l_open("{} :: struct #align({}) {{\n", struct_name(ub.struct_info.name), ub.struct_info.align); + l_open("{} :: struct #align({}) {{\n", struct_name(ub.name), ub.struct_info.align); l_open("using _: struct #packed {{\n"); int cur_offset = 0; for (const Type& uniform: ub.struct_info.struct_items) { @@ -237,7 +237,7 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program l("{}.layout = .STD140\n", ubn); if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { if (ub->flattened) { - l("{}.uniforms[0].name = \"{}\"\n", ubn, ub->struct_info.name); + l("{}.uniforms[0].name = \"{}\"\n", ubn, ub->name); // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) l("{}.uniforms[0].type = {}\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); l("{}.uniforms[0].array_count = {}\n", ubn, roundup(ub->struct_info.size, 16) / 16); @@ -439,11 +439,11 @@ std::string SokolOdinGenerator::sampler_bind_slot_name(const Sampler& smp) { } std::string SokolOdinGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return fmt::format("UB_{}", ub.struct_info.name); + return fmt::format("UB_{}", ub.name); } std::string SokolOdinGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { - return fmt::format("SBUF_{}", sbuf.struct_info.name); + return fmt::format("SBUF_{}", sbuf.name); } std::string SokolOdinGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { diff --git a/src/shdc/generators/sokolrust.cc b/src/shdc/generators/sokolrust.cc index 04c1ffca..ac2caf86 100644 --- a/src/shdc/generators/sokolrust.cc +++ b/src/shdc/generators/sokolrust.cc @@ -28,7 +28,7 @@ void SokolRustGenerator::gen_prerequisites(const GenInput& gen) { void SokolRustGenerator::gen_uniform_block_decl(const GenInput& gen, const UniformBlock& ub) { l("#[repr(C, align({}))]\n", ub.struct_info.align); - l_open("pub struct {} {{\n", struct_name(ub.struct_info.name)); + l_open("pub struct {} {{\n", struct_name(ub.name)); int cur_offset = 0; for (const Type& uniform: ub.struct_info.struct_items) { int next_offset = uniform.offset; @@ -250,7 +250,7 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program l("{}.layout = sg::UniformLayout::Std140;\n", ubn); if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { if (ub->flattened) { - l("{}.uniforms[0].name = c\"{}\".as_ptr();\n", ubn, ub->struct_info.name); + l("{}.uniforms[0].name = c\"{}\".as_ptr();\n", ubn, ub->name); // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) l("{}.uniforms[0]._type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); l("{}.uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); @@ -453,11 +453,11 @@ std::string SokolRustGenerator::sampler_bind_slot_name(const Sampler& smp) { } std::string SokolRustGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return pystring::upper(fmt::format("UB_{}", ub.struct_info.name)); + return pystring::upper(fmt::format("UB_{}", ub.name)); } std::string SokolRustGenerator::storage_buffer_bind_slot_name(const StorageBuffer& sbuf) { - return pystring::upper(fmt::format("SBUF_{}", sbuf.struct_info.name)); + return pystring::upper(fmt::format("SBUF_{}", sbuf.name)); } std::string SokolRustGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { diff --git a/src/shdc/generators/sokolzig.cc b/src/shdc/generators/sokolzig.cc index 3825b3d7..857516be 100644 --- a/src/shdc/generators/sokolzig.cc +++ b/src/shdc/generators/sokolzig.cc @@ -27,7 +27,7 @@ void SokolZigGenerator::gen_prerequisites(const GenInput& gen) { } void SokolZigGenerator::gen_uniform_block_decl(const GenInput& gen, const UniformBlock& ub) { - l_open("pub const {} = extern struct {{\n", struct_name(ub.struct_info.name)); + l_open("pub const {} = extern struct {{\n", struct_name(ub.name)); int cur_offset = 0; for (const Type& uniform: ub.struct_info.struct_items) { int next_offset = uniform.offset; @@ -248,7 +248,7 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR l("{}.layout = .STD140;\n", ubn); if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { if (ub->flattened) { - l("{}.uniforms[0].name = \"{}\";\n", ubn, ub->struct_info.name); + l("{}.uniforms[0].name = \"{}\";\n", ubn, ub->name); // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) l("{}.uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); l("{}.uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); @@ -451,11 +451,11 @@ std::string SokolZigGenerator::sampler_bind_slot_name(const Sampler& smp) { } std::string SokolZigGenerator::uniform_block_bind_slot_name(const UniformBlock& ub) { - return fmt::format("UB_{}", ub.struct_info.name); + return fmt::format("UB_{}", ub.name); } std::string SokolZigGenerator::storage_buffer_bind_slot_name(const refl::StorageBuffer& sb) { - return fmt::format("SBUF_{}", sb.struct_info.name); + return fmt::format("SBUF_{}", sb.name); } std::string SokolZigGenerator::vertex_attr_definition(const std::string& prog_name, const StageAttr& attr) { @@ -554,7 +554,7 @@ void SokolZigGenerator::gen_uniform_block_slot_refl_func(const GenInput& gen, co wrote_stage = true; for (const UniformBlock& ub: refl.bindings.uniform_blocks) { if (ub.sokol_slot >= 0) { - l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.struct_info.name); + l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.name); l("return {};\n", ub.sokol_slot); l_close("}}\n"); wrote_ub_name = true; @@ -579,8 +579,8 @@ void SokolZigGenerator::gen_uniform_block_size_refl_func(const GenInput& gen, co wrote_stage = true; for (const UniformBlock& ub: refl.bindings.uniform_blocks) { if (ub.sokol_slot >= 0) { - l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.struct_info.name); - l("return @sizeOf({});\n", struct_name(ub.struct_info.name)); + l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.name); + l("return @sizeOf({});\n", struct_name(ub.name)); l_close("}}\n"); wrote_ub_name = true; } @@ -604,7 +604,7 @@ void SokolZigGenerator::gen_storage_buffer_slot_refl_func(const GenInput& gen, c wrote_stage = true; for (const StorageBuffer& sbuf: refl.bindings.storage_buffers) { if (sbuf.sokol_slot >= 0) { - l_open("if (std.mem.eql(u8, sbuf_name, \"{}\")) {{\n", sbuf.struct_info.name); + l_open("if (std.mem.eql(u8, sbuf_name, \"{}\")) {{\n", sbuf.name); l("return {};\n", sbuf.sokol_slot); l_close("}}\n"); wrote_sbuf_name = true; @@ -630,7 +630,7 @@ void SokolZigGenerator::gen_uniform_offset_refl_func(const GenInput& gen, const wrote_stage = true; for (const UniformBlock& ub: refl.bindings.uniform_blocks) { if (ub.sokol_slot >= 0) { - l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.struct_info.name); + l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.name); wrote_ub_name = true; for (const Type& u: ub.struct_info.struct_items) { l_open("if (std.mem.eql(u8, u_name, \"{}\")) {{\n", u.name); @@ -663,7 +663,7 @@ void SokolZigGenerator::gen_uniform_desc_refl_func(const GenInput& gen, const Pr wrote_stage = true; for (const UniformBlock& ub: refl.bindings.uniform_blocks) { if (ub.sokol_slot >= 0) { - l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.struct_info.name); + l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.name); wrote_ub_name = true; for (const Type& u: ub.struct_info.struct_items) { l_open("if (std.mem.eql(u8, u_name, \"{}\")) {{\n", u.name); diff --git a/src/shdc/generators/yaml.cc b/src/shdc/generators/yaml.cc index 9813e21a..28559c10 100644 --- a/src/shdc/generators/yaml.cc +++ b/src/shdc/generators/yaml.cc @@ -126,12 +126,12 @@ void YamlGenerator::gen_uniform_block(const GenInput& gen, const UniformBlock& u l_open("-\n"); l("slot: {}\n", ub.sokol_slot); l("size: {}\n", roundup(ub.struct_info.size, 16)); - l("struct_name: {}\n", ub.struct_info.name); + l("struct_name: {}\n", ub.name); l("inst_name: {}\n", ub.inst_name); l_open("uniforms:\n"); if (ub.flattened) { l_open("-\n"); - l("name: {}\n", ub.struct_info.name); + l("name: {}\n", ub.name); l("type: {}\n", flattened_uniform_type(ub.struct_info.struct_items[0].type)); l("array_count: {}\n", roundup(ub.struct_info.size, 16) / 16); l("offset: 0\n"); @@ -172,7 +172,7 @@ void YamlGenerator::gen_storage_buffer(const StorageBuffer& sbuf) { l("slot: {}\n", sbuf.sokol_slot); l("size: {}\n", sbuf.struct_info.size); l("align: {}\n", sbuf.struct_info.align); - l("struct_name: {}\n", sbuf.struct_info.name); + l("struct_name: {}\n", sbuf.name); l("inst_name: {}\n", sbuf.inst_name); l("readonly: {}\n", sbuf.readonly); l("inner_struct_name: {}\n", item.struct_typename); diff --git a/src/shdc/reflection.cc b/src/shdc/reflection.cc index bd48dc2c..e88ab187 100644 --- a/src/shdc/reflection.cc +++ b/src/shdc/reflection.cc @@ -74,7 +74,7 @@ static ErrMsg validate_linking(const Input& inp, const Program& prog, const Prog Reflection Reflection::build(const Args& args, const Input& inp, const std::array& spirvcross_array) { Reflection res; - ErrMsg error; + ErrMsg err; // for each program, just pick the reflection info from the first compiled slang, // the reflection info is the same for each Slang because it has been generated @@ -93,12 +93,14 @@ Reflection Reflection::build(const Args& args, const Input& inp, const std::arra prog_refl.name = prog.name; prog_refl.stages[ShaderStage::Vertex] = vs_src->stage_refl; prog_refl.stages[ShaderStage::Fragment] = fs_src->stage_refl; - prog_refl.bindings = merge_bindings({ - vs_src->stage_refl.bindings, - fs_src->stage_refl.bindings, - }, error); - if (error.valid()) { - res.error = inp.error(0, error.msg); + prog_refl.bindings = merge_bindings({ vs_src->stage_refl.bindings, fs_src->stage_refl.bindings }, err); + if (err.valid()) { + res.error = inp.error(prog.line_index, err.msg); + return res; + } + err = validate_program_bindings(prog_refl.bindings); + if (err.valid()) { + res.error = inp.error(prog.line_index, err.msg); return res; } prog_bindings.push_back(prog_refl.bindings); @@ -115,9 +117,9 @@ Reflection Reflection::build(const Args& args, const Input& inp, const std::arra for (const auto& prog_refl: res.progs) { prog_bindings.push_back(prog_refl.bindings); } - res.bindings = merge_bindings(prog_bindings, error); - if (error.valid()) { - res.error = inp.error(0, error.msg); + res.bindings = merge_bindings(prog_bindings, err); + if (err.valid()) { + res.error = inp.error(0, err.msg); } return res; } @@ -258,9 +260,10 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c } // uniform blocks always have 16 byte alignment refl_ub.struct_info.align = 16; - refl_ub.sokol_slot = inp.find_ub_slot(refl_ub.struct_info.name); + refl_ub.name = refl_ub.struct_info.name; + refl_ub.sokol_slot = inp.find_ub_slot(refl_ub.name); if (refl_ub.sokol_slot == -1) { - out_error = inp.error(0, fmt::format("no @bindslot definition found for uniformblock '{}'\n", refl_ub.struct_info.name)); + out_error = inp.error(0, fmt::format("no @bindslot definition found for uniformblock '{}'\n", refl_ub.name)); return refl; } refl.bindings.uniform_blocks.push_back(refl_ub); @@ -284,9 +287,10 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c if (out_error.valid()) { return refl; } - refl_sbuf.sokol_slot = inp.find_sbuf_slot(refl_sbuf.struct_info.name); + refl_sbuf.name = refl_sbuf.struct_info.name; + refl_sbuf.sokol_slot = inp.find_sbuf_slot(refl_sbuf.name); if (refl_sbuf.sokol_slot == -1) { - out_error = inp.error(0, fmt::format("no @bindslot definition found for storagebuffer '{}'\n", refl_sbuf.struct_info.name)); + out_error = inp.error(0, fmt::format("no @bindslot definition found for storagebuffer '{}'\n", refl_sbuf.name)); return refl; } refl.bindings.storage_buffers.push_back(refl_sbuf); @@ -375,11 +379,11 @@ Bindings Reflection::merge_bindings(const std::vector& in_bindings, Er // merge identical uniform blocks for (const UniformBlock& ub: src_bindings.uniform_blocks) { - const UniformBlock* other_ub = out_bindings.find_uniform_block_by_name(ub.struct_info.name); + const UniformBlock* other_ub = out_bindings.find_uniform_block_by_name(ub.name); if (other_ub) { // another uniform block of the same name exists, make sure it's identical if (!ub.equals(*other_ub)) { - out_error = ErrMsg::error(fmt::format("conflicting uniform block definitions found for '{}'", ub.struct_info.name)); + out_error = ErrMsg::error(fmt::format("conflicting uniform block definitions found for '{}'", ub.name)); return Bindings(); } } else { @@ -389,11 +393,11 @@ Bindings Reflection::merge_bindings(const std::vector& in_bindings, Er // merge identical storage buffers for (const StorageBuffer& sbuf: src_bindings.storage_buffers) { - const StorageBuffer* other_sbuf = out_bindings.find_storage_buffer_by_name(sbuf.struct_info.name); + const StorageBuffer* other_sbuf = out_bindings.find_storage_buffer_by_name(sbuf.name); if (other_sbuf) { // another storage buffer of the same name exists, make sure it's identical if (!sbuf.equals(*other_sbuf)) { - out_error = ErrMsg::error(fmt::format("conflicting storage buffer definitions found for '{}'", sbuf.struct_info.name)); + out_error = ErrMsg::error(fmt::format("conflicting storage buffer definitions found for '{}'", sbuf.name)); return Bindings(); } } else { @@ -524,6 +528,86 @@ Type Reflection::parse_struct_item(const Compiler& compiler, const TypeID& type_ return out; } +ErrMsg Reflection::validate_program_bindings(const Bindings& bindings) { + { + std::array ub_slots; + for (const auto& ub: bindings.uniform_blocks) { + const int slot = ub.sokol_slot; + if ((slot < 0) || (slot >= Bindings::MaxUniformBlocks)) { + return ErrMsg::error(fmt::format("binding {} out of range for uniform block '{}' (must be 0..{})", + slot, + ub.name, + Bindings::MaxUniformBlocks - 1)); + } + if (!ub_slots[slot].empty()) { + return ErrMsg::error(fmt::format("uniform blocks {} and {} cannot use the same binding {}", + ub_slots[slot], + ub.name, + slot)); + } + ub_slots[slot] = ub.name; + } + } + { + std::array sbuf_slots; + for (const auto& sbuf: bindings.storage_buffers) { + const int slot = sbuf.sokol_slot; + if ((slot < 0) || (slot >= Bindings::MaxStorageBuffers)) { + return ErrMsg::error(fmt::format("binding {} out of range for storage buffer '{}' (must be 0..{})", + slot, + sbuf.name, + Bindings::MaxStorageBuffers - 1)); + } + if (!sbuf_slots[slot].empty()) { + return ErrMsg::error(fmt::format("storage buffer '{}' and '{}' cannot use the same binding {}", + sbuf_slots[slot], + sbuf.name, + slot)); + } + sbuf_slots[slot] = sbuf.name; + } + } + { + std::array img_slots; + for (const auto& img: bindings.images) { + const int slot = img.sokol_slot; + if ((slot < 0) || (slot > Bindings::MaxImages)) { + return ErrMsg::error(fmt::format("binding {} out of range for image '{}' (must be 0..{})", + slot, + img.name, + Bindings::MaxImages - 1)); + } + if (!img_slots[slot].empty()) { + return ErrMsg::error(fmt::format("images '{}' and '{}' cannot use the same binding {}", + img_slots[slot], + img.name, + slot)); + } + img_slots[slot] = img.name; + } + } + { + std::array smp_slots; + for (const auto& smp: bindings.samplers) { + const int slot = smp.sokol_slot; + if ((slot < 0) || (slot > Bindings::MaxSamplers)) { + return ErrMsg::error(fmt::format("binding {} out of range for sampler '{}' (must be 0..{})", + slot, + smp.name, + Bindings::MaxSamplers - 1)); + } + if (!smp_slots[slot].empty()) { + return ErrMsg::error(fmt::format("samplers '{}' and '{}' cannot use the same binding {}", + smp_slots[slot], + smp.name, + slot)); + } + smp_slots[slot] = smp.name; + } + } + return ErrMsg(); +} + Type Reflection::parse_toplevel_struct(const Compiler& compiler, const Resource& res, ErrMsg& out_error) { Type out; out.name = res.name; diff --git a/src/shdc/reflection.h b/src/shdc/reflection.h index 85a06c05..237cd40f 100644 --- a/src/shdc/reflection.h +++ b/src/shdc/reflection.h @@ -33,6 +33,8 @@ struct Reflection { static Type parse_toplevel_struct(const spirv_cross::Compiler& compiler, const spirv_cross::Resource& res, ErrMsg& out_error); // parse a struct item static Type parse_struct_item(const spirv_cross::Compiler& compiler, const spirv_cross::TypeID& type_id, const spirv_cross::TypeID& base_type_id, uint32_t item_index, ErrMsg& out_error); + // check for valid sokol bindslot ranges and binding collisions across shader stages + static ErrMsg validate_program_bindings(const Bindings& bindings); }; } // namespace reflection diff --git a/src/shdc/types/reflection/bindings.h b/src/shdc/types/reflection/bindings.h index 59fd07c0..ee5b0331 100644 --- a/src/shdc/types/reflection/bindings.h +++ b/src/shdc/types/reflection/bindings.h @@ -151,7 +151,7 @@ inline const ImageSampler* Bindings::find_image_sampler_by_sokol_slot(int slot) inline const UniformBlock* Bindings::find_uniform_block_by_name(const std::string& name) const { for (const UniformBlock& ub: uniform_blocks) { - if (ub.struct_info.name == name) { + if (ub.name == name) { return &ub; } } @@ -160,7 +160,7 @@ inline const UniformBlock* Bindings::find_uniform_block_by_name(const std::strin inline const StorageBuffer* Bindings::find_storage_buffer_by_name(const std::string& name) const { for (const StorageBuffer& sbuf: storage_buffers) { - if (sbuf.struct_info.name == name) { + if (sbuf.name == name) { return &sbuf; } } diff --git a/src/shdc/types/reflection/image.h b/src/shdc/types/reflection/image.h index f50e3998..fa90f1df 100644 --- a/src/shdc/types/reflection/image.h +++ b/src/shdc/types/reflection/image.h @@ -24,6 +24,7 @@ struct Image { inline bool Image::equals(const Image& other) const { return (stage == other.stage) + && (sokol_slot == other.sokol_slot) && (name == other.name) && (type == other.type) && (sample_type == other.sample_type) diff --git a/src/shdc/types/reflection/image_sampler.h b/src/shdc/types/reflection/image_sampler.h index 0068c71b..608b3343 100644 --- a/src/shdc/types/reflection/image_sampler.h +++ b/src/shdc/types/reflection/image_sampler.h @@ -19,6 +19,7 @@ struct ImageSampler { inline bool ImageSampler::equals(const ImageSampler& other) const { return (stage == other.stage) + && (sokol_slot == other.sokol_slot) && (name == other.name) && (image_name == other.image_name) && (sampler_name == other.sampler_name); diff --git a/src/shdc/types/reflection/sampler.h b/src/shdc/types/reflection/sampler.h index 8875ce67..abcb6b04 100644 --- a/src/shdc/types/reflection/sampler.h +++ b/src/shdc/types/reflection/sampler.h @@ -21,6 +21,7 @@ struct Sampler { inline bool Sampler::equals(const Sampler& other) const { return (stage == other.stage) + && (sokol_slot == other.sokol_slot) && (name == other.name) && (type == other.type); } diff --git a/src/shdc/types/reflection/storage_buffer.h b/src/shdc/types/reflection/storage_buffer.h index 18a90396..d5e2fb8e 100644 --- a/src/shdc/types/reflection/storage_buffer.h +++ b/src/shdc/types/reflection/storage_buffer.h @@ -13,6 +13,7 @@ struct StorageBuffer { int msl_buffer_n = -1; int wgsl_group1_binding_n = -1; int glsl_binding_n = -1; + std::string name; // shortcut for struct_info.name std::string inst_name; bool readonly; Type struct_info; @@ -23,6 +24,8 @@ struct StorageBuffer { inline bool StorageBuffer::equals(const StorageBuffer& other) const { return (stage == other.stage) + && (sokol_slot == other.sokol_slot) + && (name == other.name) && (inst_name == other.inst_name) && (readonly == other.readonly) && (struct_info.equals(other.struct_info)); diff --git a/src/shdc/types/reflection/uniform_block.h b/src/shdc/types/reflection/uniform_block.h index 34f28995..7d9f2d28 100644 --- a/src/shdc/types/reflection/uniform_block.h +++ b/src/shdc/types/reflection/uniform_block.h @@ -13,6 +13,7 @@ struct UniformBlock { int hlsl_register_b_n = -1; int msl_buffer_n = -1; int wgsl_group0_binding_n = -1; + std::string name; // shortcut for struct_info.name std::string inst_name; bool flattened = false; Type struct_info; @@ -24,6 +25,7 @@ struct UniformBlock { inline bool UniformBlock::equals(const UniformBlock& other) const { return (stage == other.stage) // NOTE: ignore inst_name + && (name == other.name) && (flattened == other.flattened) && struct_info.equals(other.struct_info); } From 9ff6bfcbade8329c4c46135c1b58e8cae3d4a070 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 9 Oct 2024 18:15:10 +0200 Subject: [PATCH 17/37] fix uniforms => glsl_uniforms in C generator --- src/shdc/generators/sokolc.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shdc/generators/sokolc.cc b/src/shdc/generators/sokolc.cc index 6f9b6726..b2025e13 100644 --- a/src/shdc/generators/sokolc.cc +++ b/src/shdc/generators/sokolc.cc @@ -309,13 +309,13 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } else if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { if (ub->flattened) { // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) - l("{}.uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); - l("{}.uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); - l("{}.uniforms[0].glsl_name = \"{}\";\n", ubn, ub->name); + l("{}.glsl_uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); + l("{}.glsl_uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); + l("{}.glsl_uniforms[0].glsl_name = \"{}\";\n", ubn, ub->name); } else { for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { const Type& u = ub->struct_info.struct_items[u_index]; - const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); + const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); l("{}.type = {};\n", un, uniform_type(u.type)); l("{}.offset = {};\n", un, u.offset); l("{}.array_count = {};\n", un, u.array_count); From 09d14d56a8052f9a4ebebb6f8e52719122e0618b Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 12 Oct 2024 19:08:29 +0200 Subject: [PATCH 18/37] fix missing semicolon in C code generator --- src/shdc/generators/sokolc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shdc/generators/sokolc.cc b/src/shdc/generators/sokolc.cc index b2025e13..33d79661 100644 --- a/src/shdc/generators/sokolc.cc +++ b/src/shdc/generators/sokolc.cc @@ -355,7 +355,7 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } else if (Slang::is_msl(slang)) { l("{}.msl_texture_n = {};\n", in, img->msl_texture_n); } else if (Slang::is_wgsl(slang)) { - l("{}.wgsl_group1_binding_n = {}\n", in, img->wgsl_group1_binding_n); + l("{}.wgsl_group1_binding_n = {};\n", in, img->wgsl_group1_binding_n); } } } From 3fda63f78269dc21306216cc275342c8b72a89e9 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 12 Oct 2024 19:50:45 +0200 Subject: [PATCH 19/37] fix outdated error message for unused resources (but might need more improvement) --- src/shdc/reflection.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shdc/reflection.cc b/src/shdc/reflection.cc index e88ab187..a18c4e6e 100644 --- a/src/shdc/reflection.cc +++ b/src/shdc/reflection.cc @@ -263,7 +263,7 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c refl_ub.name = refl_ub.struct_info.name; refl_ub.sokol_slot = inp.find_ub_slot(refl_ub.name); if (refl_ub.sokol_slot == -1) { - out_error = inp.error(0, fmt::format("no @bindslot definition found for uniformblock '{}'\n", refl_ub.name)); + out_error = inp.error(0, fmt::format("no binding found for uniformblock '{}' (might be unused in shader code?)\n", refl_ub.name)); return refl; } refl.bindings.uniform_blocks.push_back(refl_ub); @@ -290,7 +290,7 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c refl_sbuf.name = refl_sbuf.struct_info.name; refl_sbuf.sokol_slot = inp.find_sbuf_slot(refl_sbuf.name); if (refl_sbuf.sokol_slot == -1) { - out_error = inp.error(0, fmt::format("no @bindslot definition found for storagebuffer '{}'\n", refl_sbuf.name)); + out_error = inp.error(0, fmt::format("no binding found for storagebuffer '{}' (might be unused in shader code?)\n", refl_sbuf.name)); return refl; } refl.bindings.storage_buffers.push_back(refl_sbuf); @@ -316,7 +316,7 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c refl_img.multisampled = spirtype_to_image_multisampled(img_type); refl_img.sokol_slot = inp.find_img_slot(refl_img.name); if (refl_img.sokol_slot == -1) { - out_error = inp.error(0, fmt::format("no @bindslot definition found for image '{}'\n", refl_img.name)); + out_error = inp.error(0, fmt::format("no binding found for image '{}' (might be unused in shader code?)\n", refl_img.name)); return refl; } refl.bindings.images.push_back(refl_img); @@ -340,7 +340,7 @@ StageReflection Reflection::parse_snippet_reflection(const Compiler& compiler, c } refl_smp.sokol_slot = inp.find_smp_slot(refl_smp.name); if (refl_smp.sokol_slot == -1) { - out_error = inp.error(0, fmt::format("no @bindslot definition found for sampler '{}'\n", refl_smp.name)); + out_error = inp.error(0, fmt::format("no binding found for sampler '{}' (might be unused in shader code?)\n", refl_smp.name)); return refl; } refl.bindings.samplers.push_back(refl_smp); From 24665ec3041eb48273245bdc1b373a03de171664 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 16 Oct 2024 18:28:11 +0200 Subject: [PATCH 20/37] fix reflection function codegen in sokolc.cc --- src/shdc/generators/sokolc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shdc/generators/sokolc.cc b/src/shdc/generators/sokolc.cc index 33d79661..0eed2dfa 100644 --- a/src/shdc/generators/sokolc.cc +++ b/src/shdc/generators/sokolc.cc @@ -524,7 +524,7 @@ void SokolCGenerator::gen_uniform_desc_refl_func(const GenInput& gen, const Prog l_close("}}\n"); } } - l("return desc;\n"); + l("return res;\n"); l_close("}}\n"); } From cbaa6fcad042b4030ad39dbcb8172984fbe49dd1 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Fri, 18 Oct 2024 18:58:24 +0200 Subject: [PATCH 21/37] fix test shaders --- fips-files/verbs/run_tests.py | 2 ++ test/chipvis.glsl | 6 ++--- test/fontstash.glsl | 6 ++--- test/imgui.glsl | 6 ++--- test/infinity.glsl | 8 +++--- test/inout_mismatch.glsl | 8 +++--- test/sapp/arraytex-sapp.glsl | 6 ++--- test/sapp/blend-sapp.glsl | 4 +-- test/sapp/cgltf-sapp.glsl | 27 ++++++++++---------- test/sapp/cube-sapp.glsl | 2 +- test/sapp/cubemap-jpeg-sapp.glsl | 6 ++--- test/sapp/cubemaprt-sapp.glsl | 6 ++--- test/sapp/debugtext-context-sapp.glsl | 6 ++--- test/sapp/drawcallperf-sapp.glsl | 8 +++--- test/sapp/dyntex-sapp.glsl | 6 ++--- test/sapp/dyntex3d-sapp.glsl | 34 +++++++++++++++++++++++++ test/sapp/imgui-usercallback-sapp.glsl | 2 +- test/sapp/instancing-pull-sapp.glsl | 6 ++--- test/sapp/instancing-sapp.glsl | 2 +- test/sapp/layerrender-sapp.glsl | 8 +++--- test/sapp/loadpng-sapp.glsl | 6 ++--- test/sapp/mipmap-sapp.glsl | 6 ++--- test/sapp/miprender-sapp.glsl | 6 ++--- test/sapp/mrt-pixelformats-sapp.glsl | 8 +++--- test/sapp/mrt-sapp.glsl | 16 ++++++------ test/sapp/noentry-dll-sapp.glsl | 2 +- test/sapp/noentry-sapp.glsl | 2 +- test/sapp/noninterleaved-sapp.glsl | 6 ++--- test/sapp/offscreen-msaa-sapp.glsl | 6 ++--- test/sapp/offscreen-sapp.glsl | 6 ++--- test/sapp/ozz-skin-sapp.glsl | 6 ++--- test/sapp/ozz-storagebuffer-sapp.glsl | 8 +++--- test/sapp/pixelformats-sapp.glsl | 4 +-- test/sapp/plmpeg-sapp.glsl | 10 ++++---- test/sapp/primtypes-sapp.glsl | 2 +- test/sapp/restart-sapp.glsl | 6 ++--- test/sapp/sdf-sapp.glsl | 2 +- test/sapp/shadows-depthtex-sapp.glsl | 14 +++++----- test/sapp/shadows-sapp.glsl | 14 +++++----- test/sapp/shapes-sapp.glsl | 2 +- test/sapp/shapes-transform-sapp.glsl | 2 +- test/sapp/shdfeatures-sapp.glsl | 8 +++--- test/sapp/tex3d-sapp.glsl | 6 ++--- test/sapp/texcube-sapp.glsl | 6 ++--- test/sapp/triangle-bufferless-sapp.glsl | 4 +-- test/sapp/uniformtypes-sapp.glsl | 3 +-- test/sapp/uvwrap-sapp.glsl | 6 ++--- test/sapp/vertexpull-sapp.glsl | 9 ++++--- test/sgl.glsl | 6 ++--- test/shared_ub.glsl | 4 +-- test/uniform_types.glsl | 4 +-- 51 files changed, 192 insertions(+), 157 deletions(-) create mode 100644 test/sapp/dyntex3d-sapp.glsl diff --git a/fips-files/verbs/run_tests.py b/fips-files/verbs/run_tests.py index 2a98cf75..6ced6688 100644 --- a/fips-files/verbs/run_tests.py +++ b/fips-files/verbs/run_tests.py @@ -27,6 +27,7 @@ 'sapp/debugtext-context-sapp.glsl', 'sapp/drawcallperf-sapp.glsl', 'sapp/dyntex-sapp.glsl', + 'sapp/dyntex3d-sapp.glsl', 'sapp/fontstash-layers-sapp.glsl', 'sapp/imgui-usercallback-sapp.glsl', 'sapp/instancing-pull-sapp.glsl', @@ -49,6 +50,7 @@ 'sapp/primtypes-sapp.glsl', 'sapp/quad-sapp.glsl', 'sapp/restart-sapp.glsl', + 'sapp/sbuftex-sapp.glsl', 'sapp/sdf-sapp.glsl', 'sapp/shadows-depthtex-sapp.glsl', 'sapp/shadows-sapp.glsl', diff --git a/test/chipvis.glsl b/test/chipvis.glsl index 7d4fbc6c..e39a9334 100644 --- a/test/chipvis.glsl +++ b/test/chipvis.glsl @@ -6,14 +6,14 @@ @ctype vec2 float2_t @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { vec4 color0; vec2 half_size; vec2 offset; vec2 scale; }; -uniform texture2D palette_tex; -uniform sampler smp; +layout(binding=0) uniform texture2D palette_tex; +layout(binding=0) uniform sampler smp; in vec2 pos; in vec2 uv; out vec4 color; diff --git a/test/fontstash.glsl b/test/fontstash.glsl index e3f425a4..8079cae4 100644 --- a/test/fontstash.glsl +++ b/test/fontstash.glsl @@ -1,5 +1,5 @@ @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { uniform mat4 mvp; uniform mat4 tm; }; @@ -16,8 +16,8 @@ void main() { @end @fs fs -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec4 uv; in vec4 color; out vec4 frag_color; diff --git a/test/imgui.glsl b/test/imgui.glsl index 74b4c43d..97478490 100644 --- a/test/imgui.glsl +++ b/test/imgui.glsl @@ -1,5 +1,5 @@ @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { vec2 disp_size; }; in vec2 position; @@ -15,8 +15,8 @@ void main() { @end @fs fs -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec2 uv; in vec4 color; out vec4 frag_color; diff --git a/test/infinity.glsl b/test/infinity.glsl index 035e5bab..861318da 100644 --- a/test/infinity.glsl +++ b/test/infinity.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -21,9 +21,9 @@ void main() { @end @fs fs -uniform texture2D tex0; -uniform texture2D tex1; -uniform sampler smp; +layout(binding=0) uniform texture2D tex0; +layout(binding=1) uniform texture2D tex1; +layout(binding=0) uniform sampler smp; in vec4 color; in vec2 uv; diff --git a/test/inout_mismatch.glsl b/test/inout_mismatch.glsl index d3bdced2..3ab03517 100644 --- a/test/inout_mismatch.glsl +++ b/test/inout_mismatch.glsl @@ -2,7 +2,7 @@ #pragma sokol @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 u_MVMatrix; // A constant representing the combined model/view matrix. mat4 u_MVPMatrix; // A constant representing the combined model/view/projection matrix. mat4 u_NMatrix; // A constant representing the Normal Matrix @@ -42,9 +42,9 @@ void main() #pragma sokol @fs fs //precision mediump float; // Set the default precision to medium. We don't need as high of a precision in the fragment shader -uniform texture2D tex; -uniform sampler smp; -uniform fs_params { +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; +layout(binding=1) uniform fs_params { vec4 u_LightPos; // The position of the light in eye space. vec4 ambientColor; vec4 diffuseColor; diff --git a/test/sapp/arraytex-sapp.glsl b/test/sapp/arraytex-sapp.glsl index 675a2e8b..23056e9b 100644 --- a/test/sapp/arraytex-sapp.glsl +++ b/test/sapp/arraytex-sapp.glsl @@ -5,7 +5,7 @@ @ctype vec2 hmm_vec2 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; vec2 offset0; vec2 offset1; @@ -28,8 +28,8 @@ void main() { @end @fs fs -uniform texture2DArray tex; -uniform sampler smp; +layout(binding=0) uniform texture2DArray tex; +layout(binding=0) uniform sampler smp; in vec3 uv0; in vec3 uv1; diff --git a/test/sapp/blend-sapp.glsl b/test/sapp/blend-sapp.glsl index 861a2945..be4d2ad8 100644 --- a/test/sapp/blend-sapp.glsl +++ b/test/sapp/blend-sapp.glsl @@ -11,7 +11,7 @@ void main() { @end @fs fs_bg -uniform bg_fs_params { +layout(binding=0) uniform bg_fs_params { float tick; }; @@ -26,7 +26,7 @@ void main() { @program bg vs_bg fs_bg @vs vs_quad -uniform quad_vs_params { +layout(binding=0) uniform quad_vs_params { mat4 mvp; }; diff --git a/test/sapp/cgltf-sapp.glsl b/test/sapp/cgltf-sapp.glsl index 5d0ef041..e4aaebf5 100644 --- a/test/sapp/cgltf-sapp.glsl +++ b/test/sapp/cgltf-sapp.glsl @@ -8,7 +8,7 @@ @ctype vec3 hmm_vec3 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 model; mat4 view_proj; vec3 eye_pos; @@ -51,31 +51,31 @@ struct material_info_t { vec3 specular_color; // color contribution from specular lighting }; -uniform metallic_params { +layout(binding=1) uniform metallic_params { vec4 base_color_factor; vec3 emissive_factor; float metallic_factor; float roughness_factor; }; -uniform light_params { +layout(binding=2) uniform light_params { vec3 light_pos; float light_range; vec3 light_color; float light_intensity; }; -uniform texture2D base_color_tex; -uniform texture2D metallic_roughness_tex; -uniform texture2D normal_tex; -uniform texture2D occlusion_tex; -uniform texture2D emissive_tex; +layout(binding=0) uniform texture2D base_color_tex; +layout(binding=1) uniform texture2D metallic_roughness_tex; +layout(binding=2) uniform texture2D normal_tex; +layout(binding=3) uniform texture2D occlusion_tex; +layout(binding=4) uniform texture2D emissive_tex; -uniform sampler base_color_smp; -uniform sampler metallic_roughness_smp; -uniform sampler normal_smp; -uniform sampler occlusion_smp; -uniform sampler emissive_smp; +layout(binding=0) uniform sampler base_color_smp; +layout(binding=1) uniform sampler metallic_roughness_smp; +layout(binding=2) uniform sampler normal_smp; +layout(binding=3) uniform sampler occlusion_smp; +layout(binding=4) uniform sampler emissive_smp; vec3 linear_to_srgb(vec3 linear) { return pow(linear, vec3(1.0/2.2)); @@ -275,4 +275,3 @@ void main() { @end @program cgltf_metallic vs metallic_fs - diff --git a/test/sapp/cube-sapp.glsl b/test/sapp/cube-sapp.glsl index 4dc4082c..7ff7bb6a 100644 --- a/test/sapp/cube-sapp.glsl +++ b/test/sapp/cube-sapp.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; diff --git a/test/sapp/cubemap-jpeg-sapp.glsl b/test/sapp/cubemap-jpeg-sapp.glsl index b71ebbf3..e71d6948 100644 --- a/test/sapp/cubemap-jpeg-sapp.glsl +++ b/test/sapp/cubemap-jpeg-sapp.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -15,8 +15,8 @@ void main() { @end @fs fs -uniform textureCube tex; -uniform sampler smp; +layout(binding=0) uniform textureCube tex; +layout(binding=0) uniform sampler smp; in vec3 uvw; out vec4 frag_color; diff --git a/test/sapp/cubemaprt-sapp.glsl b/test/sapp/cubemaprt-sapp.glsl index 67491965..05b90e78 100644 --- a/test/sapp/cubemaprt-sapp.glsl +++ b/test/sapp/cubemaprt-sapp.glsl @@ -6,7 +6,7 @@ // same vertex shader for offscreen- and default-pass @vs vs -uniform shape_uniforms { +layout(binding=0) uniform shape_uniforms { mat4 mvp; // model-view-projection matrix mat4 model; // model matrix vec4 shape_color; @@ -75,8 +75,8 @@ void main() { @include_block lighting @include_block fs_inputs -uniform textureCube tex; -uniform sampler smp; +layout(binding=0) uniform textureCube tex; +layout(binding=0) uniform sampler smp; out vec4 frag_color; void main() { diff --git a/test/sapp/debugtext-context-sapp.glsl b/test/sapp/debugtext-context-sapp.glsl index 30ed231e..d20ca3d3 100644 --- a/test/sapp/debugtext-context-sapp.glsl +++ b/test/sapp/debugtext-context-sapp.glsl @@ -4,7 +4,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -24,8 +24,8 @@ void main() { @end @fs fs -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec2 uv; out vec4 frag_color; diff --git a/test/sapp/drawcallperf-sapp.glsl b/test/sapp/drawcallperf-sapp.glsl index 0fc7efa3..5285f89c 100644 --- a/test/sapp/drawcallperf-sapp.glsl +++ b/test/sapp/drawcallperf-sapp.glsl @@ -2,11 +2,11 @@ @ctype vec4 hmm_vec4 @vs vs -uniform vs_per_frame { +layout(binding=0) uniform vs_per_frame { mat4 viewproj; }; -uniform vs_per_instance { +layout(binding=1) uniform vs_per_instance { vec4 world_pos; }; @@ -24,8 +24,8 @@ void main() { @end @fs fs -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec2 uv; in float bright; diff --git a/test/sapp/dyntex-sapp.glsl b/test/sapp/dyntex-sapp.glsl index 5bb8c3f3..86488609 100644 --- a/test/sapp/dyntex-sapp.glsl +++ b/test/sapp/dyntex-sapp.glsl @@ -4,7 +4,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -23,8 +23,8 @@ void main() { @end @fs fs -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; layout(location=0) in vec4 color; layout(location=1) in vec2 uv; out vec4 frag_color; diff --git a/test/sapp/dyntex3d-sapp.glsl b/test/sapp/dyntex3d-sapp.glsl new file mode 100644 index 00000000..ee583e39 --- /dev/null +++ b/test/sapp/dyntex3d-sapp.glsl @@ -0,0 +1,34 @@ +//------------------------------------------------------------------------------ +// shaders for dyntex3d-sapp sample +//------------------------------------------------------------------------------ +@ctype mat4 hmm_mat4 + +@vs vs +layout(binding=0) uniform vs_params { + float w; +}; + +const vec2 vertices[4] = { vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1) }; +const int indices[6] = { 0, 1, 2, 2, 3, 0 }; + +out vec3 uvw; + +void main() { + int idx = indices[gl_VertexIndex]; + gl_Position = vec4(vertices[idx] - 0.5, 0.5, 1.0); + uvw = vec3(vertices[idx], w); +} +@end + +@fs fs +layout(binding=0) uniform texture3D tex; +layout(binding=0) uniform sampler smp; +in vec3 uvw; +out vec4 frag_color; + +void main() { + frag_color = texture(sampler3D(tex, smp), uvw); +} +@end + +@program dyntex3d vs fs diff --git a/test/sapp/imgui-usercallback-sapp.glsl b/test/sapp/imgui-usercallback-sapp.glsl index 3d9ccb3b..5f9ab0ec 100644 --- a/test/sapp/imgui-usercallback-sapp.glsl +++ b/test/sapp/imgui-usercallback-sapp.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; diff --git a/test/sapp/instancing-pull-sapp.glsl b/test/sapp/instancing-pull-sapp.glsl index 945620fe..b6954a82 100644 --- a/test/sapp/instancing-pull-sapp.glsl +++ b/test/sapp/instancing-pull-sapp.glsl @@ -3,7 +3,7 @@ @ctype vec4 hmm_vec4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -16,11 +16,11 @@ struct sb_instance { vec3 pos; }; -readonly buffer vertices { +layout(binding=0) readonly buffer vertices { sb_vertex vtx[]; }; -readonly buffer instances { +layout(binding=1) readonly buffer instances { sb_instance inst[]; }; diff --git a/test/sapp/instancing-sapp.glsl b/test/sapp/instancing-sapp.glsl index eec40f0b..1a715804 100644 --- a/test/sapp/instancing-sapp.glsl +++ b/test/sapp/instancing-sapp.glsl @@ -4,7 +4,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; diff --git a/test/sapp/layerrender-sapp.glsl b/test/sapp/layerrender-sapp.glsl index 4b8fa5a3..43e1cc1a 100644 --- a/test/sapp/layerrender-sapp.glsl +++ b/test/sapp/layerrender-sapp.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @block vs_uniforms -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @end @@ -44,8 +44,8 @@ void main() { @end @fs fs_display -uniform texture2DArray tex; -uniform sampler smp; +layout(binding=0) uniform texture2DArray tex; +layout(binding=0) uniform sampler smp; in vec2 uv; out vec4 frag_color; @@ -58,4 +58,4 @@ void main() { } @end -@program display vs_display fs_display \ No newline at end of file +@program display vs_display fs_display diff --git a/test/sapp/loadpng-sapp.glsl b/test/sapp/loadpng-sapp.glsl index ec4e2888..13067ce1 100644 --- a/test/sapp/loadpng-sapp.glsl +++ b/test/sapp/loadpng-sapp.glsl @@ -4,7 +4,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -19,8 +19,8 @@ void main() { @end @fs fs -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec2 uv; out vec4 frag_color; diff --git a/test/sapp/mipmap-sapp.glsl b/test/sapp/mipmap-sapp.glsl index 371e4904..7de66863 100644 --- a/test/sapp/mipmap-sapp.glsl +++ b/test/sapp/mipmap-sapp.glsl @@ -4,7 +4,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -20,8 +20,8 @@ void main() { @end @fs fs -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec2 uv; out vec4 frag_color; diff --git a/test/sapp/miprender-sapp.glsl b/test/sapp/miprender-sapp.glsl index 036ca80c..5d5fafc6 100644 --- a/test/sapp/miprender-sapp.glsl +++ b/test/sapp/miprender-sapp.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @block uniforms -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @end @@ -44,8 +44,8 @@ void main() { @end @fs fs_display -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec2 uv; out vec4 frag_color; diff --git a/test/sapp/mrt-pixelformats-sapp.glsl b/test/sapp/mrt-pixelformats-sapp.glsl index 186c8ea6..43722666 100644 --- a/test/sapp/mrt-pixelformats-sapp.glsl +++ b/test/sapp/mrt-pixelformats-sapp.glsl @@ -7,7 +7,7 @@ //--- offscreen MRT shader @vs vs_offscreen -uniform offscreen_params { +layout(binding=0) uniform offscreen_params { mat4 mvp; }; @@ -62,13 +62,13 @@ void main() { @fs fs_quad @image_sample_type tex unfilterable_float @sampler_type smp nonfiltering -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec2 uv; out vec4 frag_color; -uniform quad_params { +layout(binding=0) uniform quad_params { float color_bias; float color_scale; }; diff --git a/test/sapp/mrt-sapp.glsl b/test/sapp/mrt-sapp.glsl index 736ff95e..57a0981d 100644 --- a/test/sapp/mrt-sapp.glsl +++ b/test/sapp/mrt-sapp.glsl @@ -7,7 +7,7 @@ // shaders for offscreen-pass rendering @vs vs_offscreen -uniform offscreen_params { +layout(binding=0) uniform offscreen_params { mat4 mvp; }; @@ -42,7 +42,7 @@ void main() { @vs vs_fsq @glsl_options flip_vert_y -uniform fsq_params { +layout(binding=0) uniform fsq_params { vec2 offset; }; @@ -61,10 +61,10 @@ void main() { @end @fs fs_fsq -uniform texture2D tex0; -uniform texture2D tex1; -uniform texture2D tex2; -uniform sampler smp; +layout(binding=0) uniform texture2D tex0; +layout(binding=1) uniform texture2D tex1; +layout(binding=2) uniform texture2D tex2; +layout(binding=0) uniform sampler smp; in vec2 uv0; in vec2 uv1; @@ -96,8 +96,8 @@ void main() { @end @fs fs_dbg -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec2 uv; out vec4 frag_color; diff --git a/test/sapp/noentry-dll-sapp.glsl b/test/sapp/noentry-dll-sapp.glsl index d8a31214..9a23d4ea 100644 --- a/test/sapp/noentry-dll-sapp.glsl +++ b/test/sapp/noentry-dll-sapp.glsl @@ -4,7 +4,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; diff --git a/test/sapp/noentry-sapp.glsl b/test/sapp/noentry-sapp.glsl index d8a31214..9a23d4ea 100644 --- a/test/sapp/noentry-sapp.glsl +++ b/test/sapp/noentry-sapp.glsl @@ -4,7 +4,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; diff --git a/test/sapp/noninterleaved-sapp.glsl b/test/sapp/noninterleaved-sapp.glsl index e42acff8..a4564c59 100644 --- a/test/sapp/noninterleaved-sapp.glsl +++ b/test/sapp/noninterleaved-sapp.glsl @@ -4,12 +4,12 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; -layout(location=0) in vec4 position; -layout(location=1) in vec4 color0; +in vec4 position; +in vec4 color0; out vec4 color; void main() { diff --git a/test/sapp/offscreen-msaa-sapp.glsl b/test/sapp/offscreen-msaa-sapp.glsl index f596465c..95180dd9 100644 --- a/test/sapp/offscreen-msaa-sapp.glsl +++ b/test/sapp/offscreen-msaa-sapp.glsl @@ -5,7 +5,7 @@ // shared code for all shaders @block uniforms -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @end @@ -53,8 +53,8 @@ void main() { @end @fs fs_display -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec4 nrm; in vec2 uv; diff --git a/test/sapp/offscreen-sapp.glsl b/test/sapp/offscreen-sapp.glsl index 554d1f9e..4da8921c 100644 --- a/test/sapp/offscreen-sapp.glsl +++ b/test/sapp/offscreen-sapp.glsl @@ -5,7 +5,7 @@ // shared code for all shaders @block uniforms -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @end @@ -53,8 +53,8 @@ void main() { @end @fs fs_default -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec4 nrm; in vec2 uv; diff --git a/test/sapp/ozz-skin-sapp.glsl b/test/sapp/ozz-skin-sapp.glsl index 013ea4bf..998aff7e 100644 --- a/test/sapp/ozz-skin-sapp.glsl +++ b/test/sapp/ozz-skin-sapp.glsl @@ -45,15 +45,15 @@ void skinned_pos_nrm(in vec4 pos, in vec4 nrm, in vec4 skin_weights, in vec4 ski @end @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 view_proj; float joint_pixel_width; }; @image_sample_type joint_tex unfilterable_float -uniform texture2D joint_tex; +layout(binding=0) uniform texture2D joint_tex; @sampler_type smp nonfiltering -uniform sampler smp; +layout(binding=0) uniform sampler smp; in vec4 position; in vec4 normal; diff --git a/test/sapp/ozz-storagebuffer-sapp.glsl b/test/sapp/ozz-storagebuffer-sapp.glsl index 3ec26bb3..c967d398 100644 --- a/test/sapp/ozz-storagebuffer-sapp.glsl +++ b/test/sapp/ozz-storagebuffer-sapp.glsl @@ -46,7 +46,7 @@ void skin_pos_nrm(in vec4 pos, in vec4 nrm, in vec4 jweights, in uint jindices, @end @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 view_proj; }; @@ -67,15 +67,15 @@ struct sb_joint { vec4 zzzz; }; -readonly buffer vertices { +layout(binding=0) readonly buffer vertices { sb_vertex vtx[]; }; -readonly buffer instances { +layout(binding=1) readonly buffer instances { sb_instance inst[]; }; -readonly buffer joints { +layout(binding=2) readonly buffer joints { sb_joint joint[]; }; diff --git a/test/sapp/pixelformats-sapp.glsl b/test/sapp/pixelformats-sapp.glsl index 0ef8f753..94d1e84d 100644 --- a/test/sapp/pixelformats-sapp.glsl +++ b/test/sapp/pixelformats-sapp.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @vs vs_cube -uniform cube_vs_params { +layout(binding=0) uniform cube_vs_params { mat4 mvp; }; in vec4 pos; @@ -34,7 +34,7 @@ void main() { @end @fs fs_bg -uniform bg_fs_params { +layout(binding=0) uniform bg_fs_params { float tick; }; diff --git a/test/sapp/plmpeg-sapp.glsl b/test/sapp/plmpeg-sapp.glsl index cee56ce9..4df3db4b 100644 --- a/test/sapp/plmpeg-sapp.glsl +++ b/test/sapp/plmpeg-sapp.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -18,10 +18,10 @@ void main() { @end @fs fs -uniform texture2D tex_y; -uniform texture2D tex_cb; -uniform texture2D tex_cr; -uniform sampler smp; +layout(binding=0) uniform texture2D tex_y; +layout(binding=1) uniform texture2D tex_cb; +layout(binding=2) uniform texture2D tex_cr; +layout(binding=0) uniform sampler smp; in vec2 uv; out vec4 frag_color; diff --git a/test/sapp/primtypes-sapp.glsl b/test/sapp/primtypes-sapp.glsl index 842d9100..1d3cb335 100644 --- a/test/sapp/primtypes-sapp.glsl +++ b/test/sapp/primtypes-sapp.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; float point_size; }; diff --git a/test/sapp/restart-sapp.glsl b/test/sapp/restart-sapp.glsl index 06e26d07..3905f026 100644 --- a/test/sapp/restart-sapp.glsl +++ b/test/sapp/restart-sapp.glsl @@ -5,7 +5,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -20,8 +20,8 @@ void main() { @end @fs fs -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec2 uv; out vec4 frag_color; diff --git a/test/sapp/sdf-sapp.glsl b/test/sapp/sdf-sapp.glsl index c0bd6984..78cdc104 100644 --- a/test/sapp/sdf-sapp.glsl +++ b/test/sapp/sdf-sapp.glsl @@ -6,7 +6,7 @@ //--- vertex shader @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { float aspect; float time; }; diff --git a/test/sapp/shadows-depthtex-sapp.glsl b/test/sapp/shadows-depthtex-sapp.glsl index bf693c21..cfb01ff5 100644 --- a/test/sapp/shadows-depthtex-sapp.glsl +++ b/test/sapp/shadows-depthtex-sapp.glsl @@ -5,7 +5,7 @@ @vs vs_shadow @glsl_options fixup_clipspace // important: map clipspace z from -1..+1 to 0..+1 on GL -uniform vs_shadow_params { +layout(binding=0) uniform vs_shadow_params { mat4 mvp; }; @@ -25,7 +25,7 @@ void main() { } //=== display pass @vs vs_display -uniform vs_display_params { +layout(binding=0) uniform vs_display_params { mat4 mvp; mat4 model; mat4 light_mvp; @@ -53,13 +53,13 @@ void main() { @fs fs_display -uniform fs_display_params { +layout(binding=1) uniform fs_display_params { vec3 light_dir; vec3 eye_pos; }; -uniform texture2D shadow_map; -uniform sampler shadow_sampler; +layout(binding=0) uniform texture2D shadow_map; +layout(binding=0) uniform sampler shadow_sampler; in vec3 color; in vec4 light_proj_pos; @@ -117,8 +117,8 @@ void main() { @fs fs_dbg @image_sample_type dbg_tex unfilterable_float @sampler_type dbg_smp nonfiltering -uniform texture2D dbg_tex; -uniform sampler dbg_smp; +layout(binding=0) uniform texture2D dbg_tex; +layout(binding=0) uniform sampler dbg_smp; in vec2 uv; out vec4 frag_color; diff --git a/test/sapp/shadows-sapp.glsl b/test/sapp/shadows-sapp.glsl index 01eeafbe..8289df7d 100644 --- a/test/sapp/shadows-sapp.glsl +++ b/test/sapp/shadows-sapp.glsl @@ -43,7 +43,7 @@ float sample_shadow_pcf(texture2D tex, sampler smp, vec3 uv_depth, vec2 sm_size) //=== shadow pass @vs vs_shadow -uniform vs_shadow_params { +layout(binding=0) uniform vs_shadow_params { mat4 mvp; }; @@ -73,7 +73,7 @@ void main() { //=== display pass @vs vs_display -uniform vs_display_params { +layout(binding=0) uniform vs_display_params { mat4 mvp; mat4 model; mat4 light_mvp; @@ -102,13 +102,13 @@ void main() { @fs fs_display @include_block util -uniform fs_display_params { +layout(binding=1) uniform fs_display_params { vec3 light_dir; vec3 eye_pos; }; -uniform texture2D shadow_map; -uniform sampler shadow_sampler; +layout(binding=0) uniform texture2D shadow_map; +layout(binding=0) uniform sampler shadow_sampler; in vec3 color; in vec4 light_proj_pos; @@ -167,8 +167,8 @@ void main() { @fs fs_dbg @include_block util -uniform texture2D dbg_tex; -uniform sampler dbg_smp; +layout(binding=0) uniform texture2D dbg_tex; +layout(binding=0) uniform sampler dbg_smp; in vec2 uv; out vec4 frag_color; diff --git a/test/sapp/shapes-sapp.glsl b/test/sapp/shapes-sapp.glsl index 06799db0..a3033e59 100644 --- a/test/sapp/shapes-sapp.glsl +++ b/test/sapp/shapes-sapp.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; float draw_mode; }; diff --git a/test/sapp/shapes-transform-sapp.glsl b/test/sapp/shapes-transform-sapp.glsl index 2247ecc0..2bea6a56 100644 --- a/test/sapp/shapes-transform-sapp.glsl +++ b/test/sapp/shapes-transform-sapp.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { float draw_mode; mat4 mvp; }; diff --git a/test/sapp/shdfeatures-sapp.glsl b/test/sapp/shdfeatures-sapp.glsl index 3a9bc4e5..81e4c23e 100644 --- a/test/sapp/shdfeatures-sapp.glsl +++ b/test/sapp/shdfeatures-sapp.glsl @@ -49,7 +49,7 @@ void skinned_pos_nrm(in vec4 pos, in vec4 nrm, in vec4 skin_weights, in vec4 ski @block light_utils #if defined(LIGHTING) || defined(MATERIAL) -uniform phong_params { +layout(binding=1) uniform phong_params { #ifdef LIGHTING vec3 light_dir; vec3 eye_pos; @@ -82,7 +82,7 @@ vec4 phong(vec3 pos, vec3 nrm, vec3 l, vec3 eye, vec3 lcolor, vec3 diffuse, vec3 @end @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; mat4 model; #ifdef SKINNING @@ -96,8 +96,8 @@ in vec3 normal; #ifdef SKINNING @image_sample_type joint_tex unfilterable_float @sampler_type smp nonfiltering -uniform texture2D joint_tex; -uniform sampler smp; +layout(binding=0) uniform texture2D joint_tex; +layout(binding=0) uniform sampler smp; in vec4 jindices; in vec4 jweights; @include_block skin_utils diff --git a/test/sapp/tex3d-sapp.glsl b/test/sapp/tex3d-sapp.glsl index 40081c27..a2115444 100644 --- a/test/sapp/tex3d-sapp.glsl +++ b/test/sapp/tex3d-sapp.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; float scale; }; @@ -16,8 +16,8 @@ void main() { @end @fs fs -uniform texture3D tex; -uniform sampler smp; +layout(binding=0) uniform texture3D tex; +layout(binding=0) uniform sampler smp; in vec3 uvw; out vec4 frag_color; diff --git a/test/sapp/texcube-sapp.glsl b/test/sapp/texcube-sapp.glsl index 2aed854e..b771bcac 100644 --- a/test/sapp/texcube-sapp.glsl +++ b/test/sapp/texcube-sapp.glsl @@ -7,7 +7,7 @@ #pragma sokol @ctype mat4 hmm_mat4 #pragma sokol @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -26,8 +26,8 @@ void main() { #pragma sokol @end #pragma sokol @fs fs -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec4 color; in vec2 uv; diff --git a/test/sapp/triangle-bufferless-sapp.glsl b/test/sapp/triangle-bufferless-sapp.glsl index 3c8ae176..8e1936ab 100644 --- a/test/sapp/triangle-bufferless-sapp.glsl +++ b/test/sapp/triangle-bufferless-sapp.glsl @@ -14,8 +14,8 @@ const vec3 positions[3] = { out vec4 color; void main() { - gl_Position = vec4(positions[gl_VertexIndex & 3], 1.0); - color = colors[gl_VertexIndex & 3]; + gl_Position = vec4(positions[gl_VertexIndex], 1.0); + color = colors[gl_VertexIndex]; } @end diff --git a/test/sapp/uniformtypes-sapp.glsl b/test/sapp/uniformtypes-sapp.glsl index a5786924..efca41cc 100644 --- a/test/sapp/uniformtypes-sapp.glsl +++ b/test/sapp/uniformtypes-sapp.glsl @@ -4,7 +4,7 @@ // inefficient in the sokol-gfx GL backend, because the uniform // block will not be flattened into a single float or int array! // -uniform vs_params { +layout(binding=0) uniform vs_params { vec2 offset; vec2 scale; // scramble the vector sizes to enforce 'weird' padding @@ -67,4 +67,3 @@ void main() { @end @program uniformtypes vs fs - diff --git a/test/sapp/uvwrap-sapp.glsl b/test/sapp/uvwrap-sapp.glsl index f012e19d..12dd313b 100644 --- a/test/sapp/uvwrap-sapp.glsl +++ b/test/sapp/uvwrap-sapp.glsl @@ -3,7 +3,7 @@ // Shader code for uvwrap-sapp sample. //------------------------------------------------------------------------------ @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { vec2 offset; vec2 scale; }; @@ -18,8 +18,8 @@ void main() { @end @fs fs -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec2 uv; out vec4 frag_color; diff --git a/test/sapp/vertexpull-sapp.glsl b/test/sapp/vertexpull-sapp.glsl index b70aac21..1760195f 100644 --- a/test/sapp/vertexpull-sapp.glsl +++ b/test/sapp/vertexpull-sapp.glsl @@ -1,7 +1,7 @@ @ctype mat4 hmm_mat4 @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -11,14 +11,15 @@ struct sb_vertex { vec4 color; }; -readonly buffer ssbo { +layout(binding=0) readonly buffer ssbo { sb_vertex vtx[]; }; out vec4 color; void main() { - gl_Position = mvp * vec4(vtx[gl_VertexIndex].pos, 1.0); + vec4 position = vec4(vtx[gl_VertexIndex].pos, 1.0); + gl_Position = mvp * position; color = vtx[gl_VertexIndex].color; } @end @@ -32,4 +33,4 @@ void main() { } @end -@program vertexpull vs fs \ No newline at end of file +@program vertexpull vs fs diff --git a/test/sgl.glsl b/test/sgl.glsl index 09dfd3dd..62a9df48 100644 --- a/test/sgl.glsl +++ b/test/sgl.glsl @@ -1,5 +1,5 @@ @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { uniform mat4 mvp; uniform mat4 tm; }; @@ -16,8 +16,8 @@ void main() { @end @fs fs -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec4 uv; in vec4 color; out vec4 frag_color; diff --git a/test/shared_ub.glsl b/test/shared_ub.glsl index 4c602b35..00bb9921 100644 --- a/test/shared_ub.glsl +++ b/test/shared_ub.glsl @@ -1,6 +1,6 @@ @block shared -uniform params { +layout(binding=0) uniform params { mat4 mvp; float bla; }; @@ -17,7 +17,7 @@ void main() { @end @vs vs2 -uniform xxx { +layout(binding=1) uniform xxx { float blub; }; @include_block shared diff --git a/test/uniform_types.glsl b/test/uniform_types.glsl index 8b43222a..09ff4941 100644 --- a/test/uniform_types.glsl +++ b/test/uniform_types.glsl @@ -1,6 +1,6 @@ @vs vs -uniform params { +layout(binding=0) uniform params { mat4 mvp[3]; ivec4 b2[1]; }; @@ -21,4 +21,4 @@ void main() { } @end -@program shd vs fs +@program shd vs fs From 481f882b1dc716ea419ab6a69ae8b0411466a0f0 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Fri, 18 Oct 2024 19:15:00 +0200 Subject: [PATCH 22/37] add missing case break and minor code cleanup --- src/shdc/types/reflection/bindings.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/shdc/types/reflection/bindings.h b/src/shdc/types/reflection/bindings.h index ee5b0331..73ee273c 100644 --- a/src/shdc/types/reflection/bindings.h +++ b/src/shdc/types/reflection/bindings.h @@ -67,6 +67,7 @@ inline uint32_t Bindings::base_slot(Slang::Enum slang, ShaderStage::Enum stage, if (Slang::is_glsl(slang)) { res = ShaderStage::is_vs(stage) ? 0 : MaxImageSamplers; } + break; case Type::IMAGE: if (Slang::is_wgsl(slang)) { if (ShaderStage::is_fs(stage)) { @@ -96,8 +97,6 @@ inline uint32_t Bindings::base_slot(Slang::Enum slang, ShaderStage::Enum stage, if (ShaderStage::is_fs(stage)) { res += 64; } - } else if (Slang::is_glsl(slang)) { - } break; } From 3ae2448d4a93802410f2b4ec642814e3d98428d0 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Fri, 18 Oct 2024 19:18:13 +0200 Subject: [PATCH 23/37] fix gcc compilation (redundant inline) --- src/shdc/input.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shdc/input.cc b/src/shdc/input.cc index 0a23eb0c..6f6c45e8 100644 --- a/src/shdc/input.cc +++ b/src/shdc/input.cc @@ -49,7 +49,7 @@ const ImageSampleTypeTag* Input::find_image_sample_type_tag(const std::string& t } } -inline const SamplerTypeTag* Input::find_sampler_type_tag(const std::string& smp_name) const { +const SamplerTypeTag* Input::find_sampler_type_tag(const std::string& smp_name) const { auto it = sampler_type_tags.find(smp_name); if (it != sampler_type_tags.end()) { return &sampler_type_tags.at(smp_name); From 588e78647911877e5e711ea8f0d67f3490601ee1 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 19 Oct 2024 15:16:10 +0200 Subject: [PATCH 24/37] fix sokol-zig code generator for sokol-gfx bindings cleanup --- src/shdc/generators/sokolzig.cc | 372 ++++++++++++++++---------------- src/shdc/generators/sokolzig.h | 1 + 2 files changed, 184 insertions(+), 189 deletions(-) diff --git a/src/shdc/generators/sokolzig.cc b/src/shdc/generators/sokolzig.cc index 857516be..f672873f 100644 --- a/src/shdc/generators/sokolzig.cc +++ b/src/shdc/generators/sokolzig.cc @@ -209,21 +209,10 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR Slang::Enum slang = Slang::from_index(i); if (gen.args.slang & Slang::bit(slang)) { l_open("{} => {{\n", backend(slang)); - for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { - const StageAttr& attr = prog.vs().inputs[attr_index]; - if (attr.slot >= 0) { - if (Slang::is_glsl(slang)) { - l("desc.attrs[{}].name = \"{}\";\n", attr_index, attr.name); - } else if (Slang::is_hlsl(slang)) { - l("desc.attrs[{}].sem_name = \"{}\";\n", attr_index, attr.sem_name); - l("desc.attrs[{}].sem_index = {};\n", attr_index, attr.sem_index); - } - } - } for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("desc.{}", pystring::lower(ShaderStage::to_str(refl.stage))); + const std::string dsn = fmt::format("desc.{}", info.stage == ShaderStage::Vertex ? "vertex_func" : "fragment_func"); if (info.has_bytecode) { l("{}.bytecode.ptr = &{};\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {};\n", dsn, info.bytecode_array_size); @@ -240,66 +229,108 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); - if (ub) { - const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); - l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); - l("{}.layout = .STD140;\n", ubn); - if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { - if (ub->flattened) { - l("{}.uniforms[0].name = \"{}\";\n", ubn, ub->name); - // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) - l("{}.uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); - l("{}.uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); - } else { - for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { - const Type& u = ub->struct_info.struct_items[u_index]; - const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); - l("{}.name = \"{}.{}\";\n", un, ub->inst_name, u.name); - l("{}.type = {};\n", un, uniform_type(u.type)); - l("{}.array_count = {};\n", un, u.array_count); - } + } + for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { + const StageAttr& attr = prog.vs().inputs[attr_index]; + if (attr.slot >= 0) { + if (Slang::is_glsl(slang)) { + l("desc.attrs[{}].glsl_name = \"{}\";\n", attr_index, attr.name); + } else if (Slang::is_hlsl(slang)) { + l("desc.attrs[{}].hlsl_sem_name = \"{}\";\n", attr_index, attr.sem_name); + l("desc.attrs[{}].hlsl_sem_index = {};\n", attr_index, attr.sem_index); + } + } + } + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { + const UniformBlock* ub = prog.bindings.find_uniform_block_by_sokol_slot(ub_index); + if (ub) { + const std::string ubn = fmt::format("desc.uniform_blocks[{}]", ub_index); + l("{}.stage = {};\n", ubn, shader_stage(ub->stage)); + l("{}.layout = .STD140;\n", ubn); + l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_b_n = {};\n", ubn, ub->hlsl_register_b_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_buffer_n = {};\n", ubn, ub->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group0_binding_n = {};\n", ubn, ub->wgsl_group0_binding_n); + } else if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { + if (ub->flattened) { + // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) + l("{}.glsl_uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); + l("{}.glsl_uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); + l("{}.glsl_uniforms[0].glsl_name = \"{}\";\n", ubn, ub->name); + } else { + for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { + const Type& u = ub->struct_info.struct_items[u_index]; + const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); + l("{}.type = {};\n", un, uniform_type(u.type)); + l("{}.offset = {};", un, u.offset); + l("{}.array_count = {};\n", un, u.array_count); + l("{}.glsl_name = \"{}.{}\";\n", un, ub->inst_name, u.name); } } } } - for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); - if (sbuf) { - const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); - l("{}.used = true;\n", sbn); - l("{}.readonly = {};\n", sbn, sbuf->readonly); + } + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { + const StorageBuffer* sbuf = prog.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); + if (sbuf) { + const std::string& sbn = fmt::format("desc.storage_buffers[{}]", sbuf_index); + l("{}.stage = {};\n", sbn, shader_stage(sbuf->stage)); + l("{}.readonly = {};\n", sbn, sbuf->readonly); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_t_n = {};\n", sbn, sbuf->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_buffer_n = {};\n", sbn, sbuf->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", sbn, sbuf->wgsl_group1_binding_n); + } else if (Slang::is_glsl(slang)) { + l("{}.glsl_binding_n = {};\n", sbn, sbuf->glsl_binding_n); } } - for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); - if (img) { - const std::string in = fmt::format("{}.images[{}]", dsn, img_index); - l("{}.used = true;\n", in); - l("{}.multisampled = {};\n", in, img->multisampled ? "true" : "false"); - l("{}.image_type = {};\n", in, image_type(img->type)); - l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); + } + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { + const Image* img = prog.bindings.find_image_by_sokol_slot(img_index); + if (img) { + const std::string in = fmt::format("desc.images[{}]", img_index); + l("{}.stage = {};\n", in, shader_stage(img->stage)); + l("{}.multisampled = {};\n", in, img->multisampled ? "true" : "false"); + l("{}.image_type = {};\n", in, image_type(img->type)); + l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_t_n = {};\n", in, img->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_texture_n = {};\n", in, img->msl_texture_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", in, img->wgsl_group1_binding_n); } } - for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); - if (smp) { - const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); - l("{}.used = true;\n", sn); - l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); + } + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { + const Sampler* smp = prog.bindings.find_sampler_by_sokol_slot(smp_index); + if (smp) { + const std::string sn = fmt::format("desc.samplers[{}]", smp_index); + l("{}.stage = {};\n", sn, shader_stage(smp->stage)); + l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_s_n = {};\n", sn, smp->hlsl_register_s_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_sampler_n = {};\n", sn, smp->msl_sampler_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", sn, smp->wgsl_group1_binding_n); } } - for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); - if (img_smp) { - const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); - l("{}.used = true;\n", isn); - l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); - l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); - if (Slang::is_glsl(slang)) { - l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); - } + } + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { + const ImageSampler* img_smp = prog.bindings.find_image_sampler_by_sokol_slot(img_smp_index); + if (img_smp) { + const std::string isn = fmt::format("desc.image_sampler_pairs[{}]", img_smp_index); + l("{}.stage = {};\n", isn, shader_stage(img_smp->stage)); + l("{}.image_slot = {};\n", isn, prog.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.sampler_slot = {};\n", isn, prog.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); + if (Slang::is_glsl(slang)) { + l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); } } } @@ -348,6 +379,14 @@ std::string SokolZigGenerator::get_shader_desc_help(const std::string& prog_name return fmt::format("shd.{}ShaderDesc(sg.queryBackend());\n", to_camel_case(prog_name)); } +std::string SokolZigGenerator::shader_stage(ShaderStage::Enum e) { + switch (e) { + case ShaderStage::Vertex: return ".VERTEX"; + case ShaderStage::Fragment: return ".FRAGMENT"; + default: return "INVALID"; + } +} + std::string SokolZigGenerator::uniform_type(Type::Enum e) { switch (e) { case Type::Float: return ".FLOAT"; @@ -495,195 +534,150 @@ void SokolZigGenerator::gen_attr_slot_refl_func(const GenInput& gen, const Progr } void SokolZigGenerator::gen_image_slot_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("pub fn {}ImageSlot(stage: sg.ShaderStage, img_name: []const u8) ?usize {{\n", to_camel_case(prog.name)); - bool wrote_stage = false; + l_open("pub fn {}ImageSlot(img_name: []const u8) ?usize {{\n", to_camel_case(prog.name)); bool wrote_image = false; - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.images.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); - wrote_stage = true; - for (const Image& img: refl.bindings.images) { - if (img.sokol_slot >= 0) { - l_open("if (std.mem.eql(u8, img_name, \"{}\")) {{\n", img.name); - l("return {};\n", img.sokol_slot); - l_close("}}\n"); - wrote_image = true; - } - } + for (const Image& img: prog.bindings.images) { + if (img.sokol_slot >= 0) { + l_open("if (std.mem.eql(u8, img_name, \"{}\")) {{\n", img.name); + l("return {};\n", img.sokol_slot); l_close("}}\n"); + wrote_image = true; } } - if(!wrote_stage) l("_ = stage;\n"); - if(!wrote_image) l("_ = img_name;\n"); + if (!wrote_image) { + l("_ = img_name;\n"); + } l("return null;\n"); l_close("}}\n"); } void SokolZigGenerator::gen_sampler_slot_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("pub fn {}SamplerSlot(stage: sg.ShaderStage, smp_name: []const u8) ?usize {{\n", to_camel_case(prog.name)); - bool wrote_stage = false; + l_open("pub fn {}SamplerSlot(smp_name: []const u8) ?usize {{\n", to_camel_case(prog.name)); bool wrote_smp = false; - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.samplers.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); - wrote_stage = true; - for (const Sampler& smp: refl.bindings.samplers) { - if (smp.sokol_slot >= 0) { - l_open("if (std.mem.eql(u8, smp_name, \"{}\")) {{\n", smp.name); - l("return {};\n", smp.sokol_slot); - l_close("}}\n"); - wrote_smp = true; - } - } + for (const Sampler& smp: prog.bindings.samplers) { + if (smp.sokol_slot >= 0) { + l_open("if (std.mem.eql(u8, smp_name, \"{}\")) {{\n", smp.name); + l("return {};\n", smp.sokol_slot); l_close("}}\n"); + wrote_smp = true; } } - if(!wrote_stage) l("_ = stage;\n"); - if(!wrote_smp) l("_ = smp_name;\n"); + if (!wrote_smp) { + l("_ = smp_name;\n"); + } l("return null;\n"); l_close("}}\n"); } void SokolZigGenerator::gen_uniform_block_slot_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("pub fn {}UniformblockSlot(stage: sg.ShaderStage, ub_name: []const u8) ?usize {{\n", to_camel_case(prog.name)); - bool wrote_stage = false; + l_open("pub fn {}UniformblockSlot(ub_name: []const u8) ?usize {{\n", to_camel_case(prog.name)); bool wrote_ub_name = false; - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.uniform_blocks.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); - wrote_stage = true; - for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.sokol_slot >= 0) { - l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.name); - l("return {};\n", ub.sokol_slot); - l_close("}}\n"); - wrote_ub_name = true; - } - } + for (const UniformBlock& ub: prog.bindings.uniform_blocks) { + if (ub.sokol_slot >= 0) { + l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.name); + l("return {};\n", ub.sokol_slot); l_close("}}\n"); + wrote_ub_name = true; } } - if(!wrote_stage) l("_ = stage;\n"); - if(!wrote_ub_name) l("_ = ub_name;\n"); + if (!wrote_ub_name) { + l("_ = ub_name;\n"); + } l("return null;\n"); l_close("}}\n"); } void SokolZigGenerator::gen_uniform_block_size_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("pub fn {}UniformblockSize(stage: sg.ShaderStage, ub_name: []const u8) ?usize {{\n", to_camel_case(prog.name)); - bool wrote_stage = false; + l_open("pub fn {}UniformblockSize(ub_name: []const u8) ?usize {{\n", to_camel_case(prog.name)); bool wrote_ub_name = false; - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.uniform_blocks.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); - wrote_stage = true; - for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.sokol_slot >= 0) { - l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.name); - l("return @sizeOf({});\n", struct_name(ub.name)); - l_close("}}\n"); - wrote_ub_name = true; - } - } + for (const UniformBlock& ub: prog.bindings.uniform_blocks) { + if (ub.sokol_slot >= 0) { + l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.name); + l("return @sizeOf({});\n", struct_name(ub.name)); l_close("}}\n"); + wrote_ub_name = true; } } - if(!wrote_stage) l("_ = stage;\n"); - if(!wrote_ub_name) l("_ = ub_name;\n"); + if (!wrote_ub_name) { + l("_ = ub_name;\n"); + } l("return null;\n"); l_close("}}\n"); } void SokolZigGenerator::gen_storage_buffer_slot_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("pub fn {}StoragebufferSlot(stage: sg.ShaderStage, sbuf_name: []const u8) ?usize {{\n", to_camel_case(prog.name)); - bool wrote_stage = false; + l_open("pub fn {}StoragebufferSlot(sbuf_name: []const u8) ?usize {{\n", to_camel_case(prog.name)); bool wrote_sbuf_name = false; - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.storage_buffers.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); - wrote_stage = true; - for (const StorageBuffer& sbuf: refl.bindings.storage_buffers) { - if (sbuf.sokol_slot >= 0) { - l_open("if (std.mem.eql(u8, sbuf_name, \"{}\")) {{\n", sbuf.name); - l("return {};\n", sbuf.sokol_slot); - l_close("}}\n"); - wrote_sbuf_name = true; - } - } + for (const StorageBuffer& sbuf: prog.bindings.storage_buffers) { + if (sbuf.sokol_slot >= 0) { + l_open("if (std.mem.eql(u8, sbuf_name, \"{}\")) {{\n", sbuf.name); + l("return {};\n", sbuf.sokol_slot); l_close("}}\n"); + wrote_sbuf_name = true; } } - if(!wrote_stage) l("_ = stage;\n"); - if(!wrote_sbuf_name) l("_ = sbuf_name;\n"); + if (!wrote_sbuf_name) { + l("_ = sbuf_name;\n"); + } l("return null;\n"); l_close("}}\n"); } void SokolZigGenerator::gen_uniform_offset_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("pub fn {}UniformOffset(stage: sg.ShaderStage, ub_name: []const u8, u_name: []const u8) ?usize {{\n", to_camel_case(prog.name)); - bool wrote_stage = false; + l_open("pub fn {}UniformOffset(ub_name: []const u8, u_name: []const u8) ?usize {{\n", to_camel_case(prog.name)); bool wrote_ub_name = false; bool wrote_u_name = false; - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.uniform_blocks.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); - wrote_stage = true; - for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.sokol_slot >= 0) { - l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.name); - wrote_ub_name = true; - for (const Type& u: ub.struct_info.struct_items) { - l_open("if (std.mem.eql(u8, u_name, \"{}\")) {{\n", u.name); - l("return {};\n", u.offset); - l_close("}}\n"); - wrote_u_name = true; - } - l_close("}}\n"); - } + for (const UniformBlock& ub: prog.bindings.uniform_blocks) { + if (ub.sokol_slot >= 0) { + l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.name); + wrote_ub_name = true; + for (const Type& u: ub.struct_info.struct_items) { + l_open("if (std.mem.eql(u8, u_name, \"{}\")) {{\n", u.name); + l("return {};\n", u.offset); + l_close("}}\n"); + wrote_u_name = true; } l_close("}}\n"); } } - if(!wrote_stage) l("_ = stage;\n"); - if(!wrote_ub_name) l("_ = ub_name;\n"); - if(!wrote_u_name) l("_ = u_name;\n"); + if (!wrote_ub_name) { + l("_ = ub_name;\n"); + } + if (!wrote_u_name) { + l("_ = u_name;\n"); + } l("return null;\n"); l_close("}}\n"); } void SokolZigGenerator::gen_uniform_desc_refl_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("pub fn {}UniformDesc(stage: sg.ShaderStage, ub_name: []const u8, u_name: []const u8) ?sg.ShaderUniformDesc {{\n", to_camel_case(prog.name)); - bool wrote_stage = false; + l_open("pub fn {}UniformDesc(ub_name: []const u8, u_name: []const u8) ?sg.GlslShaderUniformDesc {{\n", to_camel_case(prog.name)); bool wrote_ub_name = false; bool wrote_u_name = false; - - for (const StageReflection& refl: prog.stages) { - if (!refl.bindings.uniform_blocks.empty()) { - l_open("if (sg.ShaderStage.{} == stage) {{\n", pystring::upper(ShaderStage::to_str(refl.stage))); - wrote_stage = true; - for (const UniformBlock& ub: refl.bindings.uniform_blocks) { - if (ub.sokol_slot >= 0) { - l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.name); - wrote_ub_name = true; - for (const Type& u: ub.struct_info.struct_items) { - l_open("if (std.mem.eql(u8, u_name, \"{}\")) {{\n", u.name); - l("var desc: sg.ShaderUniformDesc = .{{}};\n"); - l("desc.name = \"{}\";\n", u.name); - l("desc.type = {};\n", uniform_type(u.type)); - l("desc.array_count = {};\n", u.array_count); - l("return desc;\n"); - l_close("}}\n"); - wrote_u_name = true; - } - l_close("}}\n"); - } + for (const UniformBlock& ub: prog.bindings.uniform_blocks) { + if (ub.sokol_slot >= 0) { + l_open("if (std.mem.eql(u8, ub_name, \"{}\")) {{\n", ub.name); + wrote_ub_name = true; + for (const Type& u: ub.struct_info.struct_items) { + l_open("if (std.mem.eql(u8, u_name, \"{}\")) {{\n", u.name); + l("var desc: sg.ShaderUniformDesc = .{{}};\n"); + l("desc.type = {};\n", uniform_type(u.type)); + l("desc.offset = {};\n", u.offset); + l("desc.array_count = {};\n", u.array_count); + l("desc.glsl_name = \"{}\";\n", u.name); + l("return desc;\n"); + l_close("}}\n"); + wrote_u_name = true; } l_close("}}\n"); } } - if(!wrote_stage) l("_ = stage;\n"); - if(!wrote_ub_name) l("_ = ub_name;\n"); - if(!wrote_u_name) l("_ = u_name;\n"); + if (!wrote_ub_name) { + l("_ = ub_name;\n"); + } + if (!wrote_u_name) { + l("_ = u_name;\n"); + } l("return null;\n"); l_close("}}\n"); } diff --git a/src/shdc/generators/sokolzig.h b/src/shdc/generators/sokolzig.h index 8cbc1936..9896ce05 100644 --- a/src/shdc/generators/sokolzig.h +++ b/src/shdc/generators/sokolzig.h @@ -28,6 +28,7 @@ class SokolZigGenerator: public Generator { virtual std::string shader_bytecode_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string shader_source_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string get_shader_desc_help(const std::string& prog_name); + virtual std::string shader_stage(refl::ShaderStage::Enum e); virtual std::string uniform_type(refl::Type::Enum e); virtual std::string flattened_uniform_type(refl::Type::Enum e); virtual std::string image_type(refl::ImageType::Enum e); From 4c270e5fe5e477aed69c96e8388fddf386d3f658 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 19 Oct 2024 16:50:07 +0200 Subject: [PATCH 25/37] fix sokol-odin code generator for sokol-gfx bindings cleanup --- src/shdc/generators/sokolodin.cc | 163 +++++++++++++++++++------------ src/shdc/generators/sokolodin.h | 1 + 2 files changed, 102 insertions(+), 62 deletions(-) diff --git a/src/shdc/generators/sokolodin.cc b/src/shdc/generators/sokolodin.cc index 207b45bf..85243f52 100644 --- a/src/shdc/generators/sokolodin.cc +++ b/src/shdc/generators/sokolodin.cc @@ -198,21 +198,10 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program Slang::Enum slang = Slang::from_index(i); if (gen.args.slang & Slang::bit(slang)) { l_open("case {}:\n", backend(slang)); - for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { - const StageAttr& attr = prog.vs().inputs[attr_index]; - if (attr.slot >= 0) { - if (Slang::is_glsl(slang)) { - l("desc.attrs[{}].name = \"{}\"\n", attr_index, attr.name); - } else if (Slang::is_hlsl(slang)) { - l("desc.attrs[{}].sem_name = \"{}\"\n", attr_index, attr.sem_name); - l("desc.attrs[{}].sem_index = {}\n", attr_index, attr.sem_index); - } - } - } for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("desc.{}", pystring::lower(ShaderStage::to_str(refl.stage))); + const std::string dsn = fmt::format("desc.{}", info.stage == ShaderStage::Vertex ? "vertex_func" : "fragment_func"); if (info.has_bytecode) { l("{}.bytecode.ptr = &{}\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {}\n", dsn, info.bytecode_array_size); @@ -229,66 +218,108 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } l("{}.entry = \"{}\"\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); - if (ub) { - const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); - l("{}.size = {}\n", ubn, roundup(ub->struct_info.size, 16)); - l("{}.layout = .STD140\n", ubn); - if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { - if (ub->flattened) { - l("{}.uniforms[0].name = \"{}\"\n", ubn, ub->name); - // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) - l("{}.uniforms[0].type = {}\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); - l("{}.uniforms[0].array_count = {}\n", ubn, roundup(ub->struct_info.size, 16) / 16); - } else { - for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { - const Type& u = ub->struct_info.struct_items[u_index]; - const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); - l("{}.name = \"{}.{}\"\n", un, ub->inst_name, u.name); - l("{}.type = {}\n", un, uniform_type(u.type)); - l("{}.array_count = {}\n", un, u.array_count); - } + } + for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { + const StageAttr& attr = prog.vs().inputs[attr_index]; + if (attr.slot >= 0) { + if (Slang::is_glsl(slang)) { + l("desc.attrs[{}].glsl_name = \"{}\"\n", attr_index, attr.name); + } else if (Slang::is_hlsl(slang)) { + l("desc.attrs[{}].hlsl_sem_name = \"{}\"\n", attr_index, attr.sem_name); + l("desc.attrs[{}].hlsl_sem_index = {}\n", attr_index, attr.sem_index); + } + } + } + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { + const UniformBlock* ub = prog.bindings.find_uniform_block_by_sokol_slot(ub_index); + if (ub) { + const std::string ubn = fmt::format("desc.uniform_blocks[{}]", ub_index); + l("{}.stage = {}\n", ubn, shader_stage(ub->stage)); + l("{}.layout = .STD140\n", ubn); + l("{}.size = {}\n", ubn, roundup(ub->struct_info.size, 16)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_b_n = {}\n", ubn, ub->hlsl_register_b_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_buffer_n = {}\n", ubn, ub->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group0_binding_n = {}\n", ubn, ub->wgsl_group0_binding_n); + } else if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { + if (ub->flattened) { + // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) + l("{}.glsl_uniforms[0].type = {}\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); + l("{}.glsl_uniforms[0].array_count = {}\n", ubn, roundup(ub->struct_info.size, 16) / 16); + l("{}.glsl_uniforms[0].glsl_name = \"{}\"\n", ubn, ub->name); + } else { + for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { + const Type& u = ub->struct_info.struct_items[u_index]; + const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); + l("{}.type = {}\n", un, uniform_type(u.type)); + l("{}.offset = {}\n", un, u.offset); + l("{}.array_count = {}\n", un, u.array_count); + l("{}.glsl_name = \"{}.{}\"\n", un, ub->inst_name, u.name); } } } } - for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); - if (sbuf) { - const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); - l("{}.used = true\n", sbn); - l("{}.readonly = {}\n", sbn, sbuf->readonly); + } + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { + const StorageBuffer* sbuf = prog.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); + if (sbuf) { + const std::string& sbn = fmt::format("desc.storage_buffers[{}]", sbuf_index); + l("{}.stage = {}\n", sbn, shader_stage(sbuf->stage)); + l("{}.readonly = {}\n", sbn, sbuf->readonly); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_t_n = {}\n", sbn, sbuf->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_buffer_n = {}\n", sbn, sbuf->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {}\n", sbn, sbuf->wgsl_group1_binding_n); + } else if (Slang::is_glsl(slang)) { + l("{}.glsl_binding_n = {}\n", sbn, sbuf->glsl_binding_n); } } - for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); - if (img) { - const std::string in = fmt::format("{}.images[{}]", dsn, img_index); - l("{}.used = true\n", in); - l("{}.multisampled = {}\n", in, img->multisampled ? "true" : "false"); - l("{}.image_type = {}\n", in, image_type(img->type)); - l("{}.sample_type = {}\n", in, image_sample_type(img->sample_type)); + } + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { + const Image* img = prog.bindings.find_image_by_sokol_slot(img_index); + if (img) { + const std::string in = fmt::format("desc.images[{}]", img_index); + l("{}.stage = {}\n", in, shader_stage(img->stage)); + l("{}.multisampled = {}\n", in, img->multisampled ? "true" : "false"); + l("{}.image_type = {}\n", in, image_type(img->type)); + l("{}.sample_type = {}\n", in, image_sample_type(img->sample_type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_t_n = {}\n", in, img->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_texture_n = {}\n", in, img->msl_texture_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {}\n", in, img->wgsl_group1_binding_n); } } - for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); - if (smp) { - const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); - l("{}.used = true\n", sn); - l("{}.sampler_type = {}\n", sn, sampler_type(smp->type)); + } + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { + const Sampler* smp = prog.bindings.find_sampler_by_sokol_slot(smp_index); + if (smp) { + const std::string sn = fmt::format("desc.samplers[{}]", smp_index); + l("{}.stage = {}\n", sn, shader_stage(smp->stage)); + l("{}.sampler_type = {}\n", sn, sampler_type(smp->type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_s_n = {}\n", sn, smp->hlsl_register_s_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_sampler_n = {}\n", sn, smp->msl_sampler_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {}\n", sn, smp->wgsl_group1_binding_n); } } - for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); - if (img_smp) { - const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); - l("{}.used = true\n", isn); - l("{}.image_slot = {}\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); - l("{}.sampler_slot = {}\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); - if (Slang::is_glsl(slang)) { - l("{}.glsl_name = \"{}\"\n", isn, img_smp->name); - } + } + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { + const ImageSampler* img_smp = prog.bindings.find_image_sampler_by_sokol_slot(img_smp_index); + if (img_smp) { + const std::string isn = fmt::format("desc.image_sampler_pairs[{}]", img_smp_index); + l("{}.stage = {}\n", isn, shader_stage(img_smp->stage)); + l("{}.image_slot = {}\n", isn, prog.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.sampler_slot = {}\n", isn, prog.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); + if (Slang::is_glsl(slang)) { + l("{}.glsl_name = \"{}\"\n", isn, img_smp->name); } } } @@ -336,6 +367,14 @@ std::string SokolOdinGenerator::get_shader_desc_help(const std::string& prog_nam return fmt::format("{}_shader_desc(sg.query_backend())\n", prog_name); } +std::string SokolOdinGenerator::shader_stage(const ShaderStage::Enum e) { + switch (e) { + case ShaderStage::Vertex: return ".VERTEX"; + case ShaderStage::Fragment: return ".FRAGMENT"; + default: return "INVALID"; + } +} + std::string SokolOdinGenerator::uniform_type(Type::Enum e) { switch (e) { case Type::Float: return ".FLOAT"; diff --git a/src/shdc/generators/sokolodin.h b/src/shdc/generators/sokolodin.h index e44687a6..1fbaa9fd 100644 --- a/src/shdc/generators/sokolodin.h +++ b/src/shdc/generators/sokolodin.h @@ -20,6 +20,7 @@ class SokolOdinGenerator: public Generator { virtual std::string shader_bytecode_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string shader_source_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string get_shader_desc_help(const std::string& prog_name); + virtual std::string shader_stage(refl::ShaderStage::Enum e); virtual std::string uniform_type(refl::Type::Enum e); virtual std::string flattened_uniform_type(refl::Type::Enum e); virtual std::string image_type(refl::ImageType::Enum e); From 03ca68068cdacb8415242c21bd2ddf557e6f5365 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 19 Oct 2024 17:36:35 +0200 Subject: [PATCH 26/37] fix sokol-nim code generator for sokol-gfx bindings cleanup --- src/shdc/generators/sokolnim.cc | 163 ++++++++++++++++++++------------ src/shdc/generators/sokolnim.h | 1 + 2 files changed, 102 insertions(+), 62 deletions(-) diff --git a/src/shdc/generators/sokolnim.cc b/src/shdc/generators/sokolnim.cc index 834a17f5..a691e7cc 100644 --- a/src/shdc/generators/sokolnim.cc +++ b/src/shdc/generators/sokolnim.cc @@ -278,21 +278,10 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR Slang::Enum slang = Slang::from_index(i); if (gen.args.slang & Slang::bit(slang)) { l_open("of {}:\n", backend(slang)); - for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { - const StageAttr& attr = prog.vs().inputs[attr_index]; - if (attr.slot >= 0) { - if (Slang::is_glsl(slang)) { - l("result.attrs[{}].name = \"{}\"\n", attr_index, attr.name); - } else if (Slang::is_hlsl(slang)) { - l("result.attrs[{}].semName = \"{}\"\n", attr_index, attr.sem_name); - l("result.attrs[{}].semIndex = {}\n", attr_index, attr.sem_index); - } - } - } for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("result.{}", pystring::lower(ShaderStage::to_str(refl.stage))); + const std::string dsn = fmt::format("result.{}", info.stage == ShaderStage::Vertex ? "vertexFunc" : "fragmentFunc"); if (info.has_bytecode) { l("{}.bytecode.ptr = {}\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {}\n", dsn, info.bytecode_array_size); @@ -309,66 +298,108 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } l("{}.entry = \"{}\"\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); - if (ub) { - const std::string ubn = fmt::format("{}.uniformBlocks[{}]", dsn, ub_index); - l("{}.size = {}\n", ubn, roundup(ub->struct_info.size, 16)); - l("{}.layout = uniformLayoutStd140\n", ubn); - if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { - if (ub->flattened) { - l("{}.uniforms[0].name = \"{}\"\n", ubn, ub->name); - // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) - l("{}.uniforms[0].type = {}\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); - l("{}.uniforms[0].arrayCount = {}\n", ubn, roundup(ub->struct_info.size, 16) / 16); - } else { - for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { - const Type& u = ub->struct_info.struct_items[u_index]; - const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); - l("{}.name = \"{}.{}\"\n", un, ub->inst_name, u.name); - l("{}.type = {}\n", un, uniform_type(u.type)); - l(".arrayCount = {}\n", un, u.array_count); - } + } + for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { + const StageAttr& attr = prog.vs().inputs[attr_index]; + if (attr.slot >= 0) { + if (Slang::is_glsl(slang)) { + l("result.attrs[{}].glslName = \"{}\"\n", attr_index, attr.name); + } else if (Slang::is_hlsl(slang)) { + l("result.attrs[{}].hlslSemName = \"{}\"\n", attr_index, attr.sem_name); + l("result.attrs[{}].hlslSemIndex = {}\n", attr_index, attr.sem_index); + } + } + } + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { + const UniformBlock* ub = prog.bindings.find_uniform_block_by_sokol_slot(ub_index); + if (ub) { + const std::string ubn = fmt::format("result.uniformBlocks[{}]", ub_index); + l("{}.stage = {}\n", ubn, shader_stage(ub->stage)); + l("{}.layout = uniformLayoutStd140\n", ubn); + l("{}.size = {}\n", ubn, roundup(ub->struct_info.size, 16)); + if (Slang::is_hlsl(slang)) { + l("{}.hlslRegisterBN = {}\n", ubn, ub->hlsl_register_b_n); + } else if (Slang::is_msl(slang)) { + l("{}.mslBufferN = {}\n", ubn, ub->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgslGroup0BindingN = {}\n", ubn, ub->wgsl_group0_binding_n); + } else if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { + if (ub->flattened) { + // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) + l("{}.glslUniforms[0].type = {}\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); + l("{}.glslUniforms[0].arrayCount = {}\n", ubn, roundup(ub->struct_info.size, 16) / 16); + l("{}.glslUniforms[0].glslName = \"{}\"\n", ubn, ub->name); + } else { + for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { + const Type& u = ub->struct_info.struct_items[u_index]; + const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); + l("{}.type = {}\n", un, uniform_type(u.type)); + l("{}.offset = {}\n", un, u.offset); + l("{}.arrayCount = {}\n", un, u.array_count); + l("{}.glslName = \"{}.{}\"\n", un, ub->inst_name, u.name); } } } } - for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); - if (sbuf) { - const std::string& sbn = fmt::format("{}.storageBuffers[{}]", dsn, sbuf_index); - l("{}.used = true\n", sbn); - l("{}.readonly = {}\n", sbn, sbuf->readonly); + } + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { + const StorageBuffer* sbuf = prog.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); + if (sbuf) { + const std::string& sbn = fmt::format("result.storageBuffers[{}]", sbuf_index); + l("{}.stage = {}\n", sbn, shader_stage(sbuf->stage)); + l("{}.readonly = {}\n", sbn, sbuf->readonly); + if (Slang::is_hlsl(slang)) { + l("{}.hlslRegisterTN = {}\n", sbn, sbuf->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.mslBufferN = {}\n", sbn, sbuf->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgslGroup1BindingN = {}\n", sbn, sbuf->wgsl_group1_binding_n); + } else if (Slang::is_glsl(slang)) { + l("{}.glslBindingN = {}\n", sbn, sbuf->glsl_binding_n); } } - for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); - if (img) { - const std::string in = fmt::format("{}.images[{}]", dsn, img_index); - l("{}.used = true\n", in); - l("{}.multisampled = {}\n", in, img->multisampled ? "true" : "false"); - l("{}.imageType = {}\n", in, image_type(img->type)); - l("{}.sampleType = {}\n", in, image_sample_type(img->sample_type)); + } + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { + const Image* img = prog.bindings.find_image_by_sokol_slot(img_index); + if (img) { + const std::string in = fmt::format("result.images[{}]", img_index); + l("{}.stage = {}\n", in, shader_stage(img->stage)); + l("{}.multisampled = {}\n", in, img->multisampled ? "true" : "false"); + l("{}.imageType = {}\n", in, image_type(img->type)); + l("{}.sampleType = {}\n", in, image_sample_type(img->sample_type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlslRegisterTN = {}\n", in, img->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.mslTextureN = {}\n", in, img->msl_texture_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgslGroup1BindingN = {}\n", in, img->wgsl_group1_binding_n); } } - for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); - if (smp) { - const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); - l("{}.used = true\n", sn); - l("{}.samplerType = {}\n", sn, sampler_type(smp->type)); + } + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { + const Sampler* smp = prog.bindings.find_sampler_by_sokol_slot(smp_index); + if (smp) { + const std::string sn = fmt::format("result.samplers[{}]", smp_index); + l("{}.stage = {}\n", sn, shader_stage(smp->stage)); + l("{}.samplerType = {}\n", sn, sampler_type(smp->type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlslRegisterSN = {}\n", sn, smp->hlsl_register_s_n); + } else if (Slang::is_msl(slang)) { + l("{}.mslSamplerN = {}\n", sn, smp->msl_sampler_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgslGroup1BindingN = {}\n", sn, smp->wgsl_group1_binding_n); } } - for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); - if (img_smp) { - const std::string isn = fmt::format("{}.imageSamplerPairs[{}]", dsn, img_smp_index); - l("{}.used = true\n", isn); - l("{}.imageSlot = {}\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); - l("{}.samplerSlot = {}\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); - if (Slang::is_glsl(slang)) { - l("{}.glslName = \"{}\"\n", isn, img_smp->name); - } + } + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { + const ImageSampler* img_smp = prog.bindings.find_image_sampler_by_sokol_slot(img_smp_index); + if (img_smp) { + const std::string isn = fmt::format("result.imageSamplerPairs[{}]", img_smp_index); + l("{}.stage = {}\n", isn, shader_stage(img_smp->stage)); + l("{}.imageSlot = {}\n", isn, prog.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.samplerSlot = {}\n", isn, prog.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); + if (Slang::is_glsl(slang)) { + l("{}.glslName = \"{}\"\n", isn, img_smp->name); } } } @@ -416,6 +447,14 @@ std::string SokolNimGenerator::get_shader_desc_help(const std::string& prog_name return fmt::format("{}ShaderDesc(sg.queryBackend())\n", to_camel_case(prog_name)); } +std::string SokolNimGenerator::shader_stage(ShaderStage::Enum e) { + switch (e) { + case ShaderStage::Vertex: return "shaderStageVertex"; + case ShaderStage::Fragment: return "shaderStageFragment"; + default: return "INVALID"; + } +} + std::string SokolNimGenerator::uniform_type(Type::Enum e) { switch (e) { case Type::Float: return "uniformTypeFloat"; diff --git a/src/shdc/generators/sokolnim.h b/src/shdc/generators/sokolnim.h index db3ece29..2f36e898 100644 --- a/src/shdc/generators/sokolnim.h +++ b/src/shdc/generators/sokolnim.h @@ -22,6 +22,7 @@ class SokolNimGenerator: public Generator { virtual std::string shader_bytecode_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string shader_source_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string get_shader_desc_help(const std::string& prog_name); + virtual std::string shader_stage(refl::ShaderStage::Enum e); virtual std::string uniform_type(refl::Type::Enum e); virtual std::string flattened_uniform_type(refl::Type::Enum e); virtual std::string image_type(refl::ImageType::Enum e); From 1ff88c0cea74a49cbc39bc88119681b8625b8bc9 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 20 Oct 2024 18:00:49 +0200 Subject: [PATCH 27/37] fix uniforms => glsl_uniforms in Nim and Odin generator --- src/shdc/generators/sokolnim.cc | 2 +- src/shdc/generators/sokolodin.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shdc/generators/sokolnim.cc b/src/shdc/generators/sokolnim.cc index a691e7cc..a4ef515c 100644 --- a/src/shdc/generators/sokolnim.cc +++ b/src/shdc/generators/sokolnim.cc @@ -332,7 +332,7 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } else { for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { const Type& u = ub->struct_info.struct_items[u_index]; - const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); + const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); l("{}.type = {}\n", un, uniform_type(u.type)); l("{}.offset = {}\n", un, u.offset); l("{}.arrayCount = {}\n", un, u.array_count); diff --git a/src/shdc/generators/sokolodin.cc b/src/shdc/generators/sokolodin.cc index 85243f52..0033c3f5 100644 --- a/src/shdc/generators/sokolodin.cc +++ b/src/shdc/generators/sokolodin.cc @@ -252,7 +252,7 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program } else { for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { const Type& u = ub->struct_info.struct_items[u_index]; - const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); + const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); l("{}.type = {}\n", un, uniform_type(u.type)); l("{}.offset = {}\n", un, u.offset); l("{}.array_count = {}\n", un, u.array_count); From 52d1f7fa4de92be8fb88e9136e42ba689b780772 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 20 Oct 2024 18:01:08 +0200 Subject: [PATCH 28/37] udpdate Rust generator for bindings cleanup --- src/shdc/generators/sokolrust.cc | 163 +++++++++++++++++++------------ src/shdc/generators/sokolrust.h | 1 + 2 files changed, 102 insertions(+), 62 deletions(-) diff --git a/src/shdc/generators/sokolrust.cc b/src/shdc/generators/sokolrust.cc index ac2caf86..ae1b12c4 100644 --- a/src/shdc/generators/sokolrust.cc +++ b/src/shdc/generators/sokolrust.cc @@ -211,21 +211,10 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program Slang::Enum slang = Slang::from_index(i); if (gen.args.slang & Slang::bit(slang)) { l_open("{} => {{\n", backend(slang)); - for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { - const StageAttr& attr = prog.vs().inputs[attr_index]; - if (attr.slot >= 0) { - if (Slang::is_glsl(slang)) { - l("desc.attrs[{}].name = c\"{}\".as_ptr();\n", attr_index, attr.name); - } else if (Slang::is_hlsl(slang)) { - l("desc.attrs[{}].sem_name = c\"{}\".as_ptr();\n", attr_index, attr.sem_name); - l("desc.attrs[{}].sem_index = {};\n", attr_index, attr.sem_index); - } - } - } for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("desc.{}", pystring::lower(ShaderStage::to_str(refl.stage))); + const std::string dsn = fmt::format("desc.{}", info.stage == ShaderStage::Vertex ? "vertex_func" : "fragment_func"); if (info.has_bytecode) { l("{}.bytecode.ptr = &{} as *const _ as *const _;\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {};\n", dsn, info.bytecode_array_size); @@ -242,66 +231,108 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program } } l("{}.entry = c\"{}\".as_ptr();\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); - if (ub) { - const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); - l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); - l("{}.layout = sg::UniformLayout::Std140;\n", ubn); - if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { - if (ub->flattened) { - l("{}.uniforms[0].name = c\"{}\".as_ptr();\n", ubn, ub->name); - // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) - l("{}.uniforms[0]._type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); - l("{}.uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); - } else { - for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { - const Type& u = ub->struct_info.struct_items[u_index]; - const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); - l("{}.name = c\"{}:{}\".as_ptr();\n", un, ub->inst_name, u.name); - l("{}._type = {};\n", un, uniform_type(u.type)); - l("{}.array_count = {};\n", un, u.array_count); - } + } + for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { + const StageAttr& attr = prog.vs().inputs[attr_index]; + if (attr.slot >= 0) { + if (Slang::is_glsl(slang)) { + l("desc.attrs[{}].glsl_name = c\"{}\".as_ptr();\n", attr_index, attr.name); + } else if (Slang::is_hlsl(slang)) { + l("desc.attrs[{}].hlsl_sem_name = c\"{}\".as_ptr();\n", attr_index, attr.sem_name); + l("desc.attrs[{}].hlsl_sem_index = {};\n", attr_index, attr.sem_index); + } + } + } + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { + const UniformBlock* ub = prog.bindings.find_uniform_block_by_sokol_slot(ub_index); + if (ub) { + const std::string ubn = fmt::format("desc.uniform_blocks[{}]", ub_index); + l("{}.stage = {};\n", ubn, shader_stage(ub->stage)); + l("{}.layout = sg::UniformLayout::Std140;\n", ubn); + l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_b_n = {};\n", ubn, ub->hlsl_register_b_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_buffer_n = {};\n", ubn, ub->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group0_binding_n = {};\n", ubn, ub->wgsl_group0_binding_n); + } else if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { + if (ub->flattened) { + // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) + l("{}.glsl_uniforms[0]._type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); + l("{}.glsl_uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); + l("{}.glsl_uniforms[0].glsl_name = c\"{}\".as_ptr();\n", ubn, ub->name); + } else { + for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { + const Type& u = ub->struct_info.struct_items[u_index]; + const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); + l("{}._type = {};\n", un, uniform_type(u.type)); + l("{}.offset = {};\n", un, u.offset); + l("{}.array_count = {};\n", un, u.array_count); + l("{}.glsl_name = c\"{}.{}\".as_ptr();\n", un, ub->inst_name, u.name); } } } } - for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); - if (sbuf) { - const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); - l("{}.used = true;\n", sbn); - l("{}.readonly = {};\n", sbn, sbuf->readonly); + } + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { + const StorageBuffer* sbuf = prog.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); + if (sbuf) { + const std::string& sbn = fmt::format("desc.storage_buffers[{}]", sbuf_index); + l("{}.stage = {};\n", sbn, shader_stage(sbuf->stage)); + l("{}.readonly = {};\n", sbn, sbuf->readonly); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_t_n = {};\n", sbn, sbuf->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_buffer_n = {};\n", sbn, sbuf->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", sbn, sbuf->wgsl_group1_binding_n); + } else if (Slang::is_glsl(slang)) { + l("{}.glsl_binding_n = {};\n", sbn, sbuf->glsl_binding_n); } } - for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); - if (img) { - const std::string in = fmt::format("{}.images[{}]", dsn, img_index); - l("{}.used = true;\n", in); - l("{}.multisampled = {};\n", in, img->multisampled ? "true" : "false"); - l("{}.image_type = {};\n", in, image_type(img->type)); - l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); + } + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { + const Image* img = prog.bindings.find_image_by_sokol_slot(img_index); + if (img) { + const std::string in = fmt::format("desc.images[{}]", img_index); + l("{}.stage = {};\n", in, shader_stage(img->stage)); + l("{}.multisampled = {};\n", in, img->multisampled ? "true" : "false"); + l("{}.image_type = {};\n", in, image_type(img->type)); + l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_t_n = {};\n", in, img->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_texture_n = {};\n", in, img->msl_texture_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", in, img->wgsl_group1_binding_n); } } - for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); - if (smp) { - const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); - l("{}.used = true;\n", sn); - l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); + } + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { + const Sampler* smp = prog.bindings.find_sampler_by_sokol_slot(smp_index); + if (smp) { + const std::string sn = fmt::format("desc.samplers[{}]", smp_index); + l("{}.stage = {};\n", sn, shader_stage(smp->stage)); + l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_s_n = {};\n", sn, smp->hlsl_register_s_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_sampler_n = {};\n", sn, smp->msl_sampler_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", sn, smp->wgsl_group1_binding_n); } } - for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); - if (img_smp) { - const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); - l("{}.used = true;\n", isn); - l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); - l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); - if (Slang::is_glsl(slang)) { - l("{}.glsl_name = c\"{}\".as_ptr();\n", isn, img_smp->name); - } + } + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { + const ImageSampler* img_smp = prog.bindings.find_image_sampler_by_sokol_slot(img_smp_index); + if (img_smp) { + const std::string isn = fmt::format("desc.image_sampler_pairs[{}]", img_smp_index); + l("{}.stage = {};\n", isn, shader_stage(img_smp->stage)); + l("{}.image_slot = {};\n", isn, prog.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.sampler_slot = {};\n", isn, prog.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); + if (Slang::is_glsl(slang)) { + l("{}.glsl_name = c\"{}\".as_ptr();\n", isn, img_smp->name); } } } @@ -350,6 +381,14 @@ std::string SokolRustGenerator::get_shader_desc_help(const std::string& prog_nam return fmt::format("{}_shader_desc(sg::query_backend());\n", prog_name); } +std::string SokolRustGenerator::shader_stage(ShaderStage::Enum e) { + switch (e) { + case ShaderStage::Vertex: return "sg::ShaderStage::Vertex"; + case ShaderStage::Fragment: return "sg::ShaderStage::Fragment"; + default: return "INVALID"; + } +} + std::string SokolRustGenerator::uniform_type(Type::Enum e) { switch (e) { case Type::Float: return "sg::UniformType::Float"; diff --git a/src/shdc/generators/sokolrust.h b/src/shdc/generators/sokolrust.h index cde29685..9170d6ad 100644 --- a/src/shdc/generators/sokolrust.h +++ b/src/shdc/generators/sokolrust.h @@ -20,6 +20,7 @@ class SokolRustGenerator: public Generator { virtual std::string shader_bytecode_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string shader_source_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string get_shader_desc_help(const std::string& prog_name); + virtual std::string shader_stage(refl::ShaderStage::Enum e); virtual std::string uniform_type(refl::Type::Enum e); virtual std::string flattened_uniform_type(refl::Type::Enum e); virtual std::string image_type(refl::ImageType::Enum e); From 03a4f9879e11a0d3302482a153a21febf6f7e135 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 21 Oct 2024 17:55:58 +0200 Subject: [PATCH 29/37] update D generator for sokol-gfx bindings cleanup --- src/shdc/generators/sokold.cc | 163 +++++++++++++++++++++------------- src/shdc/generators/sokold.h | 1 + 2 files changed, 102 insertions(+), 62 deletions(-) diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index 30c4e3d9..83e7a5ff 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -211,21 +211,10 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef Slang::Enum slang = Slang::from_index(i); if (gen.args.slang & Slang::bit(slang)) { l_open("case {}:\n", backend(slang)); - for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { - const StageAttr& attr = prog.vs().inputs[attr_index]; - if (attr.slot >= 0) { - if (Slang::is_glsl(slang)) { - l("desc.attrs[{}].name = \"{}\";\n", attr_index, attr.name); - } else if (Slang::is_hlsl(slang)) { - l("desc.attrs[{}].sem_name = \"{}\";\n", attr_index, attr.sem_name); - l("desc.attrs[{}].sem_index = {};\n", attr_index, attr.sem_index); - } - } - } for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("desc.{}", pystring::lower(ShaderStage::to_str(refl.stage))); + const std::string dsn = fmt::format("desc.{}", info.stage == ShaderStage::Vertex ? "vertex_func" : "fragment_func"); if (info.has_bytecode) { l("{}.bytecode.ptr = {}.ptr;\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {};\n", dsn, info.bytecode_array_size); @@ -242,66 +231,108 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef } } l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); - if (ub) { - const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); - l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); - l("{}.layout = sg.UniformLayout.Std140;\n", ubn); - if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { - if (ub->flattened) { - l("{}.uniforms[0].name = \"{}\";\n", ubn, ub->name); - // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) - l("{}.uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); - l("{}.uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); - } else { - for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { - const Type& u = ub->struct_info.struct_items[u_index]; - const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); - l("{}.name = \"{}.{}\";\n", un, ub->inst_name, u.name); - l("{}.type = {};\n", un, uniform_type(u.type)); - l("{}.array_count = {};\n", un, u.array_count); - } + } + for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { + const StageAttr& attr = prog.vs().inputs[attr_index]; + if (attr.slot >= 0) { + if (Slang::is_glsl(slang)) { + l("desc.attrs[{}].glsl_name = \"{}\";\n", attr_index, attr.name); + } else if (Slang::is_hlsl(slang)) { + l("desc.attrs[{}].hlsl_sem_name = \"{}\";\n", attr_index, attr.sem_name); + l("desc.attrs[{}].hlsl_sem_index = {};\n", attr_index, attr.sem_index); + } + } + } + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { + const UniformBlock* ub = prog.bindings.find_uniform_block_by_sokol_slot(ub_index); + if (ub) { + const std::string ubn = fmt::format("desc.uniform_blocks[{}]", ub_index); + l("{}.stage = {};\n", ubn, shader_stage(ub->stage)); + l("{}.layout = sg.UniformLayout.Std140;\n", ubn); + l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_b_n = {};\n", ubn, ub->hlsl_register_b_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_buffer_n = {};\n", ubn, ub->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group0_binding_n = {};\n", ubn, ub->wgsl_group0_binding_n); + } if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { + if (ub->flattened) { + // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) + l("{}.glsl_uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); + l("{}.glsl_uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); + l("{}.glsl_uniforms[0].glsl_name = \"{}\";\n", ubn, ub->name); + } else { + for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { + const Type& u = ub->struct_info.struct_items[u_index]; + const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); + l("{}.type = {};\n", un, uniform_type(u.type)); + l("{}.offset = {};\n", un, u.offset); + l("{}.array_count = {};\n", un, u.array_count); + l("{}.glsl_name = \"{}.{}\";\n", un, ub->inst_name, u.name); } } } } - for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); - if (sbuf) { - const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); - l("{}.used = true;\n", sbn); - l("{}.readonly = {};\n", sbn, sbuf->readonly); + } + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { + const StorageBuffer* sbuf = prog.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); + if (sbuf) { + const std::string& sbn = fmt::format("desc.storage_buffers[{}]", sbuf_index); + l("{}.stage = {};\n", sbn, shader_stage(sbuf->stage)); + l("{}.readonly = {};\n", sbn, sbuf->readonly); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_t_n = {};\n", sbn, sbuf->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_buffer_n = {};\n", sbn, sbuf->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", sbn, sbuf->wgsl_group1_binding_n); + } else if (Slang::is_glsl(slang)) { + l("{}.glsl_binding_n = {};\n", sbn, sbuf->glsl_binding_n); } } - for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); - if (img) { - const std::string in = fmt::format("{}.images[{}]", dsn, img_index); - l("{}.used = true;\n", in); - l("{}.multisampled = {};\n", in, img->multisampled ? "true" : "false"); - l("{}.image_type = {};\n", in, image_type(img->type)); - l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); + } + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { + const Image* img = prog.bindings.find_image_by_sokol_slot(img_index); + if (img) { + const std::string in = fmt::format("desc.images[{}]", img_index); + l("{}.stage = {};\n", in, shader_stage(img->stage)); + l("{}.multisampled = {};\n", in, img->multisampled ? "true" : "false"); + l("{}.image_type = {};\n", in, image_type(img->type)); + l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_t_n = {};\n", in, img->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_texture_n = {};\n", in, img->msl_texture_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", in, img->wgsl_group1_binding_n); } } - for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); - if (smp) { - const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); - l("{}.used = true;\n", sn); - l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); + } + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { + const Sampler* smp = prog.bindings.find_sampler_by_sokol_slot(smp_index); + if (smp) { + const std::string sn = fmt::format("desc.samplers[{}]", smp_index); + l("{}.stage = {};\n", sn, shader_stage(smp->stage)); + l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_s_n = {};\n", sn, smp->hlsl_register_s_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_sampler_n = {};\n", sn, smp->msl_sampler_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", sn, smp->wgsl_group1_binding_n); } } - for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); - if (img_smp) { - const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); - l("{}.used = true;\n", isn); - l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); - l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); - if (Slang::is_glsl(slang)) { - l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); - } + } + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { + const ImageSampler* img_smp = prog.bindings.find_image_sampler_by_sokol_slot(img_smp_index); + if (img_smp) { + const std::string isn = fmt::format("desc.image_sampler_pairs[{}]", img_smp_index); + l("{}.stage = {};\n", isn, shader_stage(img_smp->stage)); + l("{}.image_slot = {};\n", isn, prog.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.sampler_slot = {};\n", isn, prog.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); + if (Slang::is_glsl(slang)) { + l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); } } } @@ -343,6 +374,14 @@ std::string SokolDGenerator::get_shader_desc_help(const std::string& prog_name) return fmt::format("{}ShaderDesc(sg.queryBackend());\n", prog_name); } +std::string SokolDGenerator::shader_stage(ShaderStage::Enum e) { + switch (e) { + case ShaderStage::Vertex: return "sg.ShaderStage.Vertex"; + case ShaderStage::Fragment: return "sg.ShaderStage.Fragment"; + default: return "INVALID"; + } +} + std::string SokolDGenerator::uniform_type(Type::Enum e) { switch (e) { case Type::Float: return "sg.UniformType.Float"; diff --git a/src/shdc/generators/sokold.h b/src/shdc/generators/sokold.h index 400e5a73..31a01e4b 100644 --- a/src/shdc/generators/sokold.h +++ b/src/shdc/generators/sokold.h @@ -20,6 +20,7 @@ class SokolDGenerator : public Generator { virtual std::string shader_bytecode_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string shader_source_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string get_shader_desc_help(const std::string& prog_name); + virtual std::string shader_stage(refl::ShaderStage::Enum e); virtual std::string uniform_type(refl::Type::Enum e); virtual std::string flattened_uniform_type(refl::Type::Enum e); virtual std::string image_type(refl::ImageType::Enum e); From 0c111b5cb0802d09363a72f65592f0ef82a17c2f Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 23 Oct 2024 19:39:20 +0200 Subject: [PATCH 30/37] update Jai generator for sokol-gfx bindings cleanup --- src/shdc/generators/sokoljai.cc | 163 ++++++++++++++++++++------------ src/shdc/generators/sokoljai.h | 1 + 2 files changed, 102 insertions(+), 62 deletions(-) diff --git a/src/shdc/generators/sokoljai.cc b/src/shdc/generators/sokoljai.cc index 2d5f0ce6..3a2bb1d6 100644 --- a/src/shdc/generators/sokoljai.cc +++ b/src/shdc/generators/sokoljai.cc @@ -195,21 +195,10 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR Slang::Enum slang = Slang::from_index(i); if (gen.args.slang & Slang::bit(slang)) { l_open("case {};\n", backend(slang)); - for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { - const StageAttr& attr = prog.vs().inputs[attr_index]; - if (attr.slot >= 0) { - if (Slang::is_glsl(slang)) { - l("desc.attrs[{}].name = \"{}\";\n", attr_index, attr.name); - } else if (Slang::is_hlsl(slang)) { - l("desc.attrs[{}].sem_name = \"{}\";\n", attr_index, attr.sem_name); - l("desc.attrs[{}].sem_index = {};\n", attr_index, attr.sem_index); - } - } - } for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const std::string dsn = fmt::format("desc.{}", pystring::lower(ShaderStage::to_str(refl.stage))); + const std::string dsn = fmt::format("desc.{}", info.stage == ShaderStage::Vertex ? "vertex_func" : "fragment_func"); if (info.has_bytecode) { l("{}.bytecode.ptr = *{};\n", dsn, info.bytecode_array_name); l("{}.bytecode.size = {};\n", dsn, info.bytecode_array_size); @@ -226,66 +215,108 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR } } l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); - for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { - const UniformBlock* ub = refl.bindings.find_uniform_block_by_sokol_slot(ub_index); - if (ub) { - const std::string ubn = fmt::format("{}.uniform_blocks[{}]", dsn, ub_index); - l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); - l("{}.layout = .STD140;\n", ubn); - if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { - if (ub->flattened) { - l("{}.uniforms[0].name = \"{}\";\n", ubn, ub->name); - // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) - l("{}.uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); - l("{}.uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); - } else { - for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { - const Type& u = ub->struct_info.struct_items[u_index]; - const std::string un = fmt::format("{}.uniforms[{}]", ubn, u_index); - l("{}.name = \"{}.{}\";\n", un, ub->inst_name, u.name); - l("{}.type = {};\n", un, uniform_type(u.type)); - l("{}.array_count = {};\n", un, u.array_count); - } + } + for (int attr_index = 0; attr_index < StageAttr::Num; attr_index++) { + const StageAttr& attr = prog.vs().inputs[attr_index]; + if (attr.slot >= 0) { + if (Slang::is_glsl(slang)) { + l("desc.attrs[{}].glsl_name = \"{}\";\n", attr_index, attr.name); + } else if (Slang::is_hlsl(slang)) { + l("desc.attrs[{}].hlsl_sem_name = \"{}\";\n", attr_index, attr.sem_name); + l("desc.attrs[{}].hlsl_sem_index = {};\n", attr_index, attr.sem_index); + } + } + } + for (int ub_index = 0; ub_index < Bindings::MaxUniformBlocks; ub_index++) { + const UniformBlock* ub = prog.bindings.find_uniform_block_by_sokol_slot(ub_index); + if (ub) { + const std::string ubn = fmt::format("desc.uniform_blocks[{}]", ub_index); + l("{}.stage = {}\n", ubn, shader_stage(ub->stage)); + l("{}.layout = .STD140;\n", ubn); + l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_b_n = {};\n", ubn, ub->hlsl_register_b_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_buffer_n = {};\n", ubn, ub->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group0_binding_n = {};\n", ubn, ub->wgsl_group0_binding_n); + } else if (Slang::is_glsl(slang) && (ub->struct_info.struct_items.size() > 0)) { + if (ub->flattened) { + // NOT A BUG (to take the type from the first struct item, but the size from the toplevel ub) + l("{}.glsl_uniforms[0].type = {};\n", ubn, flattened_uniform_type(ub->struct_info.struct_items[0].type)); + l("{}.glsl_uniforms[0].array_count = {};\n", ubn, roundup(ub->struct_info.size, 16) / 16); + l("{}.glsl_uniforms[0].glsl_name = \"{}\";\n", ubn, ub->name); + } else { + for (int u_index = 0; u_index < (int)ub->struct_info.struct_items.size(); u_index++) { + const Type& u = ub->struct_info.struct_items[u_index]; + const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); + l("{}.type = {};\n", un, uniform_type(u.type)); + l("{}.offset = {};\n", un, u.offset); + l("{}.array_count = {};\n", un, u.array_count); + l("{}.glsl_name = \"{}.{}\";\n", un, ub->inst_name, u.name); } } } } - for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { - const StorageBuffer* sbuf = refl.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); - if (sbuf) { - const std::string& sbn = fmt::format("{}.storage_buffers[{}]", dsn, sbuf_index); - l("{}.used = true;\n", sbn); - l("{}.readonly = {};\n", sbn, sbuf->readonly); + } + for (int sbuf_index = 0; sbuf_index < Bindings::MaxStorageBuffers; sbuf_index++) { + const StorageBuffer* sbuf = prog.bindings.find_storage_buffer_by_sokol_slot(sbuf_index); + if (sbuf) { + const std::string& sbn = fmt::format("desc.storage_buffers[{}]", sbuf_index); + l("{}.stage = {};\n", sbn, shader_stage(sbuf->stage)); + l("{}.readonly = {};\n", sbn, sbuf->readonly); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_t_n = {};\n", sbn, sbuf->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_buffer_n = {};\n", sbn, sbuf->msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", sbn, sbuf->wgsl_group1_binding_n); + } else if (Slang::is_glsl(slang)) { + l("{}.glsl_binding_n = {};\n", sbn, sbuf->glsl_binding_n); } } - for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { - const Image* img = refl.bindings.find_image_by_sokol_slot(img_index); - if (img) { - const std::string in = fmt::format("{}.images[{}]", dsn, img_index); - l("{}.used = true;\n", in); - l("{}.multisampled = {};\n", in, img->multisampled ? "true" : "false"); - l("{}.image_type = {};\n", in, image_type(img->type)); - l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); + } + for (int img_index = 0; img_index < Bindings::MaxImages; img_index++) { + const Image* img = prog.bindings.find_image_by_sokol_slot(img_index); + if (img) { + const std::string in = fmt::format("desc.images[{}]", img_index); + l("{}.stage = {};\n", in, shader_stage(img->stage)); + l("{}.multisampled = {};\n", in, img->multisampled ? "true" : "false"); + l("{}.image_type = {};\n", in, image_type(img->type)); + l("{}.sample_type = {};\n", in, image_sample_type(img->sample_type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_t_n = {};\n", in, img->hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_texture_n = {};\n", in, img->msl_texture_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", in, img->wgsl_group1_binding_n); } } - for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { - const Sampler* smp = refl.bindings.find_sampler_by_sokol_slot(smp_index); - if (smp) { - const std::string sn = fmt::format("{}.samplers[{}]", dsn, smp_index); - l("{}.used = true;\n", sn); - l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); + } + for (int smp_index = 0; smp_index < Bindings::MaxSamplers; smp_index++) { + const Sampler* smp = prog.bindings.find_sampler_by_sokol_slot(smp_index); + if (smp) { + const std::string sn = fmt::format("desc.samplers[{}]", smp_index); + l("{}.stage = {};\n", sn, shader_stage(smp->stage)); + l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); + if (Slang::is_hlsl(slang)) { + l("{}.hlsl_register_s_n = {};\n", sn, smp->hlsl_register_s_n); + } else if (Slang::is_msl(slang)) { + l("{}.msl_sampler_n = {};\n", sn, smp->msl_sampler_n); + } else if (Slang::is_wgsl(slang)) { + l("{}.wgsl_group1_binding_n = {};\n", sn, smp->wgsl_group1_binding_n); } } - for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { - const ImageSampler* img_smp = refl.bindings.find_image_sampler_by_sokol_slot(img_smp_index); - if (img_smp) { - const std::string isn = fmt::format("{}.image_sampler_pairs[{}]", dsn, img_smp_index); - l("{}.used = true;\n", isn); - l("{}.image_slot = {};\n", isn, refl.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); - l("{}.sampler_slot = {};\n", isn, refl.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); - if (Slang::is_glsl(slang)) { - l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); - } + } + for (int img_smp_index = 0; img_smp_index < Bindings::MaxImageSamplers; img_smp_index++) { + const ImageSampler* img_smp = prog.bindings.find_image_sampler_by_sokol_slot(img_smp_index); + if (img_smp) { + const std::string isn = fmt::format("desc.image_sampler_pairs[{}]", img_smp_index); + l("{}.stage = {};\n", isn, shader_stage(img_smp->stage)); + l("{}.image_slot = {};\n", isn, prog.bindings.find_image_by_name(img_smp->image_name)->sokol_slot); + l("{}.sampler_slot = {};\n", isn, prog.bindings.find_sampler_by_name(img_smp->sampler_name)->sokol_slot); + if (Slang::is_glsl(slang)) { + l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); } } } @@ -333,6 +364,14 @@ std::string SokolJaiGenerator::get_shader_desc_help(const std::string& prog_name return fmt::format("{}_shader_desc(sg_query_backend())\n", prog_name); } +std::string SokolJaiGenerator::shader_stage(ShaderStage::Enum e) { + switch (e) { + case ShaderStage::Vertex: return ".VERTEX"; + case ShaderStage::Fragment: return ".FRAGMENT"; + default: return "INVALID"; + } +} + std::string SokolJaiGenerator::uniform_type(Type::Enum e) { switch (e) { case Type::Float: return ".FLOAT"; diff --git a/src/shdc/generators/sokoljai.h b/src/shdc/generators/sokoljai.h index 5f5736f8..8c43a421 100644 --- a/src/shdc/generators/sokoljai.h +++ b/src/shdc/generators/sokoljai.h @@ -20,6 +20,7 @@ class SokolJaiGenerator: public Generator { virtual std::string shader_bytecode_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string shader_source_array_name(const std::string& snippet_name, Slang::Enum slang); virtual std::string get_shader_desc_help(const std::string& prog_name); + virtual std::string shader_stage(refl::ShaderStage::Enum e); virtual std::string uniform_type(refl::Type::Enum e); virtual std::string flattened_uniform_type(refl::Type::Enum e); virtual std::string image_type(refl::ImageType::Enum e); From 16dffda01e4143c688cfd737e7d3f19bdeedb75e Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Thu, 24 Oct 2024 18:37:57 +0200 Subject: [PATCH 31/37] update yaml generator for sokol-gfx bindings cleanup --- src/shdc/generators/generator.h | 4 +- src/shdc/generators/yaml.cc | 218 +++++++++++-------- src/shdc/generators/yaml.h | 13 +- src/shdc/types/reflection/shader_stage.h | 6 +- src/shdc/types/reflection/stage_reflection.h | 22 ++ 5 files changed, 166 insertions(+), 97 deletions(-) diff --git a/src/shdc/generators/generator.h b/src/shdc/generators/generator.h index 7995eac9..7a74cb41 100644 --- a/src/shdc/generators/generator.h +++ b/src/shdc/generators/generator.h @@ -64,8 +64,8 @@ class Generator { virtual std::string comment_block_line_prefix() { assert(false && "implement me"); return ""; }; virtual std::string comment_block_end() { assert(false && "implement me"); return ""; }; - virtual std::string shader_bytecode_array_name(const std::string& snippet_name, Slang::Enum slang) { assert(false && "implement me"); return ""; }; - virtual std::string shader_source_array_name(const std::string& snippet_name, Slang::Enum slang) { assert(false && "implement me"); return ""; }; + virtual std::string shader_bytecode_array_name(const std::string& snippet_name, Slang::Enum slang) { return "INVALID"; }; + virtual std::string shader_source_array_name(const std::string& snippet_name, Slang::Enum slang) { return "INVALID"; }; virtual std::string shader_stage(refl::ShaderStage::Enum e) { assert(false && "implement me"); return ""; }; virtual std::string uniform_type(refl::Type::Enum e) { assert(false && "implement me"); return ""; }; diff --git a/src/shdc/generators/yaml.cc b/src/shdc/generators/yaml.cc index 28559c10..16056385 100644 --- a/src/shdc/generators/yaml.cc +++ b/src/shdc/generators/yaml.cc @@ -24,72 +24,72 @@ ErrMsg YamlGenerator::generate(const GenInput& gen) { for (int slang_idx = 0; slang_idx < Slang::Num; slang_idx++) { Slang::Enum slang = Slang::from_index(slang_idx); if (gen.args.slang & Slang::bit(slang)) { - // FIXME: all slang outputs will be the same, so this is kinda redundant l_open("-\n"); l("slang: {}\n", Slang::to_str(slang)); l_open("programs:\n"); - const Spirvcross& spirvcross = gen.spirvcross[slang]; - const Bytecode& bytecode = gen.bytecode[slang]; for (const ProgramReflection& prog: gen.refl.progs) { l_open("-\n"); l("name: {}\n", prog.name); for (int stage_index = 0; stage_index < ShaderStage::Num; stage_index++) { + const ShaderStageArrayInfo& info = shader_stage_array_info(gen, prog, ShaderStage::from_index(stage_index), slang); const StageReflection& refl = prog.stages[stage_index]; - const SpirvcrossSource* src = spirvcross.find_source_by_snippet_index(refl.snippet_index); - const BytecodeBlob* blob = bytecode.find_blob_by_snippet_index(refl.snippet_index); - const std::string file_path = shader_file_path(gen, prog.name, ShaderStage::to_str(refl.stage), slang, blob != nullptr); - l_open("{}:\n", pystring::lower(ShaderStage::to_str(refl.stage))); + l_open("{}:\n", info.stage == ShaderStage::Vertex ? "vertex_func" : "fragment_func"); + const std::string file_path = shader_file_path(gen, prog.name, ShaderStage::to_str(info.stage), slang, info.has_bytecode); l("path: {}\n", file_path); - l("is_binary: {}\n", blob != nullptr); + l("is_binary: {}\n", info.has_bytecode); l("entry_point: {}\n", refl.entry_point_by_slang(slang)); - l_open("inputs:\n"); - for (const auto& input: src->stage_refl.inputs) { - if (input.slot != -1) { - gen_attr(input); - } + const char* d3d11_tgt = nullptr; + if (slang == Slang::HLSL4) { + d3d11_tgt = (0 == stage_index) ? "vs_4_0" : "ps_4_0"; + } else if (slang == Slang::HLSL5) { + d3d11_tgt = (0 == stage_index) ? "vs_5_0" : "ps_5_0"; + } + if (d3d11_tgt) { + l("d3d11_target: {}\n", d3d11_tgt); } l_close(); - l_open("outputs:\n"); - for (const auto& output: src->stage_refl.outputs) { - if (output.slot != -1) { - gen_attr(output); + } + if (prog.vs().num_inputs() > 0) { + l_open("attrs:\n"); + for (const auto& attr: prog.vs().inputs) { + if (attr.slot >= 0) { + gen_attr(attr, slang); } } l_close(); - if (refl.bindings.uniform_blocks.size() > 0) { - l_open("uniform_blocks:\n"); - for (const auto& uniform_block: refl.bindings.uniform_blocks) { - gen_uniform_block(gen, uniform_block); - } - l_close(); + } + if (prog.bindings.uniform_blocks.size() > 0) { + l_open("uniform_blocks:\n"); + for (const auto& uniform_block: prog.bindings.uniform_blocks) { + gen_uniform_block(gen, uniform_block, slang); } - if (refl.bindings.storage_buffers.size() > 0) { - l_open("storage_buffers:\n"); - for (const auto& sbuf: refl.bindings.storage_buffers) { - gen_storage_buffer(sbuf); - } - l_close(); + l_close(); + } + if (prog.bindings.storage_buffers.size() > 0) { + l_open("storage_buffers:\n"); + for (const auto& sbuf: prog.bindings.storage_buffers) { + gen_storage_buffer(sbuf, slang); } - if (refl.bindings.images.size() > 0) { - l_open("images:\n"); - for (const auto& image: refl.bindings.images) { - gen_image(image); - } - l_close(); + l_close(); + } + if (prog.bindings.images.size() > 0) { + l_open("images:\n"); + for (const auto& image: prog.bindings.images) { + gen_image(image, slang); } - if (refl.bindings.samplers.size() > 0) { - l_open("samplers:\n"); - for (const auto& sampler: refl.bindings.samplers) { - gen_sampler(sampler); - } - l_close(); + l_close(); + } + if (prog.bindings.samplers.size() > 0) { + l_open("samplers:\n"); + for (const auto& sampler: prog.bindings.samplers) { + gen_sampler(sampler, slang); } - if (src->stage_refl.bindings.image_samplers.size() > 0) { - l_open("image_sampler_pairs:\n"); - for (const auto& image_sampler: src->stage_refl.bindings.image_samplers) { - gen_image_sampler(image_sampler); - } - l_close(); + l_close(); + } + if (prog.bindings.image_samplers.size() > 0) { + l_open("image_sampler_pairs:\n"); + for (const auto& image_sampler: prog.bindings.image_samplers) { + gen_image_sampler(image_sampler, slang); } l_close(); } @@ -112,41 +112,53 @@ ErrMsg YamlGenerator::generate(const GenInput& gen) { return ErrMsg(); } -void YamlGenerator::gen_attr(const StageAttr& att) { +void YamlGenerator::gen_attr(const StageAttr& attr, Slang::Enum slang) { l_open("-\n"); - l("slot: {}\n", att.slot); - l("name: {}\n", att.name); - l("sem_name: {}\n", att.sem_name); - l("sem_index: {}\n", att.sem_index); - l("type: {}\n", uniform_type(att.type_info.type)); + l("slot: {}\n", attr.slot); + l("type: {}\n", uniform_type(attr.type_info.type)); + if (Slang::is_glsl(slang)) { + l("glsl_name: {}\n", attr.name); + } else if (Slang::is_hlsl(slang)) { + l("hlsl_sem_name: {}\n", attr.sem_name); + l("hlsl_sem_index: {}\n", attr.sem_index); + } l_close(); } -void YamlGenerator::gen_uniform_block(const GenInput& gen, const UniformBlock& ub) { +void YamlGenerator::gen_uniform_block(const GenInput& gen, const UniformBlock& ub, Slang::Enum slang) { l_open("-\n"); l("slot: {}\n", ub.sokol_slot); + l("stage: {}\n", shader_stage(ub.stage)); l("size: {}\n", roundup(ub.struct_info.size, 16)); l("struct_name: {}\n", ub.name); l("inst_name: {}\n", ub.inst_name); - l_open("uniforms:\n"); - if (ub.flattened) { - l_open("-\n"); - l("name: {}\n", ub.name); - l("type: {}\n", flattened_uniform_type(ub.struct_info.struct_items[0].type)); - l("array_count: {}\n", roundup(ub.struct_info.size, 16) / 16); - l("offset: 0\n"); - l_close(); - } else { - for (const Type& u: ub.struct_info.struct_items) { + if (Slang::is_hlsl(slang)) { + l("hlsl_register_b_n: {}\n", ub.hlsl_register_b_n); + } else if (Slang::is_msl(slang)) { + l("msl_buffer_n: {}\n", ub.msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("wgsl_group0_binding_n: {}\n", ub.wgsl_group0_binding_n); + } else if (Slang::is_glsl(slang)) { + l_open("glsl_uniforms:\n"); + if (ub.flattened) { l_open("-\n"); - l("name: {}\n", u.name); - l("type: {}\n", uniform_type(u.type)); - l("array_count: {}\n", u.array_count); - l("offset: {}\n", u.offset); + l("type: {}\n", flattened_uniform_type(ub.struct_info.struct_items[0].type)); + l("array_count: {}\n", roundup(ub.struct_info.size, 16) / 16); + l("offset: 0\n"); + l("glsl_name: {}\n", ub.name); l_close(); + } else { + for (const Type& u: ub.struct_info.struct_items) { + l_open("-\n"); + l("type: {}\n", uniform_type(u.type)); + l("array_count: {}\n", u.array_count); + l("offset: {}\n", u.offset); + l("glsl_name: {}\n", u.name); + l_close(); + } } + l_close(); } - l_close(); if (gen.args.reflection) { gen_uniform_block_refl(ub); } @@ -166,43 +178,73 @@ void YamlGenerator::gen_uniform_block_refl(const UniformBlock& ub) { l_close(); } -void YamlGenerator::gen_storage_buffer(const StorageBuffer& sbuf) { +void YamlGenerator::gen_storage_buffer(const StorageBuffer& sbuf, Slang::Enum slang) { const auto& item = sbuf.struct_info.struct_items[0]; l_open("-\n"); l("slot: {}\n", sbuf.sokol_slot); + l("stage: {}\n", shader_stage(sbuf.stage)); l("size: {}\n", sbuf.struct_info.size); l("align: {}\n", sbuf.struct_info.align); l("struct_name: {}\n", sbuf.name); l("inst_name: {}\n", sbuf.inst_name); - l("readonly: {}\n", sbuf.readonly); l("inner_struct_name: {}\n", item.struct_typename); + l("readonly: {}\n", sbuf.readonly); + if (Slang::is_hlsl(slang)) { + l("hlsl_register_t_n: {}\n", sbuf.hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("msl_buffer_n: {}\n", sbuf.msl_buffer_n); + } else if (Slang::is_wgsl(slang)) { + l("wgsl_group1_binding_n: {}\n", sbuf.wgsl_group1_binding_n); + } else if (Slang::is_glsl(slang)) { + l("glsl_binding_n: {}\n", sbuf.glsl_binding_n); + } l_close(); } -void YamlGenerator::gen_image(const Image& image) { +void YamlGenerator::gen_image(const Image& img, Slang::Enum slang) { l_open("-\n"); - l("slot: {}\n", image.sokol_slot); - l("name: {}\n", image.name); - l("multisampled: {}\n", image.multisampled); - l("type: {}\n", image_type(image.type)); - l("sample_type: {}\n", image_sample_type(image.sample_type)); + l("slot: {}\n", img.sokol_slot); + l("stage: {}\n", shader_stage(img.stage)); + l("name: {}\n", img.name); + l("multisampled: {}\n", img.multisampled); + l("type: {}\n", image_type(img.type)); + l("sample_type: {}\n", image_sample_type(img.sample_type)); + if (Slang::is_hlsl(slang)) { + l("hlsl_register_t_n: {}\n", img.hlsl_register_t_n); + } else if (Slang::is_msl(slang)) { + l("msl_texture_n: {}\n", img.msl_texture_n); + } else if (Slang::is_wgsl(slang)) { + l("wgsl_group1_binding_n: {}\n", img.wgsl_group1_binding_n); + } l_close(); } -void YamlGenerator::gen_sampler(const Sampler& sampler) { +void YamlGenerator::gen_sampler(const Sampler& smp, Slang::Enum slang) { l_open("-\n"); - l("slot: {}\n", sampler.sokol_slot); - l("name: {}\n", sampler.name); - l("sampler_type: {}\n", sampler_type(sampler.type)); + l("slot: {}\n", smp.sokol_slot); + l("stage: {}\n", shader_stage(smp.stage)); + l("name: {}\n", smp.name); + l("sampler_type: {}\n", sampler_type(smp.type)); + if (Slang::is_hlsl(slang)) { + l("hlsl_register_s_n: {}\n", smp.hlsl_register_s_n); + } else if (Slang::is_msl(slang)) { + l("msl_sampler_n: {}\n", smp.msl_sampler_n); + } else if (Slang::is_wgsl(slang)) { + l("wgsl_group1_binding_n: {}\n", smp.wgsl_group1_binding_n); + } l_close(); } -void YamlGenerator::gen_image_sampler(const ImageSampler& image_sampler) { +void YamlGenerator::gen_image_sampler(const ImageSampler& img_smp, Slang::Enum slang) { l_open("-\n"); - l("slot: {}\n", image_sampler.sokol_slot); - l("name: {}\n", image_sampler.name); - l("image_name: {}\n", image_sampler.image_name); - l("sampler_name: {}\n", image_sampler.sampler_name); + l("slot: {}\n", img_smp.sokol_slot); + l("stage: {}\n", shader_stage(img_smp.stage)); + l("name: {}\n", img_smp.name); + l("image_name: {}\n", img_smp.image_name); + l("sampler_name: {}\n", img_smp.sampler_name); + if (Slang::is_glsl(slang)) { + l("glsl_name: {}\n", img_smp.name); + } l_close(); } @@ -228,6 +270,10 @@ std::string YamlGenerator::flattened_uniform_type(Type::Enum e) { } } +std::string YamlGenerator::shader_stage(ShaderStage::Enum e) { + return ShaderStage::to_str(e); +} + std::string YamlGenerator::image_type(ImageType::Enum e) { return ImageType::to_str(e); } diff --git a/src/shdc/generators/yaml.h b/src/shdc/generators/yaml.h index 54ec908c..c47793cd 100644 --- a/src/shdc/generators/yaml.h +++ b/src/shdc/generators/yaml.h @@ -7,19 +7,20 @@ class YamlGenerator: public BareGenerator { public: virtual ErrMsg generate(const GenInput& gen); protected: + virtual std::string shader_stage(refl::ShaderStage::Enum e); virtual std::string uniform_type(refl::Type::Enum e); virtual std::string flattened_uniform_type(refl::Type::Enum e); virtual std::string image_type(refl::ImageType::Enum e); virtual std::string image_sample_type(refl::ImageSampleType::Enum e); virtual std::string sampler_type(refl::SamplerType::Enum e); private: - void gen_attr(const refl::StageAttr& attr); - void gen_uniform_block(const GenInput& gen, const refl::UniformBlock& ub); + void gen_attr(const refl::StageAttr& attr, Slang::Enum slang); + void gen_uniform_block(const GenInput& gen, const refl::UniformBlock& ub, Slang::Enum slang); void gen_uniform_block_refl(const refl::UniformBlock& ub); - void gen_storage_buffer(const refl::StorageBuffer& sbuf); - void gen_image(const refl::Image& img); - void gen_sampler(const refl::Sampler& smp); - void gen_image_sampler(const refl::ImageSampler& img_smp); + void gen_storage_buffer(const refl::StorageBuffer& sbuf, Slang::Enum slang); + void gen_image(const refl::Image& img, Slang::Enum slang); + void gen_sampler(const refl::Sampler& smp, Slang::Enum slang); + void gen_image_sampler(const refl::ImageSampler& img_smp, Slang::Enum slang); }; } // namespace diff --git a/src/shdc/types/reflection/shader_stage.h b/src/shdc/types/reflection/shader_stage.h index b67b0342..a2d8ee8a 100644 --- a/src/shdc/types/reflection/shader_stage.h +++ b/src/shdc/types/reflection/shader_stage.h @@ -20,9 +20,9 @@ struct ShaderStage { inline const char* ShaderStage::to_str(ShaderStage::Enum e) { switch (e) { - case Vertex: return "VS"; - case Fragment: return "FS"; - default: return "INVALID"; + case Vertex: return "vertex"; + case Fragment: return "fragment"; + default: return "invalid"; } } diff --git a/src/shdc/types/reflection/stage_reflection.h b/src/shdc/types/reflection/stage_reflection.h index 06b0a812..b3f2b86d 100644 --- a/src/shdc/types/reflection/stage_reflection.h +++ b/src/shdc/types/reflection/stage_reflection.h @@ -17,10 +17,32 @@ struct StageReflection { std::array outputs; // index == attribute slot Bindings bindings; + size_t num_inputs() const; + size_t num_outputs() const; std::string entry_point_by_slang(Slang::Enum slang) const; void dump_debug(const std::string& indent) const; }; +inline size_t StageReflection::num_inputs() const { + size_t num = 0; + for (const auto& attr: inputs) { + if (attr.slot >= 0) { + num += 1; + } + } + return num; +} + +inline size_t StageReflection::num_outputs() const { + size_t num = 0; + for (const auto& attr: outputs) { + if (attr.slot >= 0) { + num += 1; + } + } + return num; +} + inline std::string StageReflection::entry_point_by_slang(Slang::Enum slang) const { if (Slang::is_msl(slang)) { return entry_point + "0"; From 069082bd7c39872b0a80b77e913cb8ba585e7c5f Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 26 Oct 2024 14:51:43 +0200 Subject: [PATCH 32/37] generators: remove sg_shader_uniform.offset --- src/shdc/generators/sokolc.cc | 2 -- src/shdc/generators/sokold.cc | 1 - src/shdc/generators/sokoljai.cc | 1 - src/shdc/generators/sokolnim.cc | 1 - src/shdc/generators/sokolodin.cc | 1 - src/shdc/generators/sokolrust.cc | 1 - src/shdc/generators/sokolzig.cc | 2 -- 7 files changed, 9 deletions(-) diff --git a/src/shdc/generators/sokolc.cc b/src/shdc/generators/sokolc.cc index 0eed2dfa..36915557 100644 --- a/src/shdc/generators/sokolc.cc +++ b/src/shdc/generators/sokolc.cc @@ -317,7 +317,6 @@ void SokolCGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef const Type& u = ub->struct_info.struct_items[u_index]; const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); l("{}.type = {};\n", un, uniform_type(u.type)); - l("{}.offset = {};\n", un, u.offset); l("{}.array_count = {};\n", un, u.array_count); l("{}.glsl_name = \"{}.{}\";\n", un, ub->inst_name, u.name); } @@ -515,7 +514,6 @@ void SokolCGenerator::gen_uniform_desc_refl_func(const GenInput& gen, const Prog for (const Type& u: ub.struct_info.struct_items) { l_open("if (0 == strcmp(u_name, \"{}\")) {{\n", u.name); l("res.type = {};\n", uniform_type(u.type)); - l("res.offset = {};\n", u.offset); l("res.array_count = {};\n", u.array_count); l("res.glsl_name = \"{}\";\n", u.name); l("return res;\n"); diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index 83e7a5ff..eef51449 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -267,7 +267,6 @@ void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramRef const Type& u = ub->struct_info.struct_items[u_index]; const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); l("{}.type = {};\n", un, uniform_type(u.type)); - l("{}.offset = {};\n", un, u.offset); l("{}.array_count = {};\n", un, u.array_count); l("{}.glsl_name = \"{}.{}\";\n", un, ub->inst_name, u.name); } diff --git a/src/shdc/generators/sokoljai.cc b/src/shdc/generators/sokoljai.cc index 3a2bb1d6..562a35f4 100644 --- a/src/shdc/generators/sokoljai.cc +++ b/src/shdc/generators/sokoljai.cc @@ -251,7 +251,6 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR const Type& u = ub->struct_info.struct_items[u_index]; const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); l("{}.type = {};\n", un, uniform_type(u.type)); - l("{}.offset = {};\n", un, u.offset); l("{}.array_count = {};\n", un, u.array_count); l("{}.glsl_name = \"{}.{}\";\n", un, ub->inst_name, u.name); } diff --git a/src/shdc/generators/sokolnim.cc b/src/shdc/generators/sokolnim.cc index a4ef515c..5d8e5621 100644 --- a/src/shdc/generators/sokolnim.cc +++ b/src/shdc/generators/sokolnim.cc @@ -334,7 +334,6 @@ void SokolNimGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR const Type& u = ub->struct_info.struct_items[u_index]; const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); l("{}.type = {}\n", un, uniform_type(u.type)); - l("{}.offset = {}\n", un, u.offset); l("{}.arrayCount = {}\n", un, u.array_count); l("{}.glslName = \"{}.{}\"\n", un, ub->inst_name, u.name); } diff --git a/src/shdc/generators/sokolodin.cc b/src/shdc/generators/sokolodin.cc index 0033c3f5..d0372fe5 100644 --- a/src/shdc/generators/sokolodin.cc +++ b/src/shdc/generators/sokolodin.cc @@ -254,7 +254,6 @@ void SokolOdinGenerator::gen_shader_desc_func(const GenInput& gen, const Program const Type& u = ub->struct_info.struct_items[u_index]; const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); l("{}.type = {}\n", un, uniform_type(u.type)); - l("{}.offset = {}\n", un, u.offset); l("{}.array_count = {}\n", un, u.array_count); l("{}.glsl_name = \"{}.{}\"\n", un, ub->inst_name, u.name); } diff --git a/src/shdc/generators/sokolrust.cc b/src/shdc/generators/sokolrust.cc index ae1b12c4..dae305fb 100644 --- a/src/shdc/generators/sokolrust.cc +++ b/src/shdc/generators/sokolrust.cc @@ -267,7 +267,6 @@ void SokolRustGenerator::gen_shader_desc_func(const GenInput& gen, const Program const Type& u = ub->struct_info.struct_items[u_index]; const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); l("{}._type = {};\n", un, uniform_type(u.type)); - l("{}.offset = {};\n", un, u.offset); l("{}.array_count = {};\n", un, u.array_count); l("{}.glsl_name = c\"{}.{}\".as_ptr();\n", un, ub->inst_name, u.name); } diff --git a/src/shdc/generators/sokolzig.cc b/src/shdc/generators/sokolzig.cc index f672873f..46fa949b 100644 --- a/src/shdc/generators/sokolzig.cc +++ b/src/shdc/generators/sokolzig.cc @@ -265,7 +265,6 @@ void SokolZigGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR const Type& u = ub->struct_info.struct_items[u_index]; const std::string un = fmt::format("{}.glsl_uniforms[{}]", ubn, u_index); l("{}.type = {};\n", un, uniform_type(u.type)); - l("{}.offset = {};", un, u.offset); l("{}.array_count = {};\n", un, u.array_count); l("{}.glsl_name = \"{}.{}\";\n", un, ub->inst_name, u.name); } @@ -662,7 +661,6 @@ void SokolZigGenerator::gen_uniform_desc_refl_func(const GenInput& gen, const Pr l_open("if (std.mem.eql(u8, u_name, \"{}\")) {{\n", u.name); l("var desc: sg.ShaderUniformDesc = .{{}};\n"); l("desc.type = {};\n", uniform_type(u.type)); - l("desc.offset = {};\n", u.offset); l("desc.array_count = {};\n", u.array_count); l("desc.glsl_name = \"{}\";\n", u.name); l("return desc;\n"); From 24d9968145237208e402f66272455a0f40ee9cfe Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 27 Oct 2024 12:48:59 +0100 Subject: [PATCH 33/37] jai generator: fix missing semicolon --- src/shdc/generators/sokoljai.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shdc/generators/sokoljai.cc b/src/shdc/generators/sokoljai.cc index 562a35f4..7ee81eb4 100644 --- a/src/shdc/generators/sokoljai.cc +++ b/src/shdc/generators/sokoljai.cc @@ -231,7 +231,7 @@ void SokolJaiGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramR const UniformBlock* ub = prog.bindings.find_uniform_block_by_sokol_slot(ub_index); if (ub) { const std::string ubn = fmt::format("desc.uniform_blocks[{}]", ub_index); - l("{}.stage = {}\n", ubn, shader_stage(ub->stage)); + l("{}.stage = {};\n", ubn, shader_stage(ub->stage)); l("{}.layout = .STD140;\n", ubn); l("{}.size = {};\n", ubn, roundup(ub->struct_info.size, 16)); if (Slang::is_hlsl(slang)) { From 84d83e5f20bbc226b305f6c8a574f9515c40317f Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 28 Oct 2024 13:13:41 +0100 Subject: [PATCH 34/37] improve error message when bindings for same resource type and name differ --- src/shdc/spirv.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shdc/spirv.cc b/src/shdc/spirv.cc index 7415dcb9..aaaa608f 100644 --- a/src/shdc/spirv.cc +++ b/src/shdc/spirv.cc @@ -235,7 +235,7 @@ static bool compile(Input& inp, EShLanguage stage, Slang::Enum slang, const Merg if (slot == -1) { inp.ub_slots[name] = binding; } else if (slot != binding) { - out_spirv.errors.push_back(inp.error(0, fmt::format("binding collision for uniform block '{}' ({} vs {})", name, slot, binding))); + out_spirv.errors.push_back(inp.error(0, fmt::format("different bindings for uniform blocks of same name '{}' ({} vs {})", name, slot, binding))); return false; } } @@ -247,7 +247,7 @@ static bool compile(Input& inp, EShLanguage stage, Slang::Enum slang, const Merg if (slot == -1) { inp.sbuf_slots[name] = binding; } else if (slot != binding) { - out_spirv.errors.push_back(inp.error(0, fmt::format("binding collision for buffer block '{}' ({} vs {})", name, slot, binding))); + out_spirv.errors.push_back(inp.error(0, fmt::format("different bindings for buffer blocks of same name '{}' ({} vs {})", name, slot, binding))); return false; } } @@ -260,7 +260,7 @@ static bool compile(Input& inp, EShLanguage stage, Slang::Enum slang, const Merg if (slot == -1) { inp.smp_slots[name] = binding; } else if (slot != binding) { - out_spirv.errors.push_back(inp.error(0, fmt::format("binding collision for sampler '{}' ({} vs {})", name, slot, binding))); + out_spirv.errors.push_back(inp.error(0, fmt::format("different bindings for samplers of same name '{}' ({} vs {})", name, slot, binding))); return false; } } else if (uniform.getType()->isTexture()) { @@ -268,7 +268,7 @@ static bool compile(Input& inp, EShLanguage stage, Slang::Enum slang, const Merg if (slot == -1) { inp.img_slots[name] = binding; } else if (slot != binding) { - out_spirv.errors.push_back(inp.error(0, fmt::format("binding collision for image '{}' ({} vs {})", name, slot, binding))); + out_spirv.errors.push_back(inp.error(0, fmt::format("different bindings for textures of same name '{}' ({} vs {})", name, slot, binding))); return false; } } From 85b6fd7f62fc654fe1d62fcec16b71f3e7c89d02 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 28 Oct 2024 14:05:20 +0100 Subject: [PATCH 35/37] update docs for resource binding cleanup --- docs/sokol-shdc.md | 278 ++++++++++++++++++++++++++++++--------------- 1 file changed, 186 insertions(+), 92 deletions(-) diff --git a/docs/sokol-shdc.md b/docs/sokol-shdc.md index 94056620..bc3412d4 100644 --- a/docs/sokol-shdc.md +++ b/docs/sokol-shdc.md @@ -8,7 +8,7 @@ Shader-code-generator for sokol_gfx.h - [Build Process Integration with fips](#build-process-integration-with-fips) - [Standalone Usage](#standalone-usage) - [Shader Tags Reference](#shader-tags-reference) -- [Programming Considerations](#programming-considerations) +- [Shader Authoring Considerations](#shader-authoring-considerations-considerations) - [Runtime Inspection](#runtime-inspection) ## Feature Overview @@ -44,7 +44,7 @@ sokol-shdc supports the following output formats: - Odin for integration with [sokol-odin](https://github.com/floooh/sokol-odin) - Nim for integration with [sokol-nim](https://github.com/floooh/sokol-nim) - D for integration with [sokol-d](https://github.com/kassane/sokol-d) -- Jai (without separate sokol header bindings) +- Jai for integration with [sokol-jai](https://github.com/colinbellino/sokol-jai) - 'raw' output files in GLSL, MSL and HLSL along with reflection data in YAML files Error messages from `glslang` are mapped back to the original annotated @@ -61,7 +61,7 @@ additional information for the C code-generation (note the `@vs`, ```glsl @vs vs -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -77,8 +77,8 @@ void main() { @end @fs fs -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec2 uv; out vec4 frag_color; @@ -101,10 +101,11 @@ A generated C header contains (similar information is generated for the other ou - human-readable reflection info in a comment block - a C struct for each shader uniform block +- constants for vertex attribute locations, uniform block, image, sampler + and storage buffer binding indices - for each shader program, a C function which returns a pointer to a ```sg_shader_desc``` for a specific sokol-gfx backend which can be passed directly into `sg_make_shader()` -- constants for vertex attribute locations, uniform-block- and image-bind-slots - optionally a set of C functions for runtime inspection of the generated vertex attributes, image bind slots and uniform-block structs @@ -122,13 +123,27 @@ pip = sg_make_pipeline(&(sg_pipeline_desc){ .shader = shd, .layout = { .attrs = { - [ATTR_vs_position].format = SG_VERTEXFORMAT_FLOAT3, - [ATTR_vs_texcoord0].format = SG_VERTEXFORMAT_FLOAT2, + [ATTR_texcube_position].format = SG_VERTEXFORMAT_FLOAT3, + [ATTR_texcube_texcoord0].format = SG_VERTEXFORMAT_FLOAT2, } } }); ``` +...and then applying resource bindings and uniform updates looks like this: + +```c +sg_apply_bindings(&(sg_bindings){ + .vertex_buffers[0] = vbuf, + .images[IMG_tex] = img, + .samplers[SMP_smp] = smp, +}); +const vs_params_t vs_params = { + .mvp = ..., +}; +sg_apply_uniforms(UB_vs_params, &SG_RANGE(vs_params)); +``` + ## Build Process Integration with fips sokol-shdc can be used standalone as offline-tool from the command @@ -387,7 +402,7 @@ Example: ```glsl @vs my_vertex_shader -uniform vs_params { +layout(binding=0) uniform vs_params { mat4 mvp; }; @@ -439,7 +454,7 @@ Example for the above vertex- and fragment-shader snippets: This will generate a C function: ```C -static const sg_shader_desc* my_program_shader_desc(void); +static const sg_shader_desc* my_program_shader_desc(sg_backend backend); ``` ### @block [name] @@ -516,7 +531,7 @@ Consider the following GLSL uniform block without `@ctype` tags: ```glsl @vs my_vs -uniform shape_uniforms { +layout(binding=0) uniform shape_uniforms { mat4 mvp; mat4 model; vec4 shape_color; @@ -550,7 +565,7 @@ map the GLSL types to their matching hmm_* types: @ctype vec4 hmm_vec4 @vs my_vs -uniform shape_uniforms { +layout(binding=0) uniform shape_uniforms { mat4 mvp; mat4 model; vec4 shape_color; @@ -616,7 +631,7 @@ For instance, when adding a `@module` tag to the above @ctype-example: @ctype vec4 hmm_vec4 @vs my_vs -uniform shape_uniforms { +layout(binding=0) uniform shape_uniforms { mat4 mvp; mat4 model; vec4 shape_color; @@ -692,7 +707,7 @@ Example from https://github.com/floooh/sokol-samples/blob/master/sapp/ozz-skin-s ```glsl @image_sample_type joint_tex unfilterable_float -uniform texture2D joint_tex; +layout(binding=0) uniform texture2D joint_tex; ``` ### @sampler_type [sampler] [type] @@ -717,10 +732,10 @@ Example from https://github.com/floooh/sokol-samples/blob/master/sapp/ozz-skin-s ```glsl @sampler_type smp nonfiltering -uniform sampler smp; +layout(binding=0) uniform sampler smp; ``` -## Programming Considerations +## Shader Authoring Considerations ### Target Shader Language Defines @@ -772,9 +787,11 @@ sg_shader shd = sg_make_shader(shape_shader_desc(sg_query_backend())); ``` When creating a pipeline object, the shader code generator will -provide integer constants for the vertex attribute locations. +provide integer constants for the vertex attribute locations, unique +for each `@program`. -Consider the following vertex shader inputs in the GLSL source code: +Consider the following vertex shader inputs in the GLSL source code +and `@program` definition: ```glsl @vs vs @@ -783,18 +800,20 @@ in vec3 normal; in vec2 texcoords; ... @end +... +@program shd vs fs ``` The vertex attribute description in the `sg_pipeline_desc` struct -could look like this (note the attribute indices names `ATTR_vs_position`, etc...): +could look like this (note the attribute indices names `ATTR_shd_position`, etc...): ```c sg_pipeline pip = sg_make_pipeline(&(sg_pipeline_desc){ .layout = { .attrs = { - [ATTR_vs_position].format = SG_VERTEXFORMAT_FLOAT3, - [ATTR_vs_normal].format = SG_VERTEXFORMAT_BYTE4N, - [ATTR_vs_texcoords].format = SG_VERTEXFORMAT_SHORT2 + [ATTR_shd_position].format = SG_VERTEXFORMAT_FLOAT3, + [ATTR_shd_normal].format = SG_VERTEXFORMAT_BYTE4N, + [ATTR_shd_texcoords].format = SG_VERTEXFORMAT_SHORT2 } }, ... @@ -802,7 +821,8 @@ sg_pipeline pip = sg_make_pipeline(&(sg_pipeline_desc){ ``` It's also possible to provide explicit vertex attribute location in the -shader code: +shader code, but be aware that the explicitly defined locations must +not have gaps: ```glsl @vs vs @@ -829,90 +849,145 @@ sg_pipeline pip = sg_make_pipeline(&(sg_pipeline_desc){ }); ``` +### Defining resource bind slots + +All GLSL resource types (uniform blocks, textures, samplers and storage buffers) +must be annotated with explicit bind slots via `layout(binding=N)`. Each resource +type has its own binding space which directly maps to sokol_gfx.h bindslots: + +- uniform blocks: + - `layout(binding=N) uniform { ... }` where `(N >= 0) && (N < 8)` + - N maps to to the ub_slot params in `sg_apply_uniforms(N, ...)` +- textures: + - `layout(binding=N) texture2D tex;` where `(N >= 0) && (N < 16)` + - N maps to the image index in `sg_bindings.images[N]` +- samplers: + - `layout(binding=N) sampler smp;` where `(N >= 0) && (N < 16)` + - N maps to the sampler index in `sg_bindings.samplers[N]` +- storage buffers: + - `layout(binding=N) readonly buffer ssbo { ... }` where `(N >= 0) && (N < 8)` + - N maps to the storage buffer index in `sg_bindings.storage_buffers[N]` + +Bindings must be unique per resource type within a shader `@program` across +shader stages, and all resources of the same type and name across all programs +in a shader source file must have matching bindings. + +Violations against these rules are checked by sokol-shdc and will result in +compilation errors. + +Note that bind slots are allowed to have gaps. This allows to map specific types of resources +(like diffuse vs normal-map textures) to specific bindslots even if a shader only +uses a subset of those resources. This allows to use the same `sg_bindings` struct for +different related shaders (like the different shader variants of the same material). + ### Binding uniforms blocks -Similar to the vertex attribute location constants, the C code generator -also provides bind slot constants for images and uniform blocks. +Uniform blocks must be annotated with `layout(binding=N)` where `(N >=0) && (N < 8)`. +Those bindings directly map to the `ub_slot` parameter in `sg_apply_uniforms(int ub_slot, ...)`. +Uniform block bindings must be unique across shader stages of a `@program`. + +The sokol-shdc code generation will create a bind slot constant for each +uniquely named uniform block in a shader source file. -Consider the following uniform block in GLSL: +Consider the following uniform blocks in the vertex and fragment shader: ```glsl -uniform vs_params { +@ctype mat4 hmm_mat4 +@ctype vec4 hmm_vec4 + +@vs +layout(binding=0) uniform vs_params { mat4 mvp; }; +... +@end + +@fs +layout(binding=1) uniform fs_params { + vec4 color; +}; +... +@end ``` -The C header code generator will create a C struct and a 'bind slot' constant -for the uniform block: +The C header code generator will create two C struct and bindslot constants +looking like this: ```c -#define SLOT_vs_params (0) +#define UB_vs_params (0) +#define UB_fs_params (1) typedef struct vs_params_t { hmm_mat4 mvp; } vs_params_t; +typedef struct fs_params_t { + hmm_vec4 mvp; +} fs_params_t; ``` -...which both are used in the `sg_apply_uniforms()` call like this: +...which can be used in `sg_apply_uniforms()` calls like this: ```c vs_params_t vs_params = { .mvp = ... }; -sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_params, &SG_RANGE(vs_params)); +fs_params_t fs_params = { + .color = ... +}; +sg_apply_uniforms(UB_vs_params, &SG_RANGE(vs_params)); +sg_apply_uniforms(UB_fs_params, &SG_RANGE(fs_params)); ``` -Note that you cannot use explicit bind locations for uniform blocks in the shader -code (or rather: you can, but sokol-shdc will ignore those), instead sokol-shdc -will automatically assign bind slots to uniform blocks. - -To get the correct bind slot on the 'CPU side', either use the code -generated `SLOT_*` constants, or the optionally generated runtime -inspection functions which allow to lookup bind slots by name. +Since the bind slots have been explicitly defined in the shader code, you +may also ignore the generated bind slot constants, but in that case you need +to make to fix up the C code when changing the bind slots in the shader code. -More on the optional runtime inspection function below in the -section `Runtime Inspection`. +```c +sg_apply_uniforms(0, &SG_RANGE(vs_params)); +sg_apply_uniforms(1, &SG_RANGE(fs_params)); +``` ### Binding images and samplers Textures and samplers must be defined separately in the input GLSL (this is -also known as 'Vulkan-style GLSL'): +also known as 'Vulkan-style GLSL'). Just as with uniform blocks, you must +define explicit bind slots via `layout(binding=N)`. Textures and samplers +have separate bindslot spaces, with a range of `(N >=0) && (N < 16)`. ```glsl -uniform texture2D tex; -uniform sampler smp; +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; ``` -Shader in old 'GL-style GLSL' with combined image-samplers will now generate -an error. - The resource binding slot for texture and sampler uniforms is available as code-generated constant: ```C -#define SLOT_tex (0) -#define SLOT_smp (0) +#define IMG_tex (0) +#define SMP_smp (0) ``` -This is used in the `sg_bindings` struct as index into the `vs.images[]`, -`vs.samplers[]`, `fs.images[]` and `fs.samplers[]` arrays: +This is used in the `sg_bindings` struct as index into the `.images[]`, +and `.samplers[]` arrays: ```c sg_apply_bindings(&(sg_bindings){ .vertex_buffers[0] = vbuf, - .fs = { - .images[SLOT_tex] = img, - .samplers[SLOT_smp] = smp, - }, + .images[IMG_tex] = img, + .samplers[SMP_smp] = smp, }); ``` -Just as with uniform blocks, any explit bind slot definition in the shader -is ignored, instead bind slots will be automatically assigned. The assigned -bind slot is available either as constant as shown above, or can be looked -up by name via the optional runtime inspection functions. +Instead of the generated constants you can also use the explicit binding +numbers defined in the shader source file (but when those are changed you +must not forget also fixing the C side): -More on the optional runtime inspection function below in the -section `Runtime Inspection`. +```c +sg_apply_bindings(&(sg_bindings){ + .vertex_buffers[0] = vbuf, + .images[0] = img, + .samplers[0] = smp, +}); +``` ### Binding storage buffers @@ -929,12 +1004,40 @@ struct sb_vertex { vec4 color; }; -readonly buffer ssbo { +layout(binding=0) readonly buffer ssbo { sb_vertex vtx[]; }; ``` -The buffer content can be accessed in the a shader like this (for +The binding range for storage buffers is `(N >= 0) && (N < 8)` within one +shader program and across all shader stages. `N` directly corresponds to +the index into the `sg_bindings.storage_buffers[]` array. + +A binding constant will be generated for each uniquely named storage buffer +in a shader source file: + +```c +#define SBUF_ssbo (0) +``` + +To apply a storage buffer binding, you can either use this generated constant, +or directly the binding number from the shader source file: + +```c +// using the code-generated constant: +sg_apply_bindings(&(sg_bindings){ + .vertex_buffers[0] = vbuf, + .storage_buffers[SBUF_ssbo] = sbuf, +}); + +// or directly using the explicit binding: +sg_apply_bindings(&(sg_bindings){ + .vertex_buffers[0] = vbuf, + .storage_buffers[0] = sbuf, +}); +``` + +In the shader code, the buffer content can be accessed like this (for instance using gl_VertexIndex): ```glsl @@ -951,18 +1054,9 @@ alignment and padding (according to `std430` layout) and a `SLOT_ssbo` define which can be used in the `sg_bindings` struct to index into the `vs.storage_buffers` or `fs.storage_buffers` arrays. - -```c -sg_apply_bindings(&(sg_bindings){ - .vs = { - .storage_buffers[SLOT_ssbo] = img, - }, -}); -``` - ### GLSL uniform blocks and C structs -There are a few caveats with uniform blocks: +There are a few caveats to be aware of with uniform blocks: - The memory layout of uniform blocks on the CPU side must be compatible across all sokol-gfx backends. To achieve this, uniform block content @@ -1089,8 +1183,8 @@ sg_pipeline_desc pip_desc = { The function -**int [mod]_[prog]_image_slot(sg_shader_stage stage, const char\* image_name)** -**int [mod]_[prog]_sampler_slot(sg_shader_stage stage, const char\* sampler_name)** +**int [mod]_[prog]_image_slot(const char\* image_name)** +**int [mod]_[prog]_sampler_slot(const char\* sampler_name)** returns the bind-slot of an image or sampler on the given shader stage, or -1 if the shader doesn't expect an image or sampler of that name on that shader stage. @@ -1101,13 +1195,13 @@ Code example: sg_image specular_texture = ...; sg_bindings binds = { ... }; -// check if the shader expects a specular texture on the fragment shader stage, +// check if the shader expects a specular texture, // if yes set it in the bindings struct at the expected slot index: -const int spec_tex_slot = mod_prog_image_slot(SG_SHADERSTAGE_FS, "spec_tex"); -const int spec_smp_slot = mod_prog_sampler_slot(SG_SHADERSTAGE_FS, "spec_smp"); +const int spec_tex_slot = mod_prog_image_slot("spec_tex"); +const int spec_smp_slot = mod_prog_sampler_slot("spec_smp"); if ((spec_tex_slot >= 0) && (spec_smp_slot >= 0)) { - bindings.fs.images[spec_tex_slot] = specular_texture; - bindings.fs.samplers[spex_smp_slot] = specular_sampler; + bindings.images[spec_tex_slot] = specular_texture; + bindings.samplers[spex_smp_slot] = specular_sampler; } // apply bindings @@ -1116,16 +1210,18 @@ sg_apply_bindings(&binds); ### Uniform Block Inspection +> NOTE: some of those dynamic reflection functions are not actually needed anymore, because it's now possible to define explicit bind slots in the shader source + The function -`int [mod]_[prog]_uniformblock_slot(sg_shader_stage stage, const char* ub_name)` +`int [mod]_[prog]_uniformblock_slot(const char* ub_name)` returns the bind slot of a shader's uniform block on the given shader stage, or -1 if the shader doesn't expect a uniform block of that name on that shader stage. The function -`size_t [mod]_[prog]_uniformblock_size(sg_shader_stage stage, const char* ub_name)` +`size_t [mod]_[prog]_uniformblock_size(const char* ub_name)` return the size in bytes of a shader's uniform block on the given shader stage, or 0 if the shader doesn't expect a uniform block of that name on that shader stage. @@ -1137,10 +1233,10 @@ Code example: ```c // NOTE: in real-world code you'd probably want to lookup the uniform block // slot and size upfront in initialization code, not in the hot path -const int ub_slot = prog_mod_uniformblock_slot(SG_SHADERSTAGE_VS, "vs_params"); +const int ub_slot = prog_mod_uniformblock_slot("vs_params"); if (ub_slot >= 0) { - const size_t ub_size = prog_mod_uniformblock_size(SG_SHADERSTAGE_VS, "vs_params"); - sg_apply_uniforms(SG_SHADERSTAGE_VS, ub_slot, &(sg_range){ + const size_t ub_size = prog_mod_uniformblock_size("vs_params"); + sg_apply_uniforms(ub_slot, &(sg_range){ .ptr = pointer_to_uniform_data, .size = ub_size }); @@ -1149,23 +1245,21 @@ if (ub_slot >= 0) { The function -`int [mod]_[prog]_uniform_offset(sg_shader_stage stage, const char* ub_name, const char* u_name)` +`int [mod]_[prog]_uniform_offset(const char* ub_name, const char* u_name)` ...allows to lookup the byte offset of a specific uniform within its uniform block. This makes it possible to compose uniform data expected by a shader without the hardwired uniform block C struct. The function returns -1 if the shader doesn't expect -a uniform block of that name on that shader stage, or if the uniform block is expected +a uniform block of that name, or if the uniform block is expected but doesn't contain a uniform of that name. -It's also possible to query the ```sg_shader_uniform_desc``` struct of a given uniform, which +It's also possible to query the ```sg_shader_uniform``` of a given uniform, which provides additional type information with the following function: -`sg_shader_uniform_desc [mod]_[prog]_uniform_desc(sg_shader_stage stage, const char* ub_name, const char* u_name)` - -The ```sg_shader_uniform_desc``` struct allows to inspect the uniform type (```SG_UNIFORMTYPE_xxx```), and the array count of the uniform (which is 1 for regular uniforms, or >1 for arrays). +`sg_glsl_shader_uniform [mod]_[prog]_uniform_desc(const char* ub_name, const char* u_name)` ### Storage buffer inspection Currently, only the bind slot can be inspected for storage buffers: -`int [mod]_[prog]_storagebuffer_slot(sg_shader_stage stage, const char* sbuf_name)` +`int [mod]_[prog]_storagebuffer_slot(const char* sbuf_name)` From fe5df039adcaad393b28225e4094933650f7d37f Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Thu, 31 Oct 2024 18:21:56 +0100 Subject: [PATCH 36/37] docs: fix table of content --- docs/sokol-shdc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sokol-shdc.md b/docs/sokol-shdc.md index bc3412d4..69d14210 100644 --- a/docs/sokol-shdc.md +++ b/docs/sokol-shdc.md @@ -8,7 +8,7 @@ Shader-code-generator for sokol_gfx.h - [Build Process Integration with fips](#build-process-integration-with-fips) - [Standalone Usage](#standalone-usage) - [Shader Tags Reference](#shader-tags-reference) -- [Shader Authoring Considerations](#shader-authoring-considerations-considerations) +- [Shader Authoring Considerations](#shader-authoring-considerations) - [Runtime Inspection](#runtime-inspection) ## Feature Overview From 7cc01cf631f51becb862a4916b9e50bc48a6618c Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 6 Nov 2024 20:26:53 +0100 Subject: [PATCH 37/37] update changelog (https://github.com/floooh/sokol-tools/pull/151) --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0036c69..3718f06b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,20 @@ CHANGELOG ========= +#### **07-Nov-2024** + +This is the sokol-shdc update going with the sokol-gfx 'bindings cleanup update': + +- Input shader code now require explicit `layout(binding=N)` annotations on + uniform blocks, textures, samplers and storage buffers. +- All code generators have been updated for the new `sg_shader_desc` struct + interior (this also affects the yaml generator output). + +Associated PR: https://github.com/floooh/sokol-tools/pull/151 + +See also the [sokol repository changelog](https://github.com/floooh/sokol/blob/master/CHANGELOG.md#07-nov-2024) +for more details. + #### **04-Sep-2024** The Zig code generator (`-f sokol_zig`) now generates runtime reflection functions