/* Copyright (c) 2019-2025, Arm Limited and Contributors * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 the "License"; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "common/helpers.h" #include "common/vk_common.h" #if defined(VK_USE_PLATFORM_XLIB_KHR) # undef None #endif namespace vkb { namespace core { template class Device; using DeviceC = Device; } // namespace core /// Types of shader resources enum class ShaderResourceType { Input, InputAttachment, Output, Image, ImageSampler, ImageStorage, Sampler, BufferUniform, BufferStorage, PushConstant, SpecializationConstant, All }; /// This determines the type and method of how descriptor set should be created and bound enum class ShaderResourceMode { Static, Dynamic, UpdateAfterBind }; /// A bitmask of qualifiers applied to a resource struct ShaderResourceQualifiers { enum : uint32_t { None = 0, NonReadable = 1, NonWritable = 2, }; }; /// Store shader resource data. /// Used by the shader module. struct ShaderResource { VkShaderStageFlags stages; ShaderResourceType type; ShaderResourceMode mode; uint32_t set; uint32_t binding; uint32_t location; uint32_t input_attachment_index; uint32_t vec_size; uint32_t columns; uint32_t array_size; uint32_t offset; uint32_t size; uint32_t constant_id; uint32_t qualifiers; std::string name; }; /** * @brief Adds support for C style preprocessor macros to glsl shaders * enabling you to define or undefine certain symbols */ class ShaderVariant { public: ShaderVariant() = default; size_t get_id() const; /** * @brief Specifies the size of a named runtime array for automatic reflection. If already specified, overrides the size. * @param runtime_array_name String under which the runtime array is named in the shader * @param size Integer specifying the wanted size of the runtime array (in number of elements, not size in bytes), used for automatic allocation of buffers. * See get_declared_struct_size_runtime_array() in spirv_cross.h */ void add_runtime_array_size(const std::string &runtime_array_name, size_t size); void set_runtime_array_sizes(const std::unordered_map &sizes); const std::unordered_map &get_runtime_array_sizes() const; void clear(); private: size_t id; std::unordered_map runtime_array_sizes; }; class ShaderSource { public: ShaderSource() = default; ShaderSource(const std::string &filename); size_t get_id() const; const std::string &get_filename() const; void set_source(const std::string &source); const std::string &get_source() const; private: size_t id; std::string filename; std::string source; }; /** * @brief Contains shader code, with an entry point, for a specific shader stage. * It is needed by a PipelineLayout to create a Pipeline. * ShaderModule can do auto-pairing between shader code and textures. * The low level code can change bindings, just keeping the name of the texture. * Variants for each texture are also generated, such as HAS_BASE_COLOR_TEX. * It works similarly for attribute locations. A current limitation is that only set 0 * is considered. Uniform buffers are currently hardcoded as well. */ class ShaderModule { public: ShaderModule(vkb::core::DeviceC &device, VkShaderStageFlagBits stage, const ShaderSource &shader_source, const std::string &entry_point, const ShaderVariant &shader_variant); ShaderModule(const ShaderModule &) = delete; ShaderModule(ShaderModule &&other); ShaderModule &operator=(const ShaderModule &) = delete; ShaderModule &operator=(ShaderModule &&) = delete; size_t get_id() const; VkShaderStageFlagBits get_stage() const; const std::string &get_entry_point() const; const std::vector &get_resources() const; const std::vector &get_binary() const; inline const std::string &get_debug_name() const { return debug_name; } inline void set_debug_name(const std::string &name) { debug_name = name; } /** * @brief Flags a resource to use a different method of being bound to the shader * @param resource_name The name of the shader resource * @param resource_mode The mode of how the shader resource will be bound */ void set_resource_mode(const std::string &resource_name, const ShaderResourceMode &resource_mode); private: vkb::core::DeviceC &device; /// Shader unique id size_t id; /// Stage of the shader (vertex, fragment, etc) VkShaderStageFlagBits stage{}; /// Name of the main function std::string entry_point; /// Human-readable name for the shader std::string debug_name; /// Compiled source std::vector spirv; std::vector resources; }; } // namespace vkb