Make OFI transform push_constant-friendly.
Modify the OffsetFirstIndex transform to handle a pre-existing
push_constant block in the AST.
Bug: dawn:2185
Change-Id: If328138bab53cb94d4250f4d656ccccd524e1bbb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/171860
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/cmd/tint/main.cc b/src/tint/cmd/tint/main.cc
index 38d695b..81a9e5b 100644
--- a/src/tint/cmd/tint/main.cc
+++ b/src/tint/cmd/tint/main.cc
@@ -1067,6 +1067,10 @@
gen_options.texture_builtins_from_uniform = std::move(textureBuiltinsFromUniform);
+ // Place the first_instance push constant member after user-defined push constants (if any).
+ gen_options.first_instance_offset =
+ inspector.GetEntryPoint(entry_point_name).push_constant_size;
+
auto result = tint::glsl::writer::Generate(prg, gen_options, entry_point_name);
if (result != tint::Success) {
tint::cmd::PrintWGSL(std::cerr, prg);
diff --git a/src/tint/lang/wgsl/ast/transform/offset_first_index.cc b/src/tint/lang/wgsl/ast/transform/offset_first_index.cc
index eb64f60..04bdd9a 100644
--- a/src/tint/lang/wgsl/ast/transform/offset_first_index.cc
+++ b/src/tint/lang/wgsl/ast/transform/offset_first_index.cc
@@ -136,23 +136,29 @@
return SkipTransform;
}
- // Abort on any use of push constants in the module.
+ Vector<const ast::StructMember*, 8> members;
+
+ const ast::Variable* push_constants_var = nullptr;
+
+ // Find first push_constant.
for (auto* global : src.AST().GlobalVariables()) {
if (auto* var = global->As<ast::Var>()) {
auto* v = src.Sem().Get(var);
- if (TINT_UNLIKELY(v->AddressSpace() == core::AddressSpace::kPushConstant)) {
- TINT_ICE()
- << "OffsetFirstIndex doesn't know how to handle module that already use push "
- "constants (yet)";
- return resolver::Resolve(b);
+ if (v->AddressSpace() == core::AddressSpace::kPushConstant) {
+ push_constants_var = var;
+ auto* str = v->Type()->UnwrapRef()->As<sem::Struct>();
+ if (!str) {
+ TINT_ICE() << "expected var<push_constant> type to be struct. Was "
+ "AddBlockAttribute run?";
+ }
+ for (auto* member : str->Members()) {
+ members.Push(ctx.CloneWithoutTransform(member->Declaration()));
+ }
}
}
}
- b.Enable(wgsl::Extension::kChromiumExperimentalPushConstant);
-
// Add push constant members and calculate byte offsets
- tint::Vector<const StructMember*, 8> members;
if (has_vertex_index) {
members.Push(b.Member(kFirstVertexName, b.ty.u32(),
Vector{b.MemberOffset(AInt(*cfg->first_vertex_offset))}));
@@ -161,10 +167,37 @@
members.Push(b.Member(kFirstInstanceName, b.ty.u32(),
Vector{b.MemberOffset(AInt(*cfg->first_instance_offset))}));
}
- auto struct_ = b.Structure(b.Symbols().New("PushConstants"), std::move(members));
- // Create a global to hold the uniform buffer
- Symbol buffer_name = b.Symbols().New("push_constants");
- b.GlobalVar(buffer_name, b.ty.Of(struct_), core::AddressSpace::kPushConstant);
+
+ auto new_struct = b.Structure(b.Symbols().New("PushConstants"), std::move(members));
+
+ Symbol buffer_name;
+
+ // If this is the first use of push constants, create a global to hold them.
+ if (!push_constants_var) {
+ b.Enable(wgsl::Extension::kChromiumExperimentalPushConstant);
+
+ buffer_name = b.Symbols().New("push_constants");
+ b.GlobalVar(buffer_name, b.ty.Of(new_struct), core::AddressSpace::kPushConstant);
+ } else {
+ buffer_name = ctx.Clone(push_constants_var->name->symbol);
+ }
+
+ // Replace all variable users of the old struct with the new struct.
+ if (push_constants_var) {
+ ctx.ReplaceAll([&](const ast::Variable* var) -> const ast::Variable* {
+ if (var->type == push_constants_var->type) {
+ if (var->As<ast::Parameter>()) {
+ return ctx.dst->Param(ctx.Clone(var->name->symbol), b.ty.Of(new_struct),
+ ctx.Clone(var->attributes));
+ } else {
+ return ctx.dst->Var(ctx.Clone(var->name->symbol), b.ty.Of(new_struct),
+ ctx.Clone(var->attributes),
+ core::AddressSpace::kPushConstant);
+ }
+ }
+ return nullptr;
+ });
+ }
// Fix up all references to the builtins with the offsets
ctx.ReplaceAll([&](const Expression* expr) -> const Expression* {
@@ -172,14 +205,14 @@
if (auto* user = sem->UnwrapLoad()->As<sem::VariableUser>()) {
auto it = builtin_vars.find(user->Variable());
if (it != builtin_vars.end()) {
- return ctx.dst->Add(ctx.CloneWithoutTransform(expr),
+ return ctx.dst->Add(b.Bitcast(b.ty.u32(), ctx.CloneWithoutTransform(expr)),
ctx.dst->MemberAccessor(buffer_name, it->second));
}
}
if (auto* access = sem->As<sem::StructMemberAccess>()) {
auto it = builtin_members.find(access->Member());
if (it != builtin_members.end()) {
- return ctx.dst->Add(ctx.CloneWithoutTransform(expr),
+ return ctx.dst->Add(b.Bitcast(b.ty.u32(), ctx.CloneWithoutTransform(expr)),
ctx.dst->MemberAccessor(buffer_name, it->second));
}
}
diff --git a/src/tint/lang/wgsl/ast/transform/offset_first_index.h b/src/tint/lang/wgsl/ast/transform/offset_first_index.h
index aa37559..72d2e96 100644
--- a/src/tint/lang/wgsl/ast/transform/offset_first_index.h
+++ b/src/tint/lang/wgsl/ast/transform/offset_first_index.h
@@ -35,7 +35,7 @@
/// Adds firstVertex/Instance (injected via push constants) to
/// vertex/instance index builtins.
///
-/// This transform assumes that Name transform has been run before.
+/// This transform assumes that the Name and AddBlockAttribute transforms have been run before.
///
/// Some shading languages start vertex and instance numbering at 0,
/// regardless of the firstVertex/firstInstance value specified. This transform
diff --git a/src/tint/lang/wgsl/ast/transform/offset_first_index_test.cc b/src/tint/lang/wgsl/ast/transform/offset_first_index_test.cc
index 37a79a9..7d026ed 100644
--- a/src/tint/lang/wgsl/ast/transform/offset_first_index_test.cc
+++ b/src/tint/lang/wgsl/ast/transform/offset_first_index_test.cc
@@ -154,7 +154,7 @@
@vertex
fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
- test((vert_idx + push_constants.first_vertex));
+ test((bitcast<u32>(vert_idx) + push_constants.first_vertex));
return vec4<f32>();
}
)";
@@ -191,7 +191,7 @@
@vertex
fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
- test((vert_idx + push_constants.first_vertex));
+ test((bitcast<u32>(vert_idx) + push_constants.first_vertex));
return vec4<f32>();
}
@@ -238,7 +238,7 @@
@vertex
fn entry(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
- test((inst_idx + push_constants.first_instance));
+ test((bitcast<u32>(inst_idx) + push_constants.first_instance));
return vec4<f32>();
}
)";
@@ -277,7 +277,7 @@
@vertex
fn entry(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
- test((inst_idx + push_constants.first_instance));
+ test((bitcast<u32>(inst_idx) + push_constants.first_instance));
return vec4<f32>();
}
@@ -336,7 +336,7 @@
@vertex
fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
- test((inputs.instance_idx + push_constants.first_instance), (inputs.vert_idx + push_constants.first_vertex));
+ test((bitcast<u32>(inputs.instance_idx) + push_constants.first_instance), (bitcast<u32>(inputs.vert_idx) + push_constants.first_vertex));
return vec4<f32>();
}
)";
@@ -380,7 +380,7 @@
@vertex
fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
- test((inputs.instance_idx + push_constants.first_instance), (inputs.vert_idx + push_constants.first_vertex));
+ test((bitcast<u32>(inputs.instance_idx) + push_constants.first_instance), (bitcast<u32>(inputs.vert_idx) + push_constants.first_vertex));
return vec4<f32>();
}
@@ -444,7 +444,7 @@
@vertex
fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
- test((inputs.instance_idx + push_constants.first_instance), inputs.vert_idx);
+ test((bitcast<u32>(inputs.instance_idx) + push_constants.first_instance), inputs.vert_idx);
return vec4<f32>();
}
)";
@@ -497,7 +497,7 @@
@vertex
fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
- test(inputs.instance_idx, (inputs.vert_idx + push_constants.first_vertex));
+ test(inputs.instance_idx, (bitcast<u32>(inputs.vert_idx) + push_constants.first_vertex));
return vec4<f32>();
}
)";
@@ -572,7 +572,7 @@
@vertex
fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
- return vec4<f32>((f32((vert_idx + push_constants.first_vertex)) + p.f));
+ return vec4<f32>((f32((bitcast<u32>(vert_idx) + push_constants.first_vertex)) + p.f));
}
)";
@@ -609,7 +609,7 @@
@vertex
fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
- return vec4<f32>(f32((vert_idx + push_constants_1.first_vertex)));
+ return vec4<f32>(f32((bitcast<u32>(vert_idx) + push_constants_1.first_vertex)));
}
)";
@@ -657,7 +657,7 @@
@vertex
fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
- func2((vert_idx + push_constants.first_vertex));
+ func2((bitcast<u32>(vert_idx) + push_constants.first_vertex));
return vec4<f32>();
}
)";
@@ -698,7 +698,7 @@
@vertex
fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
- func2((vert_idx + push_constants.first_vertex));
+ func2((bitcast<u32>(vert_idx) + push_constants.first_vertex));
return vec4<f32>();
}
@@ -761,19 +761,19 @@
@vertex
fn entry_a(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
- func((vert_idx + push_constants.first_vertex));
+ func((bitcast<u32>(vert_idx) + push_constants.first_vertex));
return vec4<f32>();
}
@vertex
fn entry_b(@builtin(vertex_index) vert_idx : u32, @builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
- func(((vert_idx + push_constants.first_vertex) + (inst_idx + push_constants.first_instance)));
+ func(((bitcast<u32>(vert_idx) + push_constants.first_vertex) + (bitcast<u32>(inst_idx) + push_constants.first_instance)));
return vec4<f32>();
}
@vertex
fn entry_c(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
- func((inst_idx + push_constants.first_instance));
+ func((bitcast<u32>(inst_idx) + push_constants.first_instance));
return vec4<f32>();
}
)";
@@ -824,19 +824,19 @@
@vertex
fn entry_a(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
- func((vert_idx + push_constants.first_vertex));
+ func((bitcast<u32>(vert_idx) + push_constants.first_vertex));
return vec4<f32>();
}
@vertex
fn entry_b(@builtin(vertex_index) vert_idx : u32, @builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
- func(((vert_idx + push_constants.first_vertex) + (inst_idx + push_constants.first_instance)));
+ func(((bitcast<u32>(vert_idx) + push_constants.first_vertex) + (bitcast<u32>(inst_idx) + push_constants.first_instance)));
return vec4<f32>();
}
@vertex
fn entry_c(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
- func((inst_idx + push_constants.first_instance));
+ func((bitcast<u32>(inst_idx) + push_constants.first_instance));
return vec4<f32>();
}
diff --git a/src/tint/lang/wgsl/inspector/entry_point.h b/src/tint/lang/wgsl/inspector/entry_point.h
index 24164d0..3709ade 100644
--- a/src/tint/lang/wgsl/inspector/entry_point.h
+++ b/src/tint/lang/wgsl/inspector/entry_point.h
@@ -165,6 +165,8 @@
std::optional<WorkgroupSize> workgroup_size;
/// The total size in bytes of all Workgroup storage-class storage accessed via the entry point.
uint32_t workgroup_storage_size = 0;
+ /// The total size in bytes of all push_constant variables accessed by the entry point.
+ uint32_t push_constant_size = 0;
/// List of the input variable accessed via this entry point.
std::vector<StageVariable> input_variables;
/// List of the output variable accessed via this entry point.
diff --git a/src/tint/lang/wgsl/inspector/inspector.cc b/src/tint/lang/wgsl/inspector/inspector.cc
index a69fb67..8efa350 100644
--- a/src/tint/lang/wgsl/inspector/inspector.cc
+++ b/src/tint/lang/wgsl/inspector/inspector.cc
@@ -174,6 +174,8 @@
}
}
+ entry_point.push_constant_size = ComputePushConstantSize(func);
+
for (auto* param : sem->Parameters()) {
AddEntryPointInOutVariables(param->Declaration()->name->symbol.Name(),
param->Declaration()->name->symbol.Name(), param->Type(),
@@ -927,6 +929,18 @@
return total_size;
}
+uint32_t Inspector::ComputePushConstantSize(const ast::Function* func) const {
+ uint32_t size = 0;
+ auto* func_sem = program_.Sem().Get(func);
+ for (const sem::Variable* var : func_sem->TransitivelyReferencedGlobals()) {
+ if (var->AddressSpace() == core::AddressSpace::kPushConstant) {
+ size += var->Type()->UnwrapRef()->Size();
+ }
+ }
+
+ return size;
+}
+
std::vector<PixelLocalMemberType> Inspector::ComputePixelLocalMemberTypes(
const ast::Function* func) const {
auto* func_sem = program_.Sem().Get(func);
diff --git a/src/tint/lang/wgsl/inspector/inspector.h b/src/tint/lang/wgsl/inspector/inspector.h
index af839df..736b2da 100644
--- a/src/tint/lang/wgsl/inspector/inspector.h
+++ b/src/tint/lang/wgsl/inspector/inspector.h
@@ -264,6 +264,10 @@
/// @returns the total size in bytes of all Workgroup storage-class storage accessed via func.
uint32_t ComputeWorkgroupStorageSize(const ast::Function* func) const;
+ /// @param func the root function of the callgraph to consider for the computation.
+ /// @returns the total size in bytes of all push_constant variables accessed via func.
+ uint32_t ComputePushConstantSize(const ast::Function* func) const;
+
/// @param func the root function of the callgraph to consider for the computation
/// @returns the list of member types for the `pixel_local` variable accessed via func, if any.
std::vector<PixelLocalMemberType> ComputePixelLocalMemberTypes(const ast::Function* func) const;
diff --git a/src/tint/lang/wgsl/inspector/inspector_test.cc b/src/tint/lang/wgsl/inspector/inspector_test.cc
index e3d97bb..8d1a4b3 100644
--- a/src/tint/lang/wgsl/inspector/inspector_test.cc
+++ b/src/tint/lang/wgsl/inspector/inspector_test.cc
@@ -258,6 +258,85 @@
EXPECT_EQ(1u, workgroup_size->z);
}
+// Test that push_constant_size is zero if there are no push constants.
+TEST_F(InspectorGetEntryPointTest, PushConstantSizeNone) {
+ MakeEmptyBodyFunction("foo", Vector{
+ Stage(ast::PipelineStage::kFragment),
+ });
+
+ Inspector& inspector = Build();
+
+ auto result = inspector.GetEntryPoints();
+ ASSERT_FALSE(inspector.has_error()) << inspector.error();
+
+ ASSERT_EQ(1u, result.size());
+ EXPECT_EQ(0u, result[0].push_constant_size);
+}
+
+// Test that push_constant_size is 4 (bytes) if there is a single F32 push constant.
+TEST_F(InspectorGetEntryPointTest, PushConstantSizeOneWord) {
+ Enable(wgsl::Extension::kChromiumExperimentalPushConstant);
+ GlobalVar("pc", core::AddressSpace::kPushConstant, ty.f32());
+ MakePlainGlobalReferenceBodyFunction("foo", "pc", ty.f32(),
+ Vector{
+ Stage(ast::PipelineStage::kFragment),
+ });
+
+ Inspector& inspector = Build();
+
+ auto result = inspector.GetEntryPoints();
+ ASSERT_FALSE(inspector.has_error()) << inspector.error();
+
+ ASSERT_EQ(1u, result.size());
+ EXPECT_EQ(4u, result[0].push_constant_size);
+}
+
+// Test that push_constant_size is 12 (bytes) if there is a struct containing one
+// each of i32, f32 and u32.
+TEST_F(InspectorGetEntryPointTest, PushConstantSizeThreeWords) {
+ Enable(wgsl::Extension::kChromiumExperimentalPushConstant);
+ auto* pc_struct_type =
+ MakeStructType("PushConstantStruct", Vector{ty.i32(), ty.f32(), ty.u32()});
+ GlobalVar("pc", core::AddressSpace::kPushConstant, ty.Of(pc_struct_type));
+ MakePlainGlobalReferenceBodyFunction("foo", "pc", ty.Of(pc_struct_type),
+ Vector{
+ Stage(ast::PipelineStage::kFragment),
+ });
+
+ Inspector& inspector = Build();
+
+ auto result = inspector.GetEntryPoints();
+ ASSERT_FALSE(inspector.has_error()) << inspector.error();
+
+ ASSERT_EQ(1u, result.size());
+ EXPECT_EQ(12u, result[0].push_constant_size);
+}
+
+// Test that push_constant_size is 4 (bytes) if there are two push constants,
+// one used by the entry point containing an f32, and one unused by the entry
+// point containing a struct of size 12 bytes.
+TEST_F(InspectorGetEntryPointTest, PushConstantSizeTwoConstants) {
+ Enable(wgsl::Extension::kChromiumExperimentalPushConstant);
+ auto* unused_struct_type =
+ MakeStructType("PushConstantStruct", Vector{ty.i32(), ty.f32(), ty.u32()});
+ GlobalVar("unused", core::AddressSpace::kPushConstant, ty.Of(unused_struct_type));
+ GlobalVar("pc", core::AddressSpace::kPushConstant, ty.f32());
+ MakePlainGlobalReferenceBodyFunction("foo", "pc", ty.f32(),
+ Vector{
+ Stage(ast::PipelineStage::kFragment),
+ });
+
+ Inspector& inspector = Build();
+
+ auto result = inspector.GetEntryPoints();
+ ASSERT_FALSE(inspector.has_error()) << inspector.error();
+
+ ASSERT_EQ(1u, result.size());
+
+ // Check that the result only includes the single f32 push constant.
+ EXPECT_EQ(4u, result[0].push_constant_size);
+}
+
TEST_F(InspectorGetEntryPointTest, NonDefaultWorkgroupSize) {
MakeEmptyBodyFunction("foo", Vector{
Stage(ast::PipelineStage::kCompute),
diff --git a/test/tint/bug/chromium/1251009.wgsl.expected.glsl b/test/tint/bug/chromium/1251009.wgsl.expected.glsl
index 5ae88f4..f4292a7 100644
--- a/test/tint/bug/chromium/1251009.wgsl.expected.glsl
+++ b/test/tint/bug/chromium/1251009.wgsl.expected.glsl
@@ -4,6 +4,11 @@
layout(location = 1) in uint loc1_1;
layout(location = 2) in uint loc1_2;
layout(location = 3) in vec4 loc3_1;
+struct PushConstants {
+ uint first_instance;
+};
+
+layout(location=0) uniform PushConstants push_constants;
struct VertexInputs0 {
uint vertex_index;
int loc0;
@@ -15,7 +20,7 @@
};
vec4 tint_symbol(VertexInputs0 inputs0, uint loc1, uint instance_index, VertexInputs1 inputs1) {
- uint foo = (inputs0.vertex_index + instance_index);
+ uint foo = (inputs0.vertex_index + (instance_index + push_constants.first_instance));
return vec4(0.0f);
}
diff --git a/test/tint/bug/tint/824.wgsl.expected.glsl b/test/tint/bug/tint/824.wgsl.expected.glsl
index 074047c..b2dc49c 100644
--- a/test/tint/bug/tint/824.wgsl.expected.glsl
+++ b/test/tint/bug/tint/824.wgsl.expected.glsl
@@ -1,6 +1,11 @@
#version 310 es
layout(location = 0) out vec4 color_1;
+struct PushConstants {
+ uint first_instance;
+};
+
+layout(location=0) uniform PushConstants push_constants;
struct Output {
vec4 Position;
vec4 color;
@@ -8,11 +13,11 @@
Output tint_symbol(uint VertexIndex, uint InstanceIndex) {
vec2 zv[4] = vec2[4](vec2(0.20000000298023223877f), vec2(0.30000001192092895508f), vec2(-0.10000000149011611938f), vec2(1.10000002384185791016f));
- float z = zv[InstanceIndex].x;
+ float z = zv[(InstanceIndex + push_constants.first_instance)].x;
Output tint_symbol_1 = Output(vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f));
tint_symbol_1.Position = vec4(0.5f, 0.5f, z, 1.0f);
vec4 colors[4] = vec4[4](vec4(1.0f, 0.0f, 0.0f, 1.0f), vec4(0.0f, 1.0f, 0.0f, 1.0f), vec4(0.0f, 0.0f, 1.0f, 1.0f), vec4(1.0f));
- tint_symbol_1.color = colors[InstanceIndex];
+ tint_symbol_1.color = colors[(InstanceIndex + push_constants.first_instance)];
return tint_symbol_1;
}
diff --git a/test/tint/types/functions/shader_io/vertex_input_builtins.wgsl.expected.glsl b/test/tint/types/functions/shader_io/vertex_input_builtins.wgsl.expected.glsl
index e5e32ae..eaa2763 100644
--- a/test/tint/types/functions/shader_io/vertex_input_builtins.wgsl.expected.glsl
+++ b/test/tint/types/functions/shader_io/vertex_input_builtins.wgsl.expected.glsl
@@ -1,7 +1,12 @@
#version 310 es
+struct PushConstants {
+ uint first_instance;
+};
+
+layout(location=0) uniform PushConstants push_constants;
vec4 tint_symbol(uint vertex_index, uint instance_index) {
- uint foo = (vertex_index + instance_index);
+ uint foo = (vertex_index + (instance_index + push_constants.first_instance));
return vec4(0.0f);
}
diff --git a/test/tint/types/functions/shader_io/vertex_input_builtins_struct.wgsl.expected.glsl b/test/tint/types/functions/shader_io/vertex_input_builtins_struct.wgsl.expected.glsl
index 7daad03..4f64082 100644
--- a/test/tint/types/functions/shader_io/vertex_input_builtins_struct.wgsl.expected.glsl
+++ b/test/tint/types/functions/shader_io/vertex_input_builtins_struct.wgsl.expected.glsl
@@ -1,12 +1,17 @@
#version 310 es
+struct PushConstants {
+ uint first_instance;
+};
+
+layout(location=0) uniform PushConstants push_constants;
struct VertexInputs {
uint vertex_index;
uint instance_index;
};
vec4 tint_symbol(VertexInputs inputs) {
- uint foo = (inputs.vertex_index + inputs.instance_index);
+ uint foo = (inputs.vertex_index + (inputs.instance_index + push_constants.first_instance));
return vec4(0.0f);
}
diff --git a/test/tint/types/functions/shader_io/vertex_input_mixed.wgsl.expected.glsl b/test/tint/types/functions/shader_io/vertex_input_mixed.wgsl.expected.glsl
index 2470a13..2208401 100644
--- a/test/tint/types/functions/shader_io/vertex_input_mixed.wgsl.expected.glsl
+++ b/test/tint/types/functions/shader_io/vertex_input_mixed.wgsl.expected.glsl
@@ -4,6 +4,11 @@
layout(location = 1) in uint loc1_1;
layout(location = 2) in float loc2_1;
layout(location = 3) in vec4 loc3_1;
+struct PushConstants {
+ uint first_instance;
+};
+
+layout(location=0) uniform PushConstants push_constants;
struct VertexInputs0 {
uint vertex_index;
int loc0;
@@ -15,7 +20,7 @@
};
vec4 tint_symbol(VertexInputs0 inputs0, uint loc1, uint instance_index, VertexInputs1 inputs1) {
- uint foo = (inputs0.vertex_index + instance_index);
+ uint foo = (inputs0.vertex_index + (instance_index + push_constants.first_instance));
int i = inputs0.loc0;
uint u = loc1;
float f = inputs1.loc2;
diff --git a/test/tint/types/functions/shader_io/vertex_input_mixed_f16.wgsl.expected.glsl b/test/tint/types/functions/shader_io/vertex_input_mixed_f16.wgsl.expected.glsl
index 8d16b68..1cd4f6a 100644
--- a/test/tint/types/functions/shader_io/vertex_input_mixed_f16.wgsl.expected.glsl
+++ b/test/tint/types/functions/shader_io/vertex_input_mixed_f16.wgsl.expected.glsl
@@ -7,6 +7,11 @@
layout(location = 3) in vec4 loc3_1;
layout(location = 5) in f16vec3 loc5_1;
layout(location = 4) in float16_t loc4_1;
+struct PushConstants {
+ uint first_instance;
+};
+
+layout(location=0) uniform PushConstants push_constants;
struct VertexInputs0 {
uint vertex_index;
int loc0;
@@ -19,7 +24,7 @@
};
vec4 tint_symbol(VertexInputs0 inputs0, uint loc1, uint instance_index, VertexInputs1 inputs1, float16_t loc4) {
- uint foo = (inputs0.vertex_index + instance_index);
+ uint foo = (inputs0.vertex_index + (instance_index + push_constants.first_instance));
int i = inputs0.loc0;
uint u = loc1;
float f = inputs1.loc2;
diff --git a/test/tint/var/uses/instance_index.wgsl b/test/tint/var/uses/instance_index.wgsl
new file mode 100644
index 0000000..6305dac
--- /dev/null
+++ b/test/tint/var/uses/instance_index.wgsl
@@ -0,0 +1,3 @@
+@vertex fn main(@builtin(instance_index) b : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>(f32(b));
+}
diff --git a/test/tint/var/uses/instance_index.wgsl.expected.glsl b/test/tint/var/uses/instance_index.wgsl.expected.glsl
new file mode 100644
index 0000000..c543334
--- /dev/null
+++ b/test/tint/var/uses/instance_index.wgsl.expected.glsl
@@ -0,0 +1,19 @@
+#version 310 es
+
+struct PushConstants {
+ uint first_instance;
+};
+
+layout(location=0) uniform PushConstants push_constants;
+vec4 tint_symbol(uint b) {
+ return vec4(float((b + push_constants.first_instance)));
+}
+
+void main() {
+ gl_PointSize = 1.0;
+ vec4 inner_result = tint_symbol(uint(gl_InstanceID));
+ gl_Position = inner_result;
+ gl_Position.y = -(gl_Position.y);
+ gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+ return;
+}
diff --git a/test/tint/var/uses/push_constant.wgsl.expected.msl b/test/tint/var/uses/push_constant.wgsl.expected.msl
index 925fc2a..c106eee 100644
--- a/test/tint/var/uses/push_constant.wgsl.expected.msl
+++ b/test/tint/var/uses/push_constant.wgsl.expected.msl
@@ -43,6 +43,3 @@
Failed to generate: error: unhandled module-scope address space (push_constant)
error: unhandled module-scope address space (push_constant)
error: unhandled module-scope address space (push_constant)
-error: unhandled module-scope address space (push_constant)
-error: unhandled module-scope address space (push_constant)
-error: unhandled module-scope address space (push_constant)
diff --git a/test/tint/var/uses/push_constant_and_instance_index.wgsl b/test/tint/var/uses/push_constant_and_instance_index.wgsl
new file mode 100644
index 0000000..5f9d6c4
--- /dev/null
+++ b/test/tint/var/uses/push_constant_and_instance_index.wgsl
@@ -0,0 +1,7 @@
+enable chromium_experimental_push_constant;
+
+var<push_constant> a : f32;
+
+@vertex fn main(@builtin(instance_index) b : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>(a + f32(b));
+}
diff --git a/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.dxc.hlsl b/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..b85ac2b
--- /dev/null
+++ b/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.dxc.hlsl
@@ -0,0 +1,13 @@
+SKIP: FAILED
+
+
+enable chromium_experimental_push_constant;
+
+var<push_constant> a : f32;
+
+@vertex
+fn main(@builtin(instance_index) b : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>((a + f32(b)));
+}
+
+Failed to generate: error: unhandled address space push_constant
diff --git a/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.fxc.hlsl b/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..b85ac2b
--- /dev/null
+++ b/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.fxc.hlsl
@@ -0,0 +1,13 @@
+SKIP: FAILED
+
+
+enable chromium_experimental_push_constant;
+
+var<push_constant> a : f32;
+
+@vertex
+fn main(@builtin(instance_index) b : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>((a + f32(b)));
+}
+
+Failed to generate: error: unhandled address space push_constant
diff --git a/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.glsl b/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.glsl
new file mode 100644
index 0000000..7989941
--- /dev/null
+++ b/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.glsl
@@ -0,0 +1,20 @@
+#version 310 es
+
+struct PushConstants {
+ float inner;
+ uint first_instance;
+};
+
+layout(location=0) uniform PushConstants a;
+vec4 tint_symbol(uint b) {
+ return vec4((a.inner + float((b + a.first_instance))));
+}
+
+void main() {
+ gl_PointSize = 1.0;
+ vec4 inner_result = tint_symbol(uint(gl_InstanceID));
+ gl_Position = inner_result;
+ gl_Position.y = -(gl_Position.y);
+ gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
+ return;
+}
diff --git a/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.msl b/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.msl
new file mode 100644
index 0000000..db4c340
--- /dev/null
+++ b/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.msl
@@ -0,0 +1,9 @@
+SKIP: FAILED
+
+../../src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc:220 internal compiler error: unhandled module-scope address space (push_constant)
+********************************************************************
+* The tint shader compiler has encountered an unexpected error. *
+* *
+* Please help us fix this issue by submitting a bug report at *
+* crbug.com/tint with the source program that triggered the bug. *
+********************************************************************
diff --git a/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.spvasm b/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.spvasm
new file mode 100644
index 0000000..2592150
--- /dev/null
+++ b/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.spvasm
@@ -0,0 +1,60 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %b_1 %value %vertex_point_size
+ OpName %b_1 "b_1"
+ OpName %value "value"
+ OpName %vertex_point_size "vertex_point_size"
+ OpName %a_block "a_block"
+ OpMemberName %a_block 0 "inner"
+ OpName %a "a"
+ OpName %main_inner "main_inner"
+ OpName %b "b"
+ OpName %main "main"
+ OpDecorate %b_1 BuiltIn InstanceIndex
+ OpDecorate %value BuiltIn Position
+ OpDecorate %vertex_point_size BuiltIn PointSize
+ OpDecorate %a_block Block
+ OpMemberDecorate %a_block 0 Offset 0
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+ %b_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
+ %a_block = OpTypeStruct %float
+%_ptr_PushConstant_a_block = OpTypePointer PushConstant %a_block
+ %a = OpVariable %_ptr_PushConstant_a_block PushConstant
+ %15 = OpTypeFunction %v4float %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_PushConstant_float = OpTypePointer PushConstant %float
+ %void = OpTypeVoid
+ %26 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+ %main_inner = OpFunction %v4float None %15
+ %b = OpFunctionParameter %uint
+ %18 = OpLabel
+ %21 = OpAccessChain %_ptr_PushConstant_float %a %uint_0
+ %22 = OpLoad %float %21
+ %23 = OpConvertUToF %float %b
+ %24 = OpFAdd %float %22 %23
+ %25 = OpCompositeConstruct %v4float %24 %24 %24 %24
+ OpReturnValue %25
+ OpFunctionEnd
+ %main = OpFunction %void None %26
+ %29 = OpLabel
+ %31 = OpLoad %uint %b_1
+ %30 = OpFunctionCall %v4float %main_inner %31
+ OpStore %value %30
+ OpStore %vertex_point_size %float_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.wgsl b/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.wgsl
new file mode 100644
index 0000000..3b1e555
--- /dev/null
+++ b/test/tint/var/uses/push_constant_and_instance_index.wgsl.expected.wgsl
@@ -0,0 +1,8 @@
+enable chromium_experimental_push_constant;
+
+var<push_constant> a : f32;
+
+@vertex
+fn main(@builtin(instance_index) b : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>((a + f32(b)));
+}