writer/spirv: Do not add Flat to fragment outputs

Use the sanitizer to add the decoration only to the variables that are
vertex outputs and fragment inputs.

Bug: dawn:963, tint:746
Change-Id: I1b91cf3550fb3c6f583d69e822444534a576e0cd
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56460
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
This commit is contained in:
James Price 2021-06-29 18:05:25 +00:00 committed by Tint LUCI CQ
parent 9432c97070
commit d18f2e0d6e
14 changed files with 209 additions and 51 deletions

View File

@ -320,6 +320,14 @@ Symbol Spirv::HoistToInputVariables(
new_decorations.push_back(
ctx.dst->ASTNodes().Create<ast::DisableValidationDecoration>(
ctx.dst->ID(), ast::DisabledValidation::kIgnoreStorageClass));
if (ty->is_integer_scalar_or_vector() &&
ast::HasDecoration<ast::LocationDecoration>(new_decorations) &&
func->pipeline_stage() == ast::PipelineStage::kFragment) {
// Vulkan requires that integer user-defined fragment inputs are
// always decorated with `Flat`.
new_decorations.push_back(ctx.dst->Interpolate(
ast::InterpolationType::kFlat, ast::InterpolationSampling::kNone));
}
auto global_var_symbol = ctx.dst->Sym();
auto* global_var =
ctx.dst->Var(global_var_symbol, ctx.Clone(declared_ty),
@ -378,6 +386,14 @@ void Spirv::HoistToOutputVariables(CloneContext& ctx,
new_decorations.push_back(
ctx.dst->ASTNodes().Create<ast::DisableValidationDecoration>(
ctx.dst->ID(), ast::DisabledValidation::kIgnoreStorageClass));
if (ty->is_integer_scalar_or_vector() &&
ast::HasDecoration<ast::LocationDecoration>(new_decorations) &&
func->pipeline_stage() == ast::PipelineStage::kVertex) {
// Vulkan requires that integer user-defined vertex outputs are
// always decorated with `Flat`.
new_decorations.push_back(ctx.dst->Interpolate(
ast::InterpolationType::kFlat, ast::InterpolationSampling::kNone));
}
auto global_var_symbol = ctx.dst->Sym();
auto* global_var =
ctx.dst->Var(global_var_symbol, ctx.Clone(declared_ty),

View File

@ -125,7 +125,7 @@ fn frag_main([[location(0)]] loc_in : u32) -> [[location(0)]] f32 {
)";
auto* expect = R"(
[[location(0), internal(disable_validation__ignore_storage_class)]] var<in> tint_symbol : u32;
[[location(0), internal(disable_validation__ignore_storage_class), interpolate(flat)]] var<in> tint_symbol : u32;
[[location(0), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_2 : f32;
@ -165,7 +165,7 @@ fn frag_main([[location(0)]] loc_in : u32) -> [[location(0)]] myf32 {
auto* expect = R"(
type myf32 = f32;
[[location(0), internal(disable_validation__ignore_storage_class)]] var<in> tint_symbol : u32;
[[location(0), internal(disable_validation__ignore_storage_class), interpolate(flat)]] var<in> tint_symbol : u32;
[[location(0), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_2 : myf32;
@ -472,6 +472,135 @@ fn frag_main() {
EXPECT_EQ(expect, str(got));
}
TEST_F(SpirvTest, HandleEntryPointIOTypes_InterpolateAttributes_Integers) {
// Test that we add a Flat attribute to integers that are vertex outputs and
// fragment inputs, but not vertex inputs or fragment outputs.
auto* src = R"(
struct VertexIn {
[[location(0)]] i : i32;
[[location(1)]] u : u32;
[[location(2)]] vi : vec4<i32>;
[[location(3)]] vu : vec4<u32>;
};
struct VertexOut {
[[location(0)]] i : i32;
[[location(1)]] u : u32;
[[location(2)]] vi : vec4<i32>;
[[location(3)]] vu : vec4<u32>;
[[builtin(position)]] pos : vec4<f32>;
};
struct FragmentInterface {
[[location(0)]] i : i32;
[[location(1)]] u : u32;
[[location(2)]] vi : vec4<i32>;
[[location(3)]] vu : vec4<u32>;
};
[[stage(vertex)]]
fn vert_main(in : VertexIn) -> VertexOut {
return VertexOut(in.i, in.u, in.vi, in.vu);
}
[[stage(fragment)]]
fn frag_main(inputs : FragmentInterface) -> FragmentInterface {
return inputs;
}
)";
auto* expect = R"(
struct VertexIn {
i : i32;
u : u32;
vi : vec4<i32>;
vu : vec4<u32>;
};
struct VertexOut {
i : i32;
u : u32;
vi : vec4<i32>;
vu : vec4<u32>;
pos : vec4<f32>;
};
struct FragmentInterface {
i : i32;
u : u32;
vi : vec4<i32>;
vu : vec4<u32>;
};
[[location(0), internal(disable_validation__ignore_storage_class)]] var<in> tint_symbol : i32;
[[location(1), internal(disable_validation__ignore_storage_class)]] var<in> tint_symbol_1 : u32;
[[location(2), internal(disable_validation__ignore_storage_class)]] var<in> tint_symbol_2 : vec4<i32>;
[[location(3), internal(disable_validation__ignore_storage_class)]] var<in> tint_symbol_3 : vec4<u32>;
[[location(0), internal(disable_validation__ignore_storage_class), interpolate(flat)]] var<out> tint_symbol_6 : i32;
[[location(1), internal(disable_validation__ignore_storage_class), interpolate(flat)]] var<out> tint_symbol_7 : u32;
[[location(2), internal(disable_validation__ignore_storage_class), interpolate(flat)]] var<out> tint_symbol_8 : vec4<i32>;
[[location(3), internal(disable_validation__ignore_storage_class), interpolate(flat)]] var<out> tint_symbol_9 : vec4<u32>;
[[builtin(position), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_10 : vec4<f32>;
fn tint_symbol_11(tint_symbol_5 : VertexOut) {
tint_symbol_6 = tint_symbol_5.i;
tint_symbol_7 = tint_symbol_5.u;
tint_symbol_8 = tint_symbol_5.vi;
tint_symbol_9 = tint_symbol_5.vu;
tint_symbol_10 = tint_symbol_5.pos;
}
[[stage(vertex)]]
fn vert_main() {
let tint_symbol_4 : VertexIn = VertexIn(tint_symbol, tint_symbol_1, tint_symbol_2, tint_symbol_3);
tint_symbol_11(VertexOut(tint_symbol_4.i, tint_symbol_4.u, tint_symbol_4.vi, tint_symbol_4.vu));
return;
}
[[location(0), internal(disable_validation__ignore_storage_class), interpolate(flat)]] var<in> tint_symbol_12 : i32;
[[location(1), internal(disable_validation__ignore_storage_class), interpolate(flat)]] var<in> tint_symbol_13 : u32;
[[location(2), internal(disable_validation__ignore_storage_class), interpolate(flat)]] var<in> tint_symbol_14 : vec4<i32>;
[[location(3), internal(disable_validation__ignore_storage_class), interpolate(flat)]] var<in> tint_symbol_15 : vec4<u32>;
[[location(0), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_18 : i32;
[[location(1), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_19 : u32;
[[location(2), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_20 : vec4<i32>;
[[location(3), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_21 : vec4<u32>;
fn tint_symbol_22(tint_symbol_17 : FragmentInterface) {
tint_symbol_18 = tint_symbol_17.i;
tint_symbol_19 = tint_symbol_17.u;
tint_symbol_20 = tint_symbol_17.vi;
tint_symbol_21 = tint_symbol_17.vu;
}
[[stage(fragment)]]
fn frag_main() {
let tint_symbol_16 : FragmentInterface = FragmentInterface(tint_symbol_12, tint_symbol_13, tint_symbol_14, tint_symbol_15);
tint_symbol_22(tint_symbol_16);
return;
}
)";
auto got = Run<Spirv>(src);
EXPECT_EQ(expect, str(got));
}
TEST_F(SpirvTest, HandleEntryPointIOTypes_StructLayoutDecorations) {
auto* src = R"(
[[block]]

View File

@ -848,11 +848,6 @@ bool Builder::GenerateGlobalVariable(ast::Variable* var) {
push_annot(spv::Op::OpDecorate,
{Operand::Int(var_id), Operand::Int(SpvDecorationLocation),
Operand::Int(location->value())});
if (type->is_integer_scalar_or_vector()) {
// Vulkan requires that integers are always decorated with `Flat`.
AddInterpolationDecorations(var_id, ast::InterpolationType::kFlat,
ast::InterpolationSampling::kNone);
}
} else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
AddInterpolationDecorations(var_id, interpolate->type(),
interpolate->sampling());

View File

@ -30,9 +30,7 @@
OpName %tint_symbol_9 "tint_symbol_9"
OpName %main3 "main3"
OpDecorate %tint_symbol_1 Location 0
OpDecorate %tint_symbol_1 Flat
OpDecorate %tint_symbol_4 Location 1
OpDecorate %tint_symbol_4 Flat
OpDecorate %tint_symbol_7 Location 2
OpDecorate %tint_symbol_10 Location 3
%int = OpTypeInt 32 1

View File

@ -20,9 +20,7 @@
OpName %tint_symbol "tint_symbol"
OpName %main "main"
OpDecorate %tint_symbol_1 Location 0
OpDecorate %tint_symbol_1 Flat
OpDecorate %tint_symbol_2 Location 1
OpDecorate %tint_symbol_2 Flat
OpDecorate %tint_symbol_3 Location 2
OpDecorate %tint_symbol_4 Location 3
OpMemberDecorate %FragmentOutputs 0 Offset 0

View File

@ -25,10 +25,8 @@
OpName %tint_symbol "tint_symbol"
OpName %main "main"
OpDecorate %tint_symbol_1 Location 0
OpDecorate %tint_symbol_1 Flat
OpDecorate %tint_symbol_2 BuiltIn FragDepth
OpDecorate %tint_symbol_3 Location 1
OpDecorate %tint_symbol_3 Flat
OpDecorate %tint_symbol_4 Location 2
OpDecorate %_arr_uint_uint_1 ArrayStride 4
OpDecorate %tint_symbol_5 BuiltIn SampleMask

View File

@ -12,5 +12,6 @@ fn vert_main() -> Interface {
}
[[stage(fragment)]]
fn frag_main(inputs : Interface) {
fn frag_main(inputs : Interface) -> [[location(0)]] i32 {
return inputs.i;
}

View File

@ -15,8 +15,8 @@ struct tint_symbol {
tint_symbol vert_main() {
const Interface tint_symbol_1 = {0, 0u, int4(0, 0, 0, 0), uint4(0u, 0u, 0u, 0u), float4(0.0f, 0.0f, 0.0f, 0.0f)};
const tint_symbol tint_symbol_4 = {tint_symbol_1.i, tint_symbol_1.u, tint_symbol_1.vi, tint_symbol_1.vu, tint_symbol_1.pos};
return tint_symbol_4;
const tint_symbol tint_symbol_5 = {tint_symbol_1.i, tint_symbol_1.u, tint_symbol_1.vi, tint_symbol_1.vu, tint_symbol_1.pos};
return tint_symbol_5;
}
struct tint_symbol_3 {
@ -26,8 +26,12 @@ struct tint_symbol_3 {
uint4 vu : TEXCOORD3;
float4 pos : SV_Position;
};
struct tint_symbol_4 {
int value : SV_Target0;
};
void frag_main(tint_symbol_3 tint_symbol_2) {
tint_symbol_4 frag_main(tint_symbol_3 tint_symbol_2) {
const Interface inputs = {tint_symbol_2.i, tint_symbol_2.u, tint_symbol_2.vi, tint_symbol_2.vu, tint_symbol_2.pos};
return;
const tint_symbol_4 tint_symbol_6 = {inputs.i};
return tint_symbol_6;
}

View File

@ -21,15 +21,19 @@ struct tint_symbol_4 {
int4 vi [[user(locn2)]];
uint4 vu [[user(locn3)]];
};
struct tint_symbol_5 {
int value [[color(0)]];
};
vertex tint_symbol vert_main() {
Interface const tint_symbol_1 = {};
tint_symbol const tint_symbol_5 = {.i=tint_symbol_1.i, .u=tint_symbol_1.u, .vi=tint_symbol_1.vi, .vu=tint_symbol_1.vu, .pos=tint_symbol_1.pos};
return tint_symbol_5;
tint_symbol const tint_symbol_6 = {.i=tint_symbol_1.i, .u=tint_symbol_1.u, .vi=tint_symbol_1.vi, .vu=tint_symbol_1.vu, .pos=tint_symbol_1.pos};
return tint_symbol_6;
}
fragment void frag_main(float4 tint_symbol_3 [[position]], tint_symbol_4 tint_symbol_2 [[stage_in]]) {
fragment tint_symbol_5 frag_main(float4 tint_symbol_3 [[position]], tint_symbol_4 tint_symbol_2 [[stage_in]]) {
Interface const inputs = {.i=tint_symbol_2.i, .u=tint_symbol_2.u, .vi=tint_symbol_2.vi, .vu=tint_symbol_2.vu, .pos=tint_symbol_3};
return;
tint_symbol_5 const tint_symbol_7 = {.value=inputs.i};
return tint_symbol_7;
}

View File

@ -1,12 +1,12 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 54
; Bound: 67
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %vert_main "vert_main" %tint_pointsize %tint_symbol_1 %tint_symbol_2 %tint_symbol_3 %tint_symbol_4 %tint_symbol_5
OpEntryPoint Fragment %frag_main "frag_main"
OpEntryPoint Fragment %frag_main "frag_main" %tint_symbol_7 %tint_symbol_8 %tint_symbol_9 %tint_symbol_10 %tint_symbol_11 %tint_symbol_14
OpExecutionMode %frag_main OriginUpperLeft
OpName %tint_pointsize "tint_pointsize"
OpName %tint_symbol_1 "tint_symbol_1"
@ -19,6 +19,7 @@
OpName %tint_symbol_9 "tint_symbol_9"
OpName %tint_symbol_10 "tint_symbol_10"
OpName %tint_symbol_11 "tint_symbol_11"
OpName %tint_symbol_14 "tint_symbol_14"
OpName %Interface "Interface"
OpMemberName %Interface 0 "i"
OpMemberName %Interface 1 "u"
@ -28,6 +29,8 @@
OpName %tint_symbol_6 "tint_symbol_6"
OpName %tint_symbol "tint_symbol"
OpName %vert_main "vert_main"
OpName %tint_symbol_15 "tint_symbol_15"
OpName %tint_symbol_13 "tint_symbol_13"
OpName %frag_main "frag_main"
OpDecorate %tint_pointsize BuiltIn PointSize
OpDecorate %tint_symbol_1 Location 0
@ -48,6 +51,7 @@
OpDecorate %tint_symbol_10 Location 3
OpDecorate %tint_symbol_10 Flat
OpDecorate %tint_symbol_11 BuiltIn FragCoord
OpDecorate %tint_symbol_14 Location 0
OpMemberDecorate %Interface 0 Offset 0
OpMemberDecorate %Interface 1 Offset 4
OpMemberDecorate %Interface 2 Offset 16
@ -87,34 +91,50 @@
%tint_symbol_10 = OpVariable %_ptr_Input_v4uint Input
%_ptr_Input_v4float = OpTypePointer Input %v4float
%tint_symbol_11 = OpVariable %_ptr_Input_v4float Input
%tint_symbol_14 = OpVariable %_ptr_Output_int Output %8
%void = OpTypeVoid
%Interface = OpTypeStruct %int %uint %v4int %v4uint %v4float
%35 = OpTypeFunction %void %Interface
%46 = OpTypeFunction %void
%36 = OpTypeFunction %void %Interface
%47 = OpTypeFunction %void
%float_1 = OpConstant %float 1
%51 = OpConstantNull %Interface
%tint_symbol_6 = OpFunction %void None %35
%52 = OpConstantNull %Interface
%53 = OpTypeFunction %void %int
%tint_symbol_6 = OpFunction %void None %36
%tint_symbol = OpFunctionParameter %Interface
%40 = OpLabel
%41 = OpCompositeExtract %int %tint_symbol 0
OpStore %tint_symbol_1 %41
%42 = OpCompositeExtract %uint %tint_symbol 1
OpStore %tint_symbol_2 %42
%43 = OpCompositeExtract %v4int %tint_symbol 2
OpStore %tint_symbol_3 %43
%44 = OpCompositeExtract %v4uint %tint_symbol 3
OpStore %tint_symbol_4 %44
%45 = OpCompositeExtract %v4float %tint_symbol 4
OpStore %tint_symbol_5 %45
%41 = OpLabel
%42 = OpCompositeExtract %int %tint_symbol 0
OpStore %tint_symbol_1 %42
%43 = OpCompositeExtract %uint %tint_symbol 1
OpStore %tint_symbol_2 %43
%44 = OpCompositeExtract %v4int %tint_symbol 2
OpStore %tint_symbol_3 %44
%45 = OpCompositeExtract %v4uint %tint_symbol 3
OpStore %tint_symbol_4 %45
%46 = OpCompositeExtract %v4float %tint_symbol 4
OpStore %tint_symbol_5 %46
OpReturn
OpFunctionEnd
%vert_main = OpFunction %void None %46
%48 = OpLabel
%vert_main = OpFunction %void None %47
%49 = OpLabel
OpStore %tint_pointsize %float_1
%50 = OpFunctionCall %void %tint_symbol_6 %51
%51 = OpFunctionCall %void %tint_symbol_6 %52
OpReturn
OpFunctionEnd
%frag_main = OpFunction %void None %46
%53 = OpLabel
%tint_symbol_15 = OpFunction %void None %53
%tint_symbol_13 = OpFunctionParameter %int
%56 = OpLabel
OpStore %tint_symbol_14 %tint_symbol_13
OpReturn
OpFunctionEnd
%frag_main = OpFunction %void None %47
%58 = OpLabel
%59 = OpLoad %int %tint_symbol_7
%60 = OpLoad %uint %tint_symbol_8
%61 = OpLoad %v4int %tint_symbol_9
%62 = OpLoad %v4uint %tint_symbol_10
%63 = OpLoad %v4float %tint_symbol_11
%64 = OpCompositeConstruct %Interface %59 %60 %61 %62 %63
%66 = OpCompositeExtract %int %64 0
%65 = OpFunctionCall %void %tint_symbol_15 %66
OpReturn
OpFunctionEnd

View File

@ -17,5 +17,6 @@ fn vert_main() -> Interface {
}
[[stage(fragment)]]
fn frag_main(inputs : Interface) {
fn frag_main(inputs : Interface) -> [[location(0)]] i32 {
return inputs.i;
}

View File

@ -17,9 +17,7 @@
OpName %main "main"
OpDecorate %tint_pointsize BuiltIn PointSize
OpDecorate %tint_symbol Location 0
OpDecorate %tint_symbol Flat
OpDecorate %tint_symbol_1 Location 1
OpDecorate %tint_symbol_1 Flat
OpDecorate %tint_symbol_2 Location 2
OpDecorate %tint_symbol_3 Location 3
OpDecorate %tint_symbol_5 BuiltIn Position

View File

@ -22,9 +22,7 @@
OpMemberName %VertexInputs 3 "loc3"
OpDecorate %tint_pointsize BuiltIn PointSize
OpDecorate %tint_symbol Location 0
OpDecorate %tint_symbol Flat
OpDecorate %tint_symbol_1 Location 1
OpDecorate %tint_symbol_1 Flat
OpDecorate %tint_symbol_2 Location 2
OpDecorate %tint_symbol_3 Location 3
OpDecorate %tint_symbol_6 BuiltIn Position

View File

@ -26,9 +26,7 @@
OpDecorate %tint_pointsize BuiltIn PointSize
OpDecorate %tint_symbol BuiltIn VertexIndex
OpDecorate %tint_symbol_1 Location 0
OpDecorate %tint_symbol_1 Flat
OpDecorate %tint_symbol_3 Location 1
OpDecorate %tint_symbol_3 Flat
OpDecorate %tint_symbol_4 BuiltIn InstanceIndex
OpDecorate %tint_symbol_5 Location 2
OpDecorate %tint_symbol_6 Location 3