summaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-11-03 09:48:04 +0100
committerHampusM <hampus@hampusmat.com>2026-11-03 09:48:04 +0100
commit51c85583a0d3eda5e8cf41273ecfa9b6d994e59c (patch)
tree1913605835d236a2e7cc8040e10fa460e71a4b22 /engine
parent1529915d58524ab4de3eaa0b3441fc09c1dcf4f0 (diff)
feat(engine): add shader context session initialization options
Diffstat (limited to 'engine')
-rw-r--r--engine/src/rendering/backend/opengl.rs27
-rw-r--r--engine/src/rendering/shader.rs149
2 files changed, 166 insertions, 10 deletions
diff --git a/engine/src/rendering/backend/opengl.rs b/engine/src/rendering/backend/opengl.rs
index bdaa555..2926cde 100644
--- a/engine/src/rendering/backend/opengl.rs
+++ b/engine/src/rendering/backend/opengl.rs
@@ -119,8 +119,15 @@ use crate::rendering::shader::cursor::{
};
use crate::rendering::shader::reflection::Stage as ShaderStage;
use crate::rendering::shader::{
+ CompileTarget as ShaderCompileTarget,
+ CompileTargetFormat as ShaderCompileTargetFormat,
+ Context as ShaderContext,
+ ContextSessionInitOpts as ShaderContextSessionInitOpts,
+ DebugInfoLevel as ShaderDebugInfoLevel,
EntrypointFlags as ShaderEntrypointFlags,
Error as ShaderError,
+ LineDirectiveMode as ShaderLineDirectiveMode,
+ OptimizationLevel as ShaderOptimizationLevel,
Program as ShaderProgram,
VertexDescCreationError as ShaderVertexDescCreationError,
VertexDescription as ShaderVertexDescription,
@@ -521,15 +528,27 @@ impl crate::ecs::extension::Extension for Extension
}
fn init(
- mut shader_context: Single<crate::rendering::shader::Context>,
+ mut shader_context: Single<ShaderContext>,
mut actions: Actions,
) -> Result<(), crate::Error>
{
let shader_context = shader_context.get_mut()?;
- let shader_target_ids = shader_context
- .init_session(&[&crate::rendering::shader::CompileTarget::default()
- .format(crate::rendering::shader::CompileTargetFormat::Glsl)])?;
+ let shader_target_ids = shader_context.init_session(
+ &if cfg!(debug_assertions) {
+ ShaderContextSessionInitOpts::default()
+ .optimization_level(ShaderOptimizationLevel::Default)
+ .debug_info_level(ShaderDebugInfoLevel::Maximal)
+ .line_directive_mode(ShaderLineDirectiveMode::Standard)
+ .no_mangle(true)
+ } else {
+ ShaderContextSessionInitOpts::default()
+ .optimization_level(ShaderOptimizationLevel::High)
+ .debug_info_level(ShaderDebugInfoLevel::None)
+ .line_directive_mode(ShaderLineDirectiveMode::None)
+ },
+ &[&ShaderCompileTarget::default().format(ShaderCompileTargetFormat::Glsl)],
+ )?;
actions.create_sole(BackendProperties {
shader_target_id: shader_target_ids[0],
diff --git a/engine/src/rendering/shader.rs b/engine/src/rendering/shader.rs
index 926302a..6a52b0a 100644
--- a/engine/src/rendering/shader.rs
+++ b/engine/src/rendering/shader.rs
@@ -10,7 +10,6 @@ use ecs::phase::INIT as INIT_PHASE;
use shader_slang::{
Blob as SlangBlob,
ComponentType as SlangComponentType,
- DebugInfoLevel as SlangDebugInfoLevel,
EntryPoint as SlangEntryPoint,
GlobalSession as SlangGlobalSession,
Module as SlangModule,
@@ -245,6 +244,7 @@ impl Context
#[allow(clippy::missing_errors_doc)]
pub fn init_session(
&mut self,
+ opts: &ContextSessionInitOpts,
compile_targets: &[&CompileTarget],
) -> Result<Vec<CompileTargetId>, ContextSessionInitError>
{
@@ -257,10 +257,11 @@ impl Context
}
let session_options = shader_slang::CompilerOptions::default()
- .optimization(shader_slang::OptimizationLevel::None)
- .matrix_layout_row(true)
- .debug_information(SlangDebugInfoLevel::Maximal)
- .no_mangle(true);
+ .matrix_layout_row(true) // Matrices must be row major
+ .optimization(opts.optimization_level.into_slang())
+ .debug_information(opts.debug_info_level.into_slang())
+ .line_directive_mode(opts.line_directive_mode.into_slang())
+ .no_mangle(opts.no_mangle);
let (compile_target_ids, target_descs) = compile_targets
.iter()
@@ -271,7 +272,10 @@ impl Context
(
CompileTargetId { index: index as u32 },
shader_slang::TargetDesc::default()
- .format(compile_target.format.into_slang()),
+ .format(compile_target.format.into_slang())
+ // For some reason, the compiler options need to be specified
+ // for each target as well. Otherwise, they are not used
+ .options(&session_options),
)
})
.collect::<(Vec<_>, Vec<_>)>();
@@ -350,6 +354,139 @@ impl Context
}
}
+#[derive(Debug, Default, Clone)]
+#[non_exhaustive]
+pub struct ContextSessionInitOpts
+{
+ pub optimization_level: OptimizationLevel,
+ pub debug_info_level: DebugInfoLevel,
+ pub line_directive_mode: LineDirectiveMode,
+ pub no_mangle: bool,
+}
+
+impl ContextSessionInitOpts
+{
+ pub fn optimization_level(mut self, optimization_level: OptimizationLevel) -> Self
+ {
+ self.optimization_level = optimization_level;
+ self
+ }
+
+ pub fn debug_info_level(mut self, debug_info_level: DebugInfoLevel) -> Self
+ {
+ self.debug_info_level = debug_info_level;
+ self
+ }
+
+ pub fn line_directive_mode(mut self, line_directive_mode: LineDirectiveMode) -> Self
+ {
+ self.line_directive_mode = line_directive_mode;
+ self
+ }
+
+ pub fn no_mangle(mut self, no_mangle: bool) -> Self
+ {
+ self.no_mangle = no_mangle;
+ self
+ }
+}
+
+#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)]
+#[non_exhaustive]
+pub enum OptimizationLevel
+{
+ /// Don't optimize at all.
+ None,
+
+ /// Default optimization level: balance code quality and compilation time.
+ #[default]
+ Default,
+
+ /// Optimize aggressively.
+ High,
+
+ /// Include optimizations that may take a very long time, or may involve severe
+ /// space-vs-speed tradeoffs
+ Maximal,
+}
+
+impl OptimizationLevel
+{
+ fn into_slang(self) -> shader_slang::OptimizationLevel
+ {
+ match self {
+ Self::None => shader_slang::OptimizationLevel::None,
+ Self::Default => shader_slang::OptimizationLevel::Default,
+ Self::High => shader_slang::OptimizationLevel::High,
+ Self::Maximal => shader_slang::OptimizationLevel::Maximal,
+ }
+ }
+}
+
+#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)]
+#[non_exhaustive]
+pub enum DebugInfoLevel
+{
+ /// Don't emit debug information at all.
+ #[default]
+ None,
+
+ /// Emit as little debug information as possible, while still supporting stack
+ /// trackers.
+ Minimal,
+
+ /// Emit whatever is the standard level of debug information for each target.
+ Standard,
+
+ /// Emit as much debug information as possible for each target.
+ Maximal,
+}
+
+impl DebugInfoLevel
+{
+ fn into_slang(self) -> shader_slang::DebugInfoLevel
+ {
+ match self {
+ Self::None => shader_slang::DebugInfoLevel::None,
+ Self::Minimal => shader_slang::DebugInfoLevel::Minimal,
+ Self::Standard => shader_slang::DebugInfoLevel::Standard,
+ Self::Maximal => shader_slang::DebugInfoLevel::Maximal,
+ }
+ }
+}
+
+#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
+#[non_exhaustive]
+pub enum LineDirectiveMode
+{
+ /// Don't emit line directives at all.
+ #[default]
+ None,
+
+ /// Emit standard C-style `#line` directives.
+ Standard,
+
+ /// Emit GLSL-style directives with file *number* instead of name
+ Glsl,
+
+ /// Use a source map to track line mappings (ie no #line will appear in emitting
+ /// source)
+ SourceMap,
+}
+
+impl LineDirectiveMode
+{
+ fn into_slang(self) -> shader_slang::LineDirectiveMode
+ {
+ match self {
+ Self::None => shader_slang::LineDirectiveMode::None,
+ Self::Standard => shader_slang::LineDirectiveMode::Standard,
+ Self::Glsl => shader_slang::LineDirectiveMode::Glsl,
+ Self::SourceMap => shader_slang::LineDirectiveMode::SourceMap,
+ }
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CompileTargetId
{