mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 20:58:31 +09:00
81 lines
5.1 KiB
C++
81 lines
5.1 KiB
C++
// MobileGL - MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.h
|
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
|
// Licensed under the GNU Lesser General Public License v3.0:
|
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
// End of Source File Header
|
|
|
|
#pragma once
|
|
#include <Includes.h>
|
|
#include <MG_State/GLState/ProgramState/ShaderObject.h>
|
|
#include <MG_Util/ShaderTranspiler/CompileEnv.h>
|
|
|
|
namespace MobileGL {
|
|
enum class ShaderProfile {
|
|
Core,
|
|
Compatibility,
|
|
ES,
|
|
};
|
|
|
|
namespace MG_Util {
|
|
namespace ShaderTranspiler {
|
|
// The whole source-rewriting pipeline. `env` is the compile-time snapshot of
|
|
// everything outside (stage, source) this reads - advertised extensions and the
|
|
// device-quirk inputs - so the transformation is a pure function of its three
|
|
// arguments and can run on a worker thread.
|
|
void PreprocessShaderSource(ShaderStage stage, String& source, const CompileEnv& env);
|
|
// Convenience overload that resolves the current context's env itself. GL thread
|
|
// only, and deliberately not used by the compile pipeline: it exists for the unit
|
|
// tests and diagnostics that drive the preprocessor standalone.
|
|
void PreprocessShaderSource(ShaderStage stage, String& source);
|
|
|
|
// Rewrites a "#version 330 core" directive that PreprocessShaderSource normalized down
|
|
// from a legacy desktop version back up to "#version 460 core". Returns false (leaving
|
|
// the source untouched) for anything else: ES, compatibility, or an already-modern
|
|
// declaration. Exists so a shader that only parses under the laxer 460 rules - e.g. it
|
|
// uses 420-era syntax without the matching #extension line, which real drivers tend to
|
|
// accept - can be retried instead of failing to compile.
|
|
Bool RetargetLegacyVersionDirectiveTo460(String& source);
|
|
|
|
// GLSL reserves a few names glslang happily accepts as identifiers ("packed",
|
|
// "row_major" outside a layout(...) list, the image*Shadow family). Returns the
|
|
// compile-error text for the first violation, or nullopt for a clean source.
|
|
std::optional<String> FindReservedIdentifierViolation(const String& source);
|
|
|
|
// Explicit layout(location = N) qualifiers on default-block uniform declarations,
|
|
// keyed by declared name (no "[0]" suffix). Multi-declarator statements assign
|
|
// consecutive locations, advancing by the array element count.
|
|
//
|
|
// Exists because the single link-compatible parse runs under relaxed Vulkan rules,
|
|
// where glslang's vkRelaxedRemapUniformVariable moves plain uniforms into
|
|
// MGL_GLOBAL_UBO and DISCARDS their location qualifiers ("ignoring layout qualifier
|
|
// for uniform location"); opaque uniforms keep theirs. This lexical side-channel
|
|
// restores the discarded locations to the GL location assigner
|
|
// (ProgramObject::DoReflection). It scans preprocessor-visible text, so a
|
|
// declaration inside an inactive #if branch is still recorded - harmless unless a
|
|
// pack declares the same uniform with different explicit locations in alternative
|
|
// branches (none observed; explicit uniform locations have zero incidence in the
|
|
// shader-pack corpus, this is an ARB_explicit_uniform_location conformance surface).
|
|
UnorderedMap<String, Int> ExtractExplicitUniformLocations(const String& source);
|
|
|
|
// Explicit layout(binding = N) on sampler/image uniforms, i.e. their initial
|
|
// texture/image units. The Vulkan-client relaxed parse strips these before
|
|
// mapIO can capture them, so they are recovered lexically (same narrow
|
|
// grammar discipline as ExtractExplicitUniformLocations).
|
|
UnorderedMap<String, Uint> ExtractExplicitOpaqueBindings(const String& source);
|
|
|
|
// A shader storage block whose layout(binding = N) reaches or passes
|
|
// GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS is a compile-time error in GL 4.3 core 4.4.5,
|
|
// and an arrayed block instance takes CONSECUTIVE points, so the last element is what
|
|
// has to fit. glslang cannot raise it for MobileGL: every shader is parsed as a Vulkan
|
|
// client under relaxed rules, where the GL ceilings do not apply, and TBuiltInResource
|
|
// has no storage-buffer binding field to check against in the first place. Returns the
|
|
// compile-error text for the first violation, or nullopt for a clean source.
|
|
// `maxBindings` is what glGetIntegerv answers for that pname; a non-positive value
|
|
// means "nothing to check against" and every declaration passes.
|
|
std::optional<String> FindShaderStorageBindingViolation(const String& source, Int maxBindings);
|
|
} // namespace ShaderTranspiler
|
|
} // namespace MG_Util
|
|
} // namespace MobileGL
|