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",
|
"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]]
|
[[package]]
|
||||||
name = "crossfont"
|
name = "crossfont"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
@ -606,6 +649,15 @@ version = "0.12.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
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]]
|
[[package]]
|
||||||
name = "ident_case"
|
name = "ident_case"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -822,6 +874,7 @@ dependencies = [
|
||||||
"librashader-reflect",
|
"librashader-reflect",
|
||||||
"librashader-runtime",
|
"librashader-runtime",
|
||||||
"librashader-spirv-cross",
|
"librashader-spirv-cross",
|
||||||
|
"rayon",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"windows",
|
"windows",
|
||||||
|
@ -841,6 +894,7 @@ dependencies = [
|
||||||
"librashader-reflect",
|
"librashader-reflect",
|
||||||
"librashader-runtime",
|
"librashader-runtime",
|
||||||
"librashader-spirv-cross",
|
"librashader-spirv-cross",
|
||||||
|
"rayon",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"windows",
|
"windows",
|
||||||
|
@ -879,6 +933,7 @@ dependencies = [
|
||||||
"librashader-spirv-cross",
|
"librashader-spirv-cross",
|
||||||
"num",
|
"num",
|
||||||
"raw-window-handle 0.5.0",
|
"raw-window-handle 0.5.0",
|
||||||
|
"rayon",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"winit",
|
"winit",
|
||||||
|
@ -947,6 +1002,15 @@ dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimal-lexical"
|
name = "minimal-lexical"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -1059,7 +1123,7 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"memoffset",
|
"memoffset 0.6.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1072,7 +1136,7 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"memoffset",
|
"memoffset 0.6.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1181,6 +1245,16 @@ dependencies = [
|
||||||
"autocfg",
|
"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]]
|
[[package]]
|
||||||
name = "num_enum"
|
name = "num_enum"
|
||||||
version = "0.5.9"
|
version = "0.5.9"
|
||||||
|
@ -1353,6 +1427,28 @@ dependencies = [
|
||||||
"raw-window-handle 0.5.0",
|
"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]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
|
|
|
@ -30,7 +30,7 @@ impl FromCompilation<GlslangCompilation> for GLSL {
|
||||||
compile: GlslangCompilation,
|
compile: GlslangCompilation,
|
||||||
) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
|
) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
|
||||||
Ok(CompilerBackend {
|
Ok(CompilerBackend {
|
||||||
backend: GlslReflect::try_from(compile)?,
|
backend: GlslReflect::try_from(&compile)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ impl FromCompilation<GlslangCompilation> for HLSL {
|
||||||
compile: GlslangCompilation,
|
compile: GlslangCompilation,
|
||||||
) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
|
) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
|
||||||
Ok(CompilerBackend {
|
Ok(CompilerBackend {
|
||||||
backend: HlslReflect::try_from(compile)?,
|
backend: HlslReflect::try_from(&compile)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,9 @@ impl FromCompilation<GlslangCompilation> for DXIL {
|
||||||
fn from_compilation(
|
fn from_compilation(
|
||||||
compile: GlslangCompilation,
|
compile: GlslangCompilation,
|
||||||
) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
|
) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
|
||||||
let vertex = compile.vertex.as_binary().to_vec();
|
let reflect = GlslReflect::try_from(&compile)?;
|
||||||
let fragment = compile.fragment.as_binary().to_vec();
|
let vertex = compile.vertex;
|
||||||
let reflect = GlslReflect::try_from(compile)?;
|
let fragment = compile.fragment;
|
||||||
Ok(CompilerBackend {
|
Ok(CompilerBackend {
|
||||||
// we can just reuse WriteSpirV as the backend.
|
// we can just reuse WriteSpirV as the backend.
|
||||||
backend: WriteSpirV {
|
backend: WriteSpirV {
|
||||||
|
|
|
@ -23,9 +23,9 @@ impl FromCompilation<GlslangCompilation> for SPIRV {
|
||||||
fn from_compilation(
|
fn from_compilation(
|
||||||
compile: GlslangCompilation,
|
compile: GlslangCompilation,
|
||||||
) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
|
) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
|
||||||
let vertex = compile.vertex.as_binary().to_vec();
|
let reflect = GlslReflect::try_from(&compile)?;
|
||||||
let fragment = compile.fragment.as_binary().to_vec();
|
let vertex = compile.vertex;
|
||||||
let reflect = GlslReflect::try_from(compile)?;
|
let fragment = compile.fragment;
|
||||||
Ok(CompilerBackend {
|
Ok(CompilerBackend {
|
||||||
backend: WriteSpirV {
|
backend: WriteSpirV {
|
||||||
reflect,
|
reflect,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::error::ShaderCompileError;
|
use crate::error::ShaderCompileError;
|
||||||
use librashader_preprocess::ShaderSource;
|
use librashader_preprocess::ShaderSource;
|
||||||
use shaderc::{CompilationArtifact, CompileOptions, Limit, ShaderKind};
|
use shaderc::{CompileOptions, Limit, ShaderKind};
|
||||||
|
|
||||||
/// A reflectable shader compilation via glslang (shaderc).
|
/// A reflectable shader compilation via glslang (shaderc).
|
||||||
pub struct GlslangCompilation {
|
pub struct GlslangCompilation {
|
||||||
pub(crate) vertex: CompilationArtifact,
|
pub(crate) vertex: Vec<u32>,
|
||||||
pub(crate) fragment: CompilationArtifact,
|
pub(crate) fragment: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlslangCompilation {
|
impl GlslangCompilation {
|
||||||
|
@ -137,6 +137,11 @@ pub(crate) fn compile_spirv(
|
||||||
"main",
|
"main",
|
||||||
Some(&options),
|
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 })
|
Ok(GlslangCompilation { vertex, fragment })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ 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::ops::Deref;
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use spirv_cross::hlsl::ShaderModel;
|
use spirv_cross::hlsl::ShaderModel;
|
||||||
use spirv_cross::spirv::{Ast, Decoration, Module, Resource, ShaderResources, Type};
|
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::back::{CompileShader, ShaderCompilerOutput};
|
||||||
use crate::reflect::helper::{SemanticErrorBlame, TextureData, UboData};
|
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>
|
pub(crate) struct CrossReflect<T>
|
||||||
where
|
where
|
||||||
T: spirv_cross::spirv::Target,
|
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
|
where
|
||||||
T: spirv_cross::spirv::Target,
|
T: spirv_cross::spirv::Target,
|
||||||
Ast<T>: spirv_cross::spirv::Compile<T>,
|
Ast<T>: spirv_cross::spirv::Compile<T>,
|
||||||
|
@ -118,9 +121,9 @@ where
|
||||||
{
|
{
|
||||||
type Error = ShaderReflectError;
|
type Error = ShaderReflectError;
|
||||||
|
|
||||||
fn try_from(value: GlslangCompilation) -> Result<Self, Self::Error> {
|
fn try_from(value: &GlslangCompilation) -> Result<Self, Self::Error> {
|
||||||
let vertex_module = Module::from_words(value.vertex.as_binary());
|
let vertex_module = Module::from_words(&value.vertex);
|
||||||
let fragment_module = Module::from_words(value.fragment.as_binary());
|
let fragment_module = Module::from_words(&value.fragment);
|
||||||
|
|
||||||
let vertex = Ast::parse(&vertex_module)?;
|
let vertex = Ast::parse(&vertex_module)?;
|
||||||
let fragment = Ast::parse(&fragment_module)?;
|
let fragment = Ast::parse(&fragment_module)?;
|
||||||
|
@ -878,7 +881,7 @@ mod test {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let spirv = GlslangCompilation::compile(&result).unwrap();
|
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
|
let _shader_reflection = reflect
|
||||||
.reflect(
|
.reflect(
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -23,16 +23,16 @@ impl TryFrom<NagaCompilation> for NagaReflect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<GlslangCompilation> for NagaReflect {
|
impl TryFrom<&GlslangCompilation> for NagaReflect {
|
||||||
type Error = ShaderReflectError;
|
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 ops = Options::default();
|
||||||
let vertex =
|
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()?;
|
.parse()?;
|
||||||
let fragment =
|
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()?;
|
.parse()?;
|
||||||
Ok(NagaReflect { vertex, fragment })
|
Ok(NagaReflect { vertex, fragment })
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ spirv_cross = { package = "librashader-spirv-cross", version = "0.23" }
|
||||||
|
|
||||||
rustc-hash = "1.1.0"
|
rustc-hash = "1.1.0"
|
||||||
bytemuck = "1.12.3"
|
bytemuck = "1.12.3"
|
||||||
|
rayon = "1.6.1"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies.windows]
|
[target.'cfg(windows)'.dependencies.windows]
|
||||||
version = "0.44.0"
|
version = "0.44.0"
|
||||||
|
|
|
@ -32,13 +32,14 @@ use windows::Win32::Graphics::Direct3D11::{
|
||||||
D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_USAGE_DYNAMIC,
|
D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_USAGE_DYNAMIC,
|
||||||
};
|
};
|
||||||
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R8G8B8A8_UNORM;
|
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
use rayon::prelude::*;
|
||||||
|
|
||||||
pub struct FilterMutable {
|
pub struct FilterMutable {
|
||||||
pub(crate) passes_enabled: usize,
|
pub(crate) passes_enabled: usize,
|
||||||
pub(crate) parameters: FxHashMap<String, f32>,
|
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.
|
/// A Direct3D 11 filter chain.
|
||||||
pub struct FilterChainD3D11 {
|
pub struct FilterChainD3D11 {
|
||||||
|
@ -220,81 +221,85 @@ impl FilterChainD3D11 {
|
||||||
passes: Vec<ShaderPassMeta>,
|
passes: Vec<ShaderPassMeta>,
|
||||||
semantics: &ShaderSemantics,
|
semantics: &ShaderSemantics,
|
||||||
) -> error::Result<Vec<FilterPass>> {
|
) -> 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 vertex_dxbc =
|
||||||
let reflection = reflect.reflect(index, semantics)?;
|
util::d3d_compile_shader(hlsl.vertex.as_bytes(), b"main\0", b"vs_5_0\0")?;
|
||||||
let hlsl = reflect.compile(None)?;
|
let vs = d3d11_compile_bound_shader(
|
||||||
|
device,
|
||||||
|
&vertex_dxbc,
|
||||||
|
None,
|
||||||
|
ID3D11Device::CreateVertexShader,
|
||||||
|
)?;
|
||||||
|
|
||||||
let vertex_dxbc =
|
let ia_desc = DrawQuad::get_spirv_cross_vbo_desc();
|
||||||
util::d3d_compile_shader(hlsl.vertex.as_bytes(), b"main\0", b"vs_5_0\0")?;
|
let vao = util::d3d11_create_input_layout(device, &ia_desc, &vertex_dxbc)?;
|
||||||
let vs = d3d11_compile_bound_shader(
|
|
||||||
device,
|
|
||||||
&vertex_dxbc,
|
|
||||||
None,
|
|
||||||
ID3D11Device::CreateVertexShader,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let ia_desc = DrawQuad::get_spirv_cross_vbo_desc();
|
let fragment_dxbc =
|
||||||
let vao = util::d3d11_create_input_layout(device, &ia_desc, &vertex_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 =
|
let ubo_cbuffer = if let Some(ubo) = &reflection.ubo && ubo.size != 0 {
|
||||||
util::d3d_compile_shader(hlsl.fragment.as_bytes(), b"main\0", b"ps_5_0\0")?;
|
let buffer = FilterChainD3D11::create_constant_buffer(device, ubo.size)?;
|
||||||
let ps = d3d11_compile_bound_shader(
|
Some(ConstantBufferBinding {
|
||||||
device,
|
binding: ubo.binding,
|
||||||
&fragment_dxbc,
|
size: ubo.size,
|
||||||
None,
|
stage_mask: ubo.stage_mask,
|
||||||
ID3D11Device::CreatePixelShader,
|
buffer,
|
||||||
)?;
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let ubo_cbuffer = if let Some(ubo) = &reflection.ubo && ubo.size != 0 {
|
let push_cbuffer = if let Some(push) = &reflection.push_constant && push.size != 0 {
|
||||||
let buffer = FilterChainD3D11::create_constant_buffer(device, ubo.size)?;
|
let buffer = FilterChainD3D11::create_constant_buffer(device, push.size)?;
|
||||||
Some(ConstantBufferBinding {
|
Some(ConstantBufferBinding {
|
||||||
binding: ubo.binding,
|
binding: if ubo_cbuffer.is_some() { 1 } else { 0 },
|
||||||
size: ubo.size,
|
size: push.size,
|
||||||
stage_mask: ubo.stage_mask,
|
stage_mask: push.stage_mask,
|
||||||
buffer,
|
buffer,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let push_cbuffer = if let Some(push) = &reflection.push_constant && push.size != 0 {
|
let uniform_storage = UniformStorage::new(
|
||||||
let buffer = FilterChainD3D11::create_constant_buffer(device, push.size)?;
|
reflection.ubo.as_ref().map_or(0, |ubo| ubo.size as usize),
|
||||||
Some(ConstantBufferBinding {
|
reflection
|
||||||
binding: if ubo_cbuffer.is_some() { 1 } else { 0 },
|
.push_constant
|
||||||
size: push.size,
|
.as_ref()
|
||||||
stage_mask: push.stage_mask,
|
.map_or(0, |push| push.size as usize),
|
||||||
buffer,
|
);
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let uniform_storage = UniformStorage::new(
|
let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset());
|
||||||
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());
|
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 {
|
let filters: error::Result<Vec<FilterPass>> = filters.into_iter().collect();
|
||||||
reflection,
|
let filters = filters?;
|
||||||
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(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Ok(filters)
|
Ok(filters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,6 @@ pub struct ConstantBufferBinding {
|
||||||
// slang_process.cpp 141
|
// slang_process.cpp 141
|
||||||
pub struct FilterPass {
|
pub struct FilterPass {
|
||||||
pub reflection: ShaderReflection,
|
pub reflection: ShaderReflection,
|
||||||
pub compiled: ShaderCompilerOutput<String, CrossHlslContext>,
|
|
||||||
pub vertex_shader: ID3D11VertexShader,
|
pub vertex_shader: ID3D11VertexShader,
|
||||||
pub vertex_layout: ID3D11InputLayout,
|
pub vertex_layout: ID3D11InputLayout,
|
||||||
pub pixel_shader: ID3D11PixelShader,
|
pub pixel_shader: ID3D11PixelShader,
|
||||||
|
|
|
@ -38,7 +38,7 @@ mod tests {
|
||||||
// "../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
|
// "../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
|
||||||
// "../test/null.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";
|
const IMAGE_PATH: &str = "../test/finalfightlong.png";
|
||||||
#[test]
|
#[test]
|
||||||
fn triangle_d3d11_args() {
|
fn triangle_d3d11_args() {
|
||||||
|
@ -84,7 +84,8 @@ mod tests {
|
||||||
force_no_mipmaps: false,
|
force_no_mipmaps: false,
|
||||||
}),
|
}),
|
||||||
// replace below with 'None' for the triangle
|
// replace below with 'None' for the triangle
|
||||||
None,
|
// None,
|
||||||
|
Some(Image::load(IMAGE_PATH, UVDirection::TopLeft).unwrap())
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// let sample = hello_triangle_old::d3d11_hello_triangle::Sample::new(
|
// let sample = hello_triangle_old::d3d11_hello_triangle::Sample::new(
|
||||||
|
|
|
@ -25,6 +25,8 @@ bytemuck = "1.12.3"
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
ash = { version = "0.37.1+1.3.235", features = ["linked", "debug"] }
|
ash = { version = "0.37.1+1.3.235", features = ["linked", "debug"] }
|
||||||
|
|
||||||
|
rayon = "1.6.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
num = "0.4.0"
|
num = "0.4.0"
|
||||||
glfw = "0.49.0"
|
glfw = "0.49.0"
|
||||||
|
|
|
@ -31,6 +31,7 @@ use std::collections::VecDeque;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use rayon::prelude::*;
|
||||||
/// A Vulkan device and metadata that is required by the shader runtime.
|
/// A Vulkan device and metadata that is required by the shader runtime.
|
||||||
pub struct VulkanObjects {
|
pub struct VulkanObjects {
|
||||||
pub(crate) device: Arc<ash::Device>,
|
pub(crate) device: Arc<ash::Device>,
|
||||||
|
@ -39,7 +40,7 @@ pub struct VulkanObjects {
|
||||||
pipeline_cache: vk::PipelineCache,
|
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.
|
/// A collection of handles needed to access the Vulkan instance.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -308,69 +309,66 @@ impl FilterChainVulkan {
|
||||||
frames_in_flight: u32,
|
frames_in_flight: u32,
|
||||||
use_render_pass: bool,
|
use_render_pass: bool,
|
||||||
) -> error::Result<Box<[FilterPass]>> {
|
) -> error::Result<Box<[FilterPass]>> {
|
||||||
let mut filters = Vec::new();
|
|
||||||
let frames_in_flight = std::cmp::max(1, frames_in_flight);
|
let frames_in_flight = std::cmp::max(1, frames_in_flight);
|
||||||
|
|
||||||
// initialize passes
|
let filters: Vec<error::Result<FilterPass>> = passes.into_par_iter()
|
||||||
for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() {
|
.enumerate()
|
||||||
let reflection = reflect.reflect(index, semantics)?;
|
.map(|(index, (config, source, mut reflect))| {
|
||||||
let spirv_words = reflect.compile(None)?;
|
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 ubo_size = reflection.ubo.as_ref().map_or(0, |ubo| ubo.size as usize);
|
||||||
let uniform_storage = UniformStorage::new_with_storage(
|
let uniform_storage = UniformStorage::new_with_storage(
|
||||||
RawVulkanBuffer::new(
|
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.device,
|
||||||
&vulkan.memory_properties,
|
&vulkan.pipeline_cache,
|
||||||
vk::BufferUsageFlags::UNIFORM_BUFFER,
|
&spirv_words,
|
||||||
ubo_size,
|
&reflection,
|
||||||
)?,
|
frames_in_flight,
|
||||||
reflection
|
render_pass_format,
|
||||||
.push_constant
|
)?;
|
||||||
.as_ref()
|
|
||||||
.map_or(0, |push| push.size as usize),
|
|
||||||
);
|
|
||||||
|
|
||||||
let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset());
|
Ok(FilterPass {
|
||||||
|
device: vulkan.device.clone(),
|
||||||
let render_pass_format = if !use_render_pass {
|
reflection,
|
||||||
vk::Format::UNDEFINED
|
// compiled: spirv_words,
|
||||||
} else if let Some(format) = config.get_format_override() {
|
uniform_storage,
|
||||||
format.into()
|
uniform_bindings,
|
||||||
} else if source.format != ImageFormat::Unknown {
|
source,
|
||||||
source.format.into()
|
config,
|
||||||
} else {
|
graphics_pipeline,
|
||||||
ImageFormat::R8G8B8A8Unorm.into()
|
// ubo_ring,
|
||||||
};
|
frames_in_flight,
|
||||||
|
})
|
||||||
let graphics_pipeline = VulkanGraphicsPipeline::new(
|
}).collect();
|
||||||
&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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let filters: error::Result<Vec<FilterPass>> = filters.into_iter().collect();
|
||||||
|
let filters = filters?;
|
||||||
Ok(filters.into_boxed_slice())
|
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 {
|
pub struct RawVulkanBuffer {
|
||||||
buffer: ManuallyDrop<VulkanBuffer>,
|
buffer: ManuallyDrop<VulkanBuffer>,
|
||||||
ptr: NonNull<c_void>,
|
ptr: NonNull<c_void>,
|
||||||
|
|
Loading…
Reference in a new issue