From 7d5eb2bc2728d854a10834baae45dd47d44f86dc Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sat, 26 Mar 2016 17:59:50 +0100 Subject: [PATCH] Vulkan: Add pass name handling. Add #pragma name. --- gfx/drivers_shader/glslang_util.cpp | 34 ++++++++++- gfx/drivers_shader/glslang_util.hpp | 7 +++ gfx/drivers_shader/shader_vulkan.cpp | 87 ++++++++++++++++++++++++++++ gfx/drivers_shader/shader_vulkan.h | 4 ++ 4 files changed, 129 insertions(+), 3 deletions(-) diff --git a/gfx/drivers_shader/glslang_util.cpp b/gfx/drivers_shader/glslang_util.cpp index 191d075fd9..1ab19a272e 100644 --- a/gfx/drivers_shader/glslang_util.cpp +++ b/gfx/drivers_shader/glslang_util.cpp @@ -101,8 +101,11 @@ static string build_stage_source(const vector &lines, const char *stage) { if (itr->find("#pragma stage ") != string::npos) { - auto expected = string("#pragma stage ") + stage; - active = itr->find(expected) != string::npos; + if (stage) + { + auto expected = string("#pragma stage ") + stage; + active = itr->find(expected) != string::npos; + } // Improve debuggability. if (active) @@ -120,14 +123,39 @@ static string build_stage_source(const vector &lines, const char *stage) return str.str(); } +static bool glslang_parse_meta(const vector &lines, glslang_meta *meta) +{ + *meta = glslang_meta{}; + for (auto &line : lines) + { + if (line.find("#pragma name ") != string::npos) + { + if (!meta->name.empty()) + { + RARCH_ERR("[slang]: Trying to declare multiple names for file.\n"); + return false; + } + + const char *str = line.c_str() + strlen("#pragma name "); + while (*str == ' ') + str++; + meta->name = str; + } + } + return true; +} + bool glslang_compile_shader(const char *shader_path, glslang_output *output) { vector lines; - RARCH_LOG("Compiling shader \"%s\".\n", shader_path); + RARCH_LOG("[slang]: Compiling shader \"%s\".\n", shader_path); if (!read_shader_file(shader_path, &lines)) return false; + if (!glslang_parse_meta(lines, &output->meta)) + return false; + auto &header = lines.front(); if (header.find_first_of("#version ") == string::npos) { diff --git a/gfx/drivers_shader/glslang_util.hpp b/gfx/drivers_shader/glslang_util.hpp index 7602e6ff8e..5e8037cd2e 100644 --- a/gfx/drivers_shader/glslang_util.hpp +++ b/gfx/drivers_shader/glslang_util.hpp @@ -18,11 +18,18 @@ #include #include +#include + +struct glslang_meta +{ + std::string name; +}; struct glslang_output { std::vector vertex; std::vector fragment; + glslang_meta meta; }; bool glslang_compile_shader(const char *shader_path, glslang_output *output); diff --git a/gfx/drivers_shader/shader_vulkan.cpp b/gfx/drivers_shader/shader_vulkan.cpp index 008d594a2f..66f9dba12b 100644 --- a/gfx/drivers_shader/shader_vulkan.cpp +++ b/gfx/drivers_shader/shader_vulkan.cpp @@ -290,6 +290,16 @@ class Pass frame_count_period = period; } + void set_name(const char *name) + { + pass_name = name; + } + + const string &get_name() const + { + return pass_name; + } + vulkan_filter_chain_filter get_source_filter() const { return pass_info.source_filter; @@ -375,6 +385,8 @@ class Pass uint64_t frame_count = 0; unsigned frame_count_period = 0; + + string pass_name; }; // struct here since we're implementing the opaque typedef from C. @@ -411,6 +423,7 @@ struct vulkan_filter_chain void set_frame_count(uint64_t count); void set_frame_count_period(unsigned pass, unsigned period); + void set_pass_name(unsigned pass, const char *name); private: VkDevice device; @@ -439,6 +452,7 @@ struct vulkan_filter_chain bool init_history(); bool init_feedback(); + bool init_alias(); void update_history(DeferredDisposer &disposer, VkCommandBuffer cmd); vector> original_history; bool require_clear = false; @@ -543,6 +557,11 @@ void vulkan_filter_chain::set_frame_count_period(unsigned pass, unsigned period) passes[pass]->set_frame_count_period(period); } +void vulkan_filter_chain::set_pass_name(unsigned pass, const char *name) +{ + passes[pass]->set_name(name); +} + void vulkan_filter_chain::execute_deferred() { for (auto &calls : deferred_calls) @@ -674,13 +693,66 @@ bool vulkan_filter_chain::init_feedback() return true; } +template +static bool set_unique_map(M &m, const string &name, const P &p) +{ + auto itr = m.find(name); + if (itr != end(m)) + { + RARCH_ERR("[slang]: Alias \"%s\" already exists.\n", + name.c_str()); + return false; + } + + m[name] = p; + return true; +} + +bool vulkan_filter_chain::init_alias() +{ + common.texture_semantic_map.clear(); + common.texture_semantic_uniform_map.clear(); + common.semantic_map.clear(); + + unsigned i = 0; + for (auto &pass : passes) + { + auto &name = pass->get_name(); + if (name.empty()) + continue; + + if (!set_unique_map(common.texture_semantic_map, name, + slang_texture_semantic_map{ SLANG_TEXTURE_SEMANTIC_PASS_OUTPUT, i })) + return false; + + if (!set_unique_map(common.texture_semantic_uniform_map, name + "Size", + slang_texture_semantic_map{ SLANG_TEXTURE_SEMANTIC_PASS_OUTPUT, i })) + return false; + + if (!set_unique_map(common.texture_semantic_map, name + "Feedback", + slang_texture_semantic_map{ SLANG_TEXTURE_SEMANTIC_PASS_FEEDBACK, i })) + return false; + + if (!set_unique_map(common.texture_semantic_uniform_map, name + "FeedbackSize", + slang_texture_semantic_map{ SLANG_TEXTURE_SEMANTIC_PASS_FEEDBACK, i })) + return false; + + i++; + } + return true; +} + bool vulkan_filter_chain::init() { Size2D source = max_input_size; + if (!init_alias()) + return false; for (unsigned i = 0; i < passes.size(); i++) { auto &pass = passes[i]; + RARCH_LOG("[slang]: Building pass #%u (%s)\n", i, pass->get_name().empty() ? "N/A" : pass->get_name().c_str()); + source = pass->set_pass_info(max_input_size, source, swapchain_info, pass_info[i]); if (!pass->build()) @@ -1955,6 +2027,13 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( chain->set_frame_count_period(i, pass->frame_count_mod); + if (!output.meta.name.empty()) + chain->set_pass_name(i, output.meta.name.c_str()); + + // Preset overrides. + if (*pass->alias) + chain->set_pass_name(i, pass->alias); + if (pass->filter == RARCH_FILTER_UNSPEC) pass_info.source_filter = filter; else @@ -2129,6 +2208,14 @@ void vulkan_filter_chain_set_frame_count_period( chain->set_frame_count_period(pass, period); } +void vulkan_filter_chain_set_pass_name( + vulkan_filter_chain_t *chain, + unsigned pass, + const char *name) +{ + chain->set_pass_name(pass, name); +} + void vulkan_filter_chain_build_offscreen_passes( vulkan_filter_chain_t *chain, VkCommandBuffer cmd, const VkViewport *vp) diff --git a/gfx/drivers_shader/shader_vulkan.h b/gfx/drivers_shader/shader_vulkan.h index 86eab01d42..d1a9ca3b71 100644 --- a/gfx/drivers_shader/shader_vulkan.h +++ b/gfx/drivers_shader/shader_vulkan.h @@ -123,6 +123,10 @@ void vulkan_filter_chain_set_frame_count_period(vulkan_filter_chain_t *chain, unsigned pass, unsigned period); +void vulkan_filter_chain_set_pass_name(vulkan_filter_chain_t *chain, + unsigned pass, + const char *name); + void vulkan_filter_chain_build_offscreen_passes(vulkan_filter_chain_t *chain, VkCommandBuffer cmd, const VkViewport *vp); void vulkan_filter_chain_build_viewport_pass(vulkan_filter_chain_t *chain,