tint/transform: Fix PromoteInitializersToLetTest for materialized constants

PromoteInitializersToLet was not handling sem::Materialize nodes.
This can happen for const arrays when they are dynamically indexed.

Fixed: tint:1653
Change-Id: I3d67d8139e481c89b31a3a30c7ef44384b7545ba
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/99500
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2022-08-17 17:26:41 +00:00 committed by Dawn LUCI CQ
parent 873f92e741
commit 0f0ba20208
9 changed files with 205 additions and 12 deletions

View File

@ -75,19 +75,22 @@ void PromoteInitializersToLet::Run(CloneContext& ctx, const DataMap&, DataMap&)
return true;
},
[&](const ast::IdentifierExpression* expr) {
if (auto* user = ctx.src->Sem().Get<sem::VariableUser>(expr)) {
// Identifier resolves to a variable
if (auto* stmt = user->Stmt()) {
if (auto* decl = stmt->Declaration()->As<ast::VariableDeclStatement>();
decl && decl->variable->Is<ast::Const>()) {
// The identifier is used on the RHS of a 'const' declaration. Ignore.
return true;
if (auto* sem = ctx.src->Sem().Get(expr)) {
if (auto* user = sem->UnwrapMaterialize()->As<sem::VariableUser>()) {
// Identifier resolves to a variable
if (auto* stmt = user->Stmt()) {
if (auto* decl = stmt->Declaration()->As<ast::VariableDeclStatement>();
decl && decl->variable->Is<ast::Const>()) {
// The identifier is used on the RHS of a 'const' declaration.
// Ignore.
return true;
}
}
if (user->Variable()->Declaration()->Is<ast::Const>()) {
// The identifier resolves to a 'const' variable, but isn't used to
// initialize another 'const'. This needs promoting.
return promote(user);
}
}
if (user->Variable()->Declaration()->Is<ast::Const>()) {
// The identifier resolves to a 'const' variable, but isn't used to
// initialize another 'const'. This needs promoting.
return promote(user);
}
}
return true;

View File

@ -158,6 +158,37 @@ fn f() {
EXPECT_EQ(expect, str(got));
}
TEST_F(PromoteInitializersToLetTest, GlobalConstArrayDynamicIndex) {
auto* src = R"(
const TRI_VERTICES = array(
vec4(0., 0., 0., 1.),
vec4(0., 1., 0., 1.),
vec4(1., 1., 0., 1.),
);
@vertex
fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> {
// note: TRI_VERTICES requires a materialize before the dynamic index.
return TRI_VERTICES[in_vertex_index];
}
)";
auto* expect = R"(
const TRI_VERTICES = array(vec4(0.0, 0.0, 0.0, 1.0), vec4(0.0, 1.0, 0.0, 1.0), vec4(1.0, 1.0, 0.0, 1.0));
@vertex
fn vs_main(@builtin(vertex_index) in_vertex_index : u32) -> @builtin(position) vec4<f32> {
let tint_symbol = TRI_VERTICES;
return tint_symbol[in_vertex_index];
}
)";
DataMap data;
auto got = Run<PromoteInitializersToLet>(src);
EXPECT_EQ(expect, str(got));
}
TEST_F(PromoteInitializersToLetTest, GlobalConstBasicArray_OutOfOrder) {
auto* src = R"(
fn f() {

View File

@ -0,0 +1,10 @@
const TRI_VERTICES = array(
vec4(0., 0., 0., 1.),
vec4(0., 1., 0., 1.),
vec4(1., 1., 0., 1.),
);
@vertex
fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> {
return TRI_VERTICES[in_vertex_index];
}

View File

@ -0,0 +1,18 @@
struct tint_symbol_1 {
uint in_vertex_index : SV_VertexID;
};
struct tint_symbol_2 {
float4 value : SV_Position;
};
float4 vs_main_inner(uint in_vertex_index) {
const float4 tint_symbol_3[3] = {float4(0.0f, 0.0f, 0.0f, 1.0f), float4(0.0f, 1.0f, 0.0f, 1.0f), float4(1.0f, 1.0f, 0.0f, 1.0f)};
return tint_symbol_3[in_vertex_index];
}
tint_symbol_2 vs_main(tint_symbol_1 tint_symbol) {
const float4 inner_result = vs_main_inner(tint_symbol.in_vertex_index);
tint_symbol_2 wrapper_result = (tint_symbol_2)0;
wrapper_result.value = inner_result;
return wrapper_result;
}

View File

@ -0,0 +1,18 @@
struct tint_symbol_1 {
uint in_vertex_index : SV_VertexID;
};
struct tint_symbol_2 {
float4 value : SV_Position;
};
float4 vs_main_inner(uint in_vertex_index) {
const float4 tint_symbol_3[3] = {float4(0.0f, 0.0f, 0.0f, 1.0f), float4(0.0f, 1.0f, 0.0f, 1.0f), float4(1.0f, 1.0f, 0.0f, 1.0f)};
return tint_symbol_3[in_vertex_index];
}
tint_symbol_2 vs_main(tint_symbol_1 tint_symbol) {
const float4 inner_result = vs_main_inner(tint_symbol.in_vertex_index);
tint_symbol_2 wrapper_result = (tint_symbol_2)0;
wrapper_result.value = inner_result;
return wrapper_result;
}

View File

@ -0,0 +1,15 @@
#version 310 es
vec4 vs_main(uint in_vertex_index) {
vec4 tint_symbol[3] = vec4[3](vec4(0.0f, 0.0f, 0.0f, 1.0f), vec4(0.0f, 1.0f, 0.0f, 1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f));
return tint_symbol[in_vertex_index];
}
void main() {
gl_PointSize = 1.0;
vec4 inner_result = vs_main(uint(gl_VertexID));
gl_Position = inner_result;
gl_Position.y = -(gl_Position.y);
gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
return;
}

View File

@ -0,0 +1,32 @@
#include <metal_stdlib>
using namespace metal;
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
device T& operator[](size_t i) device { return elements[i]; }
const device T& operator[](size_t i) const device { return elements[i]; }
thread T& operator[](size_t i) thread { return elements[i]; }
const thread T& operator[](size_t i) const thread { return elements[i]; }
threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
T elements[N];
};
struct tint_symbol {
float4 value [[position]];
};
float4 vs_main_inner(uint in_vertex_index) {
tint_array<float4, 3> const tint_symbol_1 = tint_array<float4, 3>{float4(0.0f, 0.0f, 0.0f, 1.0f), float4(0.0f, 1.0f, 0.0f, 1.0f), float4(1.0f, 1.0f, 0.0f, 1.0f)};
return tint_symbol_1[in_vertex_index];
}
vertex tint_symbol vs_main(uint in_vertex_index [[vertex_id]]) {
float4 const inner_result = vs_main_inner(in_vertex_index);
tint_symbol wrapper_result = {};
wrapper_result.value = inner_result;
return wrapper_result;
}

View File

@ -0,0 +1,60 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 35
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %vs_main "vs_main" %in_vertex_index_1 %value %vertex_point_size
OpName %in_vertex_index_1 "in_vertex_index_1"
OpName %value "value"
OpName %vertex_point_size "vertex_point_size"
OpName %vs_main_inner "vs_main_inner"
OpName %in_vertex_index "in_vertex_index"
OpName %var_for_index "var_for_index"
OpName %vs_main "vs_main"
OpDecorate %in_vertex_index_1 BuiltIn VertexIndex
OpDecorate %value BuiltIn Position
OpDecorate %vertex_point_size BuiltIn PointSize
OpDecorate %_arr_v4float_uint_3 ArrayStride 16
%uint = OpTypeInt 32 0
%_ptr_Input_uint = OpTypePointer Input %uint
%in_vertex_index_1 = OpVariable %_ptr_Input_uint Input
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%8 = OpConstantNull %v4float
%value = OpVariable %_ptr_Output_v4float Output %8
%_ptr_Output_float = OpTypePointer Output %float
%11 = OpConstantNull %float
%vertex_point_size = OpVariable %_ptr_Output_float Output %11
%12 = OpTypeFunction %v4float %uint
%uint_3 = OpConstant %uint 3
%_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
%float_1 = OpConstant %float 1
%19 = OpConstantComposite %v4float %11 %11 %11 %float_1
%20 = OpConstantComposite %v4float %11 %float_1 %11 %float_1
%21 = OpConstantComposite %v4float %float_1 %float_1 %11 %float_1
%22 = OpConstantComposite %_arr_v4float_uint_3 %19 %20 %21
%_ptr_Function__arr_v4float_uint_3 = OpTypePointer Function %_arr_v4float_uint_3
%25 = OpConstantNull %_arr_v4float_uint_3
%_ptr_Function_v4float = OpTypePointer Function %v4float
%void = OpTypeVoid
%29 = OpTypeFunction %void
%vs_main_inner = OpFunction %v4float None %12
%in_vertex_index = OpFunctionParameter %uint
%15 = OpLabel
%var_for_index = OpVariable %_ptr_Function__arr_v4float_uint_3 Function %25
OpStore %var_for_index %22
%27 = OpAccessChain %_ptr_Function_v4float %var_for_index %in_vertex_index
%28 = OpLoad %v4float %27
OpReturnValue %28
OpFunctionEnd
%vs_main = OpFunction %void None %29
%32 = OpLabel
%34 = OpLoad %uint %in_vertex_index_1
%33 = OpFunctionCall %v4float %vs_main_inner %34
OpStore %value %33
OpStore %vertex_point_size %float_1
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,6 @@
const TRI_VERTICES = array(vec4(0.0, 0.0, 0.0, 1.0), vec4(0.0, 1.0, 0.0, 1.0), vec4(1.0, 1.0, 0.0, 1.0));
@vertex
fn vs_main(@builtin(vertex_index) in_vertex_index : u32) -> @builtin(position) vec4<f32> {
return TRI_VERTICES[in_vertex_index];
}