mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
hlsl: special constants for base vertex/index
This commit is contained in:
committed by
Dzmitry Malyshau
parent
d3243bd774
commit
a7ac13a61d
@@ -92,14 +92,18 @@ pub struct Options {
|
||||
pub binding_map: BindingMap,
|
||||
/// Don't panic on missing bindings, instead generate any HLSL.
|
||||
pub fake_missing_bindings: bool,
|
||||
/// Add special constants to `SV_VertexIndex` and `SV_InstanceIndex`,
|
||||
/// to make them work like in Vulkan/Metal, with help of the host.
|
||||
pub special_constants_binding: Option<BindTarget>,
|
||||
}
|
||||
|
||||
impl Default for Options {
|
||||
fn default() -> Self {
|
||||
Options {
|
||||
shader_model: ShaderModel::V5_0,
|
||||
shader_model: ShaderModel::V5_1,
|
||||
binding_map: BindingMap::default(),
|
||||
fake_missing_bindings: true,
|
||||
special_constants_binding: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@ use crate::{
|
||||
use std::fmt;
|
||||
|
||||
const LOCATION_SEMANTIC: &str = "LOC";
|
||||
const SPECIAL_CBUF_TYPE: &str = "NagaConstants";
|
||||
const SPECIAL_CBUF_VAR: &str = "_NagaConstants";
|
||||
const SPECIAL_BASE_VERTEX: &str = "base_vertex";
|
||||
const SPECIAL_BASE_INSTANCE: &str = "base_instance";
|
||||
|
||||
/// Structure contains information required for generating
|
||||
/// wrapped structure of all entry points arguments
|
||||
@@ -65,6 +69,23 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||
) -> Result<super::ReflectionInfo, Error> {
|
||||
self.reset(module);
|
||||
|
||||
// Write special constants, if needed
|
||||
if let Some(ref bt) = self.options.special_constants_binding {
|
||||
writeln!(self.out, "struct {} {{", SPECIAL_CBUF_TYPE)?;
|
||||
writeln!(self.out, "{}int {};", back::INDENT, SPECIAL_BASE_VERTEX)?;
|
||||
writeln!(self.out, "{}int {};", back::INDENT, SPECIAL_BASE_INSTANCE)?;
|
||||
writeln!(self.out, "}};")?;
|
||||
write!(
|
||||
self.out,
|
||||
"ConstantBuffer<{}> {}: register(b{}",
|
||||
SPECIAL_CBUF_TYPE, SPECIAL_CBUF_VAR, bt.register
|
||||
)?;
|
||||
if bt.space != 0 {
|
||||
write!(self.out, ", space{}", bt.space)?;
|
||||
}
|
||||
writeln!(self.out, ");")?;
|
||||
}
|
||||
|
||||
// Write all constants
|
||||
// For example, input wgsl shader:
|
||||
// ```wgsl
|
||||
@@ -410,7 +431,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||
// this was already resolved earlier when we started evaluating an entry point.
|
||||
let bt = self.options.resolve_resource_binding(binding).unwrap();
|
||||
write!(self.out, " : register({}{}", register_ty, bt.register)?;
|
||||
if self.options.shader_model > super::ShaderModel::V5_0 {
|
||||
if bt.space != 0 {
|
||||
write!(self.out, ", space{}", bt.space)?;
|
||||
}
|
||||
write!(self.out, ")")?;
|
||||
@@ -1105,8 +1126,30 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||
) -> BackendResult {
|
||||
use crate::Expression;
|
||||
|
||||
// Handle the special semantics for base vertex/instance
|
||||
let ff_input = if self.options.special_constants_binding.is_some() {
|
||||
func_ctx.is_fixed_function_input(expr, module)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let closing_bracket = match ff_input {
|
||||
Some(crate::BuiltIn::VertexIndex) => {
|
||||
write!(self.out, "({}.{} + ", SPECIAL_CBUF_VAR, SPECIAL_BASE_VERTEX)?;
|
||||
")"
|
||||
}
|
||||
Some(crate::BuiltIn::InstanceIndex) => {
|
||||
write!(
|
||||
self.out,
|
||||
"({}.{} + ",
|
||||
SPECIAL_CBUF_VAR, SPECIAL_BASE_INSTANCE
|
||||
)?;
|
||||
")"
|
||||
}
|
||||
_ => "",
|
||||
};
|
||||
|
||||
if let Some(name) = self.named_expressions.get(&expr) {
|
||||
write!(self.out, "{}", name)?;
|
||||
write!(self.out, "{}{}", name, closing_bracket)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -1627,6 +1670,9 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||
_ => return Err(Error::Unimplemented(format!("write_expr {:?}", expression))),
|
||||
}
|
||||
|
||||
if !closing_bracket.is_empty() {
|
||||
write!(self.out, "{}", closing_bracket)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,43 @@ impl<'a> FunctionCtx<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the given expression points to a fixed-function pipeline input.
|
||||
fn is_fixed_function_input(
|
||||
&self,
|
||||
mut expression: crate::Handle<crate::Expression>,
|
||||
module: &crate::Module,
|
||||
) -> Option<crate::BuiltIn> {
|
||||
let ep_function = match self.ty {
|
||||
FunctionType::Function(_) => return None,
|
||||
FunctionType::EntryPoint(ep_index) => &module.entry_points[ep_index as usize].function,
|
||||
};
|
||||
let mut built_in = None;
|
||||
loop {
|
||||
match self.expressions[expression] {
|
||||
crate::Expression::FunctionArgument(arg_index) => {
|
||||
return match ep_function.arguments[arg_index as usize].binding {
|
||||
Some(crate::Binding::BuiltIn(bi)) => Some(bi),
|
||||
_ => built_in,
|
||||
};
|
||||
}
|
||||
crate::Expression::AccessIndex { base, index } => {
|
||||
match *self.info[base].ty.inner_with(&module.types) {
|
||||
crate::TypeInner::Struct { ref members, .. } => {
|
||||
if let Some(crate::Binding::BuiltIn(bi)) =
|
||||
members[index as usize].binding
|
||||
{
|
||||
built_in = Some(bi);
|
||||
}
|
||||
}
|
||||
_ => return None,
|
||||
}
|
||||
expression = base;
|
||||
}
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// How should code generated by Naga do indexing bounds checks?
|
||||
|
||||
@@ -53,5 +53,6 @@
|
||||
(group: 0, binding: 2): (space: 1, register: 0),
|
||||
},
|
||||
fake_missing_bindings: false,
|
||||
special_constants_binding: Some((space: 0, register: 1)),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=(foo:vs_5_0 )
|
||||
vertex=(foo:vs_5_1 )
|
||||
fragment=()
|
||||
compute=()
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=()
|
||||
fragment=()
|
||||
compute=(main:cs_5_0 )
|
||||
compute=(main:cs_5_1 )
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=()
|
||||
fragment=()
|
||||
compute=(main:cs_5_0 )
|
||||
compute=(main:cs_5_1 )
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=()
|
||||
fragment=()
|
||||
compute=(main:cs_5_0 )
|
||||
compute=(main:cs_5_1 )
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=()
|
||||
fragment=()
|
||||
compute=(main:cs_5_0 )
|
||||
compute=(main:cs_5_1 )
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=()
|
||||
fragment=()
|
||||
compute=(main:cs_5_0 )
|
||||
compute=(main:cs_5_1 )
|
||||
|
||||
@@ -11,9 +11,9 @@ TextureCube<float4> image_cube : register(t3);
|
||||
TextureCubeArray<float4> image_cube_array : register(t4);
|
||||
Texture3D<float4> image_3d : register(t5);
|
||||
Texture2DMS<float4> image_aa : register(t6);
|
||||
SamplerState sampler_reg : register(s0);
|
||||
SamplerComparisonState sampler_cmp : register(s1);
|
||||
Texture2D<float> image_2d_depth : register(t2);
|
||||
SamplerState sampler_reg : register(s0, space1);
|
||||
SamplerComparisonState sampler_cmp : register(s1, space1);
|
||||
Texture2D<float> image_2d_depth : register(t2, space1);
|
||||
|
||||
struct ComputeInput_main {
|
||||
uint3 local_id1 : SV_GroupThreadID;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=(queries:vs_5_0 )
|
||||
fragment=(sample1:ps_5_0 sample_comparison:ps_5_0 )
|
||||
compute=(main:cs_5_0 )
|
||||
vertex=(queries:vs_5_1 )
|
||||
fragment=(sample1:ps_5_1 sample_comparison:ps_5_1 )
|
||||
compute=(main:cs_5_1 )
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=(vertex:vs_5_0 )
|
||||
fragment=(fragment:ps_5_0 )
|
||||
compute=(compute:cs_5_0 )
|
||||
vertex=(vertex:vs_5_1 )
|
||||
fragment=(fragment:ps_5_1 )
|
||||
compute=(compute:cs_5_1 )
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=(main:vs_5_0 )
|
||||
fragment=(main1:ps_5_0 )
|
||||
vertex=(main:vs_5_1 )
|
||||
fragment=(main1:ps_5_1 )
|
||||
compute=()
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=()
|
||||
fragment=()
|
||||
compute=(main:cs_5_0 )
|
||||
compute=(main:cs_5_1 )
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=(main:vs_5_0 )
|
||||
vertex=(main:vs_5_1 )
|
||||
fragment=()
|
||||
compute=()
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=(main:vs_5_0 )
|
||||
fragment=(main1:ps_5_0 fs_extra:ps_5_0 )
|
||||
vertex=(main:vs_5_1 )
|
||||
fragment=(main1:ps_5_1 fs_extra:ps_5_1 )
|
||||
compute=()
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=()
|
||||
fragment=(fs_main:ps_5_0 )
|
||||
fragment=(fs_main:ps_5_1 )
|
||||
compute=()
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
struct NagaConstants {
|
||||
int base_vertex;
|
||||
int base_instance;
|
||||
};
|
||||
ConstantBuffer<NagaConstants> _NagaConstants: register(b1);
|
||||
|
||||
struct VertexOutput {
|
||||
float4 position : SV_Position;
|
||||
@@ -9,8 +14,8 @@ struct Data {
|
||||
float4x4 view;
|
||||
};
|
||||
|
||||
cbuffer r_data : register(b0, space0) { Data r_data; }
|
||||
TextureCube<float4> r_texture : register(t0, space0);
|
||||
cbuffer r_data : register(b0) { Data r_data; }
|
||||
TextureCube<float4> r_texture : register(t0);
|
||||
SamplerState r_sampler : register(s0, space1);
|
||||
|
||||
struct VertexInput_vs_main {
|
||||
@@ -26,8 +31,8 @@ VertexOutput vs_main(VertexInput_vs_main vertexinput_vs_main)
|
||||
int tmp1_ = (int)0;
|
||||
int tmp2_ = (int)0;
|
||||
|
||||
tmp1_ = (int(vertexinput_vs_main.vertex_index1) / 2);
|
||||
tmp2_ = (int(vertexinput_vs_main.vertex_index1) & 1);
|
||||
tmp1_ = (int((_NagaConstants.base_vertex + vertexinput_vs_main.vertex_index1)) / 2);
|
||||
tmp2_ = (int((_NagaConstants.base_vertex + vertexinput_vs_main.vertex_index1)) & 1);
|
||||
int _expr10 = tmp1_;
|
||||
int _expr16 = tmp2_;
|
||||
float4 pos = float4(((float(_expr10) * 4.0) - 1.0), ((float(_expr16) * 4.0) - 1.0), 0.0, 1.0);
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=()
|
||||
fragment=(derivatives:ps_5_0 )
|
||||
fragment=(derivatives:ps_5_1 )
|
||||
compute=()
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
vertex=()
|
||||
fragment=(main:ps_5_0 )
|
||||
fragment=(main:ps_5_1 )
|
||||
compute=()
|
||||
|
||||
Reference in New Issue
Block a user