Skip to content

Commit

Permalink
feat(wgsl): add first and either sampling types
Browse files Browse the repository at this point in the history
  • Loading branch information
ErichDonGubler committed Aug 29, 2024
1 parent 0ce5996 commit c8831c5
Show file tree
Hide file tree
Showing 18 changed files with 484 additions and 253 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions naga/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ cfg_aliases.workspace = true
[dev-dependencies]
diff = "0.1"
env_logger.workspace = true
itertools.workspace = true
# This _cannot_ have a version specified. If it does, crates.io will look
# for a version of the package on crates when we publish naga. Path dependencies
# are allowed through though.
Expand Down
2 changes: 1 addition & 1 deletion naga/src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4774,7 +4774,7 @@ const fn glsl_sampling(sampling: crate::Sampling) -> Option<&'static str> {
use crate::Sampling as S;

match sampling {
S::Center => None,
S::Center | S::First | S::Either => None,
S::Centroid => Some("centroid"),
S::Sample => Some("sample"),
}
Expand Down
2 changes: 1 addition & 1 deletion naga/src/back/hlsl/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ impl crate::Sampling {
/// Return the HLSL auxiliary qualifier for the given sampling value.
pub(super) const fn to_hlsl_str(self) -> Option<&'static str> {
match self {
Self::Center => None,
Self::Center | Self::First | Self::Either => None,
Self::Centroid => Some("centroid"),
Self::Sample => Some("sample"),
}
Expand Down
1 change: 1 addition & 0 deletions naga/src/back/msl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,7 @@ impl ResolvedInterpolation {
(I::Linear, S::Centroid) => Self::CentroidNoPerspective,
(I::Linear, S::Sample) => Self::SampleNoPerspective,
(I::Flat, _) => Self::Flat,
_ => unreachable!(),
}
}

Expand Down
7 changes: 6 additions & 1 deletion naga/src/back/spv/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1511,7 +1511,12 @@ impl Writer {
}
match sampling {
// Center sampling is the default in SPIR-V.
None | Some(crate::Sampling::Center) => (),
None
| Some(
crate::Sampling::Center
| crate::Sampling::First
| crate::Sampling::Either,
) => (),
Some(crate::Sampling::Centroid) => {
self.decorate(id, Decoration::Centroid, &[]);
}
Expand Down
2 changes: 1 addition & 1 deletion naga/src/back/wgsl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2050,7 +2050,7 @@ const fn sampling_str(sampling: crate::Sampling) -> &'static str {
use crate::Sampling as S;

match sampling {
S::Center => "",
S::Center | S::First | S::Either => "",
S::Centroid => "centroid",
S::Sample => "sample",
}
Expand Down
2 changes: 2 additions & 0 deletions naga/src/front/wgsl/parse/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ pub fn map_sampling(word: &str, span: Span) -> Result<crate::Sampling, Error<'_>
"center" => Ok(crate::Sampling::Center),
"centroid" => Ok(crate::Sampling::Centroid),
"sample" => Ok(crate::Sampling::Sample),
"first" => Ok(crate::Sampling::First),
"either" => Ok(crate::Sampling::Either),
_ => Err(Error::UnknownAttribute(span)),
}
}
Expand Down
7 changes: 7 additions & 0 deletions naga/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,13 @@ pub enum Sampling {
/// Interpolate the value at each sample location. In multisampling, invoke
/// the fragment shader once per sample.
Sample,

/// Use the value provided by the first vertex of the current primitive.
First,

/// Use the value provided by the first or last vertex of the current primitive. The exact
/// choice is implementation-dependent.
Either,
}

/// Member of a user-defined structure.
Expand Down
30 changes: 30 additions & 0 deletions naga/src/valid/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ pub enum VaryingError {
NotIOShareableType(Handle<crate::Type>),
#[error("Interpolation is not valid")]
InvalidInterpolation,
#[error("Cannot combine {interpolation:?} interpolation with the {sampling:?} sample type")]
InvalidInterpolationSamplingCombination {
interpolation: crate::Interpolation,
sampling: crate::Sampling,
},
#[error("Interpolation must be specified on vertex shader outputs and fragment shader inputs")]
MissingInterpolation,
#[error("Built-in {0:?} is not available at this stage")]
Expand Down Expand Up @@ -339,6 +344,31 @@ impl VaryingContext<'_> {
}
}

if let Some(interpolation) = interpolation {
let invalid_sampling = match (interpolation, sampling) {
(_, None)
| (
crate::Interpolation::Perspective | crate::Interpolation::Linear,
Some(
crate::Sampling::Center
| crate::Sampling::Centroid
| crate::Sampling::Sample,
),
)
| (
crate::Interpolation::Flat,
Some(crate::Sampling::First | crate::Sampling::Either),
) => None,
(_, Some(invalid_sampling)) => Some(invalid_sampling),
};
if let Some(sampling) = invalid_sampling {
return Err(VaryingError::InvalidInterpolationSamplingCombination {
interpolation,
sampling,
});
}
}

let needs_interpolation = match self.stage {
crate::ShaderStage::Vertex => self.output,
crate::ShaderStage::Fragment => !self.output,
Expand Down
18 changes: 12 additions & 6 deletions naga/tests/in/interpolate.wgsl
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
//TODO: merge with "interface"?

// NOTE: invalid combinations are tested in the
// `validation::incompatible_interpolation_and_sampling_types` test.
struct FragmentInput {
@builtin(position) position: vec4<f32>,
@location(0) @interpolate(flat) _flat : u32,
@location(1) @interpolate(linear) _linear : f32,
@location(2) @interpolate(linear, centroid) linear_centroid : vec2<f32>,
@location(3) @interpolate(linear, sample) linear_sample : vec3<f32>,
@location(4) @interpolate(perspective) perspective : vec4<f32>,
@location(5) @interpolate(perspective, centroid) perspective_centroid : f32,
@location(6) @interpolate(perspective, sample) perspective_sample : f32,
@location(1) @interpolate(flat, first) flat_first : u32,
@location(2) @interpolate(flat, either) flat_either : u32,
@location(3) @interpolate(linear) _linear : f32,
@location(4) @interpolate(linear, centroid) linear_centroid : vec2<f32>,
@location(6) @interpolate(linear, sample) linear_sample : vec3<f32>,
@location(7) @interpolate(perspective) perspective : vec4<f32>,
@location(8) @interpolate(perspective, centroid) perspective_centroid : f32,
@location(9) @interpolate(perspective, sample) perspective_sample : f32,
}

@vertex
Expand All @@ -17,6 +21,8 @@ fn vert_main() -> FragmentInput {

out.position = vec4<f32>(2.0, 4.0, 5.0, 6.0);
out._flat = 8u;
out.flat_first = 9u;
out.flat_either = 10u;
out._linear = 27.0;
out.linear_centroid = vec2<f32>(64.0, 125.0);
out.linear_sample = vec3<f32>(216.0, 343.0, 512.0);
Expand Down
18 changes: 11 additions & 7 deletions naga/tests/out/glsl/interpolate.frag_main.Fragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
struct FragmentInput {
vec4 position;
uint _flat;
uint flat_first;
uint flat_either;
float _linear;
vec2 linear_centroid;
vec3 linear_sample;
Expand All @@ -10,15 +12,17 @@ struct FragmentInput {
float perspective_sample;
};
flat in uint _vs2fs_location0;
noperspective in float _vs2fs_location1;
noperspective centroid in vec2 _vs2fs_location2;
noperspective sample in vec3 _vs2fs_location3;
smooth in vec4 _vs2fs_location4;
smooth centroid in float _vs2fs_location5;
smooth sample in float _vs2fs_location6;
flat in uint _vs2fs_location1;
flat in uint _vs2fs_location2;
noperspective in float _vs2fs_location3;
noperspective centroid in vec2 _vs2fs_location4;
noperspective sample in vec3 _vs2fs_location6;
smooth in vec4 _vs2fs_location7;
smooth centroid in float _vs2fs_location8;
smooth sample in float _vs2fs_location9;

void main() {
FragmentInput val = FragmentInput(gl_FragCoord, _vs2fs_location0, _vs2fs_location1, _vs2fs_location2, _vs2fs_location3, _vs2fs_location4, _vs2fs_location5, _vs2fs_location6);
FragmentInput val = FragmentInput(gl_FragCoord, _vs2fs_location0, _vs2fs_location1, _vs2fs_location2, _vs2fs_location3, _vs2fs_location4, _vs2fs_location6, _vs2fs_location7, _vs2fs_location8, _vs2fs_location9);
return;
}

40 changes: 24 additions & 16 deletions naga/tests/out/glsl/interpolate.vert_main.Vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
struct FragmentInput {
vec4 position;
uint _flat;
uint flat_first;
uint flat_either;
float _linear;
vec2 linear_centroid;
vec3 linear_sample;
Expand All @@ -10,32 +12,38 @@ struct FragmentInput {
float perspective_sample;
};
flat out uint _vs2fs_location0;
noperspective out float _vs2fs_location1;
noperspective centroid out vec2 _vs2fs_location2;
noperspective sample out vec3 _vs2fs_location3;
smooth out vec4 _vs2fs_location4;
smooth centroid out float _vs2fs_location5;
smooth sample out float _vs2fs_location6;
flat out uint _vs2fs_location1;
flat out uint _vs2fs_location2;
noperspective out float _vs2fs_location3;
noperspective centroid out vec2 _vs2fs_location4;
noperspective sample out vec3 _vs2fs_location6;
smooth out vec4 _vs2fs_location7;
smooth centroid out float _vs2fs_location8;
smooth sample out float _vs2fs_location9;

void main() {
FragmentInput out_ = FragmentInput(vec4(0.0), 0u, 0.0, vec2(0.0), vec3(0.0), vec4(0.0), 0.0, 0.0);
FragmentInput out_ = FragmentInput(vec4(0.0), 0u, 0u, 0u, 0.0, vec2(0.0), vec3(0.0), vec4(0.0), 0.0, 0.0);
out_.position = vec4(2.0, 4.0, 5.0, 6.0);
out_._flat = 8u;
out_.flat_first = 9u;
out_.flat_either = 10u;
out_._linear = 27.0;
out_.linear_centroid = vec2(64.0, 125.0);
out_.linear_sample = vec3(216.0, 343.0, 512.0);
out_.perspective = vec4(729.0, 1000.0, 1331.0, 1728.0);
out_.perspective_centroid = 2197.0;
out_.perspective_sample = 2744.0;
FragmentInput _e30 = out_;
gl_Position = _e30.position;
_vs2fs_location0 = _e30._flat;
_vs2fs_location1 = _e30._linear;
_vs2fs_location2 = _e30.linear_centroid;
_vs2fs_location3 = _e30.linear_sample;
_vs2fs_location4 = _e30.perspective;
_vs2fs_location5 = _e30.perspective_centroid;
_vs2fs_location6 = _e30.perspective_sample;
FragmentInput _e34 = out_;
gl_Position = _e34.position;
_vs2fs_location0 = _e34._flat;
_vs2fs_location1 = _e34.flat_first;
_vs2fs_location2 = _e34.flat_either;
_vs2fs_location3 = _e34._linear;
_vs2fs_location4 = _e34.linear_centroid;
_vs2fs_location6 = _e34.linear_sample;
_vs2fs_location7 = _e34.perspective;
_vs2fs_location8 = _e34.perspective_centroid;
_vs2fs_location9 = _e34.perspective_sample;
return;
}

52 changes: 30 additions & 22 deletions naga/tests/out/hlsl/interpolate.hlsl
Original file line number Diff line number Diff line change
@@ -1,33 +1,39 @@
struct FragmentInput {
float4 position : SV_Position;
nointerpolation uint _flat : LOC0;
noperspective float _linear : LOC1;
noperspective centroid float2 linear_centroid : LOC2;
noperspective sample float3 linear_sample : LOC3;
float4 perspective : LOC4;
centroid float perspective_centroid : LOC5;
sample float perspective_sample : LOC6;
nointerpolation uint flat_first : LOC1;
nointerpolation uint flat_either : LOC2;
noperspective float _linear : LOC3;
noperspective centroid float2 linear_centroid : LOC4;
noperspective sample float3 linear_sample : LOC6;
float4 perspective : LOC7;
centroid float perspective_centroid : LOC8;
sample float perspective_sample : LOC9;
};

struct VertexOutput_vert_main {
nointerpolation uint _flat : LOC0;
noperspective float _linear : LOC1;
noperspective centroid float2 linear_centroid : LOC2;
noperspective sample float3 linear_sample : LOC3;
float4 perspective : LOC4;
centroid float perspective_centroid : LOC5;
sample float perspective_sample : LOC6;
nointerpolation uint flat_first : LOC1;
nointerpolation uint flat_either : LOC2;
noperspective float _linear : LOC3;
noperspective centroid float2 linear_centroid : LOC4;
noperspective sample float3 linear_sample : LOC6;
float4 perspective : LOC7;
centroid float perspective_centroid : LOC8;
sample float perspective_sample : LOC9;
float4 position : SV_Position;
};

struct FragmentInput_frag_main {
nointerpolation uint _flat_1 : LOC0;
noperspective float _linear_1 : LOC1;
noperspective centroid float2 linear_centroid_1 : LOC2;
noperspective sample float3 linear_sample_1 : LOC3;
float4 perspective_1 : LOC4;
centroid float perspective_centroid_1 : LOC5;
sample float perspective_sample_1 : LOC6;
nointerpolation uint flat_first_1 : LOC1;
nointerpolation uint flat_either_1 : LOC2;
noperspective float _linear_1 : LOC3;
noperspective centroid float2 linear_centroid_1 : LOC4;
noperspective sample float3 linear_sample_1 : LOC6;
float4 perspective_1 : LOC7;
centroid float perspective_centroid_1 : LOC8;
sample float perspective_sample_1 : LOC9;
float4 position_1 : SV_Position;
};

Expand All @@ -37,20 +43,22 @@ VertexOutput_vert_main vert_main()

out_.position = float4(2.0, 4.0, 5.0, 6.0);
out_._flat = 8u;
out_.flat_first = 9u;
out_.flat_either = 10u;
out_._linear = 27.0;
out_.linear_centroid = float2(64.0, 125.0);
out_.linear_sample = float3(216.0, 343.0, 512.0);
out_.perspective = float4(729.0, 1000.0, 1331.0, 1728.0);
out_.perspective_centroid = 2197.0;
out_.perspective_sample = 2744.0;
FragmentInput _e30 = out_;
const FragmentInput fragmentinput = _e30;
const VertexOutput_vert_main fragmentinput_1 = { fragmentinput._flat, fragmentinput._linear, fragmentinput.linear_centroid, fragmentinput.linear_sample, fragmentinput.perspective, fragmentinput.perspective_centroid, fragmentinput.perspective_sample, fragmentinput.position };
FragmentInput _e34 = out_;
const FragmentInput fragmentinput = _e34;
const VertexOutput_vert_main fragmentinput_1 = { fragmentinput._flat, fragmentinput.flat_first, fragmentinput.flat_either, fragmentinput._linear, fragmentinput.linear_centroid, fragmentinput.linear_sample, fragmentinput.perspective, fragmentinput.perspective_centroid, fragmentinput.perspective_sample, fragmentinput.position };
return fragmentinput_1;
}

void frag_main(FragmentInput_frag_main fragmentinput_frag_main)
{
FragmentInput val = { fragmentinput_frag_main.position_1, fragmentinput_frag_main._flat_1, fragmentinput_frag_main._linear_1, fragmentinput_frag_main.linear_centroid_1, fragmentinput_frag_main.linear_sample_1, fragmentinput_frag_main.perspective_1, fragmentinput_frag_main.perspective_centroid_1, fragmentinput_frag_main.perspective_sample_1 };
FragmentInput val = { fragmentinput_frag_main.position_1, fragmentinput_frag_main._flat_1, fragmentinput_frag_main.flat_first_1, fragmentinput_frag_main.flat_either_1, fragmentinput_frag_main._linear_1, fragmentinput_frag_main.linear_centroid_1, fragmentinput_frag_main.linear_sample_1, fragmentinput_frag_main.perspective_1, fragmentinput_frag_main.perspective_centroid_1, fragmentinput_frag_main.perspective_sample_1 };
return;
}
Loading

0 comments on commit c8831c5

Please sign in to comment.