mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-27 01:03:41 +00:00
[spirv-out] Fix adding illegal decorators on fragment outputs. (#2286)
* [spirv-out] Fix adding illegal decorators on fragment outputs. Furthermore, fix allowing to add `Centroid` and `Sample` decorator to vertex inputs. Fixes #2270 * Add test for fragment outputs * Fix fragment-output.wgsl test using more than 8 outputs in a single shader Breaks HLSL & MSL validation * formatting
This commit is contained in:
parent
6db8da72ca
commit
67c081bebe
@ -1407,12 +1407,17 @@ impl Writer {
|
||||
} => {
|
||||
self.decorate(id, Decoration::Location, &[location]);
|
||||
|
||||
// The Vulkan spec says: VUID-StandaloneSpirv-Flat-06202
|
||||
//
|
||||
// > The Flat, NoPerspective, Sample, and Centroid decorations
|
||||
// > must not be used on variables with the Input storage class in
|
||||
// > a vertex shader
|
||||
if class != spirv::StorageClass::Input || stage != crate::ShaderStage::Vertex {
|
||||
let no_decorations =
|
||||
// VUID-StandaloneSpirv-Flat-06202
|
||||
// > The Flat, NoPerspective, Sample, and Centroid decorations
|
||||
// > must not be used on variables with the Input storage class in a vertex shader
|
||||
(class == spirv::StorageClass::Input && stage == crate::ShaderStage::Vertex) ||
|
||||
// VUID-StandaloneSpirv-Flat-06201
|
||||
// > The Flat, NoPerspective, Sample, and Centroid decorations
|
||||
// > must not be used on variables with the Output storage class in a fragment shader
|
||||
(class == spirv::StorageClass::Output && stage == crate::ShaderStage::Fragment);
|
||||
|
||||
if !no_decorations {
|
||||
match interpolation {
|
||||
// Perspective-correct interpolation is the default in SPIR-V.
|
||||
None | Some(crate::Interpolation::Perspective) => (),
|
||||
@ -1423,20 +1428,19 @@ impl Writer {
|
||||
self.decorate(id, Decoration::NoPerspective, &[]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match sampling {
|
||||
// Center sampling is the default in SPIR-V.
|
||||
None | Some(crate::Sampling::Center) => (),
|
||||
Some(crate::Sampling::Centroid) => {
|
||||
self.decorate(id, Decoration::Centroid, &[]);
|
||||
}
|
||||
Some(crate::Sampling::Sample) => {
|
||||
self.require_any(
|
||||
"per-sample interpolation",
|
||||
&[spirv::Capability::SampleRateShading],
|
||||
)?;
|
||||
self.decorate(id, Decoration::Sample, &[]);
|
||||
match sampling {
|
||||
// Center sampling is the default in SPIR-V.
|
||||
None | Some(crate::Sampling::Center) => (),
|
||||
Some(crate::Sampling::Centroid) => {
|
||||
self.decorate(id, Decoration::Centroid, &[]);
|
||||
}
|
||||
Some(crate::Sampling::Sample) => {
|
||||
self.require_any(
|
||||
"per-sample interpolation",
|
||||
&[spirv::Capability::SampleRateShading],
|
||||
)?;
|
||||
self.decorate(id, Decoration::Sample, &[]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
41
tests/in/fragment-output.wgsl
Normal file
41
tests/in/fragment-output.wgsl
Normal file
@ -0,0 +1,41 @@
|
||||
// Split up because some output languages limit number of locations to 8.
|
||||
struct FragmentOutputVec4Vec3 {
|
||||
@location(0) vec4f: vec4<f32>,
|
||||
@location(1) vec4i: vec4<i32>,
|
||||
@location(2) vec4u: vec4<u32>,
|
||||
@location(3) vec3f: vec3<f32>,
|
||||
@location(4) vec3i: vec3<i32>,
|
||||
@location(5) vec3u: vec3<u32>,
|
||||
}
|
||||
@fragment
|
||||
fn main_vec4vec3() -> FragmentOutputVec4Vec3 {
|
||||
var output: FragmentOutputVec4Vec3;
|
||||
output.vec4f = vec4<f32>(0.0);
|
||||
output.vec4i = vec4<i32>(0);
|
||||
output.vec4u = vec4<u32>(0u);
|
||||
output.vec3f = vec3<f32>(0.0);
|
||||
output.vec3i = vec3<i32>(0);
|
||||
output.vec3u = vec3<u32>(0u);
|
||||
return output;
|
||||
}
|
||||
|
||||
struct FragmentOutputVec2Scalar {
|
||||
@location(0) vec2f: vec2<f32>,
|
||||
@location(1) vec2i: vec2<i32>,
|
||||
@location(2) vec2u: vec2<u32>,
|
||||
@location(3) scalarf: f32,
|
||||
@location(4) scalari: i32,
|
||||
@location(5) scalaru: u32,
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn main_vec2scalar() -> FragmentOutputVec2Scalar {
|
||||
var output: FragmentOutputVec2Scalar;
|
||||
output.vec2f = vec2<f32>(0.0);
|
||||
output.vec2i = vec2<i32>(0);
|
||||
output.vec2u = vec2<u32>(0u);
|
||||
output.scalarf = 0.0;
|
||||
output.scalari = 0;
|
||||
output.scalaru = 0u;
|
||||
return output;
|
||||
}
|
62
tests/out/glsl/fragment-output.main.Fragment.glsl
Normal file
62
tests/out/glsl/fragment-output.main.Fragment.glsl
Normal file
@ -0,0 +1,62 @@
|
||||
#version 310 es
|
||||
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
|
||||
struct FragmentOutput {
|
||||
vec4 vec4f;
|
||||
ivec4 vec4i;
|
||||
uvec4 vec4u;
|
||||
vec3 vec3f;
|
||||
ivec3 vec3i;
|
||||
uvec3 vec3u;
|
||||
vec2 vec2f;
|
||||
ivec2 vec2i;
|
||||
uvec2 vec2u;
|
||||
float scalarf;
|
||||
int scalari;
|
||||
uint scalaru;
|
||||
};
|
||||
layout(location = 0) out vec4 _fs2p_location0;
|
||||
layout(location = 1) out ivec4 _fs2p_location1;
|
||||
layout(location = 2) out uvec4 _fs2p_location2;
|
||||
layout(location = 3) out vec3 _fs2p_location3;
|
||||
layout(location = 4) out ivec3 _fs2p_location4;
|
||||
layout(location = 5) out uvec3 _fs2p_location5;
|
||||
layout(location = 6) out vec2 _fs2p_location6;
|
||||
layout(location = 7) out ivec2 _fs2p_location7;
|
||||
layout(location = 8) out uvec2 _fs2p_location8;
|
||||
layout(location = 9) out float _fs2p_location9;
|
||||
layout(location = 10) out int _fs2p_location10;
|
||||
layout(location = 11) out uint _fs2p_location11;
|
||||
|
||||
void main() {
|
||||
FragmentOutput output_ = FragmentOutput(vec4(0.0), ivec4(0), uvec4(0u), vec3(0.0), ivec3(0), uvec3(0u), vec2(0.0), ivec2(0), uvec2(0u), 0.0, 0, 0u);
|
||||
output_.vec4f = vec4(0.0);
|
||||
output_.vec4i = ivec4(0);
|
||||
output_.vec4u = uvec4(0u);
|
||||
output_.vec3f = vec3(0.0);
|
||||
output_.vec3i = ivec3(0);
|
||||
output_.vec3u = uvec3(0u);
|
||||
output_.vec2f = vec2(0.0);
|
||||
output_.vec2i = ivec2(0);
|
||||
output_.vec2u = uvec2(0u);
|
||||
output_.scalarf = 0.0;
|
||||
output_.scalari = 0;
|
||||
output_.scalaru = 0u;
|
||||
FragmentOutput _e34 = output_;
|
||||
_fs2p_location0 = _e34.vec4f;
|
||||
_fs2p_location1 = _e34.vec4i;
|
||||
_fs2p_location2 = _e34.vec4u;
|
||||
_fs2p_location3 = _e34.vec3f;
|
||||
_fs2p_location4 = _e34.vec3i;
|
||||
_fs2p_location5 = _e34.vec3u;
|
||||
_fs2p_location6 = _e34.vec2f;
|
||||
_fs2p_location7 = _e34.vec2i;
|
||||
_fs2p_location8 = _e34.vec2u;
|
||||
_fs2p_location9 = _e34.scalarf;
|
||||
_fs2p_location10 = _e34.scalari;
|
||||
_fs2p_location11 = _e34.scalaru;
|
||||
return;
|
||||
}
|
||||
|
46
tests/out/glsl/fragment-output.main_vec2scalar.Fragment.glsl
Normal file
46
tests/out/glsl/fragment-output.main_vec2scalar.Fragment.glsl
Normal file
@ -0,0 +1,46 @@
|
||||
#version 310 es
|
||||
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
|
||||
struct FragmentOutputVec4Vec3_ {
|
||||
vec4 vec4f;
|
||||
ivec4 vec4i;
|
||||
uvec4 vec4u;
|
||||
vec3 vec3f;
|
||||
ivec3 vec3i;
|
||||
uvec3 vec3u;
|
||||
};
|
||||
struct FragmentOutputVec2Scalar {
|
||||
vec2 vec2f;
|
||||
ivec2 vec2i;
|
||||
uvec2 vec2u;
|
||||
float scalarf;
|
||||
int scalari;
|
||||
uint scalaru;
|
||||
};
|
||||
layout(location = 0) out vec2 _fs2p_location0;
|
||||
layout(location = 1) out ivec2 _fs2p_location1;
|
||||
layout(location = 2) out uvec2 _fs2p_location2;
|
||||
layout(location = 3) out float _fs2p_location3;
|
||||
layout(location = 4) out int _fs2p_location4;
|
||||
layout(location = 5) out uint _fs2p_location5;
|
||||
|
||||
void main() {
|
||||
FragmentOutputVec2Scalar output_1 = FragmentOutputVec2Scalar(vec2(0.0), ivec2(0), uvec2(0u), 0.0, 0, 0u);
|
||||
output_1.vec2f = vec2(0.0);
|
||||
output_1.vec2i = ivec2(0);
|
||||
output_1.vec2u = uvec2(0u);
|
||||
output_1.scalarf = 0.0;
|
||||
output_1.scalari = 0;
|
||||
output_1.scalaru = 0u;
|
||||
FragmentOutputVec2Scalar _e16 = output_1;
|
||||
_fs2p_location0 = _e16.vec2f;
|
||||
_fs2p_location1 = _e16.vec2i;
|
||||
_fs2p_location2 = _e16.vec2u;
|
||||
_fs2p_location3 = _e16.scalarf;
|
||||
_fs2p_location4 = _e16.scalari;
|
||||
_fs2p_location5 = _e16.scalaru;
|
||||
return;
|
||||
}
|
||||
|
46
tests/out/glsl/fragment-output.main_vec4vec3.Fragment.glsl
Normal file
46
tests/out/glsl/fragment-output.main_vec4vec3.Fragment.glsl
Normal file
@ -0,0 +1,46 @@
|
||||
#version 310 es
|
||||
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
|
||||
struct FragmentOutputVec4Vec3_ {
|
||||
vec4 vec4f;
|
||||
ivec4 vec4i;
|
||||
uvec4 vec4u;
|
||||
vec3 vec3f;
|
||||
ivec3 vec3i;
|
||||
uvec3 vec3u;
|
||||
};
|
||||
struct FragmentOutputVec2Scalar {
|
||||
vec2 vec2f;
|
||||
ivec2 vec2i;
|
||||
uvec2 vec2u;
|
||||
float scalarf;
|
||||
int scalari;
|
||||
uint scalaru;
|
||||
};
|
||||
layout(location = 0) out vec4 _fs2p_location0;
|
||||
layout(location = 1) out ivec4 _fs2p_location1;
|
||||
layout(location = 2) out uvec4 _fs2p_location2;
|
||||
layout(location = 3) out vec3 _fs2p_location3;
|
||||
layout(location = 4) out ivec3 _fs2p_location4;
|
||||
layout(location = 5) out uvec3 _fs2p_location5;
|
||||
|
||||
void main() {
|
||||
FragmentOutputVec4Vec3_ output_ = FragmentOutputVec4Vec3_(vec4(0.0), ivec4(0), uvec4(0u), vec3(0.0), ivec3(0), uvec3(0u));
|
||||
output_.vec4f = vec4(0.0);
|
||||
output_.vec4i = ivec4(0);
|
||||
output_.vec4u = uvec4(0u);
|
||||
output_.vec3f = vec3(0.0);
|
||||
output_.vec3i = ivec3(0);
|
||||
output_.vec3u = uvec3(0u);
|
||||
FragmentOutputVec4Vec3_ _e19 = output_;
|
||||
_fs2p_location0 = _e19.vec4f;
|
||||
_fs2p_location1 = _e19.vec4i;
|
||||
_fs2p_location2 = _e19.vec4u;
|
||||
_fs2p_location3 = _e19.vec3f;
|
||||
_fs2p_location4 = _e19.vec3i;
|
||||
_fs2p_location5 = _e19.vec3u;
|
||||
return;
|
||||
}
|
||||
|
48
tests/out/hlsl/fragment-output.hlsl
Normal file
48
tests/out/hlsl/fragment-output.hlsl
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
struct FragmentOutputVec4Vec3_ {
|
||||
float4 vec4f : SV_Target0;
|
||||
nointerpolation int4 vec4i : SV_Target1;
|
||||
nointerpolation uint4 vec4u : SV_Target2;
|
||||
float3 vec3f : SV_Target3;
|
||||
nointerpolation int3 vec3i : SV_Target4;
|
||||
nointerpolation uint3 vec3u : SV_Target5;
|
||||
};
|
||||
|
||||
struct FragmentOutputVec2Scalar {
|
||||
float2 vec2f : SV_Target0;
|
||||
nointerpolation int2 vec2i : SV_Target1;
|
||||
nointerpolation uint2 vec2u : SV_Target2;
|
||||
float scalarf : SV_Target3;
|
||||
nointerpolation int scalari : SV_Target4;
|
||||
nointerpolation uint scalaru : SV_Target5;
|
||||
};
|
||||
|
||||
FragmentOutputVec4Vec3_ main_vec4vec3_()
|
||||
{
|
||||
FragmentOutputVec4Vec3_ output = (FragmentOutputVec4Vec3_)0;
|
||||
|
||||
output.vec4f = (0.0).xxxx;
|
||||
output.vec4i = (0).xxxx;
|
||||
output.vec4u = (0u).xxxx;
|
||||
output.vec3f = (0.0).xxx;
|
||||
output.vec3i = (0).xxx;
|
||||
output.vec3u = (0u).xxx;
|
||||
FragmentOutputVec4Vec3_ _expr19 = output;
|
||||
const FragmentOutputVec4Vec3_ fragmentoutputvec4vec3_ = _expr19;
|
||||
return fragmentoutputvec4vec3_;
|
||||
}
|
||||
|
||||
FragmentOutputVec2Scalar main_vec2scalar()
|
||||
{
|
||||
FragmentOutputVec2Scalar output_1 = (FragmentOutputVec2Scalar)0;
|
||||
|
||||
output_1.vec2f = (0.0).xx;
|
||||
output_1.vec2i = (0).xx;
|
||||
output_1.vec2u = (0u).xx;
|
||||
output_1.scalarf = 0.0;
|
||||
output_1.scalari = 0;
|
||||
output_1.scalaru = 0u;
|
||||
FragmentOutputVec2Scalar _expr16 = output_1;
|
||||
const FragmentOutputVec2Scalar fragmentoutputvec2scalar = _expr16;
|
||||
return fragmentoutputvec2scalar;
|
||||
}
|
3
tests/out/hlsl/fragment-output.hlsl.config
Normal file
3
tests/out/hlsl/fragment-output.hlsl.config
Normal file
@ -0,0 +1,3 @@
|
||||
vertex=()
|
||||
fragment=(main_vec4vec3_:ps_5_1 main_vec2scalar:ps_5_1 )
|
||||
compute=()
|
67
tests/out/msl/fragment-output.msl
Normal file
67
tests/out/msl/fragment-output.msl
Normal file
@ -0,0 +1,67 @@
|
||||
// language: metal2.0
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using metal::uint;
|
||||
|
||||
struct FragmentOutputVec4Vec3_ {
|
||||
metal::float4 vec4f;
|
||||
metal::int4 vec4i;
|
||||
metal::uint4 vec4u;
|
||||
metal::float3 vec3f;
|
||||
metal::int3 vec3i;
|
||||
metal::uint3 vec3u;
|
||||
};
|
||||
struct FragmentOutputVec2Scalar {
|
||||
metal::float2 vec2f;
|
||||
metal::int2 vec2i;
|
||||
metal::uint2 vec2u;
|
||||
float scalarf;
|
||||
int scalari;
|
||||
uint scalaru;
|
||||
};
|
||||
|
||||
struct main_vec4vec3_Output {
|
||||
metal::float4 vec4f [[color(0)]];
|
||||
metal::int4 vec4i [[color(1)]];
|
||||
metal::uint4 vec4u [[color(2)]];
|
||||
metal::float3 vec3f [[color(3)]];
|
||||
metal::int3 vec3i [[color(4)]];
|
||||
metal::uint3 vec3u [[color(5)]];
|
||||
};
|
||||
fragment main_vec4vec3_Output main_vec4vec3_(
|
||||
) {
|
||||
FragmentOutputVec4Vec3_ output = {};
|
||||
output.vec4f = metal::float4(0.0);
|
||||
output.vec4i = metal::int4(0);
|
||||
output.vec4u = metal::uint4(0u);
|
||||
output.vec3f = metal::float3(0.0);
|
||||
output.vec3i = metal::int3(0);
|
||||
output.vec3u = metal::uint3(0u);
|
||||
FragmentOutputVec4Vec3_ _e19 = output;
|
||||
const auto _tmp = _e19;
|
||||
return main_vec4vec3_Output { _tmp.vec4f, _tmp.vec4i, _tmp.vec4u, _tmp.vec3f, _tmp.vec3i, _tmp.vec3u };
|
||||
}
|
||||
|
||||
|
||||
struct main_vec2scalarOutput {
|
||||
metal::float2 vec2f [[color(0)]];
|
||||
metal::int2 vec2i [[color(1)]];
|
||||
metal::uint2 vec2u [[color(2)]];
|
||||
float scalarf [[color(3)]];
|
||||
int scalari [[color(4)]];
|
||||
uint scalaru [[color(5)]];
|
||||
};
|
||||
fragment main_vec2scalarOutput main_vec2scalar(
|
||||
) {
|
||||
FragmentOutputVec2Scalar output_1 = {};
|
||||
output_1.vec2f = metal::float2(0.0);
|
||||
output_1.vec2i = metal::int2(0);
|
||||
output_1.vec2u = metal::uint2(0u);
|
||||
output_1.scalarf = 0.0;
|
||||
output_1.scalari = 0;
|
||||
output_1.scalaru = 0u;
|
||||
FragmentOutputVec2Scalar _e16 = output_1;
|
||||
const auto _tmp = _e16;
|
||||
return main_vec2scalarOutput { _tmp.vec2f, _tmp.vec2i, _tmp.vec2u, _tmp.scalarf, _tmp.scalari, _tmp.scalaru };
|
||||
}
|
172
tests/out/spv/fragment-output.spvasm
Normal file
172
tests/out/spv/fragment-output.spvasm
Normal file
@ -0,0 +1,172 @@
|
||||
; SPIR-V
|
||||
; Version: 1.1
|
||||
; Generator: rspirv
|
||||
; Bound: 109
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %36 "main_vec4vec3" %24 %26 %28 %30 %32 %34
|
||||
OpEntryPoint Fragment %85 "main_vec2scalar" %73 %75 %77 %79 %81 %83
|
||||
OpExecutionMode %36 OriginUpperLeft
|
||||
OpExecutionMode %85 OriginUpperLeft
|
||||
OpMemberDecorate %15 0 Offset 0
|
||||
OpMemberDecorate %15 1 Offset 16
|
||||
OpMemberDecorate %15 2 Offset 32
|
||||
OpMemberDecorate %15 3 Offset 48
|
||||
OpMemberDecorate %15 4 Offset 64
|
||||
OpMemberDecorate %15 5 Offset 80
|
||||
OpMemberDecorate %19 0 Offset 0
|
||||
OpMemberDecorate %19 1 Offset 8
|
||||
OpMemberDecorate %19 2 Offset 16
|
||||
OpMemberDecorate %19 3 Offset 24
|
||||
OpMemberDecorate %19 4 Offset 28
|
||||
OpMemberDecorate %19 5 Offset 32
|
||||
OpDecorate %24 Location 0
|
||||
OpDecorate %26 Location 1
|
||||
OpDecorate %28 Location 2
|
||||
OpDecorate %30 Location 3
|
||||
OpDecorate %32 Location 4
|
||||
OpDecorate %34 Location 5
|
||||
OpDecorate %73 Location 0
|
||||
OpDecorate %75 Location 1
|
||||
OpDecorate %77 Location 2
|
||||
OpDecorate %79 Location 3
|
||||
OpDecorate %81 Location 4
|
||||
OpDecorate %83 Location 5
|
||||
%2 = OpTypeVoid
|
||||
%4 = OpTypeFloat 32
|
||||
%3 = OpConstant %4 0.0
|
||||
%6 = OpTypeInt 32 1
|
||||
%5 = OpConstant %6 0
|
||||
%8 = OpTypeInt 32 0
|
||||
%7 = OpConstant %8 0
|
||||
%9 = OpTypeVector %4 4
|
||||
%10 = OpTypeVector %6 4
|
||||
%11 = OpTypeVector %8 4
|
||||
%12 = OpTypeVector %4 3
|
||||
%13 = OpTypeVector %6 3
|
||||
%14 = OpTypeVector %8 3
|
||||
%15 = OpTypeStruct %9 %10 %11 %12 %13 %14
|
||||
%16 = OpTypeVector %4 2
|
||||
%17 = OpTypeVector %6 2
|
||||
%18 = OpTypeVector %8 2
|
||||
%19 = OpTypeStruct %16 %17 %18 %4 %6 %8
|
||||
%21 = OpTypePointer Function %15
|
||||
%22 = OpConstantNull %15
|
||||
%25 = OpTypePointer Output %9
|
||||
%24 = OpVariable %25 Output
|
||||
%27 = OpTypePointer Output %10
|
||||
%26 = OpVariable %27 Output
|
||||
%29 = OpTypePointer Output %11
|
||||
%28 = OpVariable %29 Output
|
||||
%31 = OpTypePointer Output %12
|
||||
%30 = OpVariable %31 Output
|
||||
%33 = OpTypePointer Output %13
|
||||
%32 = OpVariable %33 Output
|
||||
%35 = OpTypePointer Output %14
|
||||
%34 = OpVariable %35 Output
|
||||
%37 = OpTypeFunction %2
|
||||
%39 = OpTypePointer Function %9
|
||||
%42 = OpTypePointer Function %10
|
||||
%44 = OpConstant %8 1
|
||||
%46 = OpTypePointer Function %11
|
||||
%48 = OpConstant %8 2
|
||||
%50 = OpTypePointer Function %12
|
||||
%52 = OpConstant %8 3
|
||||
%54 = OpTypePointer Function %13
|
||||
%56 = OpConstant %8 4
|
||||
%58 = OpTypePointer Function %14
|
||||
%60 = OpConstant %8 5
|
||||
%70 = OpTypePointer Function %19
|
||||
%71 = OpConstantNull %19
|
||||
%74 = OpTypePointer Output %16
|
||||
%73 = OpVariable %74 Output
|
||||
%76 = OpTypePointer Output %17
|
||||
%75 = OpVariable %76 Output
|
||||
%78 = OpTypePointer Output %18
|
||||
%77 = OpVariable %78 Output
|
||||
%80 = OpTypePointer Output %4
|
||||
%79 = OpVariable %80 Output
|
||||
%82 = OpTypePointer Output %6
|
||||
%81 = OpVariable %82 Output
|
||||
%84 = OpTypePointer Output %8
|
||||
%83 = OpVariable %84 Output
|
||||
%87 = OpTypePointer Function %16
|
||||
%90 = OpTypePointer Function %17
|
||||
%93 = OpTypePointer Function %18
|
||||
%96 = OpTypePointer Function %4
|
||||
%98 = OpTypePointer Function %6
|
||||
%100 = OpTypePointer Function %8
|
||||
%36 = OpFunction %2 None %37
|
||||
%23 = OpLabel
|
||||
%20 = OpVariable %21 Function %22
|
||||
OpBranch %38
|
||||
%38 = OpLabel
|
||||
%40 = OpCompositeConstruct %9 %3 %3 %3 %3
|
||||
%41 = OpAccessChain %39 %20 %7
|
||||
OpStore %41 %40
|
||||
%43 = OpCompositeConstruct %10 %5 %5 %5 %5
|
||||
%45 = OpAccessChain %42 %20 %44
|
||||
OpStore %45 %43
|
||||
%47 = OpCompositeConstruct %11 %7 %7 %7 %7
|
||||
%49 = OpAccessChain %46 %20 %48
|
||||
OpStore %49 %47
|
||||
%51 = OpCompositeConstruct %12 %3 %3 %3
|
||||
%53 = OpAccessChain %50 %20 %52
|
||||
OpStore %53 %51
|
||||
%55 = OpCompositeConstruct %13 %5 %5 %5
|
||||
%57 = OpAccessChain %54 %20 %56
|
||||
OpStore %57 %55
|
||||
%59 = OpCompositeConstruct %14 %7 %7 %7
|
||||
%61 = OpAccessChain %58 %20 %60
|
||||
OpStore %61 %59
|
||||
%62 = OpLoad %15 %20
|
||||
%63 = OpCompositeExtract %9 %62 0
|
||||
OpStore %24 %63
|
||||
%64 = OpCompositeExtract %10 %62 1
|
||||
OpStore %26 %64
|
||||
%65 = OpCompositeExtract %11 %62 2
|
||||
OpStore %28 %65
|
||||
%66 = OpCompositeExtract %12 %62 3
|
||||
OpStore %30 %66
|
||||
%67 = OpCompositeExtract %13 %62 4
|
||||
OpStore %32 %67
|
||||
%68 = OpCompositeExtract %14 %62 5
|
||||
OpStore %34 %68
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%85 = OpFunction %2 None %37
|
||||
%72 = OpLabel
|
||||
%69 = OpVariable %70 Function %71
|
||||
OpBranch %86
|
||||
%86 = OpLabel
|
||||
%88 = OpCompositeConstruct %16 %3 %3
|
||||
%89 = OpAccessChain %87 %69 %7
|
||||
OpStore %89 %88
|
||||
%91 = OpCompositeConstruct %17 %5 %5
|
||||
%92 = OpAccessChain %90 %69 %44
|
||||
OpStore %92 %91
|
||||
%94 = OpCompositeConstruct %18 %7 %7
|
||||
%95 = OpAccessChain %93 %69 %48
|
||||
OpStore %95 %94
|
||||
%97 = OpAccessChain %96 %69 %52
|
||||
OpStore %97 %3
|
||||
%99 = OpAccessChain %98 %69 %56
|
||||
OpStore %99 %5
|
||||
%101 = OpAccessChain %100 %69 %60
|
||||
OpStore %101 %7
|
||||
%102 = OpLoad %19 %69
|
||||
%103 = OpCompositeExtract %16 %102 0
|
||||
OpStore %73 %103
|
||||
%104 = OpCompositeExtract %17 %102 1
|
||||
OpStore %75 %104
|
||||
%105 = OpCompositeExtract %18 %102 2
|
||||
OpStore %77 %105
|
||||
%106 = OpCompositeExtract %4 %102 3
|
||||
OpStore %79 %106
|
||||
%107 = OpCompositeExtract %6 %102 4
|
||||
OpStore %81 %107
|
||||
%108 = OpCompositeExtract %8 %102 5
|
||||
OpStore %83 %108
|
||||
OpReturn
|
||||
OpFunctionEnd
|
45
tests/out/wgsl/fragment-output.wgsl
Normal file
45
tests/out/wgsl/fragment-output.wgsl
Normal file
@ -0,0 +1,45 @@
|
||||
struct FragmentOutputVec4Vec3_ {
|
||||
@location(0) vec4f: vec4<f32>,
|
||||
@location(1) vec4i: vec4<i32>,
|
||||
@location(2) vec4u: vec4<u32>,
|
||||
@location(3) vec3f: vec3<f32>,
|
||||
@location(4) vec3i: vec3<i32>,
|
||||
@location(5) vec3u: vec3<u32>,
|
||||
}
|
||||
|
||||
struct FragmentOutputVec2Scalar {
|
||||
@location(0) vec2f: vec2<f32>,
|
||||
@location(1) vec2i: vec2<i32>,
|
||||
@location(2) vec2u: vec2<u32>,
|
||||
@location(3) scalarf: f32,
|
||||
@location(4) scalari: i32,
|
||||
@location(5) scalaru: u32,
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn main_vec4vec3_() -> FragmentOutputVec4Vec3_ {
|
||||
var output: FragmentOutputVec4Vec3_;
|
||||
|
||||
output.vec4f = vec4<f32>(0.0);
|
||||
output.vec4i = vec4<i32>(0);
|
||||
output.vec4u = vec4<u32>(0u);
|
||||
output.vec3f = vec3<f32>(0.0);
|
||||
output.vec3i = vec3<i32>(0);
|
||||
output.vec3u = vec3<u32>(0u);
|
||||
let _e19 = output;
|
||||
return _e19;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn main_vec2scalar() -> FragmentOutputVec2Scalar {
|
||||
var output_1: FragmentOutputVec2Scalar;
|
||||
|
||||
output_1.vec2f = vec2<f32>(0.0);
|
||||
output_1.vec2i = vec2<i32>(0);
|
||||
output_1.vec2u = vec2<u32>(0u);
|
||||
output_1.scalarf = 0.0;
|
||||
output_1.scalari = 0;
|
||||
output_1.scalaru = 0u;
|
||||
let _e16 = output_1;
|
||||
return _e16;
|
||||
}
|
@ -482,6 +482,10 @@ fn convert_wgsl() {
|
||||
"functions",
|
||||
Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::HLSL | Targets::WGSL,
|
||||
),
|
||||
(
|
||||
"fragment-output",
|
||||
Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::HLSL | Targets::WGSL,
|
||||
),
|
||||
("functions-webgl", Targets::GLSL),
|
||||
(
|
||||
"interpolate",
|
||||
|
Loading…
Reference in New Issue
Block a user