From 01feaffbb1aac4c600813131d3d50d3338c5307f Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 11 May 2024 13:21:09 +0200 Subject: [PATCH 1/8] initial port of D generator from https://github.com/floooh/sokol-tools/pull/115 --- src/shdc/generators/generate.cc | 3 + src/shdc/generators/sokold.cc | 481 ++++++++++++++++++++++++++++++++ src/shdc/generators/sokold.h | 44 +++ src/shdc/types/format.h | 4 + 4 files changed, 532 insertions(+) create mode 100644 src/shdc/generators/sokold.cc create mode 100644 src/shdc/generators/sokold.h diff --git a/src/shdc/generators/generate.cc b/src/shdc/generators/generate.cc index e5944a21..0b1b2db3 100644 --- a/src/shdc/generators/generate.cc +++ b/src/shdc/generators/generate.cc @@ -9,6 +9,7 @@ #include "sokolodin.h" #include "sokolrust.h" #include "sokolzig.h" +#include "sokold.h" #include "yaml.h" #include @@ -28,6 +29,8 @@ std::unique_ptr make_generator(Format::Enum format) { return std::make_unique(); case Format::SOKOL_RUST: return std::make_unique(); + case Format::SOKOL_D: + return std::make_unique(); default: return std::make_unique(); } diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc new file mode 100644 index 00000000..7ca2db33 --- /dev/null +++ b/src/shdc/generators/sokold.cc @@ -0,0 +1,481 @@ +/* + D language generator. +*/ +#include "sokold.h" +#include "fmt/format.h" +#include "pystring.h" +#include + +namespace shdc::gen { + +using namespace refl; + +void SokolDGenerator::gen_prolog(const GenInput& gen) { + std::string root, ext; + pystring::os::path::splitext(root, ext, gen.args.input); + l("module shaders.{};\n", pystring::os::path::basename(root)); + l("import sg = sokol.gfx;\n"); + l("extern(C):\n\n"); +} + +void SokolDGenerator::gen_epilog(const GenInput& gen) { + // empty +} + +void SokolDGenerator::gen_prerequisites(const GenInput& gen) { + // empty +} + +void SokolDGenerator::gen_uniform_block_decl(const GenInput& gen, const UniformBlock& ub) { + l_open("struct {} {{\n", struct_name(ub.struct_info.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; + int next_offset = uniform.offset; + if (next_offset > cur_offset) { + l("align({}) ubyte[{}] _pad_{};\n", align, next_offset - cur_offset, cur_offset); + cur_offset = next_offset; + } + if (gen.inp.ctype_map.count(uniform.type_as_glsl()) > 0) { + // user-provided type names + if (uniform.array_count == 0) { + l("align({}) {} {};\n", align, gen.inp.ctype_map.at(uniform.type_as_glsl()), uniform.name); + } else { + l("align({}) {}[{}] {};\n", align, gen.inp.ctype_map.at(uniform.type_as_glsl()), uniform.array_count, uniform.name); + } + } else { + // default type names (float) + if (uniform.array_count == 0) { + switch (uniform.type) { + case Type::Float: l("align({}) float {};\n", align, uniform.name); break; + case Type::Float2: l("align({}) float[2] {};\n", align, uniform.name); break; + case Type::Float3: l("align({}) float[3] {};\n", align, uniform.name); break; + case Type::Float4: l("align({}) float[4] {};\n", align, uniform.name); break; + case Type::Int: l("align({}) int {};\n", align, uniform.name); break; + case Type::Int2: l("align({}) int[2] {};\n", align, uniform.name); break; + case Type::Int3: l("align({}) int[3] {};\n", align, uniform.name); break; + case Type::Int4: l("align({}) int[4] {};\n", align, uniform.name); break; + case Type::Mat4x4: l("align({}) float[16] {};\n", align, uniform.name); break; + default: l("INVALID_UNIFORM_TYPE;\n"); break; + } + } else { + switch (uniform.type) { + case Type::Float4: l("align({}) float[4][{}] {};\n", align, uniform.array_count, uniform.name); break; + case Type::Int4: l("align({}) int[4][{}] {};\n", align, uniform.array_count, uniform.name); break; + case Type::Mat4x4: l("align({}) float[16][{}] {};\n", align, uniform.array_count, uniform.name); break; + default: l("INVALID_UNIFORM_TYPE;\n"); break; + } + } + } + cur_offset += uniform.size; + } + // pad to multiple of 16-bytes struct size + const int round16 = roundup(cur_offset, 16); + if (cur_offset < round16) { + l("align(1) ubyte[{}] _pad_{};\n", round16 - cur_offset, cur_offset); + } + l_close("}}\n"); +} + +void SokolDGenerator::gen_struct_interior_decl_std430(const GenInput& gen, const Type& struc, int alignment, int pad_to_size) { + assert(struc.type == Type::Struct); + assert(alignment > 0); + assert(pad_to_size > 0); + + int cur_offset = 0; + for (const Type& item: struc.struct_items) { + const int align = (cur_offset == 0) ? alignment : 1; + int next_offset = item.offset; + if (next_offset > cur_offset) { + l("align({}) ubyte[{}] _pad_{};\n", align, next_offset - cur_offset, cur_offset); + cur_offset = next_offset; + } + if (item.type == Type::Struct) { + // recurse into nested struct + l_open("struct {}_s {{\n", struct_name(item.name)); + gen_struct_interior_decl_std430(gen, item, 1, item.size); + l_close("}}\n"); + if (item.array_count == 0) { + l("align({}) {}_s {};\n", align, struct_name(item.name), item.name); + } else { + l("align({}) {}_s[{}] {};\n", align, struct_name(item.name), item.array_count, item.name); + } + } else if (gen.inp.ctype_map.count(item.type_as_glsl()) > 0) { + // user-provided type names + if (item.array_count == 0) { + l("align({}) {} {};\n", align, gen.inp.ctype_map.at(item.type_as_glsl()), item.name); + } else { + l("align({}) {}[{}] {};\n", align, gen.inp.ctype_map.at(item.type_as_glsl()), item.array_count, item.name); + } + } else { + // default typenames + if (item.array_count == 0) { + switch (item.type) { + // NOTE: bool => int is not a bug! + case Type::Bool: l("align({}) int {};\n", align, item.name); break; + case Type::Bool2: l("align({}) int[2] {};\n", align, item.name); break; + case Type::Bool3: l("align({}) int[3] {};\n", align, item.name); break; + case Type::Bool4: l("align({}) int[4] {};\n", align, item.name); break; + case Type::Int: l("align({}) int {};\n", align, item.name); break; + case Type::Int2: l("align({}) int[2] {};\n", align, item.name); break; + case Type::Int3: l("align({}) int[3] {};\n", align, item.name); break; + case Type::Int4: l("align({}) int[4] {};\n", align, item.name); break; + case Type::UInt: l("align({}) uint {};\n", align, item.name); break; + case Type::UInt2: l("align({}) uint[2] {};\n", align, item.name); break; + case Type::UInt3: l("align({}) uint[3] {};\n", align, item.name); break; + case Type::UInt4: l("align({}) uint[4] {};\n", align, item.name); break; + case Type::Float: l("align({}) float {};\n", align, item.name); break; + case Type::Float2: l("align({}) float[2] {};\n", align, item.name); break; + case Type::Float3: l("align({}) float[3] {};\n", align, item.name); break; + case Type::Float4: l("align({}) float[4] {};\n", align, item.name); break; + case Type::Mat2x1: l("align({}) float[2] {};\n", align, item.name); break; + case Type::Mat2x2: l("align({}) float[4] {};\n", align, item.name); break; + case Type::Mat2x3: l("align({}) float[6] {};\n", align, item.name); break; + case Type::Mat2x4: l("align({}) float[8] {};\n", align, item.name); break; + case Type::Mat3x1: l("align({}) float[3] {};\n", align, item.name); break; + case Type::Mat3x2: l("align({}) float[6] {};\n", align, item.name); break; + case Type::Mat3x3: l("align({}) float[9] {};\n", align, item.name); break; + case Type::Mat3x4: l("align({}) float[12] {};\n", align, item.name); break; + case Type::Mat4x1: l("align({}) float[4] {};\n", align, item.name); break; + case Type::Mat4x2: l("align({}) float[8] {};\n", align, item.name); break; + case Type::Mat4x3: l("align({}) float[12] {};\n", align, item.name); break; + case Type::Mat4x4: l("align({}) float[16] {};\n", align, item.name); break; + default: l("INVALID_TYPE\n"); break; + } + } else { + switch (item.type) { + // NOTE: bool => int is not a bug! + case Type::Bool: l("align({}) int[{}] {};\n", align, item.array_count, item.name); break; + case Type::Bool2: l("align({}) int[2][{}] {};\n", align, item.array_count, item.name); break; + case Type::Bool3: l("align({}) int[3][{}] {};\n", align, item.array_count, item.name); break; + case Type::Bool4: l("align({}) int[4][{}] {};\n", align, item.array_count, item.name); break; + case Type::Int: l("align({}) int[{}] {};", align, item.array_count, item.name); break; + case Type::Int2: l("align({}) int[2] {};\n", align, item.array_count, item.name); break; + case Type::Int3: l("align({}) int[3] {};\n", align, item.array_count, item.name); break; + case Type::Int4: l("align({}) int[4] {};\n", align, item.array_count, item.name); break; + case Type::UInt: l("align({}) uint[{}] {};\n", align, item.array_count, item.name); break; + case Type::UInt2: l("align({}) uint[2][{}] {};\n", align, item.array_count, item.name); break; + case Type::UInt3: l("align({}) uint[3][{}] {};\n", align, item.array_count, item.name); break; + case Type::UInt4: l("align({}) uint[4][{}] {};\n", align, item.array_count, item.name); break; + case Type::Float: l("align({}) float[{}] {};\n", align, item.array_count, item.name); break; + case Type::Float2: l("align({}) float[2][{}] {};\n", align, item.array_count, item.name); break; + case Type::Float3: l("align({}) float[3][{}] {};\n", align, item.array_count, item.name); break; + case Type::Float4: l("align({}) float[4][{}] {};\n", align, item.array_count, item.name); break; + case Type::Mat2x1: l("align({}) float[2][{}] {};\n", align, item.array_count, item.name); break; + case Type::Mat2x2: l("align({}) float[4][{}] {};\n", align, item.array_count, item.name); break; + case Type::Mat2x3: l("align({}) float[6][{}] {};\n", align, item.array_count, item.name); break; + case Type::Mat2x4: l("align({}) float[8][{}] {};\n", align, item.array_count, item.name); break; + case Type::Mat3x1: l("align({}) float[3][{}] {};\n", align, item.array_count, item.name); break; + case Type::Mat3x2: l("align({}) float[6][{}] {};\n", align, item.array_count, item.name); break; + case Type::Mat3x3: l("align({}) float[9][{}] {};\n", align, item.array_count, item.name); break; + case Type::Mat3x4: l("align({}) float[12][{}] {};\n", align, item.array_count, item.name); break; + case Type::Mat4x1: l("align({}) float[4][{}] {};\n", align, item.array_count, item.name); break; + case Type::Mat4x2: l("align({}) float[8][{}] {};\n", align, item.array_count, item.name); break; + case Type::Mat4x3: l("align({}) float[12][{}] {};\n", align, item.array_count, item.name); break; + case Type::Mat4x4: l("align({}) float[16][{}] {};\n", align, item.array_count, item.name); break; + default: l("INVALID_TYPE\n"); break; + } + } + } + cur_offset += item.size; + } + if (cur_offset < pad_to_size) { + l("align(1) ubyte[{}] _pad_{};\n", pad_to_size - cur_offset, cur_offset); + } +} + +void SokolDGenerator::gen_storage_buffer_decl(const GenInput& gen, const StorageBuffer& sbuf) { + const auto& item = sbuf.struct_info.struct_items[0]; + l_open("struct {} {{\n", struct_name(item.struct_typename)); + gen_struct_interior_decl_std430(gen, item, sbuf.struct_info.align, sbuf.struct_info.size); + l_close("}}\n"); +} + +void SokolDGenerator::gen_shader_array_start(const GenInput& gen, const std::string& array_name, size_t num_bytes, Slang::Enum slang) { + l("__gshared char[{}] {} = [\n", num_bytes, array_name); + +} +void SokolDGenerator::gen_shader_array_end(const GenInput& gen) { + l("\n];\n"); +} + +void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramReflection& prog) { + l_open("sg.ShaderDesc {}_shader_desc(sg.Backend backend) @trusted @nogc nothrow {{\n", prog.name); + l("sg.ShaderDesc desc;\n"); + l("desc.label = \"{}_shader\";\n", prog.name); + l_open("switch (backend) {{\n"); + for (int i = 0; i < Slang::Num; i++) { + 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(refl.stage_name)); + if (info.has_bytecode) { + l("{}.bytecode.ptr = {}.ptr;\n", dsn, info.bytecode_array_name); + l("{}.bytecode.size = {};\n", dsn, info.bytecode_array_size); + } else { + l("{}.source = &{}[0];\n", dsn, info.source_array_name); + 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", dsn, d3d11_tgt); + } + } + l("{}.entry = \"{}\";\n", dsn, refl.entry_point_by_slang(slang)); + for (int ub_index = 0; ub_index < UniformBlock::Num; 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); + 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 sbuf_index = 0; sbuf_index < StorageBuffer::Num; 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); + l("{}.used = true;\n", sbn); + l("{}.readonly = {};\n", sbn, sbuf->readonly); + } + } + for (int img_index = 0; img_index < Image::Num; 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); + 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 smp_index = 0; smp_index < Sampler::Num; 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); + l("{}.used = true;\n", sn); + l("{}.sampler_type = {};\n", sn, sampler_type(smp->type)); + } + } + for (int img_smp_index = 0; img_smp_index < ImageSampler::Num; 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); + 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); + if (Slang::is_glsl(slang)) { + l("{}.glsl_name = \"{}\";\n", isn, img_smp->name); + } + } + } + } + l("break;\n"); + l_close(); // current switch branch + } + } + l("default: break;\n"); + l_close("}}\n"); // close switch statement + l("return desc;\n"); + l_close("}}\n"); // close function +} + +std::string SokolDGenerator::lang_name() { + return "D"; +} + +std::string SokolDGenerator::comment_block_start() { + return "/*"; +} + +std::string SokolDGenerator::comment_block_end() { + return "*/"; +} + +std::string SokolDGenerator::comment_block_line_prefix() { + return ""; +} + +std::string SokolDGenerator::shader_bytecode_array_name(const std::string& snippet_name, Slang::Enum slang) { + return pystring::upper(fmt::format("{}_bytecode_{}", snippet_name, Slang::to_str(slang))); +} + +std::string SokolDGenerator::shader_source_array_name(const std::string& snippet_name, Slang::Enum slang) { + return pystring::upper(fmt::format("{}_source_{}", snippet_name, Slang::to_str(slang))); +} + +std::string SokolDGenerator::get_shader_desc_help(const std::string& prog_name) { + return fmt::format("{}_shader_desc(sg.query_backend());\n", prog_name); +} + +std::string SokolDGenerator::uniform_type(Type::Enum e) { + switch (e) { + case Type::Float: return "sg.UniformType.Float"; + case Type::Float2: return "sg.UniformType.Float2"; + case Type::Float3: return "sg.UniformType.Float3"; + case Type::Float4: return "sg.UniformType.Float4"; + case Type::Int: return "sg.UniformType.Int"; + case Type::Int2: return "sg.UniformType.Int2"; + case Type::Int3: return "sg.UniformType.Int3"; + case Type::Int4: return "sg.UniformType.Int4"; + case Type::Mat4x4: return "sg.UniformType.Mat4"; + default: return "INVALID"; + } +} + +std::string SokolDGenerator::flattened_uniform_type(Type::Enum e) { + switch (e) { + case Type::Float: + case Type::Float2: + case Type::Float3: + case Type::Float4: + case Type::Mat4x4: + return "sg.UniformType.Float4"; + case Type::Int: + case Type::Int2: + case Type::Int3: + case Type::Int4: + return "sg.UniformType.Int4"; + default: + return "INVALID"; + } +} + +std::string SokolDGenerator::image_type(ImageType::Enum e) { + switch (e) { + case ImageType::_2D: return "sg.ImageType._2d"; + case ImageType::CUBE: return "sg.ImageType.Cube"; + case ImageType::_3D: return "sg.ImageType._3d"; + case ImageType::ARRAY: return "sg.ImageType.Array"; + default: return "INVALID"; + } +} + +std::string SokolDGenerator::image_sample_type(ImageSampleType::Enum e) { + switch (e) { + case ImageSampleType::FLOAT: return "sg.ImageSampleType.Float"; + case ImageSampleType::DEPTH: return "sg.ImageSampleType.Depth"; + case ImageSampleType::SINT: return "sg.ImageSampleType.Sint"; + case ImageSampleType::UINT: return "sg.ImageSampleType.Uint"; + case ImageSampleType::UNFILTERABLE_FLOAT: return "sg.ImageSampleType.UnfilterableFloat"; + default: return "INVALID"; + } +} + +std::string SokolDGenerator::sampler_type(SamplerType::Enum e) { + switch (e) { + case SamplerType::FILTERING: return "sg.SamplerType.Filtering"; + case SamplerType::COMPARISON: return "sg.SamplerType.Comparison"; + case SamplerType::NONFILTERING: return "sg.SamplerType.Nonfiltering"; + default: return "INVALID"; + } +} + +std::string SokolDGenerator::backend(Slang::Enum e) { + switch (e) { + case Slang::GLSL410: + case Slang::GLSL430: + return "sg.Backend.Glcore"; + case Slang::GLSL300ES: + return "sg.Backend.Gles3"; + case Slang::HLSL4: + case Slang::HLSL5: + return "sg.Backend.D3d11"; + case Slang::METAL_MACOS: + return "sg.Backend.Metal_macos"; + case Slang::METAL_IOS: + return "sg.Backend.Metal_ios"; + case Slang::METAL_SIM: + return "sg.Backend.Metal_simulator"; + case Slang::WGSL: + return "sg.Backend.Wgpu"; + default: + return "INVALID"; + } +} + +std::string SokolDGenerator::struct_name(const std::string& name) { + return to_pascal_case(name); +} + +std::string SokolDGenerator::vertex_attr_name(const std::string& snippet_name, const StageAttr& attr) { + return pystring::upper(fmt::format("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 Image& img) { + return slot_name(img.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 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); +} + +static std::string const_def(const std::string& name, int slot) { + return fmt::format("enum {} = {};", name, slot); +} + +std::string SokolDGenerator::vertex_attr_definition(const std::string& snippet_name, const StageAttr& attr) { + return const_def(vertex_attr_name(snippet_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::sampler_bind_slot_definition(const Sampler& smp) { + return const_def(sampler_bind_slot_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::storage_buffer_bind_slot_definition(const StorageBuffer& sbuf) { + return const_def(storage_buffer_bind_slot_name(sbuf), sbuf.slot); +} + +} // namespace diff --git a/src/shdc/generators/sokold.h b/src/shdc/generators/sokold.h new file mode 100644 index 00000000..c9e02c6e --- /dev/null +++ b/src/shdc/generators/sokold.h @@ -0,0 +1,44 @@ +#pragma once +#include "generator.h" + +namespace shdc::gen { + +class SokolDGenerator : public Generator { +protected: + virtual void gen_prolog(const GenInput& gen); + virtual void gen_epilog(const GenInput& gen); + virtual void gen_prerequisites(const GenInput& gen); + virtual void gen_uniform_block_decl(const GenInput& gen, const refl::UniformBlock& ub); + virtual void gen_storage_buffer_decl(const GenInput& gen, const refl::StorageBuffer& sbuf); + virtual void gen_shader_array_start(const GenInput& gen, const std::string& array_name, size_t num_bytes, Slang::Enum slang); + virtual void gen_shader_array_end(const GenInput& gen); + virtual void gen_shader_desc_func(const GenInput& gen, const refl::ProgramReflection& prog); + virtual std::string lang_name(); + virtual std::string comment_block_start(); + virtual std::string comment_block_line_prefix(); + virtual std::string comment_block_end(); + 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 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); + 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& snippet_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 vertex_attr_definition(const std::string& snippet_name, 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); +private: + 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 diff --git a/src/shdc/types/format.h b/src/shdc/types/format.h index 7a45ae6d..63ce3f74 100644 --- a/src/shdc/types/format.h +++ b/src/shdc/types/format.h @@ -12,6 +12,7 @@ struct Format { SOKOL_NIM, SOKOL_ODIN, SOKOL_RUST, + SOKOL_D, BARE, BARE_YAML, NUM, @@ -30,6 +31,7 @@ inline const char* Format::to_str(Enum f) { case SOKOL_NIM: return "sokol_nim"; case SOKOL_ODIN: return "sokol_odin"; case SOKOL_RUST: return "sokol_rust"; + case SOKOL_D: return "sokol_d"; case BARE: return "bare"; case BARE_YAML: return "bare_yaml"; default: return ""; @@ -49,6 +51,8 @@ inline Format::Enum Format::from_str(const std::string& str) { return SOKOL_ODIN; } else if (str == "sokol_rust") { return SOKOL_RUST; + } else if (str == "sokol_d") { + return SOKOL_D; } else if (str == "bare") { return BARE; } else if (str == "bare_yaml") { From 29ec0baff0cc243f573fcbaf3ea9cc877ccc90f9 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 11 May 2024 15:07:00 +0200 Subject: [PATCH 2/8] add sokol_d related help texts --- src/shdc/args.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shdc/args.cc b/src/shdc/args.cc index db2de620..1a625fd2 100644 --- a/src/shdc/args.cc +++ b/src/shdc/args.cc @@ -39,7 +39,7 @@ static const getopt_option_t option_list[] = { { "module", 'm', GETOPT_OPTION_TYPE_REQUIRED, 0, OPTION_MODULE, "optional @module name override" }, { "reflection", 'r', GETOPT_OPTION_TYPE_NO_ARG, 0, OPTION_REFLECTION, "generate runtime reflection functions" }, { "bytecode", 'b', GETOPT_OPTION_TYPE_NO_ARG, 0, OPTION_BYTECODE, "output bytecode (HLSL and Metal)"}, - { "format", 'f', GETOPT_OPTION_TYPE_REQUIRED, 0, OPTION_FORMAT, "output format (default: sokol)", "[sokol|sokol_impl|sokol_zig|sokol_nim|sokol_odin|sokol_rust|bare|bare_yaml]" }, + { "format", 'f', GETOPT_OPTION_TYPE_REQUIRED, 0, OPTION_FORMAT, "output format (default: sokol)", "[sokol|sokol_impl|sokol_zig|sokol_nim|sokol_odin|sokol_rust|sokol_d|bare|bare_yaml]" }, { "errfmt", 'e', GETOPT_OPTION_TYPE_REQUIRED, 0, OPTION_ERRFMT, "error message format (default: gcc)", "[gcc|msvc]"}, { "dump", 'd', GETOPT_OPTION_TYPE_NO_ARG, 0, OPTION_DUMP, "dump debugging information to stderr"}, { "genver", 'g', GETOPT_OPTION_TYPE_REQUIRED, 0, OPTION_GENVER, "version-stamp for code-generation", "[int]"}, @@ -77,6 +77,7 @@ static void print_help_string(getopt_context_t& ctx) { " - sokol_nim Nim module file\n" " - sokol_odin Odin module file\n" " - sokol_rust Rust module file\n" + " - sokol_d D module file\n" " - bare raw output of SPIRV-Cross compiler, in text or binary format\n" " - bare_yaml like bare, but with reflection file in YAML format\n\n" "Options:\n\n"); From f763158db9c6889a5ef4f8146bcd22328e5e034a Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 11 May 2024 15:07:19 +0200 Subject: [PATCH 3/8] add missing header lines in sokol-d generator --- src/shdc/generators/sokold.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index 7ca2db33..1d182165 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -15,6 +15,9 @@ void SokolDGenerator::gen_prolog(const GenInput& gen) { pystring::os::path::splitext(root, ext, gen.args.input); l("module shaders.{};\n", pystring::os::path::basename(root)); l("import sg = sokol.gfx;\n"); + for (const auto& header: gen.inp.headers) { + l("{};\n", header); + } l("extern(C):\n\n"); } From 199dad3f3a860e9efaaa92187802d0eaf97142a8 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 11 May 2024 15:20:18 +0200 Subject: [PATCH 4/8] sokol-d generator: fix help text for shader desc call --- src/shdc/generators/sokold.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index 1d182165..37a7df16 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -340,7 +340,7 @@ std::string SokolDGenerator::shader_source_array_name(const std::string& snippet } std::string SokolDGenerator::get_shader_desc_help(const std::string& prog_name) { - return fmt::format("{}_shader_desc(sg.query_backend());\n", prog_name); + return fmt::format("{}_shader_desc(sg.queryBackend());\n", prog_name); } std::string SokolDGenerator::uniform_type(Type::Enum e) { From 128e742453bc6575e7902a414b646642a187f327 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 12 May 2024 13:47:03 +0200 Subject: [PATCH 5/8] dlang code generator: default-zero-initialize primitive-type struct members --- src/shdc/generators/sokold.cc | 144 +++++++++++++++++----------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index 37a7df16..c8d12de0 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -36,7 +36,7 @@ void SokolDGenerator::gen_uniform_block_decl(const GenInput& gen, const UniformB const int align = (cur_offset == 0) ? ub.struct_info.align : 1; int next_offset = uniform.offset; if (next_offset > cur_offset) { - l("align({}) ubyte[{}] _pad_{};\n", align, next_offset - cur_offset, cur_offset); + l("align({}) ubyte[{}] _pad_{} = 0;\n", align, next_offset - cur_offset, cur_offset); cur_offset = next_offset; } if (gen.inp.ctype_map.count(uniform.type_as_glsl()) > 0) { @@ -50,22 +50,22 @@ void SokolDGenerator::gen_uniform_block_decl(const GenInput& gen, const UniformB // default type names (float) if (uniform.array_count == 0) { switch (uniform.type) { - case Type::Float: l("align({}) float {};\n", align, uniform.name); break; - case Type::Float2: l("align({}) float[2] {};\n", align, uniform.name); break; - case Type::Float3: l("align({}) float[3] {};\n", align, uniform.name); break; - case Type::Float4: l("align({}) float[4] {};\n", align, uniform.name); break; - case Type::Int: l("align({}) int {};\n", align, uniform.name); break; - case Type::Int2: l("align({}) int[2] {};\n", align, uniform.name); break; - case Type::Int3: l("align({}) int[3] {};\n", align, uniform.name); break; - case Type::Int4: l("align({}) int[4] {};\n", align, uniform.name); break; - case Type::Mat4x4: l("align({}) float[16] {};\n", align, uniform.name); break; + case Type::Float: l("align({}) float {} = 0;\n", align, uniform.name); break; + case Type::Float2: l("align({}) float[2] {} = 0;\n", align, uniform.name); break; + case Type::Float3: l("align({}) float[3] {} = 0;\n", align, uniform.name); break; + case Type::Float4: l("align({}) float[4] {} = 0;\n", align, uniform.name); break; + case Type::Int: l("align({}) int {} = 0;\n", align, uniform.name); break; + case Type::Int2: l("align({}) int[2] {} = 0;\n", align, uniform.name); break; + case Type::Int3: l("align({}) int[3] {} = 0;\n", align, uniform.name); break; + case Type::Int4: l("align({}) int[4] {} = 0;\n", align, uniform.name); break; + case Type::Mat4x4: l("align({}) float[16] {} = 0;\n", align, uniform.name); break; default: l("INVALID_UNIFORM_TYPE;\n"); break; } } else { switch (uniform.type) { - case Type::Float4: l("align({}) float[4][{}] {};\n", align, uniform.array_count, uniform.name); break; - case Type::Int4: l("align({}) int[4][{}] {};\n", align, uniform.array_count, uniform.name); break; - case Type::Mat4x4: l("align({}) float[16][{}] {};\n", align, uniform.array_count, uniform.name); break; + case Type::Float4: l("align({}) float[4][{}] {} = 0;\n", align, uniform.array_count, uniform.name); break; + case Type::Int4: l("align({}) int[4][{}] {} = 0;\n", align, uniform.array_count, uniform.name); break; + case Type::Mat4x4: l("align({}) float[16][{}] {} = 0;\n", align, uniform.array_count, uniform.name); break; default: l("INVALID_UNIFORM_TYPE;\n"); break; } } @@ -75,7 +75,7 @@ void SokolDGenerator::gen_uniform_block_decl(const GenInput& gen, const UniformB // pad to multiple of 16-bytes struct size const int round16 = roundup(cur_offset, 16); if (cur_offset < round16) { - l("align(1) ubyte[{}] _pad_{};\n", round16 - cur_offset, cur_offset); + l("align(1) ubyte[{}] _pad_{} = 0;\n", round16 - cur_offset, cur_offset); } l_close("}}\n"); } @@ -90,7 +90,7 @@ void SokolDGenerator::gen_struct_interior_decl_std430(const GenInput& gen, const const int align = (cur_offset == 0) ? alignment : 1; int next_offset = item.offset; if (next_offset > cur_offset) { - l("align({}) ubyte[{}] _pad_{};\n", align, next_offset - cur_offset, cur_offset); + l("align({}) ubyte[{}] _pad_{} = 0;\n", align, next_offset - cur_offset, cur_offset); cur_offset = next_offset; } if (item.type == Type::Struct) { @@ -115,67 +115,67 @@ void SokolDGenerator::gen_struct_interior_decl_std430(const GenInput& gen, const if (item.array_count == 0) { switch (item.type) { // NOTE: bool => int is not a bug! - case Type::Bool: l("align({}) int {};\n", align, item.name); break; - case Type::Bool2: l("align({}) int[2] {};\n", align, item.name); break; - case Type::Bool3: l("align({}) int[3] {};\n", align, item.name); break; - case Type::Bool4: l("align({}) int[4] {};\n", align, item.name); break; - case Type::Int: l("align({}) int {};\n", align, item.name); break; - case Type::Int2: l("align({}) int[2] {};\n", align, item.name); break; - case Type::Int3: l("align({}) int[3] {};\n", align, item.name); break; - case Type::Int4: l("align({}) int[4] {};\n", align, item.name); break; - case Type::UInt: l("align({}) uint {};\n", align, item.name); break; - case Type::UInt2: l("align({}) uint[2] {};\n", align, item.name); break; - case Type::UInt3: l("align({}) uint[3] {};\n", align, item.name); break; - case Type::UInt4: l("align({}) uint[4] {};\n", align, item.name); break; - case Type::Float: l("align({}) float {};\n", align, item.name); break; - case Type::Float2: l("align({}) float[2] {};\n", align, item.name); break; - case Type::Float3: l("align({}) float[3] {};\n", align, item.name); break; - case Type::Float4: l("align({}) float[4] {};\n", align, item.name); break; - case Type::Mat2x1: l("align({}) float[2] {};\n", align, item.name); break; - case Type::Mat2x2: l("align({}) float[4] {};\n", align, item.name); break; - case Type::Mat2x3: l("align({}) float[6] {};\n", align, item.name); break; - case Type::Mat2x4: l("align({}) float[8] {};\n", align, item.name); break; - case Type::Mat3x1: l("align({}) float[3] {};\n", align, item.name); break; - case Type::Mat3x2: l("align({}) float[6] {};\n", align, item.name); break; - case Type::Mat3x3: l("align({}) float[9] {};\n", align, item.name); break; - case Type::Mat3x4: l("align({}) float[12] {};\n", align, item.name); break; - case Type::Mat4x1: l("align({}) float[4] {};\n", align, item.name); break; - case Type::Mat4x2: l("align({}) float[8] {};\n", align, item.name); break; - case Type::Mat4x3: l("align({}) float[12] {};\n", align, item.name); break; - case Type::Mat4x4: l("align({}) float[16] {};\n", align, item.name); break; + case Type::Bool: l("align({}) int {} = 0;\n", align, item.name); break; + case Type::Bool2: l("align({}) int[2] {} = 0;\n", align, item.name); break; + case Type::Bool3: l("align({}) int[3] {} = 0;\n", align, item.name); break; + case Type::Bool4: l("align({}) int[4] {} = 0;\n", align, item.name); break; + case Type::Int: l("align({}) int {} = 0;\n", align, item.name); break; + case Type::Int2: l("align({}) int[2] {} = 0;\n", align, item.name); break; + case Type::Int3: l("align({}) int[3] {} = 0;\n", align, item.name); break; + case Type::Int4: l("align({}) int[4] {} = 0;\n", align, item.name); break; + case Type::UInt: l("align({}) uint {} = 0;\n", align, item.name); break; + case Type::UInt2: l("align({}) uint[2] {} = 0;\n", align, item.name); break; + case Type::UInt3: l("align({}) uint[3] {} = 0;\n", align, item.name); break; + case Type::UInt4: l("align({}) uint[4] {} = 0;\n", align, item.name); break; + case Type::Float: l("align({}) float {} = 0;\n", align, item.name); break; + case Type::Float2: l("align({}) float[2] {} = 0;\n", align, item.name); break; + case Type::Float3: l("align({}) float[3] {} = 0;\n", align, item.name); break; + case Type::Float4: l("align({}) float[4] {} = 0;\n", align, item.name); break; + case Type::Mat2x1: l("align({}) float[2] {} = 0;\n", align, item.name); break; + case Type::Mat2x2: l("align({}) float[4] {} = 0;\n", align, item.name); break; + case Type::Mat2x3: l("align({}) float[6] {} = 0;\n", align, item.name); break; + case Type::Mat2x4: l("align({}) float[8] {} = 0;\n", align, item.name); break; + case Type::Mat3x1: l("align({}) float[3] {} = 0;\n", align, item.name); break; + case Type::Mat3x2: l("align({}) float[6] {} = 0;\n", align, item.name); break; + case Type::Mat3x3: l("align({}) float[9] {} = 0;\n", align, item.name); break; + case Type::Mat3x4: l("align({}) float[12] {} = 0;\n", align, item.name); break; + case Type::Mat4x1: l("align({}) float[4] {} = 0;\n", align, item.name); break; + case Type::Mat4x2: l("align({}) float[8] {} = 0;\n", align, item.name); break; + case Type::Mat4x3: l("align({}) float[12] {} = 0;\n", align, item.name); break; + case Type::Mat4x4: l("align({}) float[16] {} = 0;\n", align, item.name); break; default: l("INVALID_TYPE\n"); break; } } else { switch (item.type) { // NOTE: bool => int is not a bug! - case Type::Bool: l("align({}) int[{}] {};\n", align, item.array_count, item.name); break; - case Type::Bool2: l("align({}) int[2][{}] {};\n", align, item.array_count, item.name); break; - case Type::Bool3: l("align({}) int[3][{}] {};\n", align, item.array_count, item.name); break; - case Type::Bool4: l("align({}) int[4][{}] {};\n", align, item.array_count, item.name); break; - case Type::Int: l("align({}) int[{}] {};", align, item.array_count, item.name); break; - case Type::Int2: l("align({}) int[2] {};\n", align, item.array_count, item.name); break; - case Type::Int3: l("align({}) int[3] {};\n", align, item.array_count, item.name); break; - case Type::Int4: l("align({}) int[4] {};\n", align, item.array_count, item.name); break; - case Type::UInt: l("align({}) uint[{}] {};\n", align, item.array_count, item.name); break; - case Type::UInt2: l("align({}) uint[2][{}] {};\n", align, item.array_count, item.name); break; - case Type::UInt3: l("align({}) uint[3][{}] {};\n", align, item.array_count, item.name); break; - case Type::UInt4: l("align({}) uint[4][{}] {};\n", align, item.array_count, item.name); break; - case Type::Float: l("align({}) float[{}] {};\n", align, item.array_count, item.name); break; - case Type::Float2: l("align({}) float[2][{}] {};\n", align, item.array_count, item.name); break; - case Type::Float3: l("align({}) float[3][{}] {};\n", align, item.array_count, item.name); break; - case Type::Float4: l("align({}) float[4][{}] {};\n", align, item.array_count, item.name); break; - case Type::Mat2x1: l("align({}) float[2][{}] {};\n", align, item.array_count, item.name); break; - case Type::Mat2x2: l("align({}) float[4][{}] {};\n", align, item.array_count, item.name); break; - case Type::Mat2x3: l("align({}) float[6][{}] {};\n", align, item.array_count, item.name); break; - case Type::Mat2x4: l("align({}) float[8][{}] {};\n", align, item.array_count, item.name); break; - case Type::Mat3x1: l("align({}) float[3][{}] {};\n", align, item.array_count, item.name); break; - case Type::Mat3x2: l("align({}) float[6][{}] {};\n", align, item.array_count, item.name); break; - case Type::Mat3x3: l("align({}) float[9][{}] {};\n", align, item.array_count, item.name); break; - case Type::Mat3x4: l("align({}) float[12][{}] {};\n", align, item.array_count, item.name); break; - case Type::Mat4x1: l("align({}) float[4][{}] {};\n", align, item.array_count, item.name); break; - case Type::Mat4x2: l("align({}) float[8][{}] {};\n", align, item.array_count, item.name); break; - case Type::Mat4x3: l("align({}) float[12][{}] {};\n", align, item.array_count, item.name); break; - case Type::Mat4x4: l("align({}) float[16][{}] {};\n", align, item.array_count, item.name); break; + case Type::Bool: l("align({}) int[{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Bool2: l("align({}) int[2][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Bool3: l("align({}) int[3][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Bool4: l("align({}) int[4][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Int: l("align({}) int[{}] {} = 0;", align, item.array_count, item.name); break; + case Type::Int2: l("align({}) int[2] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Int3: l("align({}) int[3] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Int4: l("align({}) int[4] {} = 0;\n", align, item.array_count, item.name); break; + case Type::UInt: l("align({}) uint[{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::UInt2: l("align({}) uint[2][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::UInt3: l("align({}) uint[3][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::UInt4: l("align({}) uint[4][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Float: l("align({}) float[{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Float2: l("align({}) float[2][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Float3: l("align({}) float[3][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Float4: l("align({}) float[4][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Mat2x1: l("align({}) float[2][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Mat2x2: l("align({}) float[4][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Mat2x3: l("align({}) float[6][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Mat2x4: l("align({}) float[8][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Mat3x1: l("align({}) float[3][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Mat3x2: l("align({}) float[6][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Mat3x3: l("align({}) float[9][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Mat3x4: l("align({}) float[12][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Mat4x1: l("align({}) float[4][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Mat4x2: l("align({}) float[8][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Mat4x3: l("align({}) float[12][{}] {} = 0;\n", align, item.array_count, item.name); break; + case Type::Mat4x4: l("align({}) float[16][{}] {} = 0;\n", align, item.array_count, item.name); break; default: l("INVALID_TYPE\n"); break; } } @@ -183,7 +183,7 @@ void SokolDGenerator::gen_struct_interior_decl_std430(const GenInput& gen, const cur_offset += item.size; } if (cur_offset < pad_to_size) { - l("align(1) ubyte[{}] _pad_{};\n", pad_to_size - cur_offset, cur_offset); + l("align(1) ubyte[{}] _pad_{} = 0;\n", pad_to_size - cur_offset, cur_offset); } } From a15600141c63f47253caeb0a0bab1d71bf535c3b Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 12 May 2024 19:17:27 +0200 Subject: [PATCH 6/8] mention the dlang generator in the docs --- docs/sokol-shdc.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/sokol-shdc.md b/docs/sokol-shdc.md index 5322eaf8..385584a3 100644 --- a/docs/sokol-shdc.md +++ b/docs/sokol-shdc.md @@ -43,6 +43,7 @@ sokol-shdc supports the following output formats: - Rust for integration with [sokol-rust](https://github.com/floooh/sokol-rust) - 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/floooh/sokol-d) - '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 From bb18e302a8894e094ae9fcf31646997129b0c846 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 12 May 2024 19:19:58 +0200 Subject: [PATCH 7/8] update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 126c8c00..5a2e1b61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +#### **12-May-2024** + +A new code generator for the D language bindings via `-f sokol_d`. Note that the actual D bindings are +still WIP and haven't been released yet. Many thanks to @kassane for the initial D code generator! + #### **10-May-2024** A minor regression in the YAML output has been fixed (wrong indentation after storage blocks), see From 6a980d7c6d9201ecd92a4859c8b98a25e4974b2e Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 12 May 2024 20:06:55 +0200 Subject: [PATCH 8/8] dlang: fix shaderDescFunc naming convention --- src/shdc/generators/sokold.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shdc/generators/sokold.cc b/src/shdc/generators/sokold.cc index c8d12de0..264d541c 100644 --- a/src/shdc/generators/sokold.cc +++ b/src/shdc/generators/sokold.cc @@ -203,7 +203,7 @@ void SokolDGenerator::gen_shader_array_end(const GenInput& gen) { } void SokolDGenerator::gen_shader_desc_func(const GenInput& gen, const ProgramReflection& prog) { - l_open("sg.ShaderDesc {}_shader_desc(sg.Backend backend) @trusted @nogc nothrow {{\n", prog.name); + l_open("sg.ShaderDesc {}ShaderDesc(sg.Backend backend) @trusted @nogc nothrow {{\n", prog.name); l("sg.ShaderDesc desc;\n"); l("desc.label = \"{}_shader\";\n", prog.name); l_open("switch (backend) {{\n"); @@ -340,7 +340,7 @@ std::string SokolDGenerator::shader_source_array_name(const std::string& snippet } std::string SokolDGenerator::get_shader_desc_help(const std::string& prog_name) { - return fmt::format("{}_shader_desc(sg.queryBackend());\n", prog_name); + return fmt::format("{}ShaderDesc(sg.queryBackend());\n", prog_name); } std::string SokolDGenerator::uniform_type(Type::Enum e) {