reflect: port to spirv-cross2
This commit is contained in:
parent
820fb69328
commit
c3033cfbbf
64
Cargo.lock
generated
64
Cargo.lock
generated
|
@ -411,9 +411,9 @@ checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytemuck"
|
name = "bytemuck"
|
||||||
version = "1.17.1"
|
version = "1.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2"
|
checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck_derive",
|
"bytemuck_derive",
|
||||||
]
|
]
|
||||||
|
@ -1678,7 +1678,6 @@ dependencies = [
|
||||||
"ash",
|
"ash",
|
||||||
"gl",
|
"gl",
|
||||||
"librashader",
|
"librashader",
|
||||||
"librashader-spirv-cross",
|
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-metal",
|
"objc2-metal",
|
||||||
"paste",
|
"paste",
|
||||||
|
@ -1741,13 +1740,13 @@ dependencies = [
|
||||||
"librashader-common",
|
"librashader-common",
|
||||||
"librashader-preprocess",
|
"librashader-preprocess",
|
||||||
"librashader-presets",
|
"librashader-presets",
|
||||||
"librashader-spirv-cross",
|
|
||||||
"matches",
|
"matches",
|
||||||
"naga",
|
"naga",
|
||||||
"rspirv",
|
"rspirv",
|
||||||
"rustc-hash 2.0.0",
|
"rustc-hash 2.0.0",
|
||||||
"serde",
|
"serde",
|
||||||
"spirv",
|
"spirv",
|
||||||
|
"spirv-cross2",
|
||||||
"spirv-to-dxil",
|
"spirv-to-dxil",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
@ -1842,8 +1841,8 @@ dependencies = [
|
||||||
"librashader-presets",
|
"librashader-presets",
|
||||||
"librashader-reflect",
|
"librashader-reflect",
|
||||||
"librashader-runtime",
|
"librashader-runtime",
|
||||||
"librashader-spirv-cross",
|
|
||||||
"rayon",
|
"rayon",
|
||||||
|
"spirv-cross2",
|
||||||
"sptr",
|
"sptr",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
@ -1914,18 +1913,6 @@ dependencies = [
|
||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "librashader-spirv-cross"
|
|
||||||
version = "0.26.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4603464191d79d8ce9fe81f7925dfa5b74060b15be51608525f0758f6d88e238"
|
|
||||||
dependencies = [
|
|
||||||
"build-target",
|
|
||||||
"cc",
|
|
||||||
"js-sys",
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "libredox"
|
||||||
version = "0.0.2"
|
version = "0.0.2"
|
||||||
|
@ -2936,9 +2923,9 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.35"
|
version = "0.38.36"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f"
|
checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"errno",
|
"errno",
|
||||||
|
@ -3147,6 +3134,45 @@ dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spirv-cross-sys"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3aaad7cc693a12f8da9fd481ac938fdd0fc1b2e73b9f710eb723d3e7f5607f0a"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"cc",
|
||||||
|
"glob",
|
||||||
|
"num-derive",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spirv-cross2"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6f49915b223bae37821a45c93ad5c269cb6df620b4147b567cda4cf8951061e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"bytemuck",
|
||||||
|
"memchr",
|
||||||
|
"spirv",
|
||||||
|
"spirv-cross-sys",
|
||||||
|
"spirv-cross2-derive",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spirv-cross2-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "18017a288e6ce64dd5d56510166baeabb01849483555c031f573c091b6934a64"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.77",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spirv-to-dxil"
|
name = "spirv-to-dxil"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
|
|
|
@ -20,8 +20,7 @@ resolver = "2"
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
windows = "0.58.0"
|
windows = "0.58.0"
|
||||||
ash = "0.38"
|
ash = "0.38"
|
||||||
spirv_cross = { package = "librashader-spirv-cross", version = "0.26" }
|
spirv-cross2 = { version = "0.4", default-features = false }
|
||||||
|
|
||||||
objc2-metal = { version = "0.2" }
|
objc2-metal = { version = "0.2" }
|
||||||
objc2 = { version = "0.5.0" }
|
objc2 = { version = "0.5.0" }
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,6 @@ rustc-hash = "2.0.0"
|
||||||
sptr = "0.3.2"
|
sptr = "0.3.2"
|
||||||
|
|
||||||
ash = { workspace = true, optional = true }
|
ash = { workspace = true, optional = true }
|
||||||
spirv_cross = { workspace = true }
|
|
||||||
|
|
||||||
[dependencies.librashader]
|
[dependencies.librashader]
|
||||||
path = "../librashader"
|
path = "../librashader"
|
||||||
|
|
|
@ -22,7 +22,7 @@ librashader-common = { path = "../librashader-common", version = "0.3.3" }
|
||||||
librashader-preprocess = { path = "../librashader-preprocess", version = "0.3.3" }
|
librashader-preprocess = { path = "../librashader-preprocess", version = "0.3.3" }
|
||||||
librashader-presets = { path = "../librashader-presets", version = "0.3.3" }
|
librashader-presets = { path = "../librashader-presets", version = "0.3.3" }
|
||||||
|
|
||||||
spirv_cross = { workspace = true, optional = true }
|
spirv-cross2 = { workspace = true, optional = true }
|
||||||
|
|
||||||
naga = { version = "22", optional = true }
|
naga = { version = "22", optional = true }
|
||||||
rspirv = { version = "0.12.0", optional = true }
|
rspirv = { version = "0.12.0", optional = true }
|
||||||
|
@ -40,11 +40,11 @@ optional = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["cross", "naga", "serialize", "wgsl", "msl"]
|
default = ["cross", "naga", "serialize", "wgsl", "msl"]
|
||||||
dxil = ["spirv_cross/hlsl", "spirv-to-dxil"]
|
dxil = ["spirv-cross2/hlsl", "dep:spirv-to-dxil"]
|
||||||
wgsl = ["cross", "naga/wgsl-out", "spirv", "rspirv"]
|
wgsl = ["cross", "naga/wgsl-out", "dep:spirv", "dep:rspirv"]
|
||||||
cross = [ "spirv_cross", "spirv_cross/glsl", "spirv_cross/hlsl", "spirv_cross/msl" ]
|
cross = [ "dep:spirv-cross2", "spirv-cross2/glsl", "spirv-cross2/hlsl", "spirv-cross2/msl" ]
|
||||||
naga = [ "rspirv", "spirv", "naga/spv-in", "naga/spv-out", "naga/wgsl-out", "naga/msl-out" ]
|
naga = [ "dep:rspirv", "dep:spirv", "naga/spv-in", "naga/spv-out", "naga/wgsl-out", "naga/msl-out" ]
|
||||||
serialize = [ "serde" ]
|
serialize = [ "dep:serde" ]
|
||||||
msl = [ "spirv_cross/msl", "naga/msl-out" ]
|
msl = [ "spirv-cross2/msl", "naga/msl-out" ]
|
||||||
|
|
||||||
unstable-naga-in = ["naga/glsl-in"]
|
unstable-naga-in = ["naga/glsl-in"]
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::reflect::cross::{CompiledProgram, SpirvCross};
|
||||||
use crate::reflect::ReflectShader;
|
use crate::reflect::ReflectShader;
|
||||||
|
|
||||||
/// The GLSL version to target.
|
/// The GLSL version to target.
|
||||||
pub use spirv_cross::glsl::Version as GlslVersion;
|
pub use spirv_cross2::compile::glsl::GlslVersion;
|
||||||
|
|
||||||
use crate::reflect::cross::glsl::GlslReflect;
|
use crate::reflect::cross::glsl::GlslReflect;
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ pub struct CrossGlslContext {
|
||||||
/// A map of bindings of sampler names to binding locations.
|
/// A map of bindings of sampler names to binding locations.
|
||||||
pub sampler_bindings: Vec<(String, u32)>,
|
pub sampler_bindings: Vec<(String, u32)>,
|
||||||
/// The compiled program artifact after compilation.
|
/// The compiled program artifact after compilation.
|
||||||
pub artifact: CompiledProgram<spirv_cross::glsl::Target>,
|
pub artifact: CompiledProgram<spirv_cross2::targets::Glsl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromCompilation<SpirvCompilation, SpirvCross> for GLSL {
|
impl FromCompilation<SpirvCompilation, SpirvCross> for GLSL {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::reflect::cross::{CompiledProgram, SpirvCross};
|
||||||
use crate::reflect::ReflectShader;
|
use crate::reflect::ReflectShader;
|
||||||
|
|
||||||
/// The HLSL shader model version to target.
|
/// The HLSL shader model version to target.
|
||||||
pub use spirv_cross::hlsl::ShaderModel as HlslShaderModel;
|
pub use spirv_cross2::compile::hlsl::HlslShaderModel;
|
||||||
|
|
||||||
/// Buffer assignment information
|
/// Buffer assignment information
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -99,7 +99,7 @@ impl HlslBufferAssignments {
|
||||||
/// The context for a HLSL compilation via spirv-cross.
|
/// The context for a HLSL compilation via spirv-cross.
|
||||||
pub struct CrossHlslContext {
|
pub struct CrossHlslContext {
|
||||||
/// The compiled HLSL program.
|
/// The compiled HLSL program.
|
||||||
pub artifact: CompiledProgram<spirv_cross::hlsl::Target>,
|
pub artifact: CompiledProgram<spirv_cross2::targets::Hlsl>,
|
||||||
pub vertex_buffers: HlslBufferAssignments,
|
pub vertex_buffers: HlslBufferAssignments,
|
||||||
pub fragment_buffers: HlslBufferAssignments,
|
pub fragment_buffers: HlslBufferAssignments,
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ use crate::reflect::ReflectShader;
|
||||||
use naga::back::msl::TranslationInfo;
|
use naga::back::msl::TranslationInfo;
|
||||||
use naga::Module;
|
use naga::Module;
|
||||||
|
|
||||||
/// The HLSL shader model version to target.
|
/// The MSL language version to target.
|
||||||
pub use spirv_cross::msl::Version as MslVersion;
|
pub use spirv_cross2::compile::msl::MslVersion;
|
||||||
|
|
||||||
/// Compiler options for MSL
|
/// Compiler options for MSL
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
|
@ -22,7 +22,7 @@ pub struct MslNagaCompileOptions {
|
||||||
/// The context for a MSL compilation via spirv-cross.
|
/// The context for a MSL compilation via spirv-cross.
|
||||||
pub struct CrossMslContext {
|
pub struct CrossMslContext {
|
||||||
/// The compiled HLSL program.
|
/// The compiled HLSL program.
|
||||||
pub artifact: CompiledProgram<spirv_cross::msl::Target>,
|
pub artifact: CompiledProgram<spirv_cross2::targets::Msl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromCompilation<SpirvCompilation, SpirvCross> for MSL {
|
impl FromCompilation<SpirvCompilation, SpirvCross> for MSL {
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub enum ShaderCompileError {
|
||||||
|
|
||||||
/// Error when transpiling from spirv-cross.
|
/// Error when transpiling from spirv-cross.
|
||||||
#[error("spirv-cross error: {0:?}")]
|
#[error("spirv-cross error: {0:?}")]
|
||||||
SpirvCrossCompileError(#[from] spirv_cross::ErrorCode),
|
SpirvCrossCompileError(#[from] spirv_cross2::SpirvCrossError),
|
||||||
|
|
||||||
/// Error when transpiling from spirv-to-dxil
|
/// Error when transpiling from spirv-to-dxil
|
||||||
#[cfg(all(target_os = "windows", feature = "dxil"))]
|
#[cfg(all(target_os = "windows", feature = "dxil"))]
|
||||||
|
@ -87,7 +87,7 @@ pub enum SemanticsErrorKind {
|
||||||
pub enum ShaderReflectError {
|
pub enum ShaderReflectError {
|
||||||
/// Reflection error from spirv-cross.
|
/// Reflection error from spirv-cross.
|
||||||
#[error("spirv cross error: {0}")]
|
#[error("spirv cross error: {0}")]
|
||||||
SpirvCrossError(#[from] spirv_cross::ErrorCode),
|
SpirvCrossError(#[from] spirv_cross2::SpirvCrossError),
|
||||||
/// Error when validating vertex shader semantics.
|
/// Error when validating vertex shader semantics.
|
||||||
#[error("error when verifying vertex semantics: {0:?}")]
|
#[error("error when verifying vertex semantics: {0:?}")]
|
||||||
VertexSemanticError(SemanticsErrorKind),
|
VertexSemanticError(SemanticsErrorKind),
|
||||||
|
|
|
@ -2,136 +2,165 @@ use crate::back::glsl::CrossGlslContext;
|
||||||
use crate::back::targets::GLSL;
|
use crate::back::targets::GLSL;
|
||||||
use crate::back::{CompileShader, ShaderCompilerOutput};
|
use crate::back::{CompileShader, ShaderCompilerOutput};
|
||||||
use crate::error::ShaderCompileError;
|
use crate::error::ShaderCompileError;
|
||||||
use crate::reflect::cross::{CompiledAst, CompiledProgram, CrossReflect};
|
use crate::reflect::cross::{CompiledProgram, CrossReflect};
|
||||||
use spirv_cross::spirv::Decoration;
|
use spirv::Decoration;
|
||||||
use spirv_cross::ErrorCode;
|
|
||||||
|
|
||||||
pub(crate) type GlslReflect = CrossReflect<spirv_cross::glsl::Target>;
|
use spirv_cross2::compile::CompilableTarget;
|
||||||
|
use spirv_cross2::reflect::{DecorationValue, ResourceType};
|
||||||
|
use spirv_cross2::{targets, SpirvCrossError};
|
||||||
|
|
||||||
impl CompileShader<GLSL> for CrossReflect<spirv_cross::glsl::Target> {
|
pub(crate) type GlslReflect = CrossReflect<targets::Glsl>;
|
||||||
type Options = spirv_cross::glsl::Version;
|
|
||||||
|
impl CompileShader<GLSL> for CrossReflect<targets::Glsl> {
|
||||||
|
type Options = spirv_cross2::compile::glsl::GlslVersion;
|
||||||
type Context = CrossGlslContext;
|
type Context = CrossGlslContext;
|
||||||
|
|
||||||
fn compile(
|
fn compile(
|
||||||
mut self,
|
mut self,
|
||||||
version: Self::Options,
|
version: Self::Options,
|
||||||
) -> Result<ShaderCompilerOutput<String, Self::Context>, ShaderCompileError> {
|
) -> Result<ShaderCompilerOutput<String, Self::Context>, ShaderCompileError> {
|
||||||
let mut options: spirv_cross::glsl::CompilerOptions = Default::default();
|
let mut options = targets::Glsl::options();
|
||||||
|
|
||||||
options.version = version;
|
options.version = version;
|
||||||
options.fragment.default_float_precision = spirv_cross::glsl::Precision::High;
|
|
||||||
options.fragment.default_int_precision = spirv_cross::glsl::Precision::High;
|
|
||||||
options.enable_420_pack_extension = false;
|
|
||||||
|
|
||||||
self.vertex.set_compiler_options(&options)?;
|
options.es_default_float_precision_highp = true;
|
||||||
self.fragment.set_compiler_options(&options)?;
|
options.es_default_int_precision_highp = true;
|
||||||
|
options.enable_420pack_extension = false;
|
||||||
|
|
||||||
let vertex_resources = self.vertex.get_shader_resources()?;
|
let vertex_resources = self.vertex.shader_resources()?;
|
||||||
let fragment_resources = self.fragment.get_shader_resources()?;
|
let fragment_resources = self.fragment.shader_resources()?;
|
||||||
|
|
||||||
for res in &vertex_resources.stage_outputs {
|
for res in vertex_resources.resources_for_type(ResourceType::StageOutput)? {
|
||||||
// let location = self.vertex.get_decoration(res.id, Decoration::Location)?;
|
// let location = self.vertex.get_decoration(res.id, Decoration::Location)?;
|
||||||
// self.vertex
|
// self.vertex
|
||||||
// .set_name(res.id, &format!("LIBRA_VARYING_{location}"))?;
|
// .set_name(res.id, &format!("LIBRA_VARYING_{location}"))?;
|
||||||
self.vertex.unset_decoration(res.id, Decoration::Location)?;
|
self.vertex
|
||||||
|
.set_decoration(res.id, Decoration::Location, DecorationValue::unset())?;
|
||||||
}
|
}
|
||||||
for res in &fragment_resources.stage_inputs {
|
for res in fragment_resources.resources_for_type(ResourceType::StageInput)? {
|
||||||
// let location = self.fragment.get_decoration(res.id, Decoration::Location)?;
|
// let location = self.fragment.get_decoration(res.id, Decoration::Location)?;
|
||||||
// self.fragment
|
// self.fragment
|
||||||
// .set_name(res.id, &format!("LIBRA_VARYING_{location}"))?;
|
// .set_name(res.id, &format!("LIBRA_VARYING_{location}"))?;
|
||||||
self.fragment
|
self.fragment
|
||||||
.unset_decoration(res.id, Decoration::Location)?;
|
.set_decoration(res.id, Decoration::Location, DecorationValue::unset())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if vertex_resources.push_constant_buffers.len() > 1 {
|
let vertex_pcb = vertex_resources.resources_for_type(ResourceType::PushConstant)?;
|
||||||
|
if vertex_pcb.len() > 1 {
|
||||||
return Err(ShaderCompileError::SpirvCrossCompileError(
|
return Err(ShaderCompileError::SpirvCrossCompileError(
|
||||||
ErrorCode::CompilationError(String::from(
|
SpirvCrossError::InvalidArgument(String::from(
|
||||||
"Cannot have more than one push constant buffer",
|
"Cannot have more than one push constant buffer",
|
||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
for res in &vertex_resources.push_constant_buffers {
|
for res in vertex_pcb {
|
||||||
self.vertex.set_name(res.id, "LIBRA_PUSH_VERTEX_INSTANCE")?;
|
|
||||||
self.vertex
|
self.vertex
|
||||||
.set_name(res.base_type_id, "LIBRA_PUSH_VERTEX")?;
|
.set_name(res.id, c"LIBRA_PUSH_VERTEX_INSTANCE")?;
|
||||||
|
self.vertex
|
||||||
|
.set_name(res.base_type_id, c"LIBRA_PUSH_VERTEX")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: options
|
// todo: options
|
||||||
let _flatten = false;
|
let _flatten = false;
|
||||||
|
|
||||||
if vertex_resources.uniform_buffers.len() > 1 {
|
let vertex_ubo = vertex_resources.resources_for_type(ResourceType::UniformBuffer)?;
|
||||||
|
if vertex_ubo.len() > 1 {
|
||||||
return Err(ShaderCompileError::SpirvCrossCompileError(
|
return Err(ShaderCompileError::SpirvCrossCompileError(
|
||||||
ErrorCode::CompilationError(String::from(
|
SpirvCrossError::InvalidArgument(String::from(
|
||||||
"Cannot have more than one uniform buffer",
|
"Cannot have more than one uniform buffer",
|
||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
for res in &vertex_resources.uniform_buffers {
|
for res in vertex_ubo {
|
||||||
// if flatten {
|
// if flatten {
|
||||||
// self.vertex.flatten_buffer_block(res.id)?;
|
// self.vertex.flatten_buffer_block(res.id)?;
|
||||||
// }
|
// }
|
||||||
self.vertex.set_name(res.id, "LIBRA_UBO_VERTEX_INSTANCE")?;
|
self.vertex.set_name(res.id, c"LIBRA_UBO_VERTEX_INSTANCE")?;
|
||||||
self.vertex.set_name(res.base_type_id, "LIBRA_UBO_VERTEX")?;
|
|
||||||
self.vertex
|
self.vertex
|
||||||
.unset_decoration(res.id, Decoration::DescriptorSet)?;
|
.set_name(res.base_type_id, c"LIBRA_UBO_VERTEX")?;
|
||||||
self.vertex.unset_decoration(res.id, Decoration::Binding)?;
|
self.vertex.set_decoration(
|
||||||
|
res.id,
|
||||||
|
Decoration::DescriptorSet,
|
||||||
|
DecorationValue::unset(),
|
||||||
|
)?;
|
||||||
|
self.vertex
|
||||||
|
.set_decoration(res.id, Decoration::Binding, DecorationValue::unset())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if fragment_resources.push_constant_buffers.len() > 1 {
|
let fragment_pcb = fragment_resources.resources_for_type(ResourceType::PushConstant)?;
|
||||||
|
if fragment_pcb.len() > 1 {
|
||||||
return Err(ShaderCompileError::SpirvCrossCompileError(
|
return Err(ShaderCompileError::SpirvCrossCompileError(
|
||||||
ErrorCode::CompilationError(String::from(
|
SpirvCrossError::InvalidArgument(String::from(
|
||||||
"Cannot have more than one push constant buffer",
|
"Cannot have more than one push constant buffer",
|
||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
for res in &fragment_resources.push_constant_buffers {
|
|
||||||
|
for res in fragment_pcb {
|
||||||
self.fragment
|
self.fragment
|
||||||
.set_name(res.id, "LIBRA_PUSH_FRAGMENT_INSTANCE")?;
|
.set_name(res.id, c"LIBRA_PUSH_FRAGMENT_INSTANCE")?;
|
||||||
self.fragment
|
self.fragment
|
||||||
.set_name(res.base_type_id, "LIBRA_PUSH_FRAGMENT")?;
|
.set_name(res.base_type_id, c"LIBRA_PUSH_FRAGMENT")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if fragment_resources.uniform_buffers.len() > 1 {
|
let fragment_ubo = fragment_resources.resources_for_type(ResourceType::UniformBuffer)?;
|
||||||
|
if fragment_ubo.len() > 1 {
|
||||||
return Err(ShaderCompileError::SpirvCrossCompileError(
|
return Err(ShaderCompileError::SpirvCrossCompileError(
|
||||||
ErrorCode::CompilationError(String::from(
|
SpirvCrossError::InvalidArgument(String::from(
|
||||||
"Cannot have more than one uniform buffer",
|
"Cannot have more than one uniform buffer",
|
||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
for res in &fragment_resources.uniform_buffers {
|
for res in fragment_ubo {
|
||||||
// if flatten {
|
// if flatten {
|
||||||
// self.fragment.flatten_buffer_block(res.id)?;
|
// self.fragment.flatten_buffer_block(res.id)?;
|
||||||
// }
|
// }
|
||||||
self.fragment
|
self.fragment
|
||||||
.set_name(res.id, "LIBRA_UBO_FRAGMENT_INSTANCE")?;
|
.set_name(res.id, c"LIBRA_UBO_FRAGMENT_INSTANCE")?;
|
||||||
self.fragment
|
self.fragment
|
||||||
.set_name(res.base_type_id, "LIBRA_UBO_FRAGMENT")?;
|
.set_name(res.base_type_id, c"LIBRA_UBO_FRAGMENT")?;
|
||||||
|
self.fragment.set_decoration(
|
||||||
|
res.id,
|
||||||
|
Decoration::DescriptorSet,
|
||||||
|
DecorationValue::unset(),
|
||||||
|
)?;
|
||||||
self.fragment
|
self.fragment
|
||||||
.unset_decoration(res.id, Decoration::DescriptorSet)?;
|
.set_decoration(res.id, Decoration::Binding, DecorationValue::unset())?;
|
||||||
self.fragment
|
|
||||||
.unset_decoration(res.id, Decoration::Binding)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut texture_fixups = Vec::new();
|
let mut texture_fixups = Vec::new();
|
||||||
for res in fragment_resources.sampled_images {
|
|
||||||
let binding = self.fragment.get_decoration(res.id, Decoration::Binding)?;
|
for res in fragment_resources.resources_for_type(ResourceType::SampledImage)? {
|
||||||
|
let Some(DecorationValue::Literal(binding)) =
|
||||||
|
self.fragment.decoration(res.id, Decoration::Binding)?
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.fragment.set_decoration(
|
||||||
|
res.id,
|
||||||
|
Decoration::DescriptorSet,
|
||||||
|
DecorationValue::unset(),
|
||||||
|
)?;
|
||||||
self.fragment
|
self.fragment
|
||||||
.unset_decoration(res.id, Decoration::DescriptorSet)?;
|
.set_decoration(res.id, Decoration::Binding, DecorationValue::unset())?;
|
||||||
self.fragment
|
let mut name = res.name.to_string();
|
||||||
.unset_decoration(res.id, Decoration::Binding)?;
|
|
||||||
let mut name = res.name;
|
|
||||||
name.push('\0');
|
name.push('\0');
|
||||||
texture_fixups.push((name, binding));
|
texture_fixups.push((name, binding));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let vertex_compiled = self.vertex.compile(&options)?;
|
||||||
|
let fragment_compiled = self.fragment.compile(&options)?;
|
||||||
|
|
||||||
Ok(ShaderCompilerOutput {
|
Ok(ShaderCompilerOutput {
|
||||||
vertex: self.vertex.compile()?,
|
vertex: vertex_compiled.to_string(),
|
||||||
fragment: self.fragment.compile()?,
|
fragment: fragment_compiled.to_string(),
|
||||||
context: CrossGlslContext {
|
context: CrossGlslContext {
|
||||||
sampler_bindings: texture_fixups,
|
sampler_bindings: texture_fixups,
|
||||||
artifact: CompiledProgram {
|
artifact: CompiledProgram {
|
||||||
vertex: CompiledAst(self.vertex),
|
vertex: vertex_compiled,
|
||||||
fragment: CompiledAst(self.fragment),
|
fragment: fragment_compiled,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,14 +2,17 @@ use crate::back::hlsl::{CrossHlslContext, HlslBufferAssignment, HlslBufferAssign
|
||||||
use crate::back::targets::HLSL;
|
use crate::back::targets::HLSL;
|
||||||
use crate::back::{CompileShader, ShaderCompilerOutput};
|
use crate::back::{CompileShader, ShaderCompilerOutput};
|
||||||
use crate::error::ShaderCompileError;
|
use crate::error::ShaderCompileError;
|
||||||
use crate::reflect::cross::{CompiledAst, CompiledProgram, CrossReflect};
|
use crate::reflect::cross::{CompiledProgram, CrossReflect};
|
||||||
use spirv_cross::hlsl::ShaderModel as HlslShaderModel;
|
use spirv::Decoration;
|
||||||
use spirv_cross::spirv::Decoration;
|
|
||||||
use spirv_cross::ErrorCode;
|
|
||||||
|
|
||||||
pub(crate) type HlslReflect = CrossReflect<spirv_cross::hlsl::Target>;
|
use spirv_cross2::compile::hlsl::HlslShaderModel;
|
||||||
|
use spirv_cross2::compile::CompilableTarget;
|
||||||
|
use spirv_cross2::reflect::{DecorationValue, ResourceType};
|
||||||
|
use spirv_cross2::{targets, SpirvCrossError};
|
||||||
|
|
||||||
impl CompileShader<HLSL> for CrossReflect<spirv_cross::hlsl::Target> {
|
pub(crate) type HlslReflect = CrossReflect<targets::Hlsl>;
|
||||||
|
|
||||||
|
impl CompileShader<HLSL> for CrossReflect<targets::Hlsl> {
|
||||||
type Options = Option<HlslShaderModel>;
|
type Options = Option<HlslShaderModel>;
|
||||||
type Context = CrossHlslContext;
|
type Context = CrossHlslContext;
|
||||||
|
|
||||||
|
@ -17,98 +20,107 @@ impl CompileShader<HLSL> for CrossReflect<spirv_cross::hlsl::Target> {
|
||||||
mut self,
|
mut self,
|
||||||
options: Self::Options,
|
options: Self::Options,
|
||||||
) -> Result<ShaderCompilerOutput<String, CrossHlslContext>, ShaderCompileError> {
|
) -> Result<ShaderCompilerOutput<String, CrossHlslContext>, ShaderCompileError> {
|
||||||
let sm = options.unwrap_or(HlslShaderModel::V5_0);
|
let sm = options.unwrap_or(HlslShaderModel::ShaderModel5_0);
|
||||||
let mut options = spirv_cross::hlsl::CompilerOptions::default();
|
|
||||||
options.shader_model = sm;
|
|
||||||
|
|
||||||
self.vertex.set_compiler_options(&options)?;
|
let mut options = targets::Hlsl::options();
|
||||||
self.fragment.set_compiler_options(&options)?;
|
options.shader_model = sm;
|
||||||
|
|
||||||
// todo: options
|
// todo: options
|
||||||
|
|
||||||
let vertex_resources = self.vertex.get_shader_resources()?;
|
let vertex_resources = self.vertex.shader_resources()?;
|
||||||
let fragment_resources = self.fragment.get_shader_resources()?;
|
let fragment_resources = self.fragment.shader_resources()?;
|
||||||
|
|
||||||
let mut vertex_buffer_assignment = HlslBufferAssignments::default();
|
let mut vertex_buffer_assignment = HlslBufferAssignments::default();
|
||||||
let mut fragment_buffer_assignment = HlslBufferAssignments::default();
|
let mut fragment_buffer_assignment = HlslBufferAssignments::default();
|
||||||
|
|
||||||
if vertex_resources.uniform_buffers.len() > 1 {
|
let mut vertex_ubo = vertex_resources.resources_for_type(ResourceType::UniformBuffer)?;
|
||||||
|
if vertex_ubo.len() > 1 {
|
||||||
return Err(ShaderCompileError::SpirvCrossCompileError(
|
return Err(ShaderCompileError::SpirvCrossCompileError(
|
||||||
ErrorCode::CompilationError(String::from(
|
SpirvCrossError::InvalidArgument(String::from(
|
||||||
"Cannot have more than one uniform buffer",
|
"Cannot have more than one uniform buffer",
|
||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(buf) = vertex_resources.uniform_buffers.first() {
|
if let Some(buf) = vertex_ubo.next() {
|
||||||
vertex_buffer_assignment.ubo = Some(HlslBufferAssignment {
|
vertex_buffer_assignment.ubo = Some(HlslBufferAssignment {
|
||||||
name: buf.name.clone(),
|
name: buf.name.to_string(),
|
||||||
id: buf.id,
|
id: buf.id.id(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if vertex_resources.push_constant_buffers.len() > 1 {
|
let mut vertex_pcb = vertex_resources.resources_for_type(ResourceType::PushConstant)?;
|
||||||
|
if vertex_pcb.len() > 1 {
|
||||||
return Err(ShaderCompileError::SpirvCrossCompileError(
|
return Err(ShaderCompileError::SpirvCrossCompileError(
|
||||||
ErrorCode::CompilationError(String::from(
|
SpirvCrossError::InvalidArgument(String::from(
|
||||||
"Cannot have more than one push constant buffer",
|
"Cannot have more than one push constant buffer",
|
||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
if let Some(buf) = vertex_pcb.next() {
|
||||||
if let Some(buf) = vertex_resources.push_constant_buffers.first() {
|
|
||||||
vertex_buffer_assignment.push = Some(HlslBufferAssignment {
|
vertex_buffer_assignment.push = Some(HlslBufferAssignment {
|
||||||
name: buf.name.clone(),
|
name: buf.name.to_string(),
|
||||||
id: buf.id,
|
id: buf.id.id(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if fragment_resources.uniform_buffers.len() > 1 {
|
let mut fragment_ubo =
|
||||||
|
fragment_resources.resources_for_type(ResourceType::UniformBuffer)?;
|
||||||
|
if fragment_ubo.len() > 1 {
|
||||||
return Err(ShaderCompileError::SpirvCrossCompileError(
|
return Err(ShaderCompileError::SpirvCrossCompileError(
|
||||||
ErrorCode::CompilationError(String::from(
|
SpirvCrossError::InvalidArgument(String::from(
|
||||||
"Cannot have more than one uniform buffer",
|
"Cannot have more than one uniform buffer",
|
||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(buf) = fragment_resources.uniform_buffers.first() {
|
if let Some(buf) = fragment_ubo.next() {
|
||||||
fragment_buffer_assignment.ubo = Some(HlslBufferAssignment {
|
fragment_buffer_assignment.ubo = Some(HlslBufferAssignment {
|
||||||
name: buf.name.clone(),
|
name: buf.name.to_string(),
|
||||||
id: buf.id,
|
id: buf.id.id(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if fragment_resources.push_constant_buffers.len() > 1 {
|
let mut fragment_pcb = fragment_resources.resources_for_type(ResourceType::PushConstant)?;
|
||||||
|
if fragment_pcb.len() > 1 {
|
||||||
return Err(ShaderCompileError::SpirvCrossCompileError(
|
return Err(ShaderCompileError::SpirvCrossCompileError(
|
||||||
ErrorCode::CompilationError(String::from(
|
SpirvCrossError::InvalidArgument(String::from(
|
||||||
"Cannot have more than one push constant buffer",
|
"Cannot have more than one push constant buffer",
|
||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(buf) = fragment_resources.push_constant_buffers.first() {
|
if let Some(buf) = fragment_pcb.next() {
|
||||||
fragment_buffer_assignment.push = Some(HlslBufferAssignment {
|
fragment_buffer_assignment.push = Some(HlslBufferAssignment {
|
||||||
name: buf.name.clone(),
|
name: buf.name.to_string(),
|
||||||
id: buf.id,
|
id: buf.id.id(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if sm == HlslShaderModel::V3_0 {
|
if sm == HlslShaderModel::ShaderModel3_0 {
|
||||||
for res in &fragment_resources.sampled_images {
|
for res in fragment_resources.resources_for_type(ResourceType::SampledImage)? {
|
||||||
let binding = self.fragment.get_decoration(res.id, Decoration::Binding)?;
|
let Some(DecorationValue::Literal(binding)) =
|
||||||
|
self.fragment.decoration(res.id, Decoration::Binding)?
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
self.fragment
|
self.fragment
|
||||||
.set_name(res.id, &format!("LIBRA_SAMPLER2D_{binding}"))?;
|
.set_name(res.id, format!("LIBRA_SAMPLER2D_{binding}"))?;
|
||||||
// self.fragment
|
// self.fragment
|
||||||
// .unset_decoration(res.id, Decoration::Binding)?;
|
// .unset_decoration(res.id, Decoration::Binding)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let vertex_compiled = self.vertex.compile(&options)?;
|
||||||
|
let fragment_compiled = self.fragment.compile(&options)?;
|
||||||
|
|
||||||
Ok(ShaderCompilerOutput {
|
Ok(ShaderCompilerOutput {
|
||||||
vertex: self.vertex.compile()?,
|
vertex: vertex_compiled.to_string(),
|
||||||
fragment: self.fragment.compile()?,
|
fragment: fragment_compiled.to_string(),
|
||||||
context: CrossHlslContext {
|
context: CrossHlslContext {
|
||||||
artifact: CompiledProgram {
|
artifact: CompiledProgram {
|
||||||
vertex: CompiledAst(self.vertex),
|
vertex: vertex_compiled,
|
||||||
fragment: CompiledAst(self.fragment),
|
fragment: fragment_compiled,
|
||||||
},
|
},
|
||||||
|
|
||||||
vertex_buffers: vertex_buffer_assignment,
|
vertex_buffers: vertex_buffer_assignment,
|
||||||
|
|
|
@ -9,6 +9,7 @@ pub mod msl;
|
||||||
|
|
||||||
use crate::error::{SemanticsErrorKind, ShaderReflectError};
|
use crate::error::{SemanticsErrorKind, ShaderReflectError};
|
||||||
use crate::front::SpirvCompilation;
|
use crate::front::SpirvCompilation;
|
||||||
|
use crate::reflect::helper::{SemanticErrorBlame, TextureData, UboData};
|
||||||
use crate::reflect::semantics::{
|
use crate::reflect::semantics::{
|
||||||
BindingMeta, BindingStage, BufferReflection, MemberOffset, ShaderReflection, ShaderSemantics,
|
BindingMeta, BindingStage, BufferReflection, MemberOffset, ShaderReflection, ShaderSemantics,
|
||||||
TextureBinding, TextureSemanticMap, TextureSemantics, TextureSizeMeta, TypeInfo,
|
TextureBinding, TextureSemanticMap, TextureSemantics, TextureSizeMeta, TypeInfo,
|
||||||
|
@ -16,13 +17,15 @@ use crate::reflect::semantics::{
|
||||||
MAX_BINDINGS_COUNT, MAX_PUSH_BUFFER_SIZE,
|
MAX_BINDINGS_COUNT, MAX_PUSH_BUFFER_SIZE,
|
||||||
};
|
};
|
||||||
use crate::reflect::{align_uniform_size, ReflectShader};
|
use crate::reflect::{align_uniform_size, ReflectShader};
|
||||||
use std::fmt::Debug;
|
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
use crate::reflect::helper::{SemanticErrorBlame, TextureData, UboData};
|
|
||||||
use librashader_common::map::ShortString;
|
use librashader_common::map::ShortString;
|
||||||
use spirv_cross::spirv::{Ast, Decoration, Module, Resource, ShaderResources, Type};
|
use spirv_cross2::compile::CompiledArtifact;
|
||||||
use spirv_cross::ErrorCode;
|
use spirv_cross2::reflect::{
|
||||||
|
AllResources, BitWidth, DecorationValue, Resource, Scalar, ScalarKind, TypeInner,
|
||||||
|
};
|
||||||
|
use spirv_cross2::spirv::Decoration;
|
||||||
|
use spirv_cross2::Compiler;
|
||||||
|
use spirv_cross2::Module;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
/// Reflect shaders under SPIRV-Cross semantics.
|
/// Reflect shaders under SPIRV-Cross semantics.
|
||||||
///
|
///
|
||||||
|
@ -30,135 +33,115 @@ use spirv_cross::ErrorCode;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SpirvCross;
|
pub struct SpirvCross;
|
||||||
|
|
||||||
// This is "probably" OK.
|
// todo: make this under a mutex
|
||||||
unsafe impl<T: Send + spirv_cross::spirv::Target> Send for CrossReflect<T>
|
|
||||||
where
|
|
||||||
Ast<T>: spirv_cross::spirv::Compile<T>,
|
|
||||||
Ast<T>: spirv_cross::spirv::Parse<T>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct CrossReflect<T>
|
pub(crate) struct CrossReflect<T>
|
||||||
where
|
where
|
||||||
T: spirv_cross::spirv::Target,
|
T: spirv_cross2::compile::CompilableTarget,
|
||||||
Ast<T>: spirv_cross::spirv::Compile<T>,
|
|
||||||
Ast<T>: spirv_cross::spirv::Parse<T>,
|
|
||||||
{
|
{
|
||||||
vertex: Ast<T>,
|
vertex: Compiler<T>,
|
||||||
fragment: Ast<T>,
|
fragment: Compiler<T>,
|
||||||
}
|
|
||||||
|
|
||||||
///The output of the SPIR-V AST after compilation.
|
|
||||||
///
|
|
||||||
/// This output is immutable and can not be recompiled later.
|
|
||||||
pub struct CompiledAst<T: spirv_cross::spirv::Target>(Ast<T>);
|
|
||||||
impl<T: spirv_cross::spirv::Target> Deref for CompiledAst<T> {
|
|
||||||
type Target = Ast<T>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The compiled SPIR-V program after compilation.
|
/// The compiled SPIR-V program after compilation.
|
||||||
pub struct CompiledProgram<T>
|
pub struct CompiledProgram<T>
|
||||||
where
|
where
|
||||||
T: spirv_cross::spirv::Target,
|
T: spirv_cross2::compile::CompilableTarget,
|
||||||
{
|
{
|
||||||
pub vertex: CompiledAst<T>,
|
pub vertex: CompiledArtifact<T>,
|
||||||
pub fragment: CompiledAst<T>,
|
pub fragment: CompiledArtifact<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidateTypeSemantics<Type> for UniqueSemantics {
|
impl ValidateTypeSemantics<TypeInner<'_>> for UniqueSemantics {
|
||||||
fn validate_type(&self, ty: &Type) -> Option<TypeInfo> {
|
fn validate_type(&self, ty: &TypeInner) -> Option<TypeInfo> {
|
||||||
let (Type::Float {
|
let (TypeInner::Vector { .. } | TypeInner::Scalar { .. } | TypeInner::Matrix { .. }) = *ty
|
||||||
ref array,
|
|
||||||
vecsize,
|
|
||||||
columns,
|
|
||||||
..
|
|
||||||
}
|
|
||||||
| Type::Int {
|
|
||||||
ref array,
|
|
||||||
vecsize,
|
|
||||||
columns,
|
|
||||||
..
|
|
||||||
}
|
|
||||||
| Type::UInt {
|
|
||||||
ref array,
|
|
||||||
vecsize,
|
|
||||||
columns,
|
|
||||||
..
|
|
||||||
}) = *ty
|
|
||||||
else {
|
else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !array.is_empty() {
|
match self {
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let valid = match self {
|
|
||||||
UniqueSemantics::MVP => {
|
UniqueSemantics::MVP => {
|
||||||
matches!(ty, Type::Float { .. }) && vecsize == 4 && columns == 4
|
if matches!(ty, TypeInner::Matrix { columns, rows, scalar: Scalar { size, .. } } if *columns == 4
|
||||||
|
&& *rows == 4 && *size == BitWidth::Word)
|
||||||
|
{
|
||||||
|
return Some(TypeInfo {
|
||||||
|
size: 4,
|
||||||
|
columns: 4,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UniqueSemantics::FrameCount
|
UniqueSemantics::FrameCount
|
||||||
| UniqueSemantics::Rotation
|
| UniqueSemantics::Rotation
|
||||||
| UniqueSemantics::TotalSubFrames
|
| UniqueSemantics::CurrentSubFrame
|
||||||
| UniqueSemantics::CurrentSubFrame => {
|
| UniqueSemantics::TotalSubFrames => {
|
||||||
matches!(ty, Type::UInt { .. }) && vecsize == 1 && columns == 1
|
// Uint32 == width 4
|
||||||
|
if matches!(ty, TypeInner::Scalar( Scalar { kind, size }) if *kind == ScalarKind::Uint && *size == BitWidth::Word)
|
||||||
|
{
|
||||||
|
return Some(TypeInfo {
|
||||||
|
size: 1,
|
||||||
|
columns: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UniqueSemantics::FrameDirection => {
|
UniqueSemantics::FrameDirection => {
|
||||||
matches!(ty, Type::Int { .. }) && vecsize == 1 && columns == 1
|
// iint32 == width 4
|
||||||
|
if matches!(ty, TypeInner::Scalar( Scalar { kind, size }) if *kind == ScalarKind::Int && *size == BitWidth::Word)
|
||||||
|
{
|
||||||
|
return Some(TypeInfo {
|
||||||
|
size: 1,
|
||||||
|
columns: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UniqueSemantics::FloatParameter => {
|
UniqueSemantics::FloatParameter => {
|
||||||
matches!(ty, Type::Float { .. }) && vecsize == 1 && columns == 1
|
// Float32 == width 4
|
||||||
|
if matches!(ty, TypeInner::Scalar( Scalar { kind, size }) if *kind == ScalarKind::Float && *size == BitWidth::Word)
|
||||||
|
{
|
||||||
|
return Some(TypeInfo {
|
||||||
|
size: 1,
|
||||||
|
columns: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if matches!(ty, TypeInner::Vector { scalar: Scalar { size, kind }, width: vecwidth, .. }
|
||||||
|
if *kind == ScalarKind::Float && *size == BitWidth::Word && *vecwidth == 4)
|
||||||
|
{
|
||||||
|
return Some(TypeInfo {
|
||||||
|
size: 4,
|
||||||
|
columns: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => matches!(ty, Type::Float { .. }) && vecsize == 4 && columns == 1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if valid {
|
None
|
||||||
Some(TypeInfo {
|
|
||||||
size: vecsize,
|
|
||||||
columns,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidateTypeSemantics<Type> for TextureSemantics {
|
impl ValidateTypeSemantics<TypeInner<'_>> for TextureSemantics {
|
||||||
fn validate_type(&self, ty: &Type) -> Option<TypeInfo> {
|
fn validate_type(&self, ty: &TypeInner) -> Option<TypeInfo> {
|
||||||
let Type::Float {
|
let TypeInner::Vector {
|
||||||
ref array,
|
scalar: Scalar { size, kind },
|
||||||
vecsize,
|
width: vecwidth,
|
||||||
columns,
|
} = ty
|
||||||
..
|
|
||||||
} = *ty
|
|
||||||
else {
|
else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !array.is_empty() {
|
if *kind == ScalarKind::Float && *size == BitWidth::Word && *vecwidth == 4 {
|
||||||
return None;
|
return Some(TypeInfo {
|
||||||
|
size: 4,
|
||||||
|
columns: 1,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if vecsize == 4 && columns == 1 {
|
None
|
||||||
Some(TypeInfo {
|
|
||||||
size: vecsize,
|
|
||||||
columns,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> TryFrom<&SpirvCompilation> for CrossReflect<T>
|
impl<T> TryFrom<&SpirvCompilation> for CrossReflect<T>
|
||||||
where
|
where
|
||||||
T: spirv_cross::spirv::Target,
|
T: spirv_cross2::compile::CompilableTarget,
|
||||||
Ast<T>: spirv_cross::spirv::Compile<T>,
|
|
||||||
Ast<T>: spirv_cross::spirv::Parse<T>,
|
|
||||||
{
|
{
|
||||||
type Error = ShaderReflectError;
|
type Error = ShaderReflectError;
|
||||||
|
|
||||||
|
@ -166,8 +149,8 @@ where
|
||||||
let vertex_module = Module::from_words(&value.vertex);
|
let vertex_module = Module::from_words(&value.vertex);
|
||||||
let fragment_module = Module::from_words(&value.fragment);
|
let fragment_module = Module::from_words(&value.fragment);
|
||||||
|
|
||||||
let vertex = Ast::parse(&vertex_module)?;
|
let vertex = Compiler::new(vertex_module)?;
|
||||||
let fragment = Ast::parse(&fragment_module)?;
|
let fragment = Compiler::new(fragment_module)?;
|
||||||
|
|
||||||
Ok(CrossReflect { vertex, fragment })
|
Ok(CrossReflect { vertex, fragment })
|
||||||
}
|
}
|
||||||
|
@ -175,14 +158,12 @@ where
|
||||||
|
|
||||||
impl<T> CrossReflect<T>
|
impl<T> CrossReflect<T>
|
||||||
where
|
where
|
||||||
T: spirv_cross::spirv::Target,
|
T: spirv_cross2::compile::CompilableTarget,
|
||||||
Ast<T>: spirv_cross::spirv::Compile<T>,
|
|
||||||
Ast<T>: spirv_cross::spirv::Parse<T>,
|
|
||||||
{
|
{
|
||||||
fn validate(
|
fn validate(
|
||||||
&self,
|
&self,
|
||||||
vertex_res: &ShaderResources,
|
vertex_res: &AllResources,
|
||||||
fragment_res: &ShaderResources,
|
fragment_res: &AllResources,
|
||||||
) -> Result<(), ShaderReflectError> {
|
) -> Result<(), ShaderReflectError> {
|
||||||
if !vertex_res.sampled_images.is_empty()
|
if !vertex_res.sampled_images.is_empty()
|
||||||
|| !vertex_res.storage_buffers.is_empty()
|
|| !vertex_res.storage_buffers.is_empty()
|
||||||
|
@ -219,9 +200,15 @@ where
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let fragment_location = self
|
let Some(DecorationValue::Literal(fragment_location)) = self
|
||||||
.fragment
|
.fragment
|
||||||
.get_decoration(fragment_res.stage_outputs[0].id, Decoration::Location)?;
|
.decoration(fragment_res.stage_outputs[0].id, Decoration::Location)?
|
||||||
|
else {
|
||||||
|
return Err(ShaderReflectError::FragmentSemanticError(
|
||||||
|
SemanticsErrorKind::MissingBinding,
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
if fragment_location != 0 {
|
if fragment_location != 0 {
|
||||||
return Err(ShaderReflectError::FragmentSemanticError(
|
return Err(ShaderReflectError::FragmentSemanticError(
|
||||||
SemanticsErrorKind::InvalidLocation(fragment_location),
|
SemanticsErrorKind::InvalidLocation(fragment_location),
|
||||||
|
@ -229,15 +216,54 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that vertex attributes use location 0 and 1
|
// Ensure that vertex attributes use location 0 and 1
|
||||||
let vert_mask = vertex_res.stage_inputs.iter().try_fold(0, |mask, input| {
|
// Verify Vertex inputs
|
||||||
Ok::<u32, ErrorCode>(
|
'vertex: {
|
||||||
mask | 1 << self.vertex.get_decoration(input.id, Decoration::Location)?,
|
let entry_points = self.vertex.entry_points()?;
|
||||||
)
|
if entry_points.len() != 1 {
|
||||||
})?;
|
return Err(ShaderReflectError::VertexSemanticError(
|
||||||
if vert_mask != 0x3 {
|
SemanticsErrorKind::InvalidEntryPointCount(entry_points.len()),
|
||||||
return Err(ShaderReflectError::VertexSemanticError(
|
));
|
||||||
SemanticsErrorKind::InvalidLocation(vert_mask),
|
}
|
||||||
));
|
|
||||||
|
let vert_inputs = vertex_res.stage_inputs.len();
|
||||||
|
if vert_inputs != 2 {
|
||||||
|
return Err(ShaderReflectError::VertexSemanticError(
|
||||||
|
SemanticsErrorKind::InvalidInputCount(vert_inputs),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
for input in &vertex_res.stage_inputs {
|
||||||
|
let location = self.vertex.decoration(input.id, Decoration::Location)?;
|
||||||
|
let Some(DecorationValue::Literal(location)) = location else {
|
||||||
|
return Err(ShaderReflectError::VertexSemanticError(
|
||||||
|
SemanticsErrorKind::MissingBinding,
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
if location == 0 {
|
||||||
|
let pos_type = &self.vertex.type_description(input.base_type_id)?;
|
||||||
|
if !matches!(pos_type.inner, TypeInner::Vector { width, ..} if width == 4) {
|
||||||
|
return Err(ShaderReflectError::VertexSemanticError(
|
||||||
|
SemanticsErrorKind::InvalidLocation(location),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
break 'vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if location == 1 {
|
||||||
|
let coord_type = &self.vertex.type_description(input.base_type_id)?;
|
||||||
|
if !matches!(coord_type.inner, TypeInner::Vector { width, ..} if width == 2) {
|
||||||
|
return Err(ShaderReflectError::VertexSemanticError(
|
||||||
|
SemanticsErrorKind::InvalidLocation(location),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
break 'vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(ShaderReflectError::VertexSemanticError(
|
||||||
|
SemanticsErrorKind::InvalidLocation(location),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if vertex_res.uniform_buffers.len() > 1 {
|
if vertex_res.uniform_buffers.len() > 1 {
|
||||||
|
@ -271,17 +297,27 @@ where
|
||||||
|
|
||||||
impl<T> CrossReflect<T>
|
impl<T> CrossReflect<T>
|
||||||
where
|
where
|
||||||
T: spirv_cross::spirv::Target,
|
T: spirv_cross2::compile::CompilableTarget,
|
||||||
Ast<T>: spirv_cross::spirv::Compile<T>,
|
|
||||||
Ast<T>: spirv_cross::spirv::Parse<T>,
|
|
||||||
{
|
{
|
||||||
fn get_ubo_data(
|
fn get_ubo_data(
|
||||||
ast: &Ast<T>,
|
ast: &Compiler<T>,
|
||||||
ubo: &Resource,
|
ubo: &Resource,
|
||||||
blame: SemanticErrorBlame,
|
blame: SemanticErrorBlame,
|
||||||
) -> Result<UboData, ShaderReflectError> {
|
) -> Result<UboData, ShaderReflectError> {
|
||||||
let descriptor_set = ast.get_decoration(ubo.id, Decoration::DescriptorSet)?;
|
let Some(descriptor_set) = ast
|
||||||
let binding = ast.get_decoration(ubo.id, Decoration::Binding)?;
|
.decoration(ubo.id, Decoration::DescriptorSet)?
|
||||||
|
.and_then(|l| l.as_literal())
|
||||||
|
else {
|
||||||
|
return Err(blame.error(SemanticsErrorKind::MissingBinding));
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(binding) = ast
|
||||||
|
.decoration(ubo.id, Decoration::Binding)?
|
||||||
|
.and_then(|l| l.as_literal())
|
||||||
|
else {
|
||||||
|
return Err(blame.error(SemanticsErrorKind::MissingBinding));
|
||||||
|
};
|
||||||
|
|
||||||
if binding >= MAX_BINDINGS_COUNT {
|
if binding >= MAX_BINDINGS_COUNT {
|
||||||
return Err(blame.error(SemanticsErrorKind::InvalidBinding(binding)));
|
return Err(blame.error(SemanticsErrorKind::InvalidBinding(binding)));
|
||||||
}
|
}
|
||||||
|
@ -289,21 +325,19 @@ where
|
||||||
return Err(blame.error(SemanticsErrorKind::InvalidDescriptorSet(descriptor_set)));
|
return Err(blame.error(SemanticsErrorKind::InvalidDescriptorSet(descriptor_set)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let size = ast.get_declared_struct_size(ubo.base_type_id)?;
|
let size = ast.type_description(ubo.base_type_id)?.size_hint.declared() as u32;
|
||||||
Ok(UboData {
|
Ok(UboData { binding, size })
|
||||||
// descriptor_set,
|
|
||||||
// id: ubo.id,
|
|
||||||
binding,
|
|
||||||
size,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_push_size(
|
fn get_push_size(
|
||||||
ast: &Ast<T>,
|
ast: &Compiler<T>,
|
||||||
push: &Resource,
|
push: &Resource,
|
||||||
blame: SemanticErrorBlame,
|
blame: SemanticErrorBlame,
|
||||||
) -> Result<u32, ShaderReflectError> {
|
) -> Result<u32, ShaderReflectError> {
|
||||||
let size = ast.get_declared_struct_size(push.base_type_id)?;
|
let size = ast
|
||||||
|
.type_description(push.base_type_id)?
|
||||||
|
.size_hint
|
||||||
|
.declared() as u32;
|
||||||
if size > MAX_PUSH_BUFFER_SIZE {
|
if size > MAX_PUSH_BUFFER_SIZE {
|
||||||
return Err(blame.error(SemanticsErrorKind::InvalidPushBufferSize(size)));
|
return Err(blame.error(SemanticsErrorKind::InvalidPushBufferSize(size)));
|
||||||
}
|
}
|
||||||
|
@ -311,7 +345,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reflect_buffer_range_metas(
|
fn reflect_buffer_range_metas(
|
||||||
ast: &Ast<T>,
|
ast: &Compiler<T>,
|
||||||
resource: &Resource,
|
resource: &Resource,
|
||||||
pass_number: usize,
|
pass_number: usize,
|
||||||
semantics: &ShaderSemantics,
|
semantics: &ShaderSemantics,
|
||||||
|
@ -319,24 +353,30 @@ where
|
||||||
offset_type: UniformMemberBlock,
|
offset_type: UniformMemberBlock,
|
||||||
blame: SemanticErrorBlame,
|
blame: SemanticErrorBlame,
|
||||||
) -> Result<(), ShaderReflectError> {
|
) -> Result<(), ShaderReflectError> {
|
||||||
let ranges = ast.get_active_buffer_ranges(resource.id)?;
|
let ranges = ast.active_buffer_ranges(resource.id)?;
|
||||||
for range in ranges {
|
for range in ranges {
|
||||||
let name = ast.get_member_name(resource.base_type_id, range.index)?;
|
let Some(name) = ast.member_name(resource.base_type_id, range.index)? else {
|
||||||
let ubo_type = ast.get_type(resource.base_type_id)?;
|
// member has no name!
|
||||||
let range_type = match ubo_type {
|
return Err(blame.error(SemanticsErrorKind::InvalidRange(range.index)));
|
||||||
Type::Struct { member_types, .. } => {
|
};
|
||||||
let range_type = member_types
|
|
||||||
|
let ubo_type = ast.type_description(resource.base_type_id)?;
|
||||||
|
let range_type = match ubo_type.inner {
|
||||||
|
TypeInner::Struct(struct_def) => {
|
||||||
|
let range_type = struct_def
|
||||||
|
.members
|
||||||
.get(range.index as usize)
|
.get(range.index as usize)
|
||||||
.cloned()
|
|
||||||
.ok_or(blame.error(SemanticsErrorKind::InvalidRange(range.index)))?;
|
.ok_or(blame.error(SemanticsErrorKind::InvalidRange(range.index)))?;
|
||||||
ast.get_type(range_type)?
|
ast.type_description(range_type.id)?
|
||||||
}
|
}
|
||||||
_ => return Err(blame.error(SemanticsErrorKind::InvalidResourceType)),
|
_ => return Err(blame.error(SemanticsErrorKind::InvalidResourceType)),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(parameter) = semantics.uniform_semantics.get_unique_semantic(&name) {
|
if let Some(parameter) = semantics.uniform_semantics.unique_semantic(&name) {
|
||||||
let Some(typeinfo) = parameter.semantics.validate_type(&range_type) else {
|
let Some(typeinfo) = parameter.semantics.validate_type(&range_type.inner) else {
|
||||||
return Err(blame.error(SemanticsErrorKind::InvalidTypeForSemantic(name)));
|
return Err(
|
||||||
|
blame.error(SemanticsErrorKind::InvalidTypeForSemantic(name.to_string()))
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
match ¶meter.semantics {
|
match ¶meter.semantics {
|
||||||
|
@ -347,7 +387,7 @@ where
|
||||||
&& expected != offset
|
&& expected != offset
|
||||||
{
|
{
|
||||||
return Err(ShaderReflectError::MismatchedOffset {
|
return Err(ShaderReflectError::MismatchedOffset {
|
||||||
semantic: name,
|
semantic: name.to_string(),
|
||||||
expected,
|
expected,
|
||||||
received: offset,
|
received: offset,
|
||||||
ty: offset_type,
|
ty: offset_type,
|
||||||
|
@ -356,7 +396,7 @@ where
|
||||||
}
|
}
|
||||||
if meta.size != typeinfo.size {
|
if meta.size != typeinfo.size {
|
||||||
return Err(ShaderReflectError::MismatchedSize {
|
return Err(ShaderReflectError::MismatchedSize {
|
||||||
semantic: name,
|
semantic: name.to_string(),
|
||||||
vertex: meta.size,
|
vertex: meta.size,
|
||||||
fragment: typeinfo.size,
|
fragment: typeinfo.size,
|
||||||
pass: pass_number,
|
pass: pass_number,
|
||||||
|
@ -365,7 +405,7 @@ where
|
||||||
|
|
||||||
*meta.offset.offset_mut(offset_type) = Some(offset);
|
*meta.offset.offset_mut(offset_type) = Some(offset);
|
||||||
} else {
|
} else {
|
||||||
let name = ShortString::from(name);
|
let name = ShortString::from(name.as_ref());
|
||||||
meta.parameter_meta.insert(
|
meta.parameter_meta.insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
VariableMeta {
|
VariableMeta {
|
||||||
|
@ -383,7 +423,7 @@ where
|
||||||
&& expected != offset
|
&& expected != offset
|
||||||
{
|
{
|
||||||
return Err(ShaderReflectError::MismatchedOffset {
|
return Err(ShaderReflectError::MismatchedOffset {
|
||||||
semantic: name,
|
semantic: name.to_string(),
|
||||||
expected,
|
expected,
|
||||||
received: offset,
|
received: offset,
|
||||||
ty: offset_type,
|
ty: offset_type,
|
||||||
|
@ -392,7 +432,7 @@ where
|
||||||
}
|
}
|
||||||
if meta.size != typeinfo.size * typeinfo.columns {
|
if meta.size != typeinfo.size * typeinfo.columns {
|
||||||
return Err(ShaderReflectError::MismatchedSize {
|
return Err(ShaderReflectError::MismatchedSize {
|
||||||
semantic: name,
|
semantic: name.to_string(),
|
||||||
vertex: meta.size,
|
vertex: meta.size,
|
||||||
fragment: typeinfo.size,
|
fragment: typeinfo.size,
|
||||||
pass: pass_number,
|
pass: pass_number,
|
||||||
|
@ -404,7 +444,7 @@ where
|
||||||
meta.unique_meta.insert(
|
meta.unique_meta.insert(
|
||||||
*semantics,
|
*semantics,
|
||||||
VariableMeta {
|
VariableMeta {
|
||||||
id: name.into(),
|
id: ShortString::from(name.as_ref()),
|
||||||
offset: MemberOffset::new(offset, offset_type),
|
offset: MemberOffset::new(offset, offset_type),
|
||||||
size: typeinfo.size * typeinfo.columns,
|
size: typeinfo.size * typeinfo.columns,
|
||||||
},
|
},
|
||||||
|
@ -412,9 +452,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(texture) = semantics.uniform_semantics.get_texture_semantic(&name) {
|
} else if let Some(texture) = semantics.uniform_semantics.texture_semantic(&name) {
|
||||||
let Some(_typeinfo) = texture.semantics.validate_type(&range_type) else {
|
let Some(_typeinfo) = texture.semantics.validate_type(&range_type.inner) else {
|
||||||
return Err(blame.error(SemanticsErrorKind::InvalidTypeForSemantic(name)));
|
return Err(
|
||||||
|
blame.error(SemanticsErrorKind::InvalidTypeForSemantic(name.to_string()))
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
if let TextureSemantics::PassOutput = texture.semantics {
|
if let TextureSemantics::PassOutput = texture.semantics {
|
||||||
|
@ -432,7 +474,7 @@ where
|
||||||
&& expected != offset
|
&& expected != offset
|
||||||
{
|
{
|
||||||
return Err(ShaderReflectError::MismatchedOffset {
|
return Err(ShaderReflectError::MismatchedOffset {
|
||||||
semantic: name,
|
semantic: name.to_string(),
|
||||||
expected,
|
expected,
|
||||||
received: offset,
|
received: offset,
|
||||||
ty: offset_type,
|
ty: offset_type,
|
||||||
|
@ -455,12 +497,12 @@ where
|
||||||
SemanticErrorBlame::Vertex => BindingStage::VERTEX,
|
SemanticErrorBlame::Vertex => BindingStage::VERTEX,
|
||||||
SemanticErrorBlame::Fragment => BindingStage::FRAGMENT,
|
SemanticErrorBlame::Fragment => BindingStage::FRAGMENT,
|
||||||
},
|
},
|
||||||
id: ShortString::from(name),
|
id: ShortString::from(name.as_ref()),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(blame.error(SemanticsErrorKind::UnknownSemantics(name)));
|
return Err(blame.error(SemanticsErrorKind::UnknownSemantics(name.to_string())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -473,12 +515,12 @@ where
|
||||||
) -> Result<Option<BufferReflection<u32>>, ShaderReflectError> {
|
) -> Result<Option<BufferReflection<u32>>, ShaderReflectError> {
|
||||||
if let Some(vertex_ubo) = vertex_ubo {
|
if let Some(vertex_ubo) = vertex_ubo {
|
||||||
self.vertex
|
self.vertex
|
||||||
.set_decoration(vertex_ubo.id, Decoration::Binding, 0)?;
|
.set_decoration(vertex_ubo.id, Decoration::Binding, Some(0))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(fragment_ubo) = fragment_ubo {
|
if let Some(fragment_ubo) = fragment_ubo {
|
||||||
self.fragment
|
self.fragment
|
||||||
.set_decoration(fragment_ubo.id, Decoration::Binding, 0)?;
|
.set_decoration(fragment_ubo.id, Decoration::Binding, Some(0))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
match (vertex_ubo, fragment_ubo) {
|
match (vertex_ubo, fragment_ubo) {
|
||||||
|
@ -530,10 +572,7 @@ where
|
||||||
semantics: &ShaderSemantics,
|
semantics: &ShaderSemantics,
|
||||||
meta: &mut BindingMeta,
|
meta: &mut BindingMeta,
|
||||||
) -> Result<(), ShaderReflectError> {
|
) -> Result<(), ShaderReflectError> {
|
||||||
let Some(semantic) = semantics
|
let Some(semantic) = semantics.texture_semantics.texture_semantic(texture.name) else {
|
||||||
.texture_semantics
|
|
||||||
.get_texture_semantic(texture.name)
|
|
||||||
else {
|
|
||||||
return Err(
|
return Err(
|
||||||
SemanticErrorBlame::Fragment.error(SemanticsErrorKind::UnknownSemantics(
|
SemanticErrorBlame::Fragment.error(SemanticsErrorKind::UnknownSemantics(
|
||||||
texture.name.to_string(),
|
texture.name.to_string(),
|
||||||
|
@ -561,12 +600,25 @@ where
|
||||||
&'a self,
|
&'a self,
|
||||||
texture: &'a Resource,
|
texture: &'a Resource,
|
||||||
) -> Result<TextureData<'a>, ShaderReflectError> {
|
) -> Result<TextureData<'a>, ShaderReflectError> {
|
||||||
let descriptor_set = self
|
let Some(descriptor_set) = self
|
||||||
.fragment
|
.fragment
|
||||||
.get_decoration(texture.id, Decoration::DescriptorSet)?;
|
.decoration(texture.id, Decoration::DescriptorSet)?
|
||||||
let binding = self
|
.and_then(|l| l.as_literal())
|
||||||
|
else {
|
||||||
|
return Err(ShaderReflectError::FragmentSemanticError(
|
||||||
|
SemanticsErrorKind::MissingBinding,
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let Some(binding) = self
|
||||||
.fragment
|
.fragment
|
||||||
.get_decoration(texture.id, Decoration::Binding)?;
|
.decoration(texture.id, Decoration::Binding)?
|
||||||
|
.and_then(|l| l.as_literal())
|
||||||
|
else {
|
||||||
|
return Err(ShaderReflectError::FragmentSemanticError(
|
||||||
|
SemanticsErrorKind::MissingBinding,
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
if descriptor_set != 0 {
|
if descriptor_set != 0 {
|
||||||
return Err(ShaderReflectError::FragmentSemanticError(
|
return Err(ShaderReflectError::FragmentSemanticError(
|
||||||
SemanticsErrorKind::InvalidDescriptorSet(descriptor_set),
|
SemanticsErrorKind::InvalidDescriptorSet(descriptor_set),
|
||||||
|
@ -593,12 +645,12 @@ where
|
||||||
) -> Result<Option<BufferReflection<Option<u32>>>, ShaderReflectError> {
|
) -> Result<Option<BufferReflection<Option<u32>>>, ShaderReflectError> {
|
||||||
if let Some(vertex_pcb) = vertex_pcb {
|
if let Some(vertex_pcb) = vertex_pcb {
|
||||||
self.vertex
|
self.vertex
|
||||||
.set_decoration(vertex_pcb.id, Decoration::Binding, 1)?;
|
.set_decoration(vertex_pcb.id, Decoration::Binding, Some(1))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(fragment_pcb) = fragment_pcb {
|
if let Some(fragment_pcb) = fragment_pcb {
|
||||||
self.fragment
|
self.fragment
|
||||||
.set_decoration(fragment_pcb.id, Decoration::Binding, 1)?;
|
.set_decoration(fragment_pcb.id, Decoration::Binding, Some(1))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
match (vertex_pcb, fragment_pcb) {
|
match (vertex_pcb, fragment_pcb) {
|
||||||
|
@ -647,17 +699,15 @@ where
|
||||||
|
|
||||||
impl<T> ReflectShader for CrossReflect<T>
|
impl<T> ReflectShader for CrossReflect<T>
|
||||||
where
|
where
|
||||||
T: spirv_cross::spirv::Target,
|
T: spirv_cross2::compile::CompilableTarget,
|
||||||
Ast<T>: spirv_cross::spirv::Compile<T>,
|
|
||||||
Ast<T>: spirv_cross::spirv::Parse<T>,
|
|
||||||
{
|
{
|
||||||
fn reflect(
|
fn reflect(
|
||||||
&mut self,
|
&mut self,
|
||||||
pass_number: usize,
|
pass_number: usize,
|
||||||
semantics: &ShaderSemantics,
|
semantics: &ShaderSemantics,
|
||||||
) -> Result<ShaderReflection, ShaderReflectError> {
|
) -> Result<ShaderReflection, ShaderReflectError> {
|
||||||
let vertex_res = self.vertex.get_shader_resources()?;
|
let vertex_res = self.vertex.shader_resources()?.all_resources()?;
|
||||||
let fragment_res = self.fragment.get_shader_resources()?;
|
let fragment_res = self.fragment.shader_resources()?.all_resources()?;
|
||||||
self.validate(&vertex_res, &fragment_res)?;
|
self.validate(&vertex_res, &fragment_res)?;
|
||||||
|
|
||||||
let vertex_ubo = vertex_res.uniform_buffers.first();
|
let vertex_ubo = vertex_res.uniform_buffers.first();
|
||||||
|
|
|
@ -2,99 +2,101 @@ use crate::back::msl::CrossMslContext;
|
||||||
use crate::back::targets::MSL;
|
use crate::back::targets::MSL;
|
||||||
use crate::back::{CompileShader, ShaderCompilerOutput};
|
use crate::back::{CompileShader, ShaderCompilerOutput};
|
||||||
use crate::error::ShaderCompileError;
|
use crate::error::ShaderCompileError;
|
||||||
use crate::reflect::cross::{CompiledAst, CompiledProgram, CrossReflect};
|
use crate::reflect::cross::{CompiledProgram, CrossReflect};
|
||||||
use spirv_cross::msl;
|
|
||||||
use spirv_cross::msl::{ResourceBinding, ResourceBindingLocation};
|
|
||||||
use spirv_cross::spirv::{Ast, Decoration, ExecutionModel};
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
pub(crate) type MslReflect = CrossReflect<spirv_cross::msl::Target>;
|
use spirv::Decoration;
|
||||||
|
use spirv_cross2::compile::msl::{BindTarget, ResourceBinding};
|
||||||
|
use spirv_cross2::compile::{msl, CompilableTarget};
|
||||||
|
use spirv_cross2::reflect::{DecorationValue, ResourceType};
|
||||||
|
use spirv_cross2::{targets, Compiler};
|
||||||
|
|
||||||
impl CompileShader<MSL> for CrossReflect<spirv_cross::msl::Target> {
|
pub(crate) type MslReflect = CrossReflect<targets::Msl>;
|
||||||
type Options = Option<spirv_cross::msl::Version>;
|
|
||||||
|
impl CompileShader<MSL> for CrossReflect<targets::Msl> {
|
||||||
|
type Options = Option<msl::MslVersion>;
|
||||||
type Context = CrossMslContext;
|
type Context = CrossMslContext;
|
||||||
|
|
||||||
fn compile(
|
fn compile(
|
||||||
mut self,
|
mut self,
|
||||||
options: Self::Options,
|
options: Self::Options,
|
||||||
) -> Result<ShaderCompilerOutput<String, CrossMslContext>, ShaderCompileError> {
|
) -> Result<ShaderCompilerOutput<String, CrossMslContext>, ShaderCompileError> {
|
||||||
let version = options.unwrap_or(msl::Version::V2_0);
|
let version = options.unwrap_or(msl::MslVersion::new(2, 0, 0));
|
||||||
let mut vert_options = spirv_cross::msl::CompilerOptions::default();
|
let mut options = targets::Msl::options();
|
||||||
let mut frag_options = spirv_cross::msl::CompilerOptions::default();
|
options.version = version;
|
||||||
|
|
||||||
vert_options.version = version;
|
|
||||||
frag_options.version = version;
|
|
||||||
|
|
||||||
fn set_bindings(
|
fn set_bindings(
|
||||||
ast: &Ast<msl::Target>,
|
ast: &mut Compiler<targets::Msl>,
|
||||||
stage: ExecutionModel,
|
stage: spirv::ExecutionModel,
|
||||||
binding_map: &mut BTreeMap<ResourceBindingLocation, ResourceBinding>,
|
|
||||||
) -> Result<(), ShaderCompileError> {
|
) -> Result<(), ShaderCompileError> {
|
||||||
let resources = ast.get_shader_resources()?;
|
let resources = ast.shader_resources()?;
|
||||||
for resource in &resources.push_constant_buffers {
|
for resource in resources.resources_for_type(ResourceType::PushConstant)? {
|
||||||
let location = ResourceBindingLocation {
|
let Some(DecorationValue::Literal(buffer)) =
|
||||||
stage,
|
ast.decoration(resource.id, Decoration::Binding)?
|
||||||
desc_set: msl::PUSH_CONSTANT_DESCRIPTOR_SET,
|
else {
|
||||||
binding: msl::PUSH_CONSTANT_BINDING,
|
continue;
|
||||||
};
|
|
||||||
let overridden = ResourceBinding {
|
|
||||||
buffer_id: ast.get_decoration(resource.id, Decoration::Binding)?,
|
|
||||||
texture_id: 0,
|
|
||||||
sampler_id: 0,
|
|
||||||
base_type: None,
|
|
||||||
count: 0, // no arrays allowed in slang shaders, otherwise we'd have to get the type and get the array length
|
|
||||||
};
|
};
|
||||||
|
|
||||||
binding_map.insert(location, overridden);
|
ast.add_resource_binding(
|
||||||
|
stage,
|
||||||
|
ResourceBinding::PushConstantBuffer,
|
||||||
|
&BindTarget {
|
||||||
|
buffer,
|
||||||
|
texture: 0,
|
||||||
|
sampler: 0,
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
)?
|
||||||
}
|
}
|
||||||
|
|
||||||
for resource in resources
|
let ubos = resources.resources_for_type(ResourceType::UniformBuffer)?;
|
||||||
.uniform_buffers
|
let sampled = resources.resources_for_type(ResourceType::SampledImage)?;
|
||||||
.iter()
|
|
||||||
.chain(resources.sampled_images.iter())
|
for resource in ubos.chain(sampled) {
|
||||||
{
|
let Some(DecorationValue::Literal(binding)) =
|
||||||
let binding = ast.get_decoration(resource.id, Decoration::Binding)?;
|
ast.decoration(resource.id, Decoration::Binding)?
|
||||||
let location = ResourceBindingLocation {
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(DecorationValue::Literal(desc_set)) =
|
||||||
|
ast.decoration(resource.id, Decoration::DescriptorSet)?
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let overridden = BindTarget {
|
||||||
|
buffer: binding,
|
||||||
|
texture: binding,
|
||||||
|
sampler: binding,
|
||||||
|
count: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
ast.add_resource_binding(
|
||||||
stage,
|
stage,
|
||||||
desc_set: ast.get_decoration(resource.id, Decoration::DescriptorSet)?,
|
ResourceBinding::Qualified {
|
||||||
binding,
|
set: desc_set,
|
||||||
};
|
binding,
|
||||||
|
},
|
||||||
let overridden = ResourceBinding {
|
&overridden,
|
||||||
buffer_id: binding,
|
)?
|
||||||
texture_id: binding,
|
|
||||||
sampler_id: binding,
|
|
||||||
base_type: None,
|
|
||||||
count: 0, // no arrays allowed in slang shaders, otherwise we'd have to get the type and get the array length
|
|
||||||
};
|
|
||||||
|
|
||||||
binding_map.insert(location, overridden);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
set_bindings(
|
set_bindings(&mut self.vertex, spirv::ExecutionModel::Vertex)?;
|
||||||
&self.vertex,
|
|
||||||
ExecutionModel::Vertex,
|
|
||||||
&mut vert_options.resource_binding_overrides,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
set_bindings(
|
set_bindings(&mut self.fragment, spirv::ExecutionModel::Fragment)?;
|
||||||
&self.fragment,
|
|
||||||
ExecutionModel::Fragment,
|
|
||||||
&mut frag_options.resource_binding_overrides,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.vertex.set_compiler_options(&vert_options)?;
|
let vertex_compiled = self.vertex.compile(&options)?;
|
||||||
self.fragment.set_compiler_options(&frag_options)?;
|
let fragment_compiled = self.fragment.compile(&options)?;
|
||||||
|
|
||||||
Ok(ShaderCompilerOutput {
|
Ok(ShaderCompilerOutput {
|
||||||
vertex: self.vertex.compile()?,
|
vertex: vertex_compiled.to_string(),
|
||||||
fragment: self.fragment.compile()?,
|
fragment: fragment_compiled.to_string(),
|
||||||
context: CrossMslContext {
|
context: CrossMslContext {
|
||||||
artifact: CompiledProgram {
|
artifact: CompiledProgram {
|
||||||
vertex: CompiledAst(self.vertex),
|
vertex: vertex_compiled,
|
||||||
fragment: CompiledAst(self.fragment),
|
fragment: fragment_compiled,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -106,15 +108,13 @@ mod test {
|
||||||
use crate::back::targets::{MSL, WGSL};
|
use crate::back::targets::{MSL, WGSL};
|
||||||
use crate::back::{CompileShader, FromCompilation};
|
use crate::back::{CompileShader, FromCompilation};
|
||||||
use crate::reflect::cross::SpirvCross;
|
use crate::reflect::cross::SpirvCross;
|
||||||
use crate::reflect::naga::{Naga, NagaLoweringOptions};
|
|
||||||
use crate::reflect::semantics::{Semantic, ShaderSemantics, UniformSemantic, UniqueSemantics};
|
use crate::reflect::semantics::{Semantic, ShaderSemantics, UniformSemantic, UniqueSemantics};
|
||||||
use crate::reflect::ReflectShader;
|
use crate::reflect::ReflectShader;
|
||||||
use bitflags::Flags;
|
use bitflags::Flags;
|
||||||
use librashader_common::map::{FastHashMap, ShortString};
|
use librashader_common::map::{FastHashMap, ShortString};
|
||||||
use librashader_preprocess::ShaderSource;
|
use librashader_preprocess::ShaderSource;
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use spirv_cross::msl;
|
use spirv_cross2::compile::msl::MslVersion;
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_into() {
|
pub fn test_into() {
|
||||||
|
@ -148,7 +148,7 @@ mod test {
|
||||||
)
|
)
|
||||||
.expect("");
|
.expect("");
|
||||||
|
|
||||||
let compiled = msl.compile(Some(msl::Version::V2_0)).unwrap();
|
let compiled = msl.compile(Some(MslVersion::new(2, 0, 0))).unwrap();
|
||||||
|
|
||||||
println!("{}", compiled.vertex);
|
println!("{}", compiled.vertex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,7 +212,7 @@ impl ValidateTypeSemantics<&TypeInner> for UniqueSemantics {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return None;
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,7 +566,7 @@ impl NagaReflect {
|
||||||
};
|
};
|
||||||
|
|
||||||
let &Some(Binding::Location { location, .. }) = &frag_output.binding else {
|
let &Some(Binding::Location { location, .. }) = &frag_output.binding else {
|
||||||
return Err(ShaderReflectError::VertexSemanticError(
|
return Err(ShaderReflectError::FragmentSemanticError(
|
||||||
SemanticsErrorKind::MissingBinding,
|
SemanticsErrorKind::MissingBinding,
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
@ -845,10 +845,7 @@ impl NagaReflect {
|
||||||
semantics: &ShaderSemantics,
|
semantics: &ShaderSemantics,
|
||||||
meta: &mut BindingMeta,
|
meta: &mut BindingMeta,
|
||||||
) -> Result<(), ShaderReflectError> {
|
) -> Result<(), ShaderReflectError> {
|
||||||
let Some(semantic) = semantics
|
let Some(semantic) = semantics.texture_semantics.texture_semantic(texture.name) else {
|
||||||
.texture_semantics
|
|
||||||
.texture_semantic(texture.name)
|
|
||||||
else {
|
|
||||||
return Err(
|
return Err(
|
||||||
SemanticErrorBlame::Fragment.error(SemanticsErrorKind::UnknownSemantics(
|
SemanticErrorBlame::Fragment.error(SemanticsErrorKind::UnknownSemantics(
|
||||||
texture.name.to_string(),
|
texture.name.to_string(),
|
||||||
|
|
|
@ -8,19 +8,9 @@ use naga::back::msl::{
|
||||||
};
|
};
|
||||||
use naga::valid::{Capabilities, ValidationFlags};
|
use naga::valid::{Capabilities, ValidationFlags};
|
||||||
use naga::{Module, TypeInner};
|
use naga::{Module, TypeInner};
|
||||||
use spirv_cross::msl::Version;
|
|
||||||
|
|
||||||
fn msl_version_to_naga_msl(version: MslVersion) -> (u8, u8) {
|
fn msl_version_to_naga_msl(version: MslVersion) -> (u8, u8) {
|
||||||
match version {
|
(version.major as u8, version.minor as u8)
|
||||||
Version::V1_0 => (1, 0),
|
|
||||||
Version::V1_1 => (1, 1),
|
|
||||||
Version::V1_2 => (1, 2),
|
|
||||||
Version::V2_0 => (2, 0),
|
|
||||||
Version::V2_1 => (2, 1),
|
|
||||||
Version::V2_2 => (2, 2),
|
|
||||||
Version::V2_3 => (2, 3),
|
|
||||||
_ => (0, 0),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompileShader<MSL> for NagaReflect {
|
impl CompileShader<MSL> for NagaReflect {
|
||||||
|
@ -33,7 +23,7 @@ impl CompileShader<MSL> for NagaReflect {
|
||||||
) -> Result<ShaderCompilerOutput<String, Self::Context>, ShaderCompileError> {
|
) -> Result<ShaderCompilerOutput<String, Self::Context>, ShaderCompileError> {
|
||||||
// https://github.com/libretro/RetroArch/blob/434e94c782af2e4d4277a24b7ed8e5fc54870088/gfx/drivers_shader/slang_process.cpp#L524
|
// https://github.com/libretro/RetroArch/blob/434e94c782af2e4d4277a24b7ed8e5fc54870088/gfx/drivers_shader/slang_process.cpp#L524
|
||||||
|
|
||||||
let lang_version = msl_version_to_naga_msl(options.unwrap_or(MslVersion::V2_0));
|
let lang_version = msl_version_to_naga_msl(options.unwrap_or(MslVersion::new(2, 0, 0)));
|
||||||
|
|
||||||
let mut vert_options = Options {
|
let mut vert_options = Options {
|
||||||
lang_version,
|
lang_version,
|
||||||
|
|
|
@ -550,7 +550,7 @@ impl FilterChainD3D12 {
|
||||||
} else {
|
} else {
|
||||||
let hlsl_reflection = hlsl.reflect(index, semantics)?;
|
let hlsl_reflection = hlsl.reflect(index, semantics)?;
|
||||||
let hlsl = hlsl.compile(Some(
|
let hlsl = hlsl.compile(Some(
|
||||||
librashader_reflect::back::hlsl::HlslShaderModel::V6_0,
|
librashader_reflect::back::hlsl::HlslShaderModel::ShaderModel6_0,
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
let graphics_pipeline = D3D12GraphicsPipeline::new_from_hlsl(
|
let graphics_pipeline = D3D12GraphicsPipeline::new_from_hlsl(
|
||||||
|
|
|
@ -96,7 +96,7 @@ impl FilterChainD3D9 {
|
||||||
) -> error::Result<Vec<FilterPass>> {
|
) -> error::Result<Vec<FilterPass>> {
|
||||||
let builder_fn = |(index, (config, source, mut reflect)): (usize, ShaderPassMeta)| {
|
let builder_fn = |(index, (config, source, mut reflect)): (usize, ShaderPassMeta)| {
|
||||||
let mut reflection = reflect.reflect(index, semantics)?;
|
let mut reflection = reflect.reflect(index, semantics)?;
|
||||||
let hlsl = reflect.compile(Some(HlslShaderModel::V3_0))?;
|
let hlsl = reflect.compile(Some(HlslShaderModel::ShaderModel3_0))?;
|
||||||
|
|
||||||
// eprintln!("===vs===\n{}", hlsl.vertex);
|
// eprintln!("===vs===\n{}", hlsl.vertex);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ librashader-reflect = { path = "../librashader-reflect", version = "0.3.3" }
|
||||||
librashader-runtime = { path = "../librashader-runtime" , version = "0.3.3" }
|
librashader-runtime = { path = "../librashader-runtime" , version = "0.3.3" }
|
||||||
librashader-cache = { path = "../librashader-cache", version = "0.3.3" }
|
librashader-cache = { path = "../librashader-cache", version = "0.3.3" }
|
||||||
|
|
||||||
spirv_cross = { workspace = true }
|
spirv-cross2 = { workspace = true, features = ["glsl"] }
|
||||||
gl = "0.14.0"
|
gl = "0.14.0"
|
||||||
bytemuck = { version = "1.12.3", features = ["derive"] }
|
bytemuck = { version = "1.12.3", features = ["derive"] }
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub enum FilterChainError {
|
||||||
#[error("fbo initialization error")]
|
#[error("fbo initialization error")]
|
||||||
FramebufferInit(GLenum),
|
FramebufferInit(GLenum),
|
||||||
#[error("SPIRV reflection error")]
|
#[error("SPIRV reflection error")]
|
||||||
SpirvCrossReflectError(#[from] spirv_cross::ErrorCode),
|
SpirvCrossReflectError(#[from] spirv_cross2::SpirvCrossError),
|
||||||
#[error("shader preset parse error")]
|
#[error("shader preset parse error")]
|
||||||
ShaderPresetError(#[from] ParsePresetError),
|
ShaderPresetError(#[from] ParsePresetError),
|
||||||
#[error("shader preprocess error")]
|
#[error("shader preprocess error")]
|
||||||
|
|
|
@ -5,7 +5,8 @@ use crate::util;
|
||||||
use gl::types::{GLint, GLuint};
|
use gl::types::{GLint, GLuint};
|
||||||
use librashader_reflect::back::glsl::CrossGlslContext;
|
use librashader_reflect::back::glsl::CrossGlslContext;
|
||||||
use librashader_reflect::back::ShaderCompilerOutput;
|
use librashader_reflect::back::ShaderCompilerOutput;
|
||||||
use spirv_cross::spirv::Decoration;
|
use spirv_cross2::reflect::ResourceType;
|
||||||
|
use spirv_cross2::spirv::Decoration;
|
||||||
|
|
||||||
pub struct Gl3CompileProgram;
|
pub struct Gl3CompileProgram;
|
||||||
|
|
||||||
|
@ -14,7 +15,7 @@ impl CompileProgram for Gl3CompileProgram {
|
||||||
glsl: ShaderCompilerOutput<String, CrossGlslContext>,
|
glsl: ShaderCompilerOutput<String, CrossGlslContext>,
|
||||||
_cache: bool,
|
_cache: bool,
|
||||||
) -> crate::error::Result<(GLuint, UniformLocation<GLuint>)> {
|
) -> crate::error::Result<(GLuint, UniformLocation<GLuint>)> {
|
||||||
let vertex_resources = glsl.context.artifact.vertex.get_shader_resources()?;
|
let vertex_resources = glsl.context.artifact.vertex.shader_resources()?;
|
||||||
|
|
||||||
let (program, ubo_location) = unsafe {
|
let (program, ubo_location) = unsafe {
|
||||||
let vertex = util::gl_compile_shader(gl::VERTEX_SHADER, glsl.vertex.as_str())?;
|
let vertex = util::gl_compile_shader(gl::VERTEX_SHADER, glsl.vertex.as_str())?;
|
||||||
|
@ -24,13 +25,18 @@ impl CompileProgram for Gl3CompileProgram {
|
||||||
gl::AttachShader(program, vertex);
|
gl::AttachShader(program, vertex);
|
||||||
gl::AttachShader(program, fragment);
|
gl::AttachShader(program, fragment);
|
||||||
|
|
||||||
for res in vertex_resources.stage_inputs {
|
for res in vertex_resources.resources_for_type(ResourceType::StageInput)? {
|
||||||
let loc = glsl
|
let Some(loc) = glsl
|
||||||
.context
|
.context
|
||||||
.artifact
|
.artifact
|
||||||
.vertex
|
.vertex
|
||||||
.get_decoration(res.id, Decoration::Location)?;
|
.decoration(res.id, Decoration::Location)?
|
||||||
let mut name = res.name;
|
.and_then(|d| d.as_literal())
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut name = res.name.to_string();
|
||||||
name.push('\0');
|
name.push('\0');
|
||||||
|
|
||||||
gl::BindAttribLocation(program, loc, name.as_str().as_ptr().cast())
|
gl::BindAttribLocation(program, loc, name.as_str().as_ptr().cast())
|
||||||
|
|
|
@ -6,7 +6,8 @@ use gl::types::{GLint, GLsizei, GLuint};
|
||||||
use librashader_cache::Cacheable;
|
use librashader_cache::Cacheable;
|
||||||
use librashader_reflect::back::glsl::CrossGlslContext;
|
use librashader_reflect::back::glsl::CrossGlslContext;
|
||||||
use librashader_reflect::back::ShaderCompilerOutput;
|
use librashader_reflect::back::ShaderCompilerOutput;
|
||||||
use spirv_cross::spirv::Decoration;
|
use spirv_cross2::reflect::ResourceType;
|
||||||
|
use spirv_cross2::spirv::Decoration;
|
||||||
|
|
||||||
pub struct Gl4CompileProgram;
|
pub struct Gl4CompileProgram;
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ impl CompileProgram for Gl4CompileProgram {
|
||||||
glsl: ShaderCompilerOutput<String, CrossGlslContext>,
|
glsl: ShaderCompilerOutput<String, CrossGlslContext>,
|
||||||
cache: bool,
|
cache: bool,
|
||||||
) -> crate::error::Result<(GLuint, UniformLocation<GLuint>)> {
|
) -> crate::error::Result<(GLuint, UniformLocation<GLuint>)> {
|
||||||
let vertex_resources = glsl.context.artifact.vertex.get_shader_resources()?;
|
let vertex_resources = glsl.context.artifact.vertex.shader_resources()?;
|
||||||
|
|
||||||
let program = librashader_cache::cache_shader_object(
|
let program = librashader_cache::cache_shader_object(
|
||||||
"opengl4",
|
"opengl4",
|
||||||
|
@ -58,13 +59,18 @@ impl CompileProgram for Gl4CompileProgram {
|
||||||
gl::AttachShader(program, vertex);
|
gl::AttachShader(program, vertex);
|
||||||
gl::AttachShader(program, fragment);
|
gl::AttachShader(program, fragment);
|
||||||
|
|
||||||
for res in &vertex_resources.stage_inputs {
|
for res in vertex_resources.resources_for_type(ResourceType::StageInput)? {
|
||||||
let loc = glsl
|
let Some(loc) = glsl
|
||||||
.context
|
.context
|
||||||
.artifact
|
.artifact
|
||||||
.vertex
|
.vertex
|
||||||
.get_decoration(res.id, Decoration::Location)?;
|
.decoration(res.id, Decoration::Location)?
|
||||||
let mut name = res.name.clone();
|
.and_then(|d| d.as_literal())
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut name = res.name.to_string();
|
||||||
name.push('\0');
|
name.push('\0');
|
||||||
|
|
||||||
gl::BindAttribLocation(program, loc, name.as_str().as_ptr().cast())
|
gl::BindAttribLocation(program, loc, name.as_str().as_ptr().cast())
|
||||||
|
|
|
@ -36,40 +36,40 @@ pub fn gl_get_version() -> GlslVersion {
|
||||||
|
|
||||||
match maj_ver {
|
match maj_ver {
|
||||||
3 => match min_ver {
|
3 => match min_ver {
|
||||||
3 => GlslVersion::V3_30,
|
3 => GlslVersion::Glsl330,
|
||||||
2 => GlslVersion::V1_50,
|
2 => GlslVersion::Glsl150,
|
||||||
1 => GlslVersion::V1_40,
|
1 => GlslVersion::Glsl140,
|
||||||
0 => GlslVersion::V1_30,
|
0 => GlslVersion::Glsl130,
|
||||||
_ => GlslVersion::V1_50,
|
_ => GlslVersion::Glsl150,
|
||||||
},
|
},
|
||||||
4 => match min_ver {
|
4 => match min_ver {
|
||||||
6 => GlslVersion::V4_60,
|
6 => GlslVersion::Glsl460,
|
||||||
5 => GlslVersion::V4_50,
|
5 => GlslVersion::Glsl450,
|
||||||
4 => GlslVersion::V4_40,
|
4 => GlslVersion::Glsl440,
|
||||||
3 => GlslVersion::V4_30,
|
3 => GlslVersion::Glsl430,
|
||||||
2 => GlslVersion::V4_20,
|
2 => GlslVersion::Glsl420,
|
||||||
1 => GlslVersion::V4_10,
|
1 => GlslVersion::Glsl410,
|
||||||
0 => GlslVersion::V4_00,
|
0 => GlslVersion::Glsl400,
|
||||||
_ => GlslVersion::V1_50,
|
_ => GlslVersion::Glsl150,
|
||||||
},
|
},
|
||||||
_ => GlslVersion::V1_50,
|
_ => GlslVersion::Glsl150,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gl_u16_to_version(version: u16) -> GlslVersion {
|
pub fn gl_u16_to_version(version: u16) -> GlslVersion {
|
||||||
match version {
|
match version {
|
||||||
0 => gl_get_version(),
|
0 => gl_get_version(),
|
||||||
300 => GlslVersion::V1_30,
|
300 => GlslVersion::Glsl130,
|
||||||
310 => GlslVersion::V1_40,
|
310 => GlslVersion::Glsl140,
|
||||||
320 => GlslVersion::V1_50,
|
320 => GlslVersion::Glsl150,
|
||||||
330 => GlslVersion::V3_30,
|
330 => GlslVersion::Glsl330,
|
||||||
400 => GlslVersion::V4_00,
|
400 => GlslVersion::Glsl400,
|
||||||
410 => GlslVersion::V4_10,
|
410 => GlslVersion::Glsl410,
|
||||||
420 => GlslVersion::V4_20,
|
420 => GlslVersion::Glsl420,
|
||||||
430 => GlslVersion::V4_30,
|
430 => GlslVersion::Glsl430,
|
||||||
440 => GlslVersion::V4_40,
|
440 => GlslVersion::Glsl440,
|
||||||
450 => GlslVersion::V4_50,
|
450 => GlslVersion::Glsl450,
|
||||||
460 => GlslVersion::V4_60,
|
460 => GlslVersion::Glsl460,
|
||||||
_ => GlslVersion::V1_50,
|
_ => GlslVersion::Glsl150,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ impl FilterChainMetal {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, (config, source, mut reflect))| {
|
.map(|(index, (config, source, mut reflect))| {
|
||||||
let reflection = reflect.reflect(index, semantics)?;
|
let reflection = reflect.reflect(index, semantics)?;
|
||||||
let msl = reflect.compile(Some(MslVersion::V2_0))?;
|
let msl = reflect.compile(Some(MslVersion::new(2, 0, 0)))?;
|
||||||
|
|
||||||
let ubo_size = reflection.ubo.as_ref().map_or(0, |ubo| ubo.size as usize);
|
let ubo_size = reflection.ubo.as_ref().map_or(0, |ubo| ubo.size as usize);
|
||||||
let push_size = reflection
|
let push_size = reflection
|
||||||
|
|
|
@ -190,8 +190,6 @@ pub mod reflect {
|
||||||
|
|
||||||
pub use librashader_reflect::back::msl::CrossMslContext;
|
pub use librashader_reflect::back::msl::CrossMslContext;
|
||||||
|
|
||||||
pub use librashader_reflect::reflect::cross::CompiledAst;
|
|
||||||
|
|
||||||
pub use librashader_reflect::reflect::cross::CompiledProgram;
|
pub use librashader_reflect::reflect::cross::CompiledProgram;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue