#pragma once #include "globalincs/pstypes.h" #include "graphics/2d.h" #include #include namespace graphics::vulkan { class VulkanShadercLibrary; /** * @brief Runtime GLSL->SPIR-V compiler using shaderc * * Replaces build-time glslc compilation. Compiles GLSL to SPIR-V at runtime * with disk caching, #define variant injection, and include resolution. * The shaderc library is loaded dynamically. */ class VulkanShaderCompiler { public: VulkanShaderCompiler(); ~VulkanShaderCompiler(); bool init(bool hwClipDistance); void shutdown(); /** * @brief Check if the shaderc library was loaded successfully */ bool isAvailable() const; /** * @brief Compile GLSL to SPIR-V with disk caching * * @param filename GLSL source filename, e.g. "main.frag" * @param stage Vertex or fragment * @param sdrType Shader type (for variant flag lookup) * @param flags SDR_FLAG_* bitmask — matching flags injected as #defines * @param requiresRaytracing Whether this (sdrType, flags) combination uses * GL_EXT_ray_query (see shader_variant_requires_raytracing()) and * therefore needs a SPIR-V target-env new enough to support it. * Left false for all other shaders so they keep targeting the * lowest common Vulkan version. * @return SPIR-V words, or empty vector on failure */ SCP_vector compile(const SCP_string& filename, vk::ShaderStageFlagBits stage, shader_type sdrType, unsigned int flags, bool requiresRaytracing = false); /** * @brief Delete stale cache files older than ~2 months */ static void purgeOldCache(); private: /** * @brief Build the GLSL header with #defines for variant flags */ SCP_string buildHeader(vk::ShaderStageFlagBits stage, shader_type sdrType, unsigned int flags) const; /** * @brief Compute an MD5 hash of the header + source + version tag for disk caching */ static SCP_string computeSourceHash(const SCP_string& header, const SCP_string& source); std::unique_ptr m_shaderc; bool m_initialized = false; bool m_hwClipDistance = false; }; } // namespace graphics::vulkan