blob: 201e2546e737c557f7bdc7d1e3b8bbb046c1c3e5 [file] [log] [blame]
// 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/lang/wgsl/helpers/flatten_bindings.h"
#include <utility>
#include "gtest/gtest.h"
#include "src/tint/lang/core/type/texture_dimension.h"
#include "src/tint/lang/wgsl/program/program_builder.h"
#include "src/tint/lang/wgsl/resolver/resolve.h"
#include "src/tint/lang/wgsl/sem/variable.h"
namespace tint::writer {
namespace {
using namespace tint::core::number_suffixes; // NOLINT
class FlattenBindingsTest : public ::testing::Test {};
TEST_F(FlattenBindingsTest, NoBindings) {
ProgramBuilder b;
Program program(resolver::Resolve(b));
ASSERT_TRUE(program.IsValid()) << program.Diagnostics().str();
auto flattened = tint::writer::FlattenBindings(&program);
EXPECT_FALSE(flattened);
}
TEST_F(FlattenBindingsTest, AlreadyFlat) {
ProgramBuilder b;
b.GlobalVar("a", b.ty.i32(), core::AddressSpace::kUniform, b.Group(0_a), b.Binding(0_a));
b.GlobalVar("b", b.ty.i32(), core::AddressSpace::kUniform, b.Group(0_a), b.Binding(1_a));
b.GlobalVar("c", b.ty.i32(), core::AddressSpace::kUniform, b.Group(0_a), b.Binding(2_a));
Program program(resolver::Resolve(b));
ASSERT_TRUE(program.IsValid()) << program.Diagnostics().str();
auto flattened = tint::writer::FlattenBindings(&program);
EXPECT_FALSE(flattened);
}
TEST_F(FlattenBindingsTest, NotFlat_SingleNamespace) {
ProgramBuilder b;
b.GlobalVar("a", b.ty.i32(), core::AddressSpace::kUniform, b.Group(0_a), b.Binding(0_a));
b.GlobalVar("b", b.ty.i32(), core::AddressSpace::kUniform, b.Group(1_a), b.Binding(1_a));
b.GlobalVar("c", b.ty.i32(), core::AddressSpace::kUniform, b.Group(2_a), b.Binding(2_a));
b.WrapInFunction(b.Expr("a"), b.Expr("b"), b.Expr("c"));
Program program(resolver::Resolve(b));
ASSERT_TRUE(program.IsValid()) << program.Diagnostics().str();
auto flattened = tint::writer::FlattenBindings(&program);
EXPECT_TRUE(flattened);
auto& vars = flattened->AST().GlobalVariables();
auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[0]);
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint()->binding, 0u);
sem = flattened->Sem().Get<sem::GlobalVariable>(vars[1]);
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint()->binding, 1u);
sem = flattened->Sem().Get<sem::GlobalVariable>(vars[2]);
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint()->binding, 2u);
}
TEST_F(FlattenBindingsTest, NotFlat_MultipleNamespaces) {
ProgramBuilder b;
const size_t num_buffers = 3;
b.GlobalVar("buffer1", b.ty.i32(), core::AddressSpace::kUniform, b.Group(0_a), b.Binding(0_a));
b.GlobalVar("buffer2", b.ty.i32(), core::AddressSpace::kStorage, b.Group(1_a), b.Binding(1_a));
b.GlobalVar("buffer3", b.ty.i32(), core::AddressSpace::kStorage, core::Access::kRead,
b.Group(2_a), b.Binding(2_a));
const size_t num_samplers = 2;
b.GlobalVar("sampler1", b.ty.sampler(core::type::SamplerKind::kSampler), b.Group(3_a),
b.Binding(3_a));
b.GlobalVar("sampler2", b.ty.sampler(core::type::SamplerKind::kComparisonSampler), b.Group(4_a),
b.Binding(4_a));
const size_t num_textures = 6;
b.GlobalVar("texture1", b.ty.sampled_texture(core::type::TextureDimension::k2d, b.ty.f32()),
b.Group(5_a), b.Binding(5_a));
b.GlobalVar("texture2",
b.ty.multisampled_texture(core::type::TextureDimension::k2d, b.ty.f32()),
b.Group(6_a), b.Binding(6_a));
b.GlobalVar("texture3",
b.ty.storage_texture(core::type::TextureDimension::k2d,
core::TexelFormat::kR32Float, core::Access::kWrite),
b.Group(7_a), b.Binding(7_a));
b.GlobalVar("texture4", b.ty.depth_texture(core::type::TextureDimension::k2d), b.Group(8_a),
b.Binding(8_a));
b.GlobalVar("texture5", b.ty.depth_multisampled_texture(core::type::TextureDimension::k2d),
b.Group(9_a), b.Binding(9_a));
b.GlobalVar("texture6", b.ty.external_texture(), b.Group(10_a), b.Binding(10_a));
b.WrapInFunction(b.Assign(b.Phony(), "buffer1"), b.Assign(b.Phony(), "buffer2"),
b.Assign(b.Phony(), "buffer3"), b.Assign(b.Phony(), "sampler1"),
b.Assign(b.Phony(), "sampler2"), b.Assign(b.Phony(), "texture1"),
b.Assign(b.Phony(), "texture2"), b.Assign(b.Phony(), "texture3"),
b.Assign(b.Phony(), "texture4"), b.Assign(b.Phony(), "texture5"),
b.Assign(b.Phony(), "texture6"));
Program program(resolver::Resolve(b));
ASSERT_TRUE(program.IsValid()) << program.Diagnostics().str();
auto flattened = tint::writer::FlattenBindings(&program);
EXPECT_TRUE(flattened);
auto& vars = flattened->AST().GlobalVariables();
for (size_t i = 0; i < num_buffers; ++i) {
auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[i]);
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint()->binding, i);
}
for (size_t i = 0; i < num_samplers; ++i) {
auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[i + num_buffers]);
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint()->binding, i);
}
for (size_t i = 0; i < num_textures; ++i) {
auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[i + num_buffers + num_samplers]);
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint()->binding, i);
}
}
} // namespace
} // namespace tint::writer