Support #include in runtime-compiled GLSL shaders #81

Open
opened 2026-10-25 22:11:39 -07:00 by burkkyy · 0 comments
Owner

Problem

Shader::compile (engine/src/vulkan/shader.cpp) compiles GLSL at runtime with shaderc but never sets an includer. shaderc accepts #include syntax (GL_GOOGLE_include_directive) but has no way to resolve files, so any shader using #include "common.glsl" or #include <common.glsl> fails to compile.

This blocks sharing code (structs, buffer_reference layouts, helpers) between shaders, e.g. sandbox/shaders/common.glsl.

Proposal

  1. Implement a shaderc::CompileOptions::IncluderInterface (FileIncluder):
    • shaderc_include_type_relative ("..."): search the requesting file's directory first, then the include dirs.
    • shaderc_include_type_standard (<...>): search the include dirs only.
    • On failure, return an empty source_name with the error message in content (shaderc's convention).
    • Own the path and content strings via user_data; free them in ReleaseInclude.
  2. Pass it through CompileOptions::SetIncluder in Shader::compile.
  3. Add Shader::Builder::addIncludeDir(path), and have the engine always add its own shader directory so shared engine headers are available to every app (sandbox, editor, testbed).

Notes

  • GLSL has no automatic include guards. Shared headers need #ifndef / #define guards.
  • If shader hot reload is added later, it must track include dependencies so editing a header recompiles the shaders that use it.

Acceptance criteria

  • #include "common.glsl" resolves relative to the including shader.
  • #include <x.glsl> resolves from the configured include dirs.
  • A missing include produces a clear compile error naming the file.
## Problem `Shader::compile` ([engine/src/vulkan/shader.cpp](engine/src/vulkan/shader.cpp)) compiles GLSL at runtime with shaderc but never sets an includer. shaderc accepts `#include` syntax (`GL_GOOGLE_include_directive`) but has no way to resolve files, so any shader using `#include "common.glsl"` or `#include <common.glsl>` fails to compile. This blocks sharing code (structs, buffer_reference layouts, helpers) between shaders, e.g. `sandbox/shaders/common.glsl`. ## Proposal 1. Implement a `shaderc::CompileOptions::IncluderInterface` (`FileIncluder`): - `shaderc_include_type_relative` (`"..."`): search the requesting file's directory first, then the include dirs. - `shaderc_include_type_standard` (`<...>`): search the include dirs only. - On failure, return an empty `source_name` with the error message in `content` (shaderc's convention). - Own the path and content strings via `user_data`; free them in `ReleaseInclude`. 2. Pass it through `CompileOptions::SetIncluder` in `Shader::compile`. 3. Add `Shader::Builder::addIncludeDir(path)`, and have the engine always add its own shader directory so shared engine headers are available to every app (sandbox, editor, testbed). ## Notes - GLSL has no automatic include guards. Shared headers need `#ifndef` / `#define` guards. - If shader hot reload is added later, it must track include dependencies so editing a header recompiles the shaders that use it. ## Acceptance criteria - `#include "common.glsl"` resolves relative to the including shader. - `#include <x.glsl>` resolves from the configured include dirs. - A missing include produces a clear compile error naming the file.
burkkyy added the enhancement label 2026-10-25 22:11:39 -07:00
burkkyy added this to the sophia project 2026-10-25 22:11:47 -07:00
Sign in to join this conversation.