rt(d3d11/vk): allow for parallel shader compilation
OpenGL is for obvious reasons incompatible, and for DX12 the graphics pipeline creation has to be on the main thread so there isn't that much gain to be had.
This commit is contained in:
parent
b81b2b1d25
commit
f5fe3e37ef
100
Cargo.lock
generated
100
Cargo.lock
generated
|
@ -301,6 +301,49 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset 0.7.1",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossfont"
|
||||
version = "0.5.1"
|
||||
|
@ -606,6 +649,15 @@ version = "0.12.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
|
@ -822,6 +874,7 @@ dependencies = [
|
|||
"librashader-reflect",
|
||||
"librashader-runtime",
|
||||
"librashader-spirv-cross",
|
||||
"rayon",
|
||||
"rustc-hash",
|
||||
"thiserror",
|
||||
"windows",
|
||||
|
@ -841,6 +894,7 @@ dependencies = [
|
|||
"librashader-reflect",
|
||||
"librashader-runtime",
|
||||
"librashader-spirv-cross",
|
||||
"rayon",
|
||||
"rustc-hash",
|
||||
"thiserror",
|
||||
"windows",
|
||||
|
@ -879,6 +933,7 @@ dependencies = [
|
|||
"librashader-spirv-cross",
|
||||
"num",
|
||||
"raw-window-handle 0.5.0",
|
||||
"rayon",
|
||||
"rustc-hash",
|
||||
"thiserror",
|
||||
"winit",
|
||||
|
@ -947,6 +1002,15 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
|
@ -1059,7 +1123,7 @@ dependencies = [
|
|||
"bitflags",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset",
|
||||
"memoffset 0.6.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1072,7 +1136,7 @@ dependencies = [
|
|||
"bitflags",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset",
|
||||
"memoffset 0.6.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1181,6 +1245,16 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.5.9"
|
||||
|
@ -1353,6 +1427,28 @@ dependencies = [
|
|||
"raw-window-handle 0.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
|
|
|
@ -30,7 +30,7 @@ impl FromCompilation<GlslangCompilation> for GLSL {
|
|||
compile: GlslangCompilation,
|
||||
) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
|
||||
Ok(CompilerBackend {
|
||||
backend: GlslReflect::try_from(compile)?,
|
||||
backend: GlslReflect::try_from(&compile)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ impl FromCompilation<GlslangCompilation> for HLSL {
|
|||
compile: GlslangCompilation,
|
||||
) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
|
||||
Ok(CompilerBackend {
|
||||
backend: HlslReflect::try_from(compile)?,
|
||||
backend: HlslReflect::try_from(&compile)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ impl FromCompilation<GlslangCompilation> for DXIL {
|
|||
fn from_compilation(
|
||||
compile: GlslangCompilation,
|
||||
) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
|
||||
let vertex = compile.vertex.as_binary().to_vec();
|
||||
let fragment = compile.fragment.as_binary().to_vec();
|
||||
let reflect = GlslReflect::try_from(compile)?;
|
||||
let reflect = GlslReflect::try_from(&compile)?;
|
||||
let vertex = compile.vertex;
|
||||
let fragment = compile.fragment;
|
||||
Ok(CompilerBackend {
|
||||
// we can just reuse WriteSpirV as the backend.
|
||||
backend: WriteSpirV {
|
||||
|
|
|
@ -23,9 +23,9 @@ impl FromCompilation<GlslangCompilation> for SPIRV {
|
|||
fn from_compilation(
|
||||
compile: GlslangCompilation,
|
||||
) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
|
||||
let vertex = compile.vertex.as_binary().to_vec();
|
||||
let fragment = compile.fragment.as_binary().to_vec();
|
||||
let reflect = GlslReflect::try_from(compile)?;
|
||||
let reflect = GlslReflect::try_from(&compile)?;
|
||||
let vertex = compile.vertex;
|
||||
let fragment = compile.fragment;
|
||||
Ok(CompilerBackend {
|
||||
backend: WriteSpirV {
|
||||
reflect,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::error::ShaderCompileError;
|
||||
use librashader_preprocess::ShaderSource;
|
||||
use shaderc::{CompilationArtifact, CompileOptions, Limit, ShaderKind};
|
||||
use shaderc::{CompileOptions, Limit, ShaderKind};
|
||||
|
||||
/// A reflectable shader compilation via glslang (shaderc).
|
||||
pub struct GlslangCompilation {
|
||||
pub(crate) vertex: CompilationArtifact,
|
||||
pub(crate) fragment: CompilationArtifact,
|
||||
pub(crate) vertex: Vec<u32>,
|
||||
pub(crate) fragment: Vec<u32>,
|
||||
}
|
||||
|
||||
impl GlslangCompilation {
|
||||
|
@ -137,6 +137,11 @@ pub(crate) fn compile_spirv(
|
|||
"main",
|
||||
Some(&options),
|
||||
)?;
|
||||
|
||||
// shaderc has a GIL so Send is unsafe.
|
||||
let vertex = Vec::from(vertex.as_binary());
|
||||
let fragment = Vec::from(fragment.as_binary());
|
||||
|
||||
Ok(GlslangCompilation { vertex, fragment })
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::reflect::semantics::{
|
|||
MAX_BINDINGS_COUNT, MAX_PUSH_BUFFER_SIZE,
|
||||
};
|
||||
use crate::reflect::{align_uniform_size, ReflectShader};
|
||||
use std::ops::Deref;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use spirv_cross::hlsl::ShaderModel;
|
||||
use spirv_cross::spirv::{Ast, Decoration, Module, Resource, ShaderResources, Type};
|
||||
|
@ -18,6 +18,9 @@ use crate::back::targets::{GLSL, HLSL};
|
|||
use crate::back::{CompileShader, ShaderCompilerOutput};
|
||||
use crate::reflect::helper::{SemanticErrorBlame, TextureData, UboData};
|
||||
|
||||
// This is "probably" OK.
|
||||
unsafe impl<T: Send + spirv_cross::spirv::Target> Send for CrossReflect<T> {}
|
||||
|
||||
pub(crate) struct CrossReflect<T>
|
||||
where
|
||||
T: spirv_cross::spirv::Target,
|
||||
|
@ -110,7 +113,7 @@ impl ValidateTypeSemantics<Type> for TextureSemantics {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> TryFrom<GlslangCompilation> for CrossReflect<T>
|
||||
impl<T> TryFrom<&GlslangCompilation> for CrossReflect<T>
|
||||
where
|
||||
T: spirv_cross::spirv::Target,
|
||||
Ast<T>: spirv_cross::spirv::Compile<T>,
|
||||
|
@ -118,9 +121,9 @@ where
|
|||
{
|
||||
type Error = ShaderReflectError;
|
||||
|
||||
fn try_from(value: GlslangCompilation) -> Result<Self, Self::Error> {
|
||||
let vertex_module = Module::from_words(value.vertex.as_binary());
|
||||
let fragment_module = Module::from_words(value.fragment.as_binary());
|
||||
fn try_from(value: &GlslangCompilation) -> Result<Self, Self::Error> {
|
||||
let vertex_module = Module::from_words(&value.vertex);
|
||||
let fragment_module = Module::from_words(&value.fragment);
|
||||
|
||||
let vertex = Ast::parse(&vertex_module)?;
|
||||
let fragment = Ast::parse(&fragment_module)?;
|
||||
|
@ -878,7 +881,7 @@ mod test {
|
|||
);
|
||||
}
|
||||
let spirv = GlslangCompilation::compile(&result).unwrap();
|
||||
let mut reflect = CrossReflect::<glsl::Target>::try_from(spirv).unwrap();
|
||||
let mut reflect = CrossReflect::<glsl::Target>::try_from(&spirv).unwrap();
|
||||
let _shader_reflection = reflect
|
||||
.reflect(
|
||||
0,
|
||||
|
|
|
@ -23,16 +23,16 @@ impl TryFrom<NagaCompilation> for NagaReflect {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<GlslangCompilation> for NagaReflect {
|
||||
impl TryFrom<&GlslangCompilation> for NagaReflect {
|
||||
type Error = ShaderReflectError;
|
||||
|
||||
fn try_from(value: GlslangCompilation) -> Result<Self, Self::Error> {
|
||||
fn try_from(value: &GlslangCompilation) -> Result<Self, Self::Error> {
|
||||
let ops = Options::default();
|
||||
let vertex =
|
||||
naga::front::spv::Parser::new(value.vertex.as_binary().to_vec().into_iter(), &ops)
|
||||
naga::front::spv::Parser::new(value.vertex.clone().into_iter(), &ops)
|
||||
.parse()?;
|
||||
let fragment =
|
||||
naga::front::spv::Parser::new(value.fragment.as_binary().to_vec().into_iter(), &ops)
|
||||
naga::front::spv::Parser::new(value.fragment.clone().into_iter(), &ops)
|
||||
.parse()?;
|
||||
Ok(NagaReflect { vertex, fragment })
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ spirv_cross = { package = "librashader-spirv-cross", version = "0.23" }
|
|||
|
||||
rustc-hash = "1.1.0"
|
||||
bytemuck = "1.12.3"
|
||||
rayon = "1.6.1"
|
||||
|
||||
[target.'cfg(windows)'.dependencies.windows]
|
||||
version = "0.44.0"
|
||||
|
|
|
@ -32,13 +32,14 @@ use windows::Win32::Graphics::Direct3D11::{
|
|||
D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_USAGE_DYNAMIC,
|
||||
};
|
||||
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
use rayon::prelude::*;
|
||||
|
||||
pub struct FilterMutable {
|
||||
pub(crate) passes_enabled: usize,
|
||||
pub(crate) parameters: FxHashMap<String, f32>,
|
||||
}
|
||||
|
||||
type ShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation>>;
|
||||
type ShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation> + Send>;
|
||||
|
||||
/// A Direct3D 11 filter chain.
|
||||
pub struct FilterChainD3D11 {
|
||||
|
@ -220,81 +221,85 @@ impl FilterChainD3D11 {
|
|||
passes: Vec<ShaderPassMeta>,
|
||||
semantics: &ShaderSemantics,
|
||||
) -> error::Result<Vec<FilterPass>> {
|
||||
let mut filters = Vec::new();
|
||||
// access to ID3D11Device is thread safe.
|
||||
let filters: Vec<error::Result<FilterPass>> =
|
||||
passes.into_par_iter()
|
||||
.enumerate()
|
||||
.map(|(index, (config, source, mut reflect)) | {
|
||||
let reflection = reflect.reflect(index, semantics)?;
|
||||
let hlsl = reflect.compile(None)?;
|
||||
|
||||
for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() {
|
||||
let reflection = reflect.reflect(index, semantics)?;
|
||||
let hlsl = reflect.compile(None)?;
|
||||
let vertex_dxbc =
|
||||
util::d3d_compile_shader(hlsl.vertex.as_bytes(), b"main\0", b"vs_5_0\0")?;
|
||||
let vs = d3d11_compile_bound_shader(
|
||||
device,
|
||||
&vertex_dxbc,
|
||||
None,
|
||||
ID3D11Device::CreateVertexShader,
|
||||
)?;
|
||||
|
||||
let vertex_dxbc =
|
||||
util::d3d_compile_shader(hlsl.vertex.as_bytes(), b"main\0", b"vs_5_0\0")?;
|
||||
let vs = d3d11_compile_bound_shader(
|
||||
device,
|
||||
&vertex_dxbc,
|
||||
None,
|
||||
ID3D11Device::CreateVertexShader,
|
||||
)?;
|
||||
let ia_desc = DrawQuad::get_spirv_cross_vbo_desc();
|
||||
let vao = util::d3d11_create_input_layout(device, &ia_desc, &vertex_dxbc)?;
|
||||
|
||||
let ia_desc = DrawQuad::get_spirv_cross_vbo_desc();
|
||||
let vao = util::d3d11_create_input_layout(device, &ia_desc, &vertex_dxbc)?;
|
||||
let fragment_dxbc =
|
||||
util::d3d_compile_shader(hlsl.fragment.as_bytes(), b"main\0", b"ps_5_0\0")?;
|
||||
let ps = d3d11_compile_bound_shader(
|
||||
device,
|
||||
&fragment_dxbc,
|
||||
None,
|
||||
ID3D11Device::CreatePixelShader,
|
||||
)?;
|
||||
|
||||
let fragment_dxbc =
|
||||
util::d3d_compile_shader(hlsl.fragment.as_bytes(), b"main\0", b"ps_5_0\0")?;
|
||||
let ps = d3d11_compile_bound_shader(
|
||||
device,
|
||||
&fragment_dxbc,
|
||||
None,
|
||||
ID3D11Device::CreatePixelShader,
|
||||
)?;
|
||||
let ubo_cbuffer = if let Some(ubo) = &reflection.ubo && ubo.size != 0 {
|
||||
let buffer = FilterChainD3D11::create_constant_buffer(device, ubo.size)?;
|
||||
Some(ConstantBufferBinding {
|
||||
binding: ubo.binding,
|
||||
size: ubo.size,
|
||||
stage_mask: ubo.stage_mask,
|
||||
buffer,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let ubo_cbuffer = if let Some(ubo) = &reflection.ubo && ubo.size != 0 {
|
||||
let buffer = FilterChainD3D11::create_constant_buffer(device, ubo.size)?;
|
||||
Some(ConstantBufferBinding {
|
||||
binding: ubo.binding,
|
||||
size: ubo.size,
|
||||
stage_mask: ubo.stage_mask,
|
||||
buffer,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let push_cbuffer = if let Some(push) = &reflection.push_constant && push.size != 0 {
|
||||
let buffer = FilterChainD3D11::create_constant_buffer(device, push.size)?;
|
||||
Some(ConstantBufferBinding {
|
||||
binding: if ubo_cbuffer.is_some() { 1 } else { 0 },
|
||||
size: push.size,
|
||||
stage_mask: push.stage_mask,
|
||||
buffer,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let push_cbuffer = if let Some(push) = &reflection.push_constant && push.size != 0 {
|
||||
let buffer = FilterChainD3D11::create_constant_buffer(device, push.size)?;
|
||||
Some(ConstantBufferBinding {
|
||||
binding: if ubo_cbuffer.is_some() { 1 } else { 0 },
|
||||
size: push.size,
|
||||
stage_mask: push.stage_mask,
|
||||
buffer,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let uniform_storage = UniformStorage::new(
|
||||
reflection.ubo.as_ref().map_or(0, |ubo| ubo.size as usize),
|
||||
reflection
|
||||
.push_constant
|
||||
.as_ref()
|
||||
.map_or(0, |push| push.size as usize),
|
||||
);
|
||||
|
||||
let uniform_storage = UniformStorage::new(
|
||||
reflection.ubo.as_ref().map_or(0, |ubo| ubo.size as usize),
|
||||
reflection
|
||||
.push_constant
|
||||
.as_ref()
|
||||
.map_or(0, |push| push.size as usize),
|
||||
);
|
||||
let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset());
|
||||
|
||||
let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset());
|
||||
Ok(FilterPass {
|
||||
reflection,
|
||||
vertex_shader: vs,
|
||||
vertex_layout: vao,
|
||||
pixel_shader: ps,
|
||||
uniform_bindings,
|
||||
uniform_storage,
|
||||
uniform_buffer: ubo_cbuffer,
|
||||
push_buffer: push_cbuffer,
|
||||
source,
|
||||
config: config.clone(),
|
||||
})
|
||||
}).collect();
|
||||
|
||||
filters.push(FilterPass {
|
||||
reflection,
|
||||
compiled: hlsl,
|
||||
vertex_shader: vs,
|
||||
vertex_layout: vao,
|
||||
pixel_shader: ps,
|
||||
uniform_bindings,
|
||||
uniform_storage,
|
||||
uniform_buffer: ubo_cbuffer,
|
||||
push_buffer: push_cbuffer,
|
||||
source,
|
||||
config: config.clone(),
|
||||
})
|
||||
}
|
||||
let filters: error::Result<Vec<FilterPass>> = filters.into_iter().collect();
|
||||
let filters = filters?;
|
||||
Ok(filters)
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ pub struct ConstantBufferBinding {
|
|||
// slang_process.cpp 141
|
||||
pub struct FilterPass {
|
||||
pub reflection: ShaderReflection,
|
||||
pub compiled: ShaderCompilerOutput<String, CrossHlslContext>,
|
||||
pub vertex_shader: ID3D11VertexShader,
|
||||
pub vertex_layout: ID3D11InputLayout,
|
||||
pub pixel_shader: ID3D11PixelShader,
|
||||
|
|
|
@ -38,7 +38,7 @@ mod tests {
|
|||
// "../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
|
||||
// "../test/null.slangp",
|
||||
|
||||
const FILTER_PATH: &str = "../test/slang-shaders/bezel/koko-aio/monitor-bloom.slangp";
|
||||
const FILTER_PATH: &str = "../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp";
|
||||
const IMAGE_PATH: &str = "../test/finalfightlong.png";
|
||||
#[test]
|
||||
fn triangle_d3d11_args() {
|
||||
|
@ -84,7 +84,8 @@ mod tests {
|
|||
force_no_mipmaps: false,
|
||||
}),
|
||||
// replace below with 'None' for the triangle
|
||||
None,
|
||||
// None,
|
||||
Some(Image::load(IMAGE_PATH, UVDirection::TopLeft).unwrap())
|
||||
)
|
||||
.unwrap();
|
||||
// let sample = hello_triangle_old::d3d11_hello_triangle::Sample::new(
|
||||
|
|
|
@ -25,6 +25,8 @@ bytemuck = "1.12.3"
|
|||
thiserror = "1.0.37"
|
||||
ash = { version = "0.37.1+1.3.235", features = ["linked", "debug"] }
|
||||
|
||||
rayon = "1.6.1"
|
||||
|
||||
[dev-dependencies]
|
||||
num = "0.4.0"
|
||||
glfw = "0.49.0"
|
||||
|
|
|
@ -31,6 +31,7 @@ use std::collections::VecDeque;
|
|||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rayon::prelude::*;
|
||||
/// A Vulkan device and metadata that is required by the shader runtime.
|
||||
pub struct VulkanObjects {
|
||||
pub(crate) device: Arc<ash::Device>,
|
||||
|
@ -39,7 +40,7 @@ pub struct VulkanObjects {
|
|||
pipeline_cache: vk::PipelineCache,
|
||||
}
|
||||
|
||||
type ShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<SPIRV, GlslangCompilation>>;
|
||||
type ShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<SPIRV, GlslangCompilation> + Send>;
|
||||
|
||||
/// A collection of handles needed to access the Vulkan instance.
|
||||
#[derive(Clone)]
|
||||
|
@ -308,69 +309,66 @@ impl FilterChainVulkan {
|
|||
frames_in_flight: u32,
|
||||
use_render_pass: bool,
|
||||
) -> error::Result<Box<[FilterPass]>> {
|
||||
let mut filters = Vec::new();
|
||||
let frames_in_flight = std::cmp::max(1, frames_in_flight);
|
||||
|
||||
// initialize passes
|
||||
for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() {
|
||||
let reflection = reflect.reflect(index, semantics)?;
|
||||
let spirv_words = reflect.compile(None)?;
|
||||
let filters: Vec<error::Result<FilterPass>> = passes.into_par_iter()
|
||||
.enumerate()
|
||||
.map(|(index, (config, source, mut reflect))| {
|
||||
let reflection = reflect.reflect(index, semantics)?;
|
||||
let spirv_words = reflect.compile(None)?;
|
||||
|
||||
let ubo_size = reflection.ubo.as_ref().map_or(0, |ubo| ubo.size as usize);
|
||||
let uniform_storage = UniformStorage::new_with_storage(
|
||||
RawVulkanBuffer::new(
|
||||
let ubo_size = reflection.ubo.as_ref().map_or(0, |ubo| ubo.size as usize);
|
||||
let uniform_storage = UniformStorage::new_with_storage(
|
||||
RawVulkanBuffer::new(
|
||||
&vulkan.device,
|
||||
&vulkan.memory_properties,
|
||||
vk::BufferUsageFlags::UNIFORM_BUFFER,
|
||||
ubo_size,
|
||||
)?,
|
||||
reflection
|
||||
.push_constant
|
||||
.as_ref()
|
||||
.map_or(0, |push| push.size as usize),
|
||||
);
|
||||
|
||||
let uniform_bindings = reflection.meta
|
||||
.create_binding_map(|param| param.offset());
|
||||
|
||||
let render_pass_format = if !use_render_pass {
|
||||
vk::Format::UNDEFINED
|
||||
} else if let Some(format) = config.get_format_override() {
|
||||
format.into()
|
||||
} else if source.format != ImageFormat::Unknown {
|
||||
source.format.into()
|
||||
} else {
|
||||
ImageFormat::R8G8B8A8Unorm.into()
|
||||
};
|
||||
|
||||
let graphics_pipeline = VulkanGraphicsPipeline::new(
|
||||
&vulkan.device,
|
||||
&vulkan.memory_properties,
|
||||
vk::BufferUsageFlags::UNIFORM_BUFFER,
|
||||
ubo_size,
|
||||
)?,
|
||||
reflection
|
||||
.push_constant
|
||||
.as_ref()
|
||||
.map_or(0, |push| push.size as usize),
|
||||
);
|
||||
&vulkan.pipeline_cache,
|
||||
&spirv_words,
|
||||
&reflection,
|
||||
frames_in_flight,
|
||||
render_pass_format,
|
||||
)?;
|
||||
|
||||
let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset());
|
||||
|
||||
let render_pass_format = if !use_render_pass {
|
||||
vk::Format::UNDEFINED
|
||||
} else if let Some(format) = config.get_format_override() {
|
||||
format.into()
|
||||
} else if source.format != ImageFormat::Unknown {
|
||||
source.format.into()
|
||||
} else {
|
||||
ImageFormat::R8G8B8A8Unorm.into()
|
||||
};
|
||||
|
||||
let graphics_pipeline = VulkanGraphicsPipeline::new(
|
||||
&vulkan.device,
|
||||
&vulkan.pipeline_cache,
|
||||
&spirv_words,
|
||||
&reflection,
|
||||
frames_in_flight,
|
||||
render_pass_format,
|
||||
)?;
|
||||
|
||||
// let ubo_ring = VkUboRing::new(
|
||||
// &vulkan.device,
|
||||
// &vulkan.memory_properties,
|
||||
// frames_in_flight as usize,
|
||||
// ubo_size,
|
||||
// )?;
|
||||
filters.push(FilterPass {
|
||||
device: vulkan.device.clone(),
|
||||
reflection,
|
||||
// compiled: spirv_words,
|
||||
uniform_storage,
|
||||
uniform_bindings,
|
||||
source,
|
||||
config,
|
||||
graphics_pipeline,
|
||||
// ubo_ring,
|
||||
frames_in_flight,
|
||||
});
|
||||
}
|
||||
Ok(FilterPass {
|
||||
device: vulkan.device.clone(),
|
||||
reflection,
|
||||
// compiled: spirv_words,
|
||||
uniform_storage,
|
||||
uniform_bindings,
|
||||
source,
|
||||
config,
|
||||
graphics_pipeline,
|
||||
// ubo_ring,
|
||||
frames_in_flight,
|
||||
})
|
||||
}).collect();
|
||||
|
||||
let filters: error::Result<Vec<FilterPass>> = filters.into_iter().collect();
|
||||
let filters = filters?;
|
||||
Ok(filters.into_boxed_slice())
|
||||
}
|
||||
|
||||
|
|
|
@ -134,6 +134,10 @@ impl<'a> Drop for VulkanBufferMapHandle<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// SAFETY: Creating the pointer should be safe in multithreaded contexts.
|
||||
///
|
||||
/// Mutation is guarded by DerefMut<Target=[u8]>
|
||||
unsafe impl Send for RawVulkanBuffer {}
|
||||
pub struct RawVulkanBuffer {
|
||||
buffer: ManuallyDrop<VulkanBuffer>,
|
||||
ptr: NonNull<c_void>,
|
||||
|
|
Loading…
Reference in a new issue