mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 18:59:21 +00:00
Add transform to substitute overrides with const expressions.
This CL adds a SubstituteOverride transform which will convert an `override` into a `const`. The transform is provided a map of (string, double) which matches what the WebGPU API accepts as data for overrides. Bug: tint:1582 Change-Id: I6e6bf51b98ce4d4746f8de55128666c36735e585 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/96760 Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
9ec7893ad4
commit
256f1116b8
96
src/tint/transform/substitute_override.cc
Normal file
96
src/tint/transform/substitute_override.cc
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright 2022 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/tint/transform/substitute_override.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "src/tint/program_builder.h"
|
||||
#include "src/tint/sem/variable.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::transform::SubstituteOverride);
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::transform::SubstituteOverride::Config);
|
||||
|
||||
namespace tint::transform {
|
||||
|
||||
SubstituteOverride::SubstituteOverride() = default;
|
||||
|
||||
SubstituteOverride::~SubstituteOverride() = default;
|
||||
|
||||
bool SubstituteOverride::ShouldRun(const Program* program, const DataMap&) const {
|
||||
for (auto* node : program->AST().GlobalVariables()) {
|
||||
if (node->Is<ast::Override>()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SubstituteOverride::Run(CloneContext& ctx, const DataMap& config, DataMap&) const {
|
||||
const auto* data = config.Get<Config>();
|
||||
if (!data) {
|
||||
ctx.dst->Diagnostics().add_error(diag::System::Transform,
|
||||
"Missing override substitution data");
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.ReplaceAll([&](const ast::Override* w) -> const ast::Const* {
|
||||
auto ident = w->Identifier(ctx.src->Symbols());
|
||||
|
||||
auto src = ctx.Clone(w->source);
|
||||
auto sym = ctx.Clone(w->symbol);
|
||||
auto* ty = ctx.Clone(w->type);
|
||||
|
||||
// No replacement provided, just clone the override node as a const.
|
||||
auto iter = data->map.find(ident);
|
||||
if (iter == data->map.end()) {
|
||||
if (!w->constructor) {
|
||||
ctx.dst->Diagnostics().add_error(
|
||||
diag::System::Transform,
|
||||
"Initializer not provided for override, and override not overridden.");
|
||||
return nullptr;
|
||||
}
|
||||
return ctx.dst->Const(src, sym, ty, ctx.Clone(w->constructor));
|
||||
}
|
||||
|
||||
auto value = iter->second;
|
||||
auto* ctor = Switch(
|
||||
ctx.src->Sem().Get(w)->Type(),
|
||||
[&](const sem::Bool*) { return ctx.dst->Expr(!std::equal_to<double>()(value, 0.0)); },
|
||||
[&](const sem::I32*) { return ctx.dst->Expr(i32(value)); },
|
||||
[&](const sem::U32*) { return ctx.dst->Expr(u32(value)); },
|
||||
[&](const sem::F32*) { return ctx.dst->Expr(f32(value)); },
|
||||
[&](const sem::F16*) { return ctx.dst->Expr(f16(value)); });
|
||||
|
||||
if (!ctor) {
|
||||
ctx.dst->Diagnostics().add_error(diag::System::Transform,
|
||||
"Failed to create override expression");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ctx.dst->Const(src, sym, ty, ctor);
|
||||
});
|
||||
|
||||
ctx.Clone();
|
||||
}
|
||||
|
||||
SubstituteOverride::Config::Config() = default;
|
||||
|
||||
SubstituteOverride::Config::Config(const Config&) = default;
|
||||
|
||||
SubstituteOverride::Config::~Config() = default;
|
||||
|
||||
SubstituteOverride::Config& SubstituteOverride::Config::operator=(const Config&) = default;
|
||||
|
||||
} // namespace tint::transform
|
||||
89
src/tint/transform/substitute_override.h
Normal file
89
src/tint/transform/substitute_override.h
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright 2022 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_TINT_TRANSFORM_SUBSTITUTE_OVERRIDE_H_
|
||||
#define SRC_TINT_TRANSFORM_SUBSTITUTE_OVERRIDE_H_
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "src/tint/transform/transform.h"
|
||||
|
||||
namespace tint::transform {
|
||||
|
||||
/// A transform that replaces overrides with the constant values provided.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// override width: f32;
|
||||
/// @id(1) override height: i32 = 4;
|
||||
/// override depth = 1i;
|
||||
/// ```
|
||||
///
|
||||
/// When transformed with `width` -> 1, `1` -> 22, `depth` -> 42
|
||||
///
|
||||
/// ```
|
||||
/// const width: f32 = 1f;
|
||||
/// const height: i32 = 22i;
|
||||
/// const depth = 42i;
|
||||
/// ```
|
||||
///
|
||||
/// @see crbug.com/tint/1582
|
||||
class SubstituteOverride final : public Castable<SubstituteOverride, Transform> {
|
||||
public:
|
||||
/// Configuration options for the transform
|
||||
struct Config final : public Castable<Config, Data> {
|
||||
/// Constructor
|
||||
Config();
|
||||
|
||||
/// Copy constructor
|
||||
Config(const Config&);
|
||||
|
||||
/// Destructor
|
||||
~Config() override;
|
||||
|
||||
/// Assignment operator
|
||||
/// @returns this Config
|
||||
Config& operator=(const Config&);
|
||||
|
||||
/// The map of override name (either the identifier or id) to value.
|
||||
/// The value is always a double coming into the transform and will be
|
||||
/// converted to the correct type through and initializer.
|
||||
std::unordered_map<std::string, double> map;
|
||||
};
|
||||
|
||||
/// Constructor
|
||||
SubstituteOverride();
|
||||
|
||||
/// Destructor
|
||||
~SubstituteOverride() override;
|
||||
|
||||
/// @param program the program to inspect
|
||||
/// @param data optional extra transform-specific input data
|
||||
/// @returns true if this transform should be run for the given program
|
||||
bool ShouldRun(const Program* program, const DataMap& data = {}) const override;
|
||||
|
||||
protected:
|
||||
/// Runs the transform using the CloneContext built for transforming a
|
||||
/// program. Run() is responsible for calling Clone() on the CloneContext.
|
||||
/// @param ctx the CloneContext primed with the input program and
|
||||
/// ProgramBuilder
|
||||
/// @param inputs optional extra transform-specific input data
|
||||
/// @param outputs optional extra transform-specific output data
|
||||
void Run(CloneContext& ctx, const DataMap& inputs, DataMap& outputs) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::transform
|
||||
|
||||
#endif // SRC_TINT_TRANSFORM_SUBSTITUTE_OVERRIDE_H_
|
||||
243
src/tint/transform/substitute_override_test.cc
Normal file
243
src/tint/transform/substitute_override_test.cc
Normal file
@@ -0,0 +1,243 @@
|
||||
// Copyright 2022 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/tint/transform/substitute_override.h"
|
||||
|
||||
#include "src/tint/transform/test_helper.h"
|
||||
|
||||
namespace tint::transform {
|
||||
namespace {
|
||||
|
||||
using SubstituteOverrideTest = TransformTest;
|
||||
|
||||
TEST_F(SubstituteOverrideTest, Error_NoData) {
|
||||
auto* src = R"(
|
||||
override width: i32;
|
||||
@vertex
|
||||
fn main() -> @builtin(position) vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
auto* expect = "error: Missing override substitution data";
|
||||
|
||||
DataMap data;
|
||||
auto got = Run<SubstituteOverride>(src, data);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(SubstituteOverrideTest, Error_NoOverrideValue) {
|
||||
auto* src = R"(
|
||||
override width: i32;
|
||||
@vertex
|
||||
fn main() -> @builtin(position) vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
auto* expect = "error: Initializer not provided for override, and override not overridden.";
|
||||
|
||||
SubstituteOverride::Config cfg;
|
||||
DataMap data;
|
||||
data.Add<SubstituteOverride::Config>(cfg);
|
||||
|
||||
auto got = Run<SubstituteOverride>(src, data);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(SubstituteOverrideTest, Module_NoOverrides) {
|
||||
auto* src = R"(
|
||||
@vertex
|
||||
fn main() -> @builtin(position) vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
auto* expect = R"(
|
||||
@vertex
|
||||
fn main() -> @builtin(position) vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
SubstituteOverride::Config cfg;
|
||||
|
||||
DataMap data;
|
||||
data.Add<SubstituteOverride::Config>(cfg);
|
||||
auto got = Run<SubstituteOverride>(src, data);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(SubstituteOverrideTest, Identifier) {
|
||||
auto* src = R"(
|
||||
override i_width: i32;
|
||||
override i_height = 1i;
|
||||
|
||||
override f_width: f32;
|
||||
override f_height = 1.f;
|
||||
|
||||
// TODO(crbug.com/tint/1473)
|
||||
// override h_width: f16;
|
||||
// override h_height = 1.h;
|
||||
|
||||
override b_width: bool;
|
||||
override b_height = true;
|
||||
|
||||
override o_width = 2i;
|
||||
|
||||
@vertex
|
||||
fn main() -> @builtin(position) vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
auto* expect = R"(
|
||||
const i_width : i32 = 42i;
|
||||
|
||||
const i_height = 11i;
|
||||
|
||||
const f_width : f32 = 22.299999237f;
|
||||
|
||||
const f_height = 12.399999619f;
|
||||
|
||||
const b_width : bool = true;
|
||||
|
||||
const b_height = false;
|
||||
|
||||
const o_width = 2i;
|
||||
|
||||
@vertex
|
||||
fn main() -> @builtin(position) vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
SubstituteOverride::Config cfg;
|
||||
cfg.map.insert({"i_width", 42.0});
|
||||
cfg.map.insert({"i_height", 11.0});
|
||||
cfg.map.insert({"f_width", 22.3});
|
||||
cfg.map.insert({"f_height", 12.4});
|
||||
cfg.map.insert({"h_width", 9.4});
|
||||
cfg.map.insert({"h_height", 3.4});
|
||||
cfg.map.insert({"b_width", 1.0});
|
||||
cfg.map.insert({"b_height", 0.0});
|
||||
|
||||
DataMap data;
|
||||
data.Add<SubstituteOverride::Config>(cfg);
|
||||
auto got = Run<SubstituteOverride>(src, data);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(SubstituteOverrideTest, Id) {
|
||||
auto* src = R"(
|
||||
enable f16;
|
||||
|
||||
@id(0) override i_width: i32;
|
||||
@id(10) override i_height = 1i;
|
||||
|
||||
@id(1) override f_width: f32;
|
||||
@id(9) override f_height = 1.f;
|
||||
|
||||
// TODO(crbug.com/tint/1473)
|
||||
// @id(2) override h_width: f16;
|
||||
// @id(8) override h_height = 1.h;
|
||||
|
||||
@id(3) override b_width: bool;
|
||||
@id(7) override b_height = true;
|
||||
|
||||
@id(5) override o_width = 2i;
|
||||
|
||||
@vertex
|
||||
fn main() -> @builtin(position) vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
auto* expect = R"(
|
||||
enable f16;
|
||||
|
||||
const i_width : i32 = 42i;
|
||||
|
||||
const i_height = 11i;
|
||||
|
||||
const f_width : f32 = 22.299999237f;
|
||||
|
||||
const f_height = 12.399999619f;
|
||||
|
||||
const b_width : bool = true;
|
||||
|
||||
const b_height = false;
|
||||
|
||||
const o_width = 2i;
|
||||
|
||||
@vertex
|
||||
fn main() -> @builtin(position) vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
SubstituteOverride::Config cfg;
|
||||
cfg.map.insert({"0", 42.0});
|
||||
cfg.map.insert({"10", 11.0});
|
||||
cfg.map.insert({"1", 22.3});
|
||||
cfg.map.insert({"9", 12.4});
|
||||
cfg.map.insert({"2", 9.4});
|
||||
cfg.map.insert({"8", 3.4});
|
||||
cfg.map.insert({"3", 1.0});
|
||||
cfg.map.insert({"7", 0.0});
|
||||
// No effect because an @id is set for o_width
|
||||
cfg.map.insert({"o_width", 13});
|
||||
|
||||
DataMap data;
|
||||
data.Add<SubstituteOverride::Config>(cfg);
|
||||
auto got = Run<SubstituteOverride>(src, data);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(SubstituteOverrideTest, Identifier_Expression) {
|
||||
auto* src = R"(
|
||||
override i_height = ~2i;
|
||||
|
||||
@vertex
|
||||
fn main() -> @builtin(position) vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
auto* expect = R"(
|
||||
const i_height = 11i;
|
||||
|
||||
@vertex
|
||||
fn main() -> @builtin(position) vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
SubstituteOverride::Config cfg;
|
||||
cfg.map.insert({"i_height", 11.0});
|
||||
|
||||
DataMap data;
|
||||
data.Add<SubstituteOverride::Config>(cfg);
|
||||
auto got = Run<SubstituteOverride>(src, data);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::transform
|
||||
Reference in New Issue
Block a user