reflect: allow compilation of boxed trait objects

Add a hidden `compile_boxed` function to CompileShader to support this. This is to allow Box<dyn CompileReflectShader> to work.
This commit is contained in:
chyyran 2024-09-15 01:16:32 -04:00 committed by Ronny Chan
parent 805854b94b
commit 4cc3c875bf
8 changed files with 92 additions and 8 deletions

View file

@ -36,6 +36,16 @@ pub trait CompileShader<T: OutputTarget> {
self,
options: Self::Options,
) -> Result<ShaderCompilerOutput<T::Output, Self::Context>, ShaderCompileError>;
/// Consume the object and return the compiled output of the shader.
///
/// This is an internal implementation detail for stable building without TAIT,
/// to allow delegation when Self is unsized (i.e. dyn CompileReflectShader).
#[doc(hidden)]
fn compile_boxed(
self: Box<Self>,
options: Self::Options,
) -> Result<ShaderCompilerOutput<T::Output, Self::Context>, ShaderCompileError>;
}
/// Marker trait for combinations of targets and compilations that can be reflected and compiled
@ -81,6 +91,13 @@ where
) -> Result<ShaderCompilerOutput<E::Output, Self::Context>, ShaderCompileError> {
self.backend.compile(options)
}
fn compile_boxed(
self: Box<Self>,
options: Self::Options,
) -> Result<ShaderCompilerOutput<E::Output, Self::Context>, ShaderCompileError> {
self.backend.compile(options)
}
}
/// A trait for reflectable compilations that can be transformed
@ -124,6 +141,39 @@ where
}
}
impl<T: ReflectShader + ?Sized> ReflectShader for Box<T> {
fn reflect(
&mut self,
pass_number: usize,
semantics: &ShaderSemantics,
) -> Result<ShaderReflection, ShaderReflectError> {
(**self).reflect(pass_number, semantics)
}
}
impl<O, T> CompileShader<T> for Box<O>
where
O: CompileShader<T> + ?Sized,
T: OutputTarget,
{
type Options = O::Options;
type Context = O::Context;
fn compile(
self,
options: Self::Options,
) -> Result<ShaderCompilerOutput<T::Output, Self::Context>, ShaderCompileError> {
O::compile_boxed(self, options)
}
fn compile_boxed(
self: Box<Self>,
options: Self::Options,
) -> Result<ShaderCompilerOutput<T::Output, Self::Context>, ShaderCompileError> {
self.compile(options)
}
}
#[cfg(test)]
mod test {
use crate::front::{Glslang, ShaderInputCompiler};

View file

@ -1,5 +1,5 @@
use crate::back::targets::MSL;
use crate::back::{CompileReflectShader, CompileShader, CompilerBackend, FromCompilation};
use crate::back::{CompileReflectShader, CompilerBackend, FromCompilation};
use crate::error::ShaderReflectError;
use crate::front::SpirvCompilation;
use crate::reflect::cross::msl::MslReflect;
@ -29,8 +29,7 @@ impl FromCompilation<SpirvCompilation, SpirvCross> for MSL {
type Target = MSL;
type Options = Option<self::MslVersion>;
type Context = CrossMslContext;
type Output = impl CompileShader<Self::Target, Options = Self::Options, Context = Self::Context>
+ ReflectShader;
type Output = impl CompileReflectShader<Self::Target, SpirvCompilation, SpirvCross>;
fn from_compilation(
compile: SpirvCompilation,

View file

@ -1,5 +1,7 @@
use crate::back::targets::SPIRV;
use crate::back::{CompileShader, CompilerBackend, FromCompilation, ShaderCompilerOutput};
use crate::back::{
CompileReflectShader, CompileShader, CompilerBackend, FromCompilation, ShaderCompilerOutput,
};
use crate::error::{ShaderCompileError, ShaderReflectError};
use crate::front::SpirvCompilation;
use crate::reflect::cross::glsl::GlslReflect;
@ -20,8 +22,7 @@ impl FromCompilation<SpirvCompilation, SpirvCross> for SPIRV {
type Target = SPIRV;
type Options = Option<()>;
type Context = ();
type Output = impl CompileShader<Self::Target, Options = Self::Options, Context = Self::Context>
+ ReflectShader;
type Output = impl CompileReflectShader<Self::Target, SpirvCompilation, SpirvCross>;
fn from_compilation(
compile: SpirvCompilation,
@ -86,8 +87,7 @@ impl FromCompilation<SpirvCompilation, Naga> for SPIRV {
type Target = SPIRV;
type Options = NagaSpirvOptions;
type Context = NagaSpirvContext;
type Output = impl CompileShader<Self::Target, Options = Self::Options, Context = Self::Context>
+ ReflectShader;
type Output = impl CompileReflectShader<Self::Target, SpirvCompilation, Naga>;
fn from_compilation(
compile: SpirvCompilation,

View file

@ -165,4 +165,11 @@ impl CompileShader<GLSL> for CrossReflect<targets::Glsl> {
},
})
}
fn compile_boxed(
self: Box<Self>,
options: Self::Options,
) -> Result<ShaderCompilerOutput<String, Self::Context>, ShaderCompileError> {
<CrossReflect<targets::Glsl> as CompileShader<GLSL>>::compile(*self, options)
}
}

View file

@ -128,4 +128,11 @@ impl CompileShader<HLSL> for CrossReflect<targets::Hlsl> {
},
})
}
fn compile_boxed(
self: Box<Self>,
options: Self::Options,
) -> Result<ShaderCompilerOutput<String, Self::Context>, ShaderCompileError> {
<CrossReflect<targets::Hlsl> as CompileShader<HLSL>>::compile(*self, options)
}
}

View file

@ -146,6 +146,13 @@ impl CompileShader<MSL> for NagaReflect {
},
})
}
fn compile_boxed(
self: Box<Self>,
options: Self::Options,
) -> Result<ShaderCompilerOutput<String, Self::Context>, ShaderCompileError> {
<NagaReflect as CompileShader<MSL>>::compile(*self, options)
}
}
#[cfg(test)]

View file

@ -51,4 +51,11 @@ impl CompileShader<SPIRV> for NagaReflect {
},
})
}
fn compile_boxed(
self: Box<Self>,
options: Self::Options,
) -> Result<ShaderCompilerOutput<Vec<u32>, Self::Context>, ShaderCompileError> {
<NagaReflect as CompileShader<SPIRV>>::compile(*self, options)
}
}

View file

@ -38,4 +38,11 @@ impl CompileShader<WGSL> for NagaReflect {
},
})
}
fn compile_boxed(
self: Box<Self>,
options: Self::Options,
) -> Result<ShaderCompilerOutput<String, Self::Context>, ShaderCompileError> {
<NagaReflect as CompileShader<WGSL>>::compile(*self, options)
}
}