From 490795207786028c13d654e263c1828474ad7771 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sat, 4 Nov 2023 13:59:02 +0100 Subject: [PATCH 1/8] Add support for registering precompiled shader variants. Will be handy when we add support for slangmosh auto-priming the manager. --- vulkan/managers/shader_manager.cpp | 87 ++++++++++++++++++++++++------ vulkan/managers/shader_manager.hpp | 23 +++++++- 2 files changed, 92 insertions(+), 18 deletions(-) diff --git a/vulkan/managers/shader_manager.cpp b/vulkan/managers/shader_manager.cpp index fa66c077..e9b6b7bd 100644 --- a/vulkan/managers/shader_manager.cpp +++ b/vulkan/managers/shader_manager.cpp @@ -63,7 +63,7 @@ bool ShaderTemplate::init() return false; auto precompiled_file = device->get_system_handles().filesystem->open_readonly_mapping(path); - const uint32_t *ptr = nullptr; + const uint32_t *ptr; if (!precompiled_file || !(ptr = precompiled_file->data())) { @@ -100,7 +100,8 @@ bool ShaderTemplate::init() return true; } -const ShaderTemplateVariant *ShaderTemplate::register_variant(const std::vector> *defines) +const ShaderTemplateVariant *ShaderTemplate::register_variant( + const std::vector> *defines, Shader *precompiled_shader) { Hasher h; if (defines) @@ -125,23 +126,31 @@ const ShaderTemplateVariant *ShaderTemplate::register_variant(const std::vector< auto *variant = variants.allocate(); variant->hash = complete_hash; - auto *precompiled_spirv = cache.variant_to_shader.find(complete_hash); - - if (precompiled_spirv) + PrecomputedMeta *precompiled_spirv = nullptr; + if (!precompiled_shader) { - if (!device->request_shader_by_hash(precompiled_spirv->shader_hash)) - { - LOGW("Got precompiled SPIR-V hash for variant, but it does not exist, is Fossilize archive incomplete?\n"); - precompiled_spirv = nullptr; - } - else if (source_hash != precompiled_spirv->source_hash) + precompiled_spirv = cache.variant_to_shader.find(complete_hash); + + if (precompiled_spirv) { - LOGW("Source hash is invalidated for %s, recompiling.\n", path.c_str()); - precompiled_spirv = nullptr; + if (!device->request_shader_by_hash(precompiled_spirv->shader_hash)) + { + LOGW("Got precompiled SPIR-V hash for variant, but it does not exist, is Fossilize archive incomplete?\n"); + precompiled_spirv = nullptr; + } + else if (source_hash != precompiled_spirv->source_hash) + { + LOGW("Source hash is invalidated for %s, recompiling.\n", path.c_str()); + precompiled_spirv = nullptr; + } } } - if (!precompiled_spirv) + if (precompiled_shader) + { + variant->precompiled_shader = precompiled_shader; + } + else if (!precompiled_spirv) { if (!static_shader.empty()) { @@ -305,7 +314,9 @@ ShaderProgramVariant::ShaderProgramVariant(Device *device_) Vulkan::Shader *ShaderTemplateVariant::resolve(Vulkan::Device &device) const { - if (spirv.empty()) + if (precompiled_shader) + return precompiled_shader; + else if (spirv.empty()) return device.request_shader_by_hash(spirv_hash); else return device.request_shader(spirv.data(), spirv.size() * sizeof(uint32_t)); @@ -460,6 +471,43 @@ Vulkan::Program *ShaderProgramVariant::get_program() ShaderProgramVariant *ShaderProgram::register_variant(const std::vector> &defines, const ImmutableSamplerBank *sampler_bank) +{ + return register_variant(nullptr, defines, sampler_bank); +} + +ShaderProgramVariant *ShaderProgram::register_precompiled_variant(Shader *comp, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank) +{ + Shader *shaders[int(ShaderStage::Count)] = {}; + shaders[int(ShaderStage::Compute)] = comp; + return register_variant(shaders, defines, sampler_bank); +} + +ShaderProgramVariant *ShaderProgram::register_precompiled_variant(Shader *task, Shader *mesh, Shader *frag, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank) +{ + Shader *shaders[int(ShaderStage::Count)] = {}; + shaders[int(ShaderStage::Task)] = task; + shaders[int(ShaderStage::Mesh)] = mesh; + shaders[int(ShaderStage::Fragment)] = frag; + return register_variant(shaders, defines, sampler_bank); +} + +ShaderProgramVariant *ShaderProgram::register_precompiled_variant(Vulkan::Shader *vert, Vulkan::Shader *frag, + const std::vector> &defines, + const Vulkan::ImmutableSamplerBank *sampler_bank) +{ + Shader *shaders[int(ShaderStage::Count)] = {}; + shaders[int(ShaderStage::Vertex)] = vert; + shaders[int(ShaderStage::Fragment)] = frag; + return register_variant(shaders, defines, sampler_bank); +} + +ShaderProgramVariant *ShaderProgram::register_variant(Shader * const *precompiled_shaders, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank) { Hasher h; for (auto &define : defines) @@ -479,9 +527,14 @@ ShaderProgramVariant *ShaderProgram::register_variant(const std::vectorsampler_bank.reset(new ImmutableSamplerBank(*sampler_bank)); - for (unsigned i = 0; i < static_cast(Vulkan::ShaderStage::Count); i++) + for (int i = 0; i < int(Vulkan::ShaderStage::Count); i++) + { if (stages[i]) - new_variant->stages[i] = stages[i]->register_variant(&defines); + { + new_variant->stages[i] = stages[i]->register_variant( + &defines, precompiled_shaders ? precompiled_shaders[i] : nullptr); + } + } // Make sure it's compiled correctly. new_variant->get_program(); diff --git a/vulkan/managers/shader_manager.hpp b/vulkan/managers/shader_manager.hpp index 0480fff0..d7eb3c87 100644 --- a/vulkan/managers/shader_manager.hpp +++ b/vulkan/managers/shader_manager.hpp @@ -69,6 +69,7 @@ struct ShaderTemplateVariant : public Util::IntrusiveHashMapEnabled spirv; std::vector> defines; + Shader *precompiled_shader = nullptr; unsigned instance = 0; Vulkan::Shader *resolve(Vulkan::Device &device) const; @@ -84,7 +85,8 @@ class ShaderTemplate : public Util::IntrusiveHashMapEnabled bool init(); - const ShaderTemplateVariant *register_variant(const std::vector> *defines = nullptr); + const ShaderTemplateVariant *register_variant(const std::vector> *defines, + Shader *precompiled_shader); void register_dependencies(ShaderManager &manager); Util::Hash get_path_hash() const @@ -169,10 +171,29 @@ class ShaderProgram : public Util::IntrusiveHashMapEnabled ShaderProgramVariant *register_variant(const std::vector> &defines, const ImmutableSamplerBank *sampler_bank = nullptr); + ShaderProgramVariant *register_precompiled_variant( + Shader *vert, Shader *frag, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank = nullptr); + + ShaderProgramVariant *register_precompiled_variant( + Shader *comp, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank = nullptr); + + ShaderProgramVariant *register_precompiled_variant( + Shader *task, Shader *mesh, Shader *frag, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank = nullptr); + private: Device *device; ShaderTemplate *stages[static_cast(Vulkan::ShaderStage::Count)] = {}; VulkanCacheReadWrite variant_cache; + + ShaderProgramVariant *register_variant(Shader * const *precompiled_shaders, + const std::vector> &defines, + const ImmutableSamplerBank *sampler_bank); }; class ShaderManager From 4040ddfdb859897d5d3a7d291ddf226e823b79c7 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sat, 4 Nov 2023 14:03:35 +0100 Subject: [PATCH 2/8] Resolver may be unused in slangmosh generated code. Avoids warning spam. --- slangmosh/slangmosh.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/slangmosh/slangmosh.cpp b/slangmosh/slangmosh.cpp index 007ea627..71031dce 100644 --- a/slangmosh/slangmosh.cpp +++ b/slangmosh/slangmosh.cpp @@ -375,6 +375,7 @@ static std::string generate_header(const std::vector &shaders, str << "template \n"; str << "template \n"; str << "Shaders::Shaders(Device &device, Layout &layout, const Resolver &resolver)\n{\n"; + str << "\t(void)resolver;\n"; for (size_t i = 0; i < shaders.size(); i++) { From d257da710b58b46f93bf6633968e67e756fb8126 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sat, 4 Nov 2023 14:04:01 +0100 Subject: [PATCH 3/8] Add --spv14 option. --- slangmosh/slangmosh.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/slangmosh/slangmosh.cpp b/slangmosh/slangmosh.cpp index 71031dce..eb125ea0 100644 --- a/slangmosh/slangmosh.cpp +++ b/slangmosh/slangmosh.cpp @@ -44,7 +44,7 @@ using namespace Granite; static void print_help() { - LOGE("slangmosh [-O] [--strip] [--output header.hpp] [--help] [--output-interface interface.hpp]\n"); + LOGE("slangmosh [-O] [--strip] [--spv14] [--output header.hpp] [--help] [--output-interface interface.hpp]\n"); } struct ShaderVariant @@ -460,12 +460,14 @@ static int main_inner(int argc, char **argv) std::string output_interface_path; bool strip = false; bool opt = false; + Target target = Target::Vulkan11; CLICallbacks cbs; cbs.add("--help", [](CLIParser &parser) { parser.end(); }); cbs.add("--output", [&](CLIParser &parser) { output_path = parser.next_string(); }); cbs.add("-O", [&](CLIParser &) { opt = true; }); cbs.add("--strip", [&](CLIParser &) { strip = true; }); + cbs.add("--spv14", [&](CLIParser &) { target = Target::Vulkan11_Spirv14; }); cbs.add("--namespace", [&](CLIParser &parser) { generated_namespace = parser.next_string(); }); cbs.add("--output-interface", [&](CLIParser &parser) { output_interface_path = parser.next_string(); }); cbs.default_handler = [&](const char *str) { input_path = str; }; @@ -501,7 +503,7 @@ static int main_inner(int argc, char **argv) auto &shader_variants = spirv_for_shaders_and_variants[shader_index]; auto &parsed_shader = parsed_shaders[shader_index]; shader_variants.resize(parsed_shader.total_permutations()); - parsed_shader.dispatch_variants(shader_variants.data(), Target::Vulkan11, opt, strip); + parsed_shader.dispatch_variants(shader_variants.data(), target, opt, strip); } GRANITE_THREAD_GROUP()->wait_idle(); From 1459d7b00ed98db82c24da9f828493e23ced8f69 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sat, 4 Nov 2023 15:43:19 +0100 Subject: [PATCH 4/8] Add program resolve auto generation support. --- CMakeLists.txt | 2 +- slangmosh/slangmosh.cpp | 242 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 226 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d493bb1..0343f39e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -377,7 +377,7 @@ if (TARGET granite-renderer) endif() endif() -if (GRANITE_TOOLS) +if (GRANITE_TOOLS AND GRANITE_VULKAN_SPIRV_CROSS AND GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER) add_subdirectory(slangmosh) endif() diff --git a/slangmosh/slangmosh.cpp b/slangmosh/slangmosh.cpp index eb125ea0..94f3b803 100644 --- a/slangmosh/slangmosh.cpp +++ b/slangmosh/slangmosh.cpp @@ -162,15 +162,38 @@ size_t Shader::total_permutations() const return perm; } -static std::vector parse_shaders(const std::string &path) +struct ShaderReference { - std::vector parsed_shaders; + std::string name; + std::string manager_path; +}; + +struct ProgramVariant +{ + std::vector> defines; +}; + +struct Program +{ + ShaderReference vert, mesh, task, frag, comp; + std::vector variants; +}; + +struct ParseResult +{ + std::vector shaders; + std::vector programs; +}; + +static ParseResult parse_shaders(const std::string &path) +{ + ParseResult parsed; std::string input_json; if (!GRANITE_FILESYSTEM()->read_file_to_string(path, input_json)) { LOGE("Failed to read file: %s.\n", path.c_str()); - return parsed_shaders; + return parsed; } rapidjson::Document doc; @@ -179,7 +202,7 @@ static std::vector parse_shaders(const std::string &path) if (doc.HasParseError()) { LOGE("Failed to parse JSON.\n"); - return parsed_shaders; + return parsed; } std::vector base_include; @@ -224,13 +247,108 @@ static std::vector parse_shaders(const std::string &path) parsed_shader.include.emplace_back(Path::relpath(path, include_itr->GetString())); } - parsed_shaders.push_back(std::move(parsed_shader)); + parsed.shaders.push_back(std::move(parsed_shader)); + } + + if (doc.HasMember("programs")) + { + auto &programs = doc["programs"]; + + const auto parse_reference = [](const rapidjson::Value &v) { + ShaderReference ref; + ref.name = v["name"].GetString(); + ref.manager_path = v["manager_path"].GetString(); + return ref; + }; + + for (auto itr = programs.Begin(); itr != programs.End(); ++itr) + { + Program prog; + if (itr->HasMember("vert")) + prog.vert = parse_reference((*itr)["vert"]); + if (itr->HasMember("task")) + prog.task = parse_reference((*itr)["task"]); + if (itr->HasMember("mesh")) + prog.mesh = parse_reference((*itr)["mesh"]); + if (itr->HasMember("frag")) + prog.frag = parse_reference((*itr)["frag"]); + if (itr->HasMember("comp")) + prog.comp = parse_reference((*itr)["comp"]); + + if (itr->HasMember("variants")) + { + auto &v = (*itr)["variants"]; + for (auto variant_itr = v.Begin(); variant_itr != v.End(); ++variant_itr) + { + ProgramVariant program_variant; + for (auto define_itr = variant_itr->Begin(); define_itr != variant_itr->End(); ++define_itr) + { + program_variant.defines.emplace_back((*define_itr)["define"].GetString(), + (*define_itr)["value"].GetInt()); + } + prog.variants.push_back(std::move(program_variant)); + } + } + parsed.programs.push_back(std::move(prog)); + } + } + + return parsed; +} + +static const Shader *find_shader(const ParseResult &parsed, const std::string &name) +{ + auto itr = std::find_if(parsed.shaders.begin(), parsed.shaders.end(), [&name](const Shader &s) { + return s.name == name; + }); + + if (itr == parsed.shaders.end()) + { + LOGE("Shader \"%s\" does not exist.\n", name.c_str()); + return nullptr; + } + + return &*itr; +} + +static std::string resolve_shader(const ProgramVariant &variant, const Shader *shader) +{ + if (!shader) + return "{}"; + + std::string str = "this->" + shader->name; + for (auto &shader_variant : shader->variants) + { + // This define is already collapsed, so ignore it. + if (shader_variant.resolve) + continue; + + auto itr = std::find_if(variant.defines.begin(), variant.defines.end(), + [&shader_variant](const std::pair &define) { + return define.first == shader_variant.define; + }); + + if (itr == variant.defines.end()) + { + LOGE("Shader \"%s\" requires define \"%s\", but program variant does not define it.\n", + shader->name.c_str(), shader_variant.define.c_str()); + return {}; + } + else if (itr->second >= int(shader_variant.count) || itr->second < 0) + { + LOGE("Shader \"%s\" requires define \"%s\" in range [0, %u), but program variant requires value = %d.\n", + shader->name.c_str(), shader_variant.define.c_str(), + shader_variant.count, itr->second); + return {}; + } + + str + "[" + std::to_string(itr->second) + "]"; } - return parsed_shaders; + return str; } -static std::string generate_header(const std::vector &shaders, +static std::string generate_header(const ParseResult &parsed, const std::vector>> &spirv_for_shaders_and_variants, const std::string &generated_namespace, bool interface_header) { @@ -350,7 +468,7 @@ static std::string generate_header(const std::vector &shaders, str << "template \n"; str << "struct Shaders\n{\n"; - for (auto &shader: shaders) + for (auto &shader : parsed.shaders) { str << "\t"; if (shader.compute) @@ -377,9 +495,9 @@ static std::string generate_header(const std::vector &shaders, str << "Shaders::Shaders(Device &device, Layout &layout, const Resolver &resolver)\n{\n"; str << "\t(void)resolver;\n"; - for (size_t i = 0; i < shaders.size(); i++) + for (size_t i = 0; i < parsed.shaders.size(); i++) { - auto &shader = shaders[i]; + auto &shader = parsed.shaders[i]; if (!shader.variants.empty()) { @@ -444,6 +562,96 @@ static std::string generate_header(const std::vector &shaders, variant_to_output[i][0].shader_size * sizeof(uint32_t) << ", &layout);\n"; } } + + for (auto &program : parsed.programs) + { + str << "\t{\n"; + const char *kind = program.comp.name.empty() ? "graphics" : "compute"; + str << "\t\tauto *program = device.get_shader_manager().register_" << kind << "("; + + const Shader *shaders[3] = {}; + unsigned shader_count = 0; + unsigned start_verify_index = 0; + + if (!program.comp.name.empty()) + { + str << '\"' << program.comp.manager_path << "\");\n"; + shaders[shader_count] = find_shader(parsed, program.comp.name); + if (!shaders[shader_count]) + return {}; + shader_count++; + } + else if (!program.mesh.name.empty()) + { + str << '\"' << program.task.manager_path << "\", "; + str << '\"' << program.mesh.manager_path << "\", "; + str << '\"' << program.frag.manager_path << "\");\n"; + + if (!program.task.name.empty()) + { + shaders[shader_count++] = find_shader(parsed, program.task.name); + } + else + { + shader_count++; + start_verify_index = shader_count; + } + + shaders[shader_count++] = find_shader(parsed, program.mesh.name); + shaders[shader_count++] = find_shader(parsed, program.frag.name); + } + else + { + str << '\"' << program.vert.manager_path << "\", "; + str << '\"' << program.frag.manager_path << "\");\n"; + shaders[shader_count++] = find_shader(parsed, program.vert.name); + shaders[shader_count++] = find_shader(parsed, program.frag.name); + } + + for (unsigned i = start_verify_index; i < shader_count; i++) + if (!shaders[i]) + return {}; + + if (!program.variants.empty()) + { + for (auto &variant : program.variants) + { + str << "\t\tprogram->register_precompiled_variant("; + + for (unsigned i = 0; i < shader_count; i++) + { + auto resolved = resolve_shader(variant, shaders[i]); + if (shaders[i] && resolved.empty()) + return {}; + str << resolved << ", "; + } + str << "{"; + for (auto &define : variant.defines) + { + str << "{\"" << define.first << "\", " << define.second << "}"; + if (&define != &variant.defines.back()) + str << ", "; + } + str << "}"; + str << ");\n"; + } + } + else + { + str << "\t\tprogram->register_precompiled_variant("; + for (unsigned i = 0; i < shader_count; i++) + { + auto resolved = resolve_shader({}, shaders[i]); + if (shaders[i] && resolved.empty()) + return {}; + str << resolved << ", "; + } + str << "{});\n"; + } + + str << "\t}\n"; + } + str << "}\n"; str << "}\n"; } @@ -488,20 +696,20 @@ static int main_inner(int argc, char **argv) return EXIT_FAILURE; } - auto parsed_shaders = parse_shaders(input_path); - if (parsed_shaders.empty()) + auto parsed = parse_shaders(input_path); + if (parsed.shaders.empty()) { LOGE("Failed to parse shaders.\n"); return EXIT_FAILURE; } std::vector>> spirv_for_shaders_and_variants; - spirv_for_shaders_and_variants.resize(parsed_shaders.size()); + spirv_for_shaders_and_variants.resize(parsed.shaders.size()); - for (size_t shader_index = 0; shader_index < parsed_shaders.size(); shader_index++) + for (size_t shader_index = 0; shader_index < parsed.shaders.size(); shader_index++) { auto &shader_variants = spirv_for_shaders_and_variants[shader_index]; - auto &parsed_shader = parsed_shaders[shader_index]; + auto &parsed_shader = parsed.shaders[shader_index]; shader_variants.resize(parsed_shader.total_permutations()); parsed_shader.dispatch_variants(shader_variants.data(), target, opt, strip); } @@ -513,8 +721,8 @@ static int main_inner(int argc, char **argv) if (perm.empty()) return EXIT_FAILURE; - auto interface_code = generate_header(parsed_shaders, spirv_for_shaders_and_variants, generated_namespace, true); - auto generated_code = generate_header(parsed_shaders, spirv_for_shaders_and_variants, generated_namespace, false); + auto interface_code = generate_header(parsed, spirv_for_shaders_and_variants, generated_namespace, true); + auto generated_code = generate_header(parsed, spirv_for_shaders_and_variants, generated_namespace, false); if (output_interface_path.empty()) { From f4a4e475591f86f2277c8fc71bd5f0f864e25ae3 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sat, 4 Nov 2023 16:03:13 +0100 Subject: [PATCH 5/8] Fix GRANITE_SHIPPING build. --- vulkan/managers/shader_manager.cpp | 27 +++++++++++++++++---------- vulkan/managers/shader_manager.hpp | 6 +++--- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/vulkan/managers/shader_manager.cpp b/vulkan/managers/shader_manager.cpp index e9b6b7bd..18918a5c 100644 --- a/vulkan/managers/shader_manager.cpp +++ b/vulkan/managers/shader_manager.cpp @@ -40,7 +40,7 @@ namespace Vulkan { ShaderTemplate::ShaderTemplate(Device *device_, const std::string &shader_path, - Granite::Stage force_stage_, + ShaderStage force_stage_, MetaCache &cache_, Util::Hash path_hash_, const std::vector &include_directories_) @@ -49,6 +49,7 @@ ShaderTemplate::ShaderTemplate(Device *device_, , include_directories(include_directories_) #endif { + (void)include_directories_; } ShaderTemplate::~ShaderTemplate() @@ -72,7 +73,9 @@ bool ShaderTemplate::init() } static_shader = { ptr, ptr + precompiled_file->get_size() / sizeof(uint32_t) }; +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER source_hash = 0; +#endif return true; } @@ -85,7 +88,7 @@ bool ShaderTemplate::init() compiler = std::make_unique(*device->get_system_handles().filesystem); compiler->set_target(device->get_device_features().supports_spirv_1_4 ? Granite::Target::Vulkan11_Spirv14 : Granite::Target::Vulkan11); - if (!compiler->set_source_from_file(path, force_stage)) + if (!compiler->set_source_from_file(path, Granite::Stage(force_stage))) return false; compiler->set_include_directories(&include_directories); if (!compiler->preprocess()) @@ -138,11 +141,13 @@ const ShaderTemplateVariant *ShaderTemplate::register_variant( LOGW("Got precompiled SPIR-V hash for variant, but it does not exist, is Fossilize archive incomplete?\n"); precompiled_spirv = nullptr; } +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER else if (source_hash != precompiled_spirv->source_hash) { LOGW("Source hash is invalidated for %s, recompiling.\n", path.c_str()); precompiled_spirv = nullptr; } +#endif } } @@ -155,7 +160,9 @@ const ShaderTemplateVariant *ShaderTemplate::register_variant( if (!static_shader.empty()) { variant->spirv = static_shader; +#ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER update_variant_cache(*variant); +#endif } #ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER else if (compiler) @@ -270,7 +277,7 @@ void ShaderTemplate::recompile() auto newcompiler = std::make_unique(*device->get_system_handles().filesystem); newcompiler->set_target(device->get_device_features().supports_spirv_1_4 ? Granite::Target::Vulkan11_Spirv14 : Granite::Target::Vulkan11); - if (!newcompiler->set_source_from_file(path, force_stage)) + if (!newcompiler->set_source_from_file(path, Granite::Stage(force_stage))) return; newcompiler->set_include_directories(&include_directories); if (!newcompiler->preprocess()) @@ -545,7 +552,7 @@ ShaderProgramVariant *ShaderProgram::register_variant(Shader * const *precompile ShaderProgram *ShaderManager::register_compute(const std::string &compute) { - auto *tmpl = get_template(compute, Granite::Stage::Compute); + auto *tmpl = get_template(compute, ShaderStage::Compute); if (!tmpl) return nullptr; @@ -559,7 +566,7 @@ ShaderProgram *ShaderManager::register_compute(const std::string &compute) return ret; } -ShaderTemplate *ShaderManager::get_template(const std::string &path, Granite::Stage force_stage) +ShaderTemplate *ShaderManager::get_template(const std::string &path, ShaderStage force_stage) { Hasher hasher; hasher.string(path); @@ -590,8 +597,8 @@ ShaderTemplate *ShaderManager::get_template(const std::string &path, Granite::St ShaderProgram *ShaderManager::register_graphics(const std::string &vertex, const std::string &fragment) { - auto *vert_tmpl = get_template(vertex, Granite::Stage::Vertex); - auto *frag_tmpl = get_template(fragment, Granite::Stage::Fragment); + auto *vert_tmpl = get_template(vertex, ShaderStage::Vertex); + auto *frag_tmpl = get_template(fragment, ShaderStage::Fragment); if (!vert_tmpl || !frag_tmpl) return nullptr; @@ -610,9 +617,9 @@ ShaderProgram *ShaderManager::register_graphics(const std::string &task, const s { ShaderTemplate *task_tmpl = nullptr; if (!task.empty()) - task_tmpl = get_template(task, Granite::Stage::Task); - auto *mesh_tmpl = get_template(mesh, Granite::Stage::Mesh); - auto *frag_tmpl = get_template(fragment, Granite::Stage::Fragment); + task_tmpl = get_template(task, ShaderStage::Task); + auto *mesh_tmpl = get_template(mesh, ShaderStage::Mesh); + auto *frag_tmpl = get_template(fragment, ShaderStage::Fragment); if (!mesh_tmpl || !frag_tmpl) return nullptr; diff --git a/vulkan/managers/shader_manager.hpp b/vulkan/managers/shader_manager.hpp index d7eb3c87..d593d3f7 100644 --- a/vulkan/managers/shader_manager.hpp +++ b/vulkan/managers/shader_manager.hpp @@ -79,7 +79,7 @@ class ShaderTemplate : public Util::IntrusiveHashMapEnabled { public: ShaderTemplate(Device *device, const std::string &shader_path, - Granite::Stage force_stage, MetaCache &cache, + ShaderStage force_stage, MetaCache &cache, Util::Hash path_hash, const std::vector &include_directories); ~ShaderTemplate(); @@ -102,7 +102,7 @@ class ShaderTemplate : public Util::IntrusiveHashMapEnabled private: Device *device; std::string path; - Granite::Stage force_stage; + ShaderStage force_stage; MetaCache &cache; Util::Hash path_hash = 0; std::vector static_shader; @@ -239,7 +239,7 @@ class ShaderManager VulkanCache programs; std::vector include_directories; - ShaderTemplate *get_template(const std::string &source, Granite::Stage force_stage); + ShaderTemplate *get_template(const std::string &source, ShaderStage force_stage); #ifdef GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER std::unordered_map> dependees; From be1321df0bd765061ca5b33be4cfba16fa401f84 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sat, 4 Nov 2023 16:35:52 +0100 Subject: [PATCH 6/8] Report faulting variant. --- vulkan/managers/shader_manager.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/vulkan/managers/shader_manager.cpp b/vulkan/managers/shader_manager.cpp index 18918a5c..395686f2 100644 --- a/vulkan/managers/shader_manager.cpp +++ b/vulkan/managers/shader_manager.cpp @@ -204,6 +204,18 @@ const ShaderTemplateVariant *ShaderTemplate::register_variant( return nullptr; #else LOGE("Could not find shader variant for %s in cache.\n", path.c_str()); + { + std::string str; + str += "["; + for (size_t i = 0, n = defines ? defines->size() : 0; i < n; i++) + { + str += "\n\t{ \"define\" : \"" + defines->operator[](i).first + "\", \"value\" : " + std::to_string(defines->operator[](i).second) + "}"; + if (i + 1 < n) + str += ","; + } + str += "\n]"; + LOGE("Slangmosh variant:\n%s\n", str.c_str()); + } variants.free(variant); return nullptr; #endif From fa553233f1cb88ffdd112279b58d78ba4edd0054 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sat, 4 Nov 2023 16:36:07 +0100 Subject: [PATCH 7/8] Use default define of 0. --- slangmosh/slangmosh.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/slangmosh/slangmosh.cpp b/slangmosh/slangmosh.cpp index 94f3b803..1cfc81ea 100644 --- a/slangmosh/slangmosh.cpp +++ b/slangmosh/slangmosh.cpp @@ -328,21 +328,21 @@ static std::string resolve_shader(const ProgramVariant &variant, const Shader *s return define.first == shader_variant.define; }); - if (itr == variant.defines.end()) - { - LOGE("Shader \"%s\" requires define \"%s\", but program variant does not define it.\n", - shader->name.c_str(), shader_variant.define.c_str()); - return {}; - } - else if (itr->second >= int(shader_variant.count) || itr->second < 0) + int value = 0; + + if (itr != variant.defines.end()) { - LOGE("Shader \"%s\" requires define \"%s\" in range [0, %u), but program variant requires value = %d.\n", - shader->name.c_str(), shader_variant.define.c_str(), - shader_variant.count, itr->second); - return {}; - } + if (itr->second >= int(shader_variant.count) || itr->second < 0) + { + LOGE("Shader \"%s\" requires define \"%s\" in range [0, %u), but program variant requires value = %d.\n", + shader->name.c_str(), shader_variant.define.c_str(), + shader_variant.count, itr->second); + return {}; + } - str + "[" + std::to_string(itr->second) + "]"; + value = itr->second; + } + str += "[" + std::to_string(value) + "]"; } return str; From c61b12bf05ae62590ef5b1bf2dc34483a4fffa6b Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sat, 4 Nov 2023 17:22:55 +0100 Subject: [PATCH 8/8] Remove basedir from BlobFilesystem. --- filesystem/filesystem.cpp | 10 +++++----- filesystem/filesystem.hpp | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/filesystem/filesystem.cpp b/filesystem/filesystem.cpp index 6100d105..b740e23e 100644 --- a/filesystem/filesystem.cpp +++ b/filesystem/filesystem.cpp @@ -391,8 +391,8 @@ FileHandle ScratchFilesystem::open(const std::string &path, FileMode) } } -BlobFilesystem::BlobFilesystem(FileHandle file_, std::string basedir_) - : file(std::move(file_)), base(std::move(basedir_)) +BlobFilesystem::BlobFilesystem(FileHandle file_) + : file(std::move(file_)) { if (!file) return; @@ -560,7 +560,7 @@ std::vector BlobFilesystem::list(const std::string &path) auto canon_path = Path::canonicalize_path(path); std::vector entries; - if (const auto *zip_dir = find_directory(Path::join(base, canon_path))) + if (const auto *zip_dir = find_directory(canon_path)) { entries.reserve(zip_dir->dirs.size() + zip_dir->files.size()); for (auto &dir : zip_dir->dirs) @@ -573,7 +573,7 @@ std::vector BlobFilesystem::list(const std::string &path) bool BlobFilesystem::stat(const std::string &path, FileStat &stat) { - auto p = Path::join(base, Path::canonicalize_path(path)); + auto p = Path::canonicalize_path(path); if (const auto *zip_file = find_file(p)) { @@ -598,7 +598,7 @@ FileHandle BlobFilesystem::open(const std::string &path, FileMode mode) if (mode != FileMode::ReadOnly) return {}; - auto p = Path::join(base, Path::canonicalize_path(path)); + auto p = Path::canonicalize_path(path); auto *blob_file = find_file(p); if (!blob_file) return {}; diff --git a/filesystem/filesystem.hpp b/filesystem/filesystem.hpp index 244fb5dc..5ba1014d 100644 --- a/filesystem/filesystem.hpp +++ b/filesystem/filesystem.hpp @@ -285,7 +285,7 @@ class FileSlice final : public File class BlobFilesystem final : public FilesystemBackend { public: - BlobFilesystem(FileHandle file, std::string basedir); + BlobFilesystem(FileHandle file); std::vector list(const std::string &path) override; @@ -304,7 +304,6 @@ class BlobFilesystem final : public FilesystemBackend private: FileHandle file; size_t blob_base_offset = 0; - std::string base; struct BlobFile {