rt(wgpu): create pipeline bind group layouts

This commit is contained in:
chyyran 2023-12-13 19:24:00 -05:00 committed by Ronny Chan
parent 171c842c97
commit 4e052159e7
21 changed files with 1566 additions and 420 deletions

View file

@ -4,5 +4,6 @@
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/test/shaders_slang" vcs="Git" />
<mapping directory="$PROJECT_DIR$/test/slang-shaders" vcs="Git" />
</component>
</project>

View file

@ -12,14 +12,9 @@
<cargoProject FILE="$PROJECT_DIR$/Cargo.toml" />
</component>
<component name="ChangeListManager">
<list default="true" id="02471831-07cd-4975-a00c-e042450023a1" name="Changes" comment="rt(wgpu): load shaders">
<change beforePath="$PROJECT_DIR$/.idea/vcs.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<list default="true" id="02471831-07cd-4975-a00c-e042450023a1" name="Changes" comment="reflect(wgsl): give push uniform a non-overlapping bind group">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/librashader-reflect/src/back/wgsl/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/librashader-reflect/src/back/wgsl/mod.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/librashader-reflect/src/error.rs" beforeDir="false" afterPath="$PROJECT_DIR$/librashader-reflect/src/error.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/librashader-reflect/src/reflect/cross.rs" beforeDir="false" afterPath="$PROJECT_DIR$/librashader-reflect/src/reflect/cross.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/librashader-reflect/src/reflect/naga.rs" beforeDir="false" afterPath="$PROJECT_DIR$/librashader-reflect/src/reflect/naga.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/test/shaders_slang" beforeDir="false" afterPath="$PROJECT_DIR$/test/shaders_slang" afterDir="false" />
<change beforePath="$PROJECT_DIR$/librashader-runtime-wgpu/src/graphics_pipeline.rs" beforeDir="false" afterPath="$PROJECT_DIR$/librashader-runtime-wgpu/src/graphics_pipeline.rs" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -70,6 +65,11 @@
"Cargo.Test front::naga::test::naga_playground (1).executor": "Run",
"Cargo.Test front::naga::test::naga_playground.executor": "Run",
"Cargo.Test reflect::cross::test::test_into.executor": "Run",
"Cargo.Test triangle_d3d11.executor": "Run",
"Cargo.Test triangle_d3d12.executor": "Run",
"Cargo.Test triangle_gl.executor": "Run",
"Cargo.Test triangle_gl46.executor": "Run",
"Cargo.Test triangle_vk.executor": "Run",
"Cargo.Test triangle_wgpu.executor": "Run",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.RadMigrateCodeStyle": "true",
@ -78,15 +78,15 @@
"RunOnceActivity.readMode.enableVisualFormatting": "true",
"cf.first.check.clang-format": "false",
"cidr.known.project.marker": "true",
"git-widget-placeholder": "86a88bb2",
"last_opened_file_path": "F:/coding/librashader",
"git-widget-placeholder": "feat-wgpu-runtime",
"last_opened_file_path": "C:/coding/librashader",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"org.rust.cargo.project.model.PROJECT_DISCOVERY": "true",
"settings.editor.selected.configurable": "project.propVCSSupport.DirectoryMappings",
"settings.editor.selected.configurable": "language.rust",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
@ -131,40 +131,6 @@
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
<configuration name="Test front::naga::test::naga_playground (1)" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="command" value="test --package librashader-reflect --lib front::naga::test::naga_playground -- --exact" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<option name="emulateTerminal" value="true" />
<option name="channel" value="DEFAULT" />
<option name="requiredFeatures" value="true" />
<option name="allFeatures" value="false" />
<option name="withSudo" value="false" />
<option name="buildTarget" value="REMOTE" />
<option name="backtrace" value="SHORT" />
<envs />
<option name="isRedirectInput" value="false" />
<option name="redirectInputPath" value="" />
<method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
<configuration name="Test front::naga::test::naga_playground" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="command" value="test --package librashader-reflect --features=unstable-naga --lib front::naga::test::naga_playground -- --exact" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<option name="emulateTerminal" value="true" />
<option name="channel" value="DEFAULT" />
<option name="requiredFeatures" value="true" />
<option name="allFeatures" value="false" />
<option name="withSudo" value="false" />
<option name="buildTarget" value="REMOTE" />
<option name="backtrace" value="SHORT" />
<envs />
<option name="isRedirectInput" value="false" />
<option name="redirectInputPath" value="" />
<method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
<configuration name="Test librashader" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="command" value="test --workspace" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
@ -182,8 +148,8 @@
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
<configuration name="Test reflect::cross::test::test_into" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="command" value="test --package librashader-reflect --lib reflect::cross::test::test_into -- --exact" />
<configuration name="Test triangle_d3d11" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="command" value="test --package librashader-runtime-d3d11 --test triangle triangle_d3d11 -- --exact" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<option name="emulateTerminal" value="true" />
<option name="channel" value="DEFAULT" />
@ -199,8 +165,42 @@
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
<configuration name="Test triangle_wgpu" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="command" value="test --package librashader-runtime-wgpu --test triangle triangle_wgpu -- --exact" />
<configuration name="Test triangle_d3d12" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="command" value="test --package librashader-runtime-d3d12 --test triangle triangle_d3d12 -- --exact" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<option name="emulateTerminal" value="true" />
<option name="channel" value="DEFAULT" />
<option name="requiredFeatures" value="true" />
<option name="allFeatures" value="false" />
<option name="withSudo" value="false" />
<option name="buildTarget" value="REMOTE" />
<option name="backtrace" value="SHORT" />
<envs />
<option name="isRedirectInput" value="false" />
<option name="redirectInputPath" value="" />
<method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
<configuration name="Test triangle_gl46" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="command" value="test --package librashader-runtime-gl --test triangle triangle_gl46 -- --exact" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<option name="emulateTerminal" value="true" />
<option name="channel" value="DEFAULT" />
<option name="requiredFeatures" value="true" />
<option name="allFeatures" value="false" />
<option name="withSudo" value="false" />
<option name="buildTarget" value="REMOTE" />
<option name="backtrace" value="SHORT" />
<envs />
<option name="isRedirectInput" value="false" />
<option name="redirectInputPath" value="" />
<method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
<configuration name="Test triangle_vk" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="command" value="test --package librashader-runtime-vk --test triangle triangle_vk -- --exact" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<option name="emulateTerminal" value="true" />
<option name="channel" value="DEFAULT" />
@ -219,24 +219,24 @@
<list>
<item itemvalue="Cargo.Run librashader-build-script" />
<item itemvalue="Cargo.Test librashader" />
<item itemvalue="Cargo.Test triangle_d3d11" />
<item itemvalue="Cargo.Test triangle_d3d12" />
<item itemvalue="Cargo.Test triangle_gl46" />
<item itemvalue="Cargo.Test triangle_vk" />
<item itemvalue="Cargo.Test back::wgsl::test::test_into" />
<item itemvalue="Cargo.Test reflect::cross::test::test_into" />
<item itemvalue="Cargo.Test front::naga::test::naga_playground (1)" />
<item itemvalue="Cargo.Test front::naga::test::naga_playground" />
<item itemvalue="Cargo.Test triangle_wgpu" />
</list>
<recent_temporary>
<list>
<item itemvalue="Cargo.Test back::wgsl::test::test_into" />
<item itemvalue="Cargo.Test triangle_wgpu" />
<item itemvalue="Cargo.Test front::naga::test::naga_playground" />
<item itemvalue="Cargo.Test front::naga::test::naga_playground (1)" />
<item itemvalue="Cargo.Test reflect::cross::test::test_into" />
<item itemvalue="Cargo.Test triangle_gl46" />
<item itemvalue="Cargo.Test triangle_vk" />
<item itemvalue="Cargo.Test triangle_d3d11" />
<item itemvalue="Cargo.Test triangle_d3d12" />
</list>
</recent_temporary>
</component>
<component name="RustProjectSettings">
<option name="toolchainHomeDirectory" value="D:/Runtime/Rust/cargo/bin" />
<option name="toolchainHomeDirectory" value="$USER_HOME$/.rustup/toolchains/nightly-x86_64-pc-windows-msvc/bin" />
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
@ -262,6 +262,9 @@
<workItem from="1702163869988" duration="618000" />
<workItem from="1702419933111" duration="5007000" />
<workItem from="1702425796345" duration="12240000" />
<workItem from="1702482450853" duration="399000" />
<workItem from="1702482871248" duration="556000" />
<workItem from="1702484102491" duration="4924000" />
</task>
<task id="LOCAL-00001" summary="rt(wgpu): basic triangle example">
<option name="closed" value="true" />
@ -295,7 +298,15 @@
<option name="project" value="LOCAL" />
<updated>1701327201979</updated>
</task>
<option name="localTasksCounter" value="5" />
<task id="LOCAL-00005" summary="reflect(wgsl): give push uniform a non-overlapping bind group">
<option name="closed" value="true" />
<created>1702513440377</created>
<option name="number" value="00005" />
<option name="presentableId" value="LOCAL-00005" />
<option name="project" value="LOCAL" />
<updated>1702513440377</updated>
</task>
<option name="localTasksCounter" value="6" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@ -307,7 +318,8 @@
</ignored-roots>
<MESSAGE value="rt(wgpu): basic triangle example" />
<MESSAGE value="rt(wgpu): load shaders" />
<option name="LAST_COMMIT_MESSAGE" value="rt(wgpu): load shaders" />
<MESSAGE value="reflect(wgsl): give push uniform a non-overlapping bind group" />
<option name="LAST_COMMIT_MESSAGE" value="reflect(wgsl): give push uniform a non-overlapping bind group" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager>

1478
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,9 @@
//! Cache helpers for `ShaderCompilation` objects to cache compiled SPIRV.
use librashader_preprocess::ShaderSource;
use librashader_reflect::back::targets::{DXIL, GLSL, HLSL, SPIRV};
use librashader_reflect::back::targets::{GLSL, HLSL, SPIRV};
#[cfg(all(target_os = "windows", feature = "d3d"))]
use librashader_reflect::back::targets::DXIL;
use librashader_reflect::back::{CompilerBackend, FromCompilation};
use librashader_reflect::error::{ShaderCompileError, ShaderReflectError};
use librashader_reflect::front::{GlslangCompilation, ShaderCompilation};

View file

@ -99,7 +99,14 @@ impl CompileShader<WGSL> for NagaReflect {
gv.space = AddressSpace::Uniform;
}
}
} else {
for (_, gv) in self.fragment.global_variables.iter_mut() {
if gv.space == AddressSpace::PushConstant {
gv.binding = None;
}
}
}
// Reassign shit.
let images = self
.fragment
@ -197,12 +204,12 @@ mod test {
let compiled = wgsl
.compile(WgslCompileOptions {
write_pcb_as_ubo: false,
write_pcb_as_ubo: true,
sampler_bind_group: 1,
})
.unwrap();
println!("{}", compiled.vertex);
println!("{}", compiled.fragment);
// println!("{}", compiled.fragment);
// let mut loader = rspirv::dr::Loader::new();

View file

@ -1,8 +1,8 @@
use crate::error::{SemanticsErrorKind, ShaderCompileError, ShaderReflectError};
use crate::front::GlslangCompilation;
use crate::reflect::semantics::{
BindingMeta, BindingStage, MemberOffset, PushReflection, ShaderReflection, ShaderSemantics,
TextureBinding, TextureSemanticMap, TextureSemantics, TextureSizeMeta, TypeInfo, UboReflection,
BindingMeta, BindingStage, MemberOffset, ShaderReflection, ShaderSemantics,
TextureBinding, TextureSemanticMap, TextureSemantics, TextureSizeMeta, TypeInfo, BufferReflection,
UniformMemberBlock, UniqueSemanticMap, UniqueSemantics, ValidateTypeSemantics, VariableMeta,
MAX_BINDINGS_COUNT, MAX_PUSH_BUFFER_SIZE,
};
@ -449,7 +449,7 @@ where
&mut self,
vertex_ubo: Option<&Resource>,
fragment_ubo: Option<&Resource>,
) -> Result<Option<UboReflection>, ShaderReflectError> {
) -> Result<Option<BufferReflection<u32>>, ShaderReflectError> {
if let Some(vertex_ubo) = vertex_ubo {
self.vertex
.set_decoration(vertex_ubo.id, Decoration::Binding, 0)?;
@ -475,7 +475,7 @@ where
}
let size = std::cmp::max(vertex_ubo.size, fragment_ubo.size);
Ok(Some(UboReflection {
Ok(Some(BufferReflection {
binding: vertex_ubo.binding,
size: align_uniform_size(size),
stage_mask: BindingStage::VERTEX | BindingStage::FRAGMENT,
@ -484,7 +484,7 @@ where
(Some(vertex_ubo), None) => {
let vertex_ubo =
Self::get_ubo_data(&self.vertex, vertex_ubo, SemanticErrorBlame::Vertex)?;
Ok(Some(UboReflection {
Ok(Some(BufferReflection {
binding: vertex_ubo.binding,
size: align_uniform_size(vertex_ubo.size),
stage_mask: BindingStage::VERTEX,
@ -493,7 +493,7 @@ where
(None, Some(fragment_ubo)) => {
let fragment_ubo =
Self::get_ubo_data(&self.fragment, fragment_ubo, SemanticErrorBlame::Fragment)?;
Ok(Some(UboReflection {
Ok(Some(BufferReflection {
binding: fragment_ubo.binding,
size: align_uniform_size(fragment_ubo.size),
stage_mask: BindingStage::FRAGMENT,
@ -569,7 +569,7 @@ where
&mut self,
vertex_pcb: Option<&Resource>,
fragment_pcb: Option<&Resource>,
) -> Result<Option<PushReflection>, ShaderReflectError> {
) -> Result<Option<BufferReflection<Option<u32>>>, ShaderReflectError> {
if let Some(vertex_pcb) = vertex_pcb {
self.vertex
.set_decoration(vertex_pcb.id, Decoration::Binding, 1)?;
@ -593,7 +593,8 @@ where
let size = std::cmp::max(vertex_size, fragment_size);
Ok(Some(PushReflection {
Ok(Some(BufferReflection {
binding: None,
size: align_uniform_size(size),
stage_mask: BindingStage::VERTEX | BindingStage::FRAGMENT,
}))
@ -601,7 +602,8 @@ where
(Some(vertex_push), None) => {
let vertex_size =
Self::get_push_size(&self.vertex, vertex_push, SemanticErrorBlame::Vertex)?;
Ok(Some(PushReflection {
Ok(Some(BufferReflection {
binding: None,
size: align_uniform_size(vertex_size),
stage_mask: BindingStage::VERTEX,
}))
@ -612,7 +614,8 @@ where
fragment_push,
SemanticErrorBlame::Fragment,
)?;
Ok(Some(PushReflection {
Ok(Some(BufferReflection {
binding: None,
size: align_uniform_size(fragment_size),
stage_mask: BindingStage::FRAGMENT,
}))

View file

@ -7,8 +7,8 @@ use naga::{
use crate::reflect::helper::{SemanticErrorBlame, TextureData, UboData};
use crate::reflect::semantics::{
BindingMeta, BindingStage, MemberOffset, PushReflection, ShaderSemantics, TextureBinding,
TextureSemanticMap, TextureSemantics, TextureSizeMeta, TypeInfo, UboReflection,
BindingMeta, BindingStage, MemberOffset, ShaderSemantics, TextureBinding,
TextureSemanticMap, TextureSemantics, TextureSizeMeta, TypeInfo, BufferReflection,
UniformMemberBlock, UniqueSemanticMap, UniqueSemantics, ValidateTypeSemantics, VariableMeta,
MAX_BINDINGS_COUNT, MAX_PUSH_BUFFER_SIZE,
};
@ -105,23 +105,7 @@ impl NagaReflect {
&mut self,
vertex_ubo: Option<Handle<GlobalVariable>>,
fragment_ubo: Option<Handle<GlobalVariable>>,
) -> Result<Option<UboReflection>, ShaderReflectError> {
if let Some(vertex_ubo) = vertex_ubo {
let ubo = &mut self.vertex.global_variables[vertex_ubo];
ubo.binding = Some(ResourceBinding {
group: 0,
binding: 0,
})
}
if let Some(fragment_ubo) = fragment_ubo {
let ubo = &mut self.fragment.global_variables[fragment_ubo];
ubo.binding = Some(ResourceBinding {
group: 0,
binding: 0,
})
}
) -> Result<Option<BufferReflection<u32>>, ShaderReflectError> {
// todo: merge this with the spirv-cross code
match (vertex_ubo, fragment_ubo) {
(None, None) => Ok(None),
@ -144,7 +128,7 @@ impl NagaReflect {
}
let size = std::cmp::max(vertex_ubo.size, fragment_ubo.size);
Ok(Some(UboReflection {
Ok(Some(BufferReflection {
binding: vertex_ubo.binding,
size: align_uniform_size(size),
stage_mask: BindingStage::VERTEX | BindingStage::FRAGMENT,
@ -156,7 +140,7 @@ impl NagaReflect {
&self.vertex.global_variables[vertex_ubo],
SemanticErrorBlame::Vertex,
)?;
Ok(Some(UboReflection {
Ok(Some(BufferReflection {
binding: vertex_ubo.binding,
size: align_uniform_size(vertex_ubo.size),
stage_mask: BindingStage::VERTEX,
@ -168,7 +152,7 @@ impl NagaReflect {
&self.fragment.global_variables[fragment_ubo],
SemanticErrorBlame::Fragment,
)?;
Ok(Some(UboReflection {
Ok(Some(BufferReflection {
binding: fragment_ubo.binding,
size: align_uniform_size(fragment_ubo.size),
stage_mask: BindingStage::FRAGMENT,
@ -203,6 +187,34 @@ impl NagaReflect {
size,
})
}
fn get_next_binding(&self, bind_group: u32) -> u32{
let mut max_bind = 0;
for (_, gv) in self.vertex
.global_variables.iter() {
let Some(binding) = &gv.binding else {
continue;
};
if binding.group != bind_group {
continue;
}
max_bind = std::cmp::max(max_bind, binding.binding);
}
for (_, gv) in self.fragment
.global_variables.iter() {
let Some(binding) = &gv.binding else {
continue;
};
if binding.group != bind_group {
continue;
}
max_bind = std::cmp::max(max_bind, binding.binding);
}
max_bind + 1
}
fn get_push_size(
module: &Module,
push: &GlobalVariable,
@ -220,13 +232,14 @@ impl NagaReflect {
&mut self,
vertex_pcb: Option<Handle<GlobalVariable>>,
fragment_pcb: Option<Handle<GlobalVariable>>,
) -> Result<Option<PushReflection>, ShaderReflectError> {
) -> Result<Option<BufferReflection<Option<u32>>>, ShaderReflectError> {
let binding = self.get_next_binding(0);
// Reassign to UBO later if we want during compilation.
if let Some(vertex_pcb) = vertex_pcb {
let ubo = &mut self.vertex.global_variables[vertex_pcb];
ubo.binding = Some(ResourceBinding {
group: 0,
binding: 1,
binding,
});
}
@ -234,7 +247,7 @@ impl NagaReflect {
let ubo = &mut self.fragment.global_variables[fragment_pcb];
ubo.binding = Some(ResourceBinding {
group: 0,
binding: 1,
binding,
});
};
@ -254,7 +267,8 @@ impl NagaReflect {
let size = std::cmp::max(vertex_size, fragment_size);
Ok(Some(PushReflection {
Ok(Some(BufferReflection {
binding: Some(binding),
size: align_uniform_size(size),
stage_mask: BindingStage::VERTEX | BindingStage::FRAGMENT,
}))
@ -265,7 +279,8 @@ impl NagaReflect {
&self.vertex.global_variables[vertex_push],
SemanticErrorBlame::Vertex,
)?;
Ok(Some(PushReflection {
Ok(Some(BufferReflection {
binding: Some(binding),
size: align_uniform_size(vertex_size),
stage_mask: BindingStage::VERTEX,
}))
@ -276,7 +291,8 @@ impl NagaReflect {
&self.fragment.global_variables[fragment_push],
SemanticErrorBlame::Fragment,
)?;
Ok(Some(PushReflection {
Ok(Some(BufferReflection {
binding: Some(binding),
size: align_uniform_size(fragment_size),
stage_mask: BindingStage::FRAGMENT,
}))

View file

@ -169,26 +169,17 @@ bitflags! {
}
}
/// Reflection information for the Uniform Buffer
/// Reflection information for the Uniform Buffer or Push Constant Block
#[derive(Debug)]
pub struct UboReflection {
/// The binding point for this UBO.
pub binding: u32,
/// The size of the UBO buffer. UBO sizes returned by reflection is always aligned to a 16 byte boundary.
pub struct BufferReflection<T> {
/// The binding point for this buffer, if applicable
pub binding: T,
/// The size of the buffer. Buffer sizes returned by reflection is always aligned to a 16 byte boundary.
pub size: u32,
/// The mask indicating for which stages the UBO should be bound.
pub stage_mask: BindingStage,
}
/// Reflection information for the Push Constant Block
#[derive(Debug)]
pub struct PushReflection {
/// The size of the Push Constant range. The size returned by reflection is always aligned to a 16 byte boundary.
pub size: u32,
/// The mask indicating for which stages the Push Constant range should be bound.
pub stage_mask: BindingStage,
}
/// The offset of a uniform member.
///
/// A uniform can be bound to both the UBO, or as a Push Constant.
@ -279,9 +270,9 @@ pub struct TextureBinding {
#[derive(Debug)]
pub struct ShaderReflection {
/// Reflection information about the UBO for this shader.
pub ubo: Option<UboReflection>,
pub ubo: Option<BufferReflection<u32>>,
/// Reflection information about the Push Constant range for this shader.
pub push_constant: Option<PushReflection>,
pub push_constant: Option<BufferReflection<Option<u32>>>,
/// Metadata about the bindings required for this shader.
pub meta: BindingMeta,
}

View file

@ -13,7 +13,7 @@ use librashader_runtime_d3d11::options::FilterChainOptionsD3D11;
// "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID].slangp";
const FILTER_PATH: &str =
"../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp";
"../test/shaders-slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp";
// const FILTER_PATH: &str = "../test/slang-shaders/test/history.slangp";
// const FILTER_PATH: &str = "../test/slang-shaders/test/feedback.slangp";

View file

@ -5,9 +5,9 @@ use crate::hello_triangle::{DXSample, SampleCommandLine};
#[test]
fn triangle_d3d12() {
let sample = hello_triangle::d3d12_hello_triangle::Sample::new(
//"../test/shaders_slang/crt/crt-lottes.slangp",
// "../test/shaders_slang/crt/crt-lottes.slangp",
// "../test/basic.slangp",
"../test/shaders_slang/handheld/console-border/gbc-lcd-grid-v2.slangp",
// "../test/shaders_slang/handheld/console-border/gbc-lcd-grid-v2.slangp",
// "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID]-[Night].slangp",
// "../test/slang-shaders/test/feedback.slangp",
// "../test/slang-shaders/test/history.slangp",

View file

@ -1,7 +1,7 @@
use crate::binding::UniformLocation;
use crate::gl::UboRing;
use gl::types::{GLsizei, GLsizeiptr, GLuint};
use librashader_reflect::reflect::semantics::UboReflection;
use librashader_reflect::reflect::semantics::BufferReflection;
use librashader_runtime::ringbuffer::InlineRingBuffer;
use librashader_runtime::ringbuffer::RingBuffer;
use librashader_runtime::uniforms::UniformStorageAccess;
@ -31,7 +31,7 @@ impl<const SIZE: usize> UboRing<SIZE> for Gl3UboRing<SIZE> {
fn bind_for_frame(
&mut self,
ubo: &UboReflection,
ubo: &BufferReflection<u32>,
ubo_location: &UniformLocation<GLuint>,
storage: &impl UniformStorageAccess,
) {

View file

@ -1,7 +1,7 @@
use crate::binding::UniformLocation;
use crate::gl::UboRing;
use gl::types::{GLsizei, GLsizeiptr, GLuint};
use librashader_reflect::reflect::semantics::UboReflection;
use librashader_reflect::reflect::semantics::BufferReflection;
use librashader_runtime::ringbuffer::InlineRingBuffer;
use librashader_runtime::ringbuffer::RingBuffer;
use librashader_runtime::uniforms::UniformStorageAccess;
@ -30,7 +30,7 @@ impl<const SIZE: usize> UboRing<SIZE> for Gl46UboRing<SIZE> {
fn bind_for_frame(
&mut self,
ubo: &UboReflection,
ubo: &BufferReflection<u32>,
ubo_location: &UniformLocation<GLuint>,
storage: &impl UniformStorageAccess,
) {

View file

@ -13,7 +13,7 @@ use librashader_common::{ImageFormat, Size};
use librashader_presets::{Scale2D, TextureConfig};
use librashader_reflect::back::cross::CrossGlslContext;
use librashader_reflect::back::ShaderCompilerOutput;
use librashader_reflect::reflect::semantics::{TextureBinding, UboReflection};
use librashader_reflect::reflect::semantics::{TextureBinding, BufferReflection};
use librashader_runtime::uniforms::UniformStorageAccess;
use rustc_hash::FxHashMap;
@ -38,7 +38,7 @@ pub(crate) trait UboRing<const SIZE: usize> {
fn new(buffer_size: u32) -> Self;
fn bind_for_frame(
&mut self,
ubo: &UboReflection,
ubo: &BufferReflection<u32>,
ubo_location: &UniformLocation<GLuint>,
storage: &impl UniformStorageAccess,
);

View file

@ -9,7 +9,7 @@ fn triangle_gl() {
unsafe {
let mut filter = FilterChainGL::load_from_path(
"../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
"../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
Some(&FilterChainOptionsGL {
glsl_version: 0,
use_dsa: false,
@ -30,8 +30,8 @@ fn triangle_gl46() {
let mut filter = FilterChainGL::load_from_path(
// "../test/slang-shaders/vhs/VHSPro.slangp",
// "../test/slang-shaders/test/history.slangp",
// "../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
"../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
"../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
// "../test/shadersslang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
Some(&FilterChainOptionsGL {
glsl_version: 0,
use_dsa: true,

View file

@ -7,7 +7,7 @@ use crate::render_pass::VulkanRenderPass;
use ash::vk::PushConstantRange;
use librashader_cache::cache_pipeline;
use librashader_reflect::back::ShaderCompilerOutput;
use librashader_reflect::reflect::semantics::{TextureBinding, UboReflection};
use librashader_reflect::reflect::semantics::{TextureBinding, BufferReflection};
use librashader_reflect::reflect::ShaderReflection;
use librashader_runtime::render_target::RenderTarget;
use std::ffi::CStr;
@ -30,10 +30,8 @@ impl PipelineDescriptors {
}
}
pub fn add_ubo_binding(&mut self, ubo_meta: Option<&UboReflection>) {
if let Some(ubo_meta) = ubo_meta
&& !ubo_meta.stage_mask.is_empty()
{
pub fn add_ubo_binding(&mut self, ubo_meta: Option<&BufferReflection<u32>>) {
if let Some(ubo_meta) = ubo_meta && !ubo_meta.stage_mask.is_empty() {
let ubo_mask = util::binding_stage_to_vulkan_stage(ubo_meta.stage_mask);
self.layout_bindings.push(vk::DescriptorSetLayoutBinding {
@ -121,18 +119,6 @@ impl PipelineLayoutObjects {
let pipeline_create_info = pipeline_create_info.push_constant_ranges(push_constant_range);
// let pipeline_create_info = if let Some(push_constant) = &reflection.push_constant {
// let stage_mask = util::binding_stage_to_vulkan_stage(push_constant.stage_mask);
// let push_constant_range = vk::PushConstantRange::builder()
// .stage_flags(stage_mask)
// .size(push_constant.size);
// let push_constant_range = [*push_constant_range];
// pipeline_create_info
// .push_constant_ranges(&push_constant_range)
// } else {
// pipeline_create_info
// };
let layout = unsafe { device.create_pipeline_layout(&pipeline_create_info, None)? };
let pool_info = vk::DescriptorPoolCreateInfo::builder()

View file

@ -11,7 +11,7 @@ fn triangle_vk() {
unsafe {
let filter = FilterChainVulkan::load_from_path(
"../test/shaders_slang/crt/crt-royale.slangp",
"../test/slang-shaders/crt/crt-royale.slangp",
// "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID]-[Night].slangp",
&base,
// "../test/slang-shaders/test/feedback.slancargogp",

View file

@ -11,7 +11,6 @@ librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.2
librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.2" }
librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.2", features = [] }
librashader-runtime = { path = "../librashader-runtime" , version = "0.2.0-beta.2" }
librashader-cache = { path = "../librashader-cache", version = "0.2.0-beta.2" }
wgpu = { version = "0.18.0", features = ["spirv"] }
rustc-hash = "1.1.0"

View file

@ -1,5 +1,5 @@
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
use librashader_reflect::back::targets::SPIRV;
use librashader_reflect::back::targets::{SPIRV, WGSL};
use librashader_reflect::back::{CompileReflectShader, CompileShader};
use librashader_reflect::front::GlslangCompilation;
use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact};
@ -23,6 +23,7 @@ use librashader_runtime::scaling::ScaleFramebuffer;
use rayon::prelude::*;
use wgpu::{CommandBuffer, CommandEncoder, Device, Queue, TextureFormat};
use librashader_common::ImageFormat;
use librashader_reflect::back::wgsl::WgslCompileOptions;
use crate::error;
use crate::error::FilterChainError;
@ -30,20 +31,13 @@ use crate::filter_pass::FilterPass;
use crate::graphics_pipeline::WgpuGraphicsPipeline;
type ShaderPassMeta =
ShaderPassArtifact<impl CompileReflectShader<SPIRV, GlslangCompilation> + Send>;
ShaderPassArtifact<impl CompileReflectShader<WGSL, GlslangCompilation> + Send>;
fn compile_passes(
shaders: Vec<ShaderPassConfig>,
textures: &[TextureConfig],
disable_cache: bool,
) -> Result<(Vec<ShaderPassMeta>, ShaderSemantics), FilterChainError> {
let (passes, semantics) = if !disable_cache {
SPIRV::compile_preset_passes::<CachedCompilation<GlslangCompilation>, FilterChainError>(
shaders, &textures,
)?
} else {
SPIRV::compile_preset_passes::<GlslangCompilation, FilterChainError>(shaders, &textures)?
};
let (passes, semantics) =
WGSL::compile_preset_passes::<GlslangCompilation, FilterChainError>(shaders, &textures)?;
Ok((passes, semantics))
}
@ -92,8 +86,7 @@ impl FilterChainWGPU {
) -> error::Result<FilterChainWGPU>
{
let disable_cache = true;
let (passes, semantics) = compile_passes(preset.shaders, &preset.textures, disable_cache)?;
let (passes, semantics) = compile_passes(preset.shaders, &preset.textures)?;
// let device = vulkan.try_into().map_err(From::from)?;
//
@ -107,7 +100,6 @@ impl FilterChainWGPU {
&device,
passes,
&semantics,
disable_cache,
)?;
//
// let luts = FilterChainVulkan::load_luts(&device, cmd, &preset.textures)?;
@ -175,7 +167,6 @@ impl FilterChainWGPU {
device: &Device,
passes: Vec<ShaderPassMeta>,
semantics: &ShaderSemantics,
disable_cache: bool,
) -> error::Result<Box<[FilterPass]>> {
// let frames_in_flight = std::cmp::max(1, frames_in_flight);
//
@ -184,7 +175,10 @@ impl FilterChainWGPU {
.enumerate()
.map(|(index, (config, source, mut reflect))| {
let reflection = reflect.reflect(index, semantics)?;
let spirv_words = reflect.compile(None)?;
let wgsl = reflect.compile(WgslCompileOptions {
write_pcb_as_ubo: true,
sampler_bind_group: 1,
})?;
let ubo_size = reflection.ubo.as_ref().map_or(0, |ubo| ubo.size as usize);
@ -207,7 +201,7 @@ impl FilterChainWGPU {
let graphics_pipeline = WgpuGraphicsPipeline::new(
device,
&spirv_words,
&wgsl,
&reflection,
render_pass_format.unwrap_or(TextureFormat::R8Unorm)
);
@ -224,7 +218,7 @@ impl FilterChainWGPU {
Ok(FilterPass {
// device: vulkan.device.clone(),
reflection,
compiled: spirv_words,
compiled: wgsl,
uniform_storage,
uniform_bindings,
source,

View file

@ -3,6 +3,7 @@ use rustc_hash::FxHashMap;
use librashader_preprocess::ShaderSource;
use librashader_presets::ShaderPassConfig;
use librashader_reflect::back::ShaderCompilerOutput;
use librashader_reflect::back::wgsl::NagaWgslContext;
use librashader_reflect::reflect::semantics::{MemberOffset, UniformBinding};
use librashader_reflect::reflect::ShaderReflection;
use librashader_runtime::uniforms::{NoUniformBinder, UniformStorage};
@ -10,7 +11,7 @@ use crate::graphics_pipeline::WgpuGraphicsPipeline;
pub struct FilterPass {
pub reflection: ShaderReflection,
pub(crate) compiled: ShaderCompilerOutput<Vec<u32>>,
pub(crate) compiled: ShaderCompilerOutput<String, NagaWgslContext>,
pub(crate) uniform_storage: UniformStorage,
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
pub source: ShaderSource,

View file

@ -1,9 +1,10 @@
use std::borrow::Cow;
use std::num::NonZeroU32;
use std::sync::Arc;
use wgpu::{BindGroup, BindGroupDescriptor, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BufferBindingType, BufferSize, Device, PipelineLayout, PushConstantRange, ShaderModule, ShaderSource, ShaderStages, TextureFormat};
use wgpu::{BindGroup, BindGroupDescriptor, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BufferBindingType, BufferSize, Device, PipelineLayout, PushConstantRange, SamplerBindingType, ShaderModule, ShaderSource, ShaderStages, TextureFormat, TextureSampleType, TextureViewDimension};
use librashader_reflect::back::ShaderCompilerOutput;
use librashader_reflect::reflect::semantics::UboReflection;
use librashader_reflect::back::wgsl::NagaWgslContext;
use librashader_reflect::reflect::semantics::BufferReflection;
use librashader_reflect::reflect::ShaderReflection;
use crate::util;
@ -14,79 +15,120 @@ pub struct WgpuGraphicsPipeline {
pub struct PipelineLayoutObjects {
pub layout: PipelineLayout,
pub bind_groups: Vec<BindGroup>,
pub bind_group_layouts: Vec<BindGroupLayout>
}
//
// pub fn add_ubo_binding(&mut self, ubo_meta: Option<&UboReflection>) {
//
// }
pub fn add_ubo_binding(&mut self, ubo_meta: Option<&UboReflection>) {
}
pub fn add_texture_bindings<'a>(&mut self, textures: impl Iterator<Item = &'a TextureBinding>) {
let texture_mask = vk::ShaderStageFlags::FRAGMENT;
for texture in textures {
self.layout_bindings.push(vk::DescriptorSetLayoutBinding {
binding: texture.binding,
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptor_count: 1,
stage_flags: texture_mask,
p_immutable_samplers: std::ptr::null(),
});
self.pool_sizes.push(vk::DescriptorPoolSize {
ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptor_count: self.replicas,
})
}
}
// pub fn add_texture_bindings<'a>(&mut self, textures: impl Iterator<Item = &'a TextureBinding>) {
// let texture_mask = vk::ShaderStageFlags::FRAGMENT;
// for texture in textures {
// self.layout_bindings.push(vk::DescriptorSetLayoutBinding {
// binding: texture.binding,
// descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
// descriptor_count: 1,
// stage_flags: texture_mask,
// p_immutable_samplers: std::ptr::null(),
// });
//
// self.pool_sizes.push(vk::DescriptorPoolSize {
// ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
// descriptor_count: self.replicas,
// })
// }
// }
impl PipelineLayoutObjects {
pub fn new(
reflection: &ShaderReflection,
device: &Device
) -> Self {
let push_constant_range = reflection.push_constant
.as_ref()
.map(|push_constant| {
let stage_mask = util::binding_stage_to_wgpu_stage(push_constant.stage_mask);
[PushConstantRange {
stages: stage_mask,
range: 0..push_constant.size,
}]
});
let mut bind_group_layouts = Vec::new();
if let Some(ubo_meta) = reflection.ubo.as_ref() && !ubo_meta.stage_mask.is_empty() {
let ubo_mask = util::binding_stage_to_wgpu_stage(ubo_meta.stage_mask);
let mut main_bindings = Vec::new();
let mut sampler_bindings = Vec::new();
let ubo_bind_group = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: Some("ubo bind group"),
entries: &[BindGroupLayoutEntry {
binding: ubo_meta.binding,
visibility: ubo_mask,
let mut push_constant_range = Vec::new();
if let Some(push_meta) = reflection.push_constant.as_ref() && !push_meta.stage_mask.is_empty() {
let push_mask = util::binding_stage_to_wgpu_stage(push_meta.stage_mask);
if let Some(binding) = push_meta.binding {
main_bindings.push(BindGroupLayoutEntry {
binding,
visibility: push_mask,
ty: BindingType::Buffer {
ty: BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: BufferSize::new(ubo_meta.size as u64),
min_binding_size: BufferSize::new(push_meta.size as u64),
},
count: Some(NonZeroU32::MIN),
}],
count: None,
});
} else {
push_constant_range.push(PushConstantRange {
stages: push_mask,
range: 0..push_meta.size,
})
}
}
if let Some(ubo_meta) = reflection.ubo.as_ref() && !ubo_meta.stage_mask.is_empty() {
let ubo_mask = util::binding_stage_to_wgpu_stage(ubo_meta.stage_mask);
main_bindings.push(BindGroupLayoutEntry {
binding: ubo_meta.binding,
visibility: ubo_mask,
ty: BindingType::Buffer {
ty: BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: BufferSize::new(ubo_meta.size as u64),
},
count: None,
});
}
for texture in reflection.meta.texture_meta.values() {
main_bindings.push(BindGroupLayoutEntry {
binding: texture.binding,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture {
sample_type: TextureSampleType::Float { filterable: true },
view_dimension: TextureViewDimension::D2,
multisampled: false,
},
count: None,
});
bind_group_layouts.push(ubo_bind_group)
sampler_bindings.push(BindGroupLayoutEntry {
binding: texture.binding,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler(SamplerBindingType::Filtering),
count: None,
})
}
let main_bind_group = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: Some("bind group 0"),
entries: &main_bindings,
});
let sampler_bind_group = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: Some("bind group 1"),
entries: &sampler_bindings,
});
bind_group_layouts.push(main_bind_group);
bind_group_layouts.push(sampler_bind_group);
let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("shader pipeline layout"),
bind_group_layouts: &[],
push_constant_ranges: push_constant_range.as_ref()
.unwrap_or(&[]),
bind_group_layouts: &bind_group_layouts.as_ref(),
push_constant_ranges: &push_constant_range.as_ref(),
});
Self {
layout,
bind_groups: vec![],
bind_group_layouts
}
}
@ -97,26 +139,19 @@ impl PipelineLayoutObjects {
impl WgpuGraphicsPipeline {
pub fn new(
device: &Device,
shader_assembly: &ShaderCompilerOutput<Vec<u32>>,
shader_assembly: &ShaderCompilerOutput<String, NagaWgslContext>,
reflection: &ShaderReflection,
render_pass_format: TextureFormat,
) -> Self {
// todo: naga shaders man.
let vertex = unsafe {
device.create_shader_module_spirv(&wgpu::ShaderModuleDescriptorSpirV {
let vertex = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("vertex"),
source: Cow::from(&shader_assembly.vertex),
})
};
let fragment = unsafe {
device.create_shader_module_spirv(&wgpu::ShaderModuleDescriptorSpirV {
label: Some("fragment"),
source: Cow::from(&shader_assembly.fragment),
})
};
source: ShaderSource::Wgsl(Cow::from(&shader_assembly.vertex))
});
let fragment = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("fragment"),
source: ShaderSource::Wgsl(Cow::from(&shader_assembly.fragment))
});
Self {

View file

@ -92,7 +92,7 @@ impl State {
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
features: wgpu::Features::PUSH_CONSTANTS | wgpu::Features::SPIRV_SHADER_PASSTHROUGH,
features: wgpu::Features::default(),
limits: wgpu::Limits::default(),
label: None,
},