transform: Update MultiplanarExternalTexture to support OOO-decls
MultiplanarExternalTexture cannot deal with out-of-order declarations.
Re-work things so that it can.
Bug: tint:1266
Change-Id: Ie2c8237be4f6ddb91120cbeb25f3c186b572ba59
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/79768
Reviewed-by: David Neto <dneto@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/transform/multiplanar_external_texture.cc b/src/transform/multiplanar_external_texture.cc
index 18ded92..360a18d 100644
--- a/src/transform/multiplanar_external_texture.cc
+++ b/src/transform/multiplanar_external_texture.cc
@@ -48,8 +48,8 @@
/// ProgramBuilder for the context
ProgramBuilder& b;
- /// Desination binding locations for the expanded texture_external provided as
- /// input into the transform.
+ /// Destination binding locations for the expanded texture_external provided
+ /// as input into the transform.
const NewBindingPoints* new_binding_points;
/// Symbol for the ExternalTextureParams struct
@@ -63,7 +63,8 @@
/// Storage for new bindings that have been created corresponding to an
/// original texture_external binding.
- std::unordered_map<Symbol, NewBindingSymbols> new_binding_symbols;
+ std::unordered_map<const sem::Variable*, NewBindingSymbols>
+ new_binding_symbols;
/// Constructor
/// @param context the clone
@@ -80,16 +81,17 @@
// binding and create two additional bindings (one texture_2d<f32> to
// represent the secondary plane and one uniform buffer for the
// ExternalTextureParams struct).
- ctx.ReplaceAll([&](const ast::Variable* var) -> const ast::Variable* {
- if (!sem.Get<sem::ExternalTexture>(var->type)) {
- return nullptr;
+ for (auto* var : ctx.src->AST().GlobalVariables()) {
+ auto* sem_var = sem.Get(var);
+ if (!sem_var->Type()->UnwrapRef()->Is<sem::ExternalTexture>()) {
+ continue;
}
// If the attributes are empty, then this must be a texture_external
// passed as a function parameter. These variables are transformed
// elsewhere.
if (var->attributes.empty()) {
- return nullptr;
+ continue;
}
// If we find a texture_external binding, we know we must emit the
@@ -113,7 +115,7 @@
"missing new binding points for texture_external at binding {" +
std::to_string(bp.group) + "," + std::to_string(bp.binding) +
"}");
- return nullptr;
+ continue;
}
BindingPoints bps = it->second;
@@ -123,7 +125,7 @@
// the source symbol associated with the texture_external binding that
// corresponds with the new destination bindings.
// NewBindingSymbols new_binding_syms;
- auto& syms = new_binding_symbols[var->symbol];
+ auto& syms = new_binding_symbols[sem_var];
syms.plane_0 = ctx.Clone(var->symbol);
syms.plane_1 = b.Symbols().New("ext_tex_plane_1");
b.Global(syms.plane_1,
@@ -139,69 +141,21 @@
ast::AttributeList cloned_attributes = ctx.Clone(var->attributes);
const ast::Expression* cloned_constructor = ctx.Clone(var->constructor);
- return b.Var(syms.plane_0,
- b.ty.sampled_texture(ast::TextureDimension::k2d, b.ty.f32()),
- cloned_constructor, cloned_attributes);
- });
-
- // Transform the original textureLoad and textureSampleLevel calls into
- // textureLoadExternal and textureSampleExternal calls.
- ctx.ReplaceAll(
- [&](const ast::CallExpression* expr) -> const ast::CallExpression* {
- auto* builtin = sem.Get(expr)->Target()->As<sem::Builtin>();
-
- if (builtin && !builtin->Parameters().empty() &&
- builtin->Parameters()[0]->Type()->Is<sem::ExternalTexture>() &&
- builtin->Type() != sem::BuiltinType::kTextureDimensions) {
- auto it = new_binding_symbols.find(
- expr->args[0]->As<ast::IdentifierExpression>()->symbol);
- if (it == new_binding_symbols.end()) {
- // If valid new binding locations were not provided earlier, we
- // would have been unable to create these symbols. An error
- // message was emitted earlier, so just return early to avoid
- // internal compiler errors and retain a clean error message.
- return nullptr;
- }
- auto& syms = it->second;
-
- if (builtin->Type() == sem::BuiltinType::kTextureLoad) {
- return createTexLdExt(expr, syms);
- }
-
- if (builtin->Type() == sem::BuiltinType::kTextureSampleLevel) {
- return createTexSmpExt(expr, syms);
- }
-
- } else if (sem.Get(expr)->Target()->Is<sem::Function>()) {
- // The call expression may be to a user-defined function that
- // contains a texture_external parameter. These need to be expanded
- // out to multiple plane textures and the texture parameters
- // structure.
- for (const ast::Expression* arg : expr->args) {
- if (auto* id_expr = arg->As<ast::IdentifierExpression>()) {
- // Check if a parameter is a texture_external by trying to find
- // it in the transform state.
- auto it = new_binding_symbols.find(id_expr->symbol);
- if (it != new_binding_symbols.end()) {
- auto& syms = it->second;
- // When we find a texture_external, we must unpack it into its
- // components.
- ctx.Replace(id_expr, b.Expr(syms.plane_0));
- ctx.InsertAfter(expr->args, id_expr, b.Expr(syms.plane_1));
- ctx.InsertAfter(expr->args, id_expr, b.Expr(syms.params));
- }
- }
- }
- }
-
- return nullptr;
- });
+ auto* replacement =
+ b.Var(syms.plane_0,
+ b.ty.sampled_texture(ast::TextureDimension::k2d, b.ty.f32()),
+ cloned_constructor, cloned_attributes);
+ ctx.Replace(var, replacement);
+ }
// We must update all the texture_external parameters for user declared
// functions.
- ctx.ReplaceAll([&](const ast::Function* fn) -> const ast::Function* {
+ for (auto* fn : ctx.src->AST().Functions()) {
for (const ast::Variable* param : fn->params) {
- if (sem.Get<sem::ExternalTexture>(param->type)) {
+ if (auto* sem_var = sem.Get(param)) {
+ if (!sem_var->Type()->UnwrapRef()->Is<sem::ExternalTexture>()) {
+ continue;
+ }
// If we find a texture_external, we must ensure the
// ExternalTextureParams struct exists.
if (!params_struct_sym.IsValid()) {
@@ -211,7 +165,7 @@
// the texture_external into the parameter list. We must also place
// the new symbols into the transform state so they can be used when
// transforming function calls.
- auto& syms = new_binding_symbols[param->symbol];
+ auto& syms = new_binding_symbols[sem_var];
syms.plane_0 = ctx.Clone(param->symbol);
syms.plane_1 = b.Symbols().New("ext_tex_plane_1");
syms.params = b.Symbols().New("ext_tex_params");
@@ -226,10 +180,61 @@
b.Param(syms.params, b.ty.type_name(params_struct_sym)));
}
}
- // Clone the function. This will use the Replace() and InsertAfter() calls
- // above.
- return nullptr;
- });
+ }
+
+ // Transform the original textureLoad and textureSampleLevel calls into
+ // textureLoadExternal and textureSampleExternal calls.
+ ctx.ReplaceAll(
+ [&](const ast::CallExpression* expr) -> const ast::CallExpression* {
+ auto* builtin = sem.Get(expr)->Target()->As<sem::Builtin>();
+
+ if (builtin && !builtin->Parameters().empty() &&
+ builtin->Parameters()[0]->Type()->Is<sem::ExternalTexture>() &&
+ builtin->Type() != sem::BuiltinType::kTextureDimensions) {
+ if (auto* var_user = sem.Get<sem::VariableUser>(expr->args[0])) {
+ auto it = new_binding_symbols.find(var_user->Variable());
+ if (it == new_binding_symbols.end()) {
+ // If valid new binding locations were not provided earlier, we
+ // would have been unable to create these symbols. An error
+ // message was emitted earlier, so just return early to avoid
+ // internal compiler errors and retain a clean error message.
+ return nullptr;
+ }
+ auto& syms = it->second;
+
+ if (builtin->Type() == sem::BuiltinType::kTextureLoad) {
+ return createTexLdExt(expr, syms);
+ }
+
+ if (builtin->Type() == sem::BuiltinType::kTextureSampleLevel) {
+ return createTexSmpExt(expr, syms);
+ }
+ }
+
+ } else if (sem.Get(expr)->Target()->Is<sem::Function>()) {
+ // The call expression may be to a user-defined function that
+ // contains a texture_external parameter. These need to be expanded
+ // out to multiple plane textures and the texture parameters
+ // structure.
+ for (auto* arg : expr->args) {
+ if (auto* var_user = sem.Get<sem::VariableUser>(arg)) {
+ // Check if a parameter is a texture_external by trying to find
+ // it in the transform state.
+ auto it = new_binding_symbols.find(var_user->Variable());
+ if (it != new_binding_symbols.end()) {
+ auto& syms = it->second;
+ // When we find a texture_external, we must unpack it into its
+ // components.
+ ctx.Replace(arg, b.Expr(syms.plane_0));
+ ctx.InsertAfter(expr->args, arg, b.Expr(syms.plane_1));
+ ctx.InsertAfter(expr->args, arg, b.Expr(syms.params));
+ }
+ }
+ }
+ }
+
+ return nullptr;
+ });
}
/// Creates the ExternalTextureParams struct.
diff --git a/src/transform/multiplanar_external_texture_test.cc b/src/transform/multiplanar_external_texture_test.cc
index 0d8df30..a0a42b8 100644
--- a/src/transform/multiplanar_external_texture_test.cc
+++ b/src/transform/multiplanar_external_texture_test.cc
@@ -149,8 +149,6 @@
)";
auto* expect = R"(
-@group(0) @binding(0) var s : sampler;
-
struct ExternalTextureParams {
numPlanes : u32;
vr : f32;
@@ -163,6 +161,8 @@
@group(0) @binding(3) var<uniform> ext_tex_params : ExternalTextureParams;
+@group(0) @binding(0) var s : sampler;
+
@group(0) @binding(1) var ext_tex : texture_2d<f32>;
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
@@ -259,8 +259,6 @@
)";
auto* expect = R"(
-@group(0) @binding(0) var s : sampler;
-
struct ExternalTextureParams {
numPlanes : u32;
vr : f32;
@@ -273,6 +271,8 @@
@group(0) @binding(3) var<uniform> ext_tex_params : ExternalTextureParams;
+@group(0) @binding(0) var s : sampler;
+
@group(0) @binding(1) var ext_tex : texture_2d<f32>;
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
@@ -332,8 +332,6 @@
)";
auto* expect = R"(
-@group(0) @binding(0) var s : sampler;
-
struct ExternalTextureParams {
numPlanes : u32;
vr : f32;
@@ -346,24 +344,26 @@
@group(0) @binding(5) var<uniform> ext_tex_params : ExternalTextureParams;
-@group(0) @binding(1) var ext_tex : texture_2d<f32>;
-
@group(0) @binding(6) var ext_tex_plane_1_1 : texture_2d<f32>;
@group(0) @binding(7) var<uniform> ext_tex_params_1 : ExternalTextureParams;
-@group(0) @binding(2) var ext_tex_1 : texture_2d<f32>;
-
@group(0) @binding(8) var ext_tex_plane_1_2 : texture_2d<f32>;
@group(0) @binding(9) var<uniform> ext_tex_params_2 : ExternalTextureParams;
-@group(0) @binding(3) var ext_tex_2 : texture_2d<f32>;
-
@group(1) @binding(1) var ext_tex_plane_1_3 : texture_2d<f32>;
@group(1) @binding(2) var<uniform> ext_tex_params_3 : ExternalTextureParams;
+@group(0) @binding(0) var s : sampler;
+
+@group(0) @binding(1) var ext_tex : texture_2d<f32>;
+
+@group(0) @binding(2) var ext_tex_1 : texture_2d<f32>;
+
+@group(0) @binding(3) var ext_tex_2 : texture_2d<f32>;
+
@group(1) @binding(0) var ext_tex_3 : texture_2d<f32>;
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
@@ -424,6 +424,10 @@
ub : f32;
}
+@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
+
+@group(0) @binding(3) var<uniform> ext_tex_params : ExternalTextureParams;
+
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
if ((params.numPlanes == 1u)) {
return textureSampleLevel(plane0, smp, coord, 0.0);
@@ -438,21 +442,17 @@
return vec4<f32>(r, g, b, 1.0);
}
-fn f(t : texture_2d<f32>, ext_tex_plane_1 : texture_2d<f32>, ext_tex_params : ExternalTextureParams, s : sampler) {
- textureSampleExternal(t, ext_tex_plane_1, s, vec2<f32>(1.0, 2.0), ext_tex_params);
+fn f(t : texture_2d<f32>, ext_tex_plane_1_1 : texture_2d<f32>, ext_tex_params_1 : ExternalTextureParams, s : sampler) {
+ textureSampleExternal(t, ext_tex_plane_1_1, s, vec2<f32>(1.0, 2.0), ext_tex_params_1);
}
-@group(0) @binding(2) var ext_tex_plane_1_1 : texture_2d<f32>;
-
-@group(0) @binding(3) var<uniform> ext_tex_params_1 : ExternalTextureParams;
-
@group(0) @binding(0) var ext_tex : texture_2d<f32>;
@group(0) @binding(1) var smp : sampler;
@stage(fragment)
fn main() {
- f(ext_tex, ext_tex_plane_1_1, ext_tex_params_1, smp);
+ f(ext_tex, ext_tex_plane_1, ext_tex_params, smp);
}
)";
DataMap data;
@@ -490,6 +490,10 @@
ub : f32;
}
+@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
+
+@group(0) @binding(3) var<uniform> ext_tex_params : ExternalTextureParams;
+
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
if ((params.numPlanes == 1u)) {
return textureSampleLevel(plane0, smp, coord, 0.0);
@@ -504,21 +508,17 @@
return vec4<f32>(r, g, b, 1.0);
}
-fn f(s : sampler, t : texture_2d<f32>, ext_tex_plane_1 : texture_2d<f32>, ext_tex_params : ExternalTextureParams) {
- textureSampleExternal(t, ext_tex_plane_1, s, vec2<f32>(1.0, 2.0), ext_tex_params);
+fn f(s : sampler, t : texture_2d<f32>, ext_tex_plane_1_1 : texture_2d<f32>, ext_tex_params_1 : ExternalTextureParams) {
+ textureSampleExternal(t, ext_tex_plane_1_1, s, vec2<f32>(1.0, 2.0), ext_tex_params_1);
}
-@group(0) @binding(2) var ext_tex_plane_1_1 : texture_2d<f32>;
-
-@group(0) @binding(3) var<uniform> ext_tex_params_1 : ExternalTextureParams;
-
@group(0) @binding(0) var ext_tex : texture_2d<f32>;
@group(0) @binding(1) var smp : sampler;
@stage(fragment)
fn main() {
- f(smp, ext_tex, ext_tex_plane_1_1, ext_tex_params_1);
+ f(smp, ext_tex, ext_tex_plane_1, ext_tex_params);
}
)";
DataMap data;
@@ -558,6 +558,14 @@
ub : f32;
}
+@group(0) @binding(3) var ext_tex_plane_1 : texture_2d<f32>;
+
+@group(0) @binding(4) var<uniform> ext_tex_params : ExternalTextureParams;
+
+@group(0) @binding(5) var ext_tex_plane_1_1 : texture_2d<f32>;
+
+@group(0) @binding(6) var<uniform> ext_tex_params_1 : ExternalTextureParams;
+
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
if ((params.numPlanes == 1u)) {
return textureSampleLevel(plane0, smp, coord, 0.0);
@@ -572,28 +580,20 @@
return vec4<f32>(r, g, b, 1.0);
}
-fn f(t : texture_2d<f32>, ext_tex_plane_1 : texture_2d<f32>, ext_tex_params : ExternalTextureParams, s : sampler, t2 : texture_2d<f32>, ext_tex_plane_1_1 : texture_2d<f32>, ext_tex_params_1 : ExternalTextureParams) {
- textureSampleExternal(t, ext_tex_plane_1, s, vec2<f32>(1.0, 2.0), ext_tex_params);
- textureSampleExternal(t2, ext_tex_plane_1_1, s, vec2<f32>(1.0, 2.0), ext_tex_params_1);
+fn f(t : texture_2d<f32>, ext_tex_plane_1_2 : texture_2d<f32>, ext_tex_params_2 : ExternalTextureParams, s : sampler, t2 : texture_2d<f32>, ext_tex_plane_1_3 : texture_2d<f32>, ext_tex_params_3 : ExternalTextureParams) {
+ textureSampleExternal(t, ext_tex_plane_1_2, s, vec2<f32>(1.0, 2.0), ext_tex_params_2);
+ textureSampleExternal(t2, ext_tex_plane_1_3, s, vec2<f32>(1.0, 2.0), ext_tex_params_3);
}
-@group(0) @binding(3) var ext_tex_plane_1_2 : texture_2d<f32>;
-
-@group(0) @binding(4) var<uniform> ext_tex_params_2 : ExternalTextureParams;
-
@group(0) @binding(0) var ext_tex : texture_2d<f32>;
@group(0) @binding(1) var smp : sampler;
-@group(0) @binding(5) var ext_tex_plane_1_3 : texture_2d<f32>;
-
-@group(0) @binding(6) var<uniform> ext_tex_params_3 : ExternalTextureParams;
-
@group(0) @binding(2) var ext_tex2 : texture_2d<f32>;
@stage(fragment)
fn main() {
- f(ext_tex, ext_tex_plane_1_2, ext_tex_params_2, smp, ext_tex2, ext_tex_plane_1_3, ext_tex_params_3);
+ f(ext_tex, ext_tex_plane_1, ext_tex_params, smp, ext_tex2, ext_tex_plane_1_1, ext_tex_params_1);
}
)";
DataMap data;
@@ -636,6 +636,10 @@
ub : f32;
}
+@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
+
+@group(0) @binding(3) var<uniform> ext_tex_params : ExternalTextureParams;
+
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
if ((params.numPlanes == 1u)) {
return textureSampleLevel(plane0, smp, coord, 0.0);
@@ -650,25 +654,21 @@
return vec4<f32>(r, g, b, 1.0);
}
-fn nested(t : texture_2d<f32>, ext_tex_plane_1 : texture_2d<f32>, ext_tex_params : ExternalTextureParams, s : sampler) {
- textureSampleExternal(t, ext_tex_plane_1, s, vec2<f32>(1.0, 2.0), ext_tex_params);
+fn nested(t : texture_2d<f32>, ext_tex_plane_1_1 : texture_2d<f32>, ext_tex_params_1 : ExternalTextureParams, s : sampler) {
+ textureSampleExternal(t, ext_tex_plane_1_1, s, vec2<f32>(1.0, 2.0), ext_tex_params_1);
}
-fn f(t : texture_2d<f32>, ext_tex_plane_1_1 : texture_2d<f32>, ext_tex_params_1 : ExternalTextureParams, s : sampler) {
- nested(t, ext_tex_plane_1_1, ext_tex_params_1, s);
+fn f(t : texture_2d<f32>, ext_tex_plane_1_2 : texture_2d<f32>, ext_tex_params_2 : ExternalTextureParams, s : sampler) {
+ nested(t, ext_tex_plane_1_2, ext_tex_params_2, s);
}
-@group(0) @binding(2) var ext_tex_plane_1_2 : texture_2d<f32>;
-
-@group(0) @binding(3) var<uniform> ext_tex_params_2 : ExternalTextureParams;
-
@group(0) @binding(0) var ext_tex : texture_2d<f32>;
@group(0) @binding(1) var smp : sampler;
@stage(fragment)
fn main() {
- f(ext_tex, ext_tex_plane_1_2, ext_tex_params_2, smp);
+ f(ext_tex, ext_tex_plane_1, ext_tex_params, smp);
}
)";
DataMap data;
@@ -730,8 +730,6 @@
)";
auto* expect = R"(
-type ET = texture_external;
-
struct ExternalTextureParams {
numPlanes : u32;
vr : f32;
@@ -740,6 +738,12 @@
ub : f32;
}
+@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
+
+@group(0) @binding(3) var<uniform> ext_tex_params : ExternalTextureParams;
+
+type ET = texture_external;
+
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
if ((params.numPlanes == 1u)) {
return textureSampleLevel(plane0, smp, coord, 0.0);
@@ -754,21 +758,17 @@
return vec4<f32>(r, g, b, 1.0);
}
-fn f(t : texture_2d<f32>, ext_tex_plane_1 : texture_2d<f32>, ext_tex_params : ExternalTextureParams, s : sampler) {
- textureSampleExternal(t, ext_tex_plane_1, s, vec2<f32>(1.0, 2.0), ext_tex_params);
+fn f(t : texture_2d<f32>, ext_tex_plane_1_1 : texture_2d<f32>, ext_tex_params_1 : ExternalTextureParams, s : sampler) {
+ textureSampleExternal(t, ext_tex_plane_1_1, s, vec2<f32>(1.0, 2.0), ext_tex_params_1);
}
-@group(0) @binding(2) var ext_tex_plane_1_1 : texture_2d<f32>;
-
-@group(0) @binding(3) var<uniform> ext_tex_params_1 : ExternalTextureParams;
-
@group(0) @binding(0) var ext_tex : texture_2d<f32>;
@group(0) @binding(1) var smp : sampler;
@stage(fragment)
fn main() {
- f(ext_tex, ext_tex_plane_1_1, ext_tex_params_1, smp);
+ f(ext_tex, ext_tex_plane_1, ext_tex_params, smp);
}
)";
DataMap data;