Store struct member location into the sem.
This CL adds the `@location` of a Struct Member into the `StructMember` sem object as a `std::optional<uint32_t>`. The resolver then populates the location value if an attribute is found during resolution. This will provide a place to store the evaluated expression value for a location in the future. Bug: tint:1633 Change-Id: I6f696968dddf95af1f933d96cdb4a7630badac2e Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/101062 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
8dc97a8e3d
commit
97c9e0ba9f
|
@ -149,10 +149,10 @@ TEST_F(ResolverInferredTypeTest, InferStruct_Pass) {
|
||||||
auto* member = Member("x", ty.i32());
|
auto* member = Member("x", ty.i32());
|
||||||
auto* str = Structure("S", utils::Vector{member});
|
auto* str = Structure("S", utils::Vector{member});
|
||||||
|
|
||||||
auto* expected_type =
|
auto* expected_type = create<sem::Struct>(
|
||||||
create<sem::Struct>(str, str->name,
|
str, str->name,
|
||||||
sem::StructMemberList{create<sem::StructMember>(
|
sem::StructMemberList{create<sem::StructMember>(member, member->symbol, create<sem::I32>(),
|
||||||
member, member->symbol, create<sem::I32>(), 0u, 0u, 0u, 4u)},
|
0u, 0u, 0u, 4u, std::nullopt)},
|
||||||
0u, 4u, 4u);
|
0u, 4u, 4u);
|
||||||
|
|
||||||
auto* ctor_expr = Construct(ty.Of(str));
|
auto* ctor_expr = Construct(ty.Of(str));
|
||||||
|
|
|
@ -793,7 +793,8 @@ const sem::Struct* build_struct(MatchState& state,
|
||||||
/* index */ static_cast<uint32_t>(members.size()),
|
/* index */ static_cast<uint32_t>(members.size()),
|
||||||
/* offset */ offset,
|
/* offset */ offset,
|
||||||
/* align */ align,
|
/* align */ align,
|
||||||
/* size */ size));
|
/* size */ size,
|
||||||
|
/* location */ std::nullopt));
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
uint32_t size_without_padding = offset;
|
uint32_t size_without_padding = offset;
|
||||||
|
|
|
@ -2747,6 +2747,7 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
|
||||||
bool has_offset_attr = false;
|
bool has_offset_attr = false;
|
||||||
bool has_align_attr = false;
|
bool has_align_attr = false;
|
||||||
bool has_size_attr = false;
|
bool has_size_attr = false;
|
||||||
|
std::optional<uint32_t> location;
|
||||||
for (auto* attr : member->attributes) {
|
for (auto* attr : member->attributes) {
|
||||||
Mark(attr);
|
Mark(attr);
|
||||||
if (auto* o = attr->As<ast::StructMemberOffsetAttribute>()) {
|
if (auto* o = attr->As<ast::StructMemberOffsetAttribute>()) {
|
||||||
|
@ -2760,11 +2761,7 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
|
||||||
align = 1;
|
align = 1;
|
||||||
has_offset_attr = true;
|
has_offset_attr = true;
|
||||||
} else if (auto* a = attr->As<ast::StructMemberAlignAttribute>()) {
|
} else if (auto* a = attr->As<ast::StructMemberAlignAttribute>()) {
|
||||||
const auto* expr = Expression(a->align);
|
auto* materialized = Materialize(Expression(a->align));
|
||||||
if (!expr) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
auto* materialized = Materialize(expr);
|
|
||||||
if (!materialized) {
|
if (!materialized) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -2790,6 +2787,8 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
|
||||||
}
|
}
|
||||||
size = s->size;
|
size = s->size;
|
||||||
has_size_attr = true;
|
has_size_attr = true;
|
||||||
|
} else if (auto* l = attr->As<ast::LocationAttribute>()) {
|
||||||
|
location = l->value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2811,7 +2810,7 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
|
||||||
auto* sem_member = builder_->create<sem::StructMember>(
|
auto* sem_member = builder_->create<sem::StructMember>(
|
||||||
member, member->symbol, type, static_cast<uint32_t>(sem_members.size()),
|
member, member->symbol, type, static_cast<uint32_t>(sem_members.size()),
|
||||||
static_cast<uint32_t>(offset), static_cast<uint32_t>(align),
|
static_cast<uint32_t>(offset), static_cast<uint32_t>(align),
|
||||||
static_cast<uint32_t>(size));
|
static_cast<uint32_t>(size), location);
|
||||||
builder_->Sem().Add(member, sem_member);
|
builder_->Sem().Add(member, sem_member);
|
||||||
sem_members.emplace_back(sem_member);
|
sem_members.emplace_back(sem_member);
|
||||||
|
|
||||||
|
|
|
@ -174,6 +174,20 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderParamViaAlias) {
|
||||||
UnorderedElementsAre(sem::PipelineStageUsage::kFragmentInput));
|
UnorderedElementsAre(sem::PipelineStageUsage::kFragmentInput));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderParamLocationSet) {
|
||||||
|
auto* s = Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{Location(3)})});
|
||||||
|
|
||||||
|
Func("main", utils::Vector{Param("param", ty.Of(s))}, ty.void_(), utils::Empty,
|
||||||
|
utils::Vector{Stage(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
|
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
|
||||||
|
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||||
|
ASSERT_NE(sem, nullptr);
|
||||||
|
ASSERT_EQ(1u, sem->Members().size());
|
||||||
|
EXPECT_EQ(3u, sem->Members()[0]->Location());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderReturnTypeViaAlias) {
|
TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderReturnTypeViaAlias) {
|
||||||
auto* s = Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{Location(0)})});
|
auto* s = Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{Location(0)})});
|
||||||
auto* s_alias = Alias("S_alias", ty.Of(s));
|
auto* s_alias = Alias("S_alias", ty.Of(s));
|
||||||
|
@ -190,5 +204,19 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderReturnTypeViaAlias) {
|
||||||
UnorderedElementsAre(sem::PipelineStageUsage::kFragmentOutput));
|
UnorderedElementsAre(sem::PipelineStageUsage::kFragmentOutput));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderReturnTypeLocationSet) {
|
||||||
|
auto* s = Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{Location(3)})});
|
||||||
|
|
||||||
|
Func("main", utils::Empty, ty.Of(s), utils::Vector{Return(Construct(ty.Of(s), Expr(0_f)))},
|
||||||
|
utils::Vector{Stage(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
|
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
|
||||||
|
auto* sem = TypeOf(s)->As<sem::Struct>();
|
||||||
|
ASSERT_NE(sem, nullptr);
|
||||||
|
ASSERT_EQ(1u, sem->Members().size());
|
||||||
|
EXPECT_EQ(3u, sem->Members()[0]->Location());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::resolver
|
} // namespace tint::resolver
|
||||||
|
|
|
@ -105,5 +105,23 @@ TEST_F(StructTest, Layout) {
|
||||||
/* */ };)");
|
/* */ };)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(StructTest, Location) {
|
||||||
|
auto* st = Structure("st", utils::Vector{
|
||||||
|
Member("a", ty.i32(), utils::Vector{Location(1u)}),
|
||||||
|
Member("b", ty.u32()),
|
||||||
|
});
|
||||||
|
|
||||||
|
auto p = Build();
|
||||||
|
ASSERT_TRUE(p.IsValid()) << p.Diagnostics().str();
|
||||||
|
|
||||||
|
auto* sem = p.Sem().Get(st);
|
||||||
|
ASSERT_EQ(2u, sem->Members().size());
|
||||||
|
|
||||||
|
EXPECT_TRUE(sem->Members()[0]->Location().has_value());
|
||||||
|
EXPECT_EQ(sem->Members()[0]->Location().value(), 1u);
|
||||||
|
|
||||||
|
EXPECT_FALSE(sem->Members()[1]->Location().has_value());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::sem
|
} // namespace tint::sem
|
||||||
|
|
|
@ -161,14 +161,16 @@ StructMember::StructMember(const ast::StructMember* declaration,
|
||||||
uint32_t index,
|
uint32_t index,
|
||||||
uint32_t offset,
|
uint32_t offset,
|
||||||
uint32_t align,
|
uint32_t align,
|
||||||
uint32_t size)
|
uint32_t size,
|
||||||
|
std::optional<uint32_t> location)
|
||||||
: declaration_(declaration),
|
: declaration_(declaration),
|
||||||
name_(name),
|
name_(name),
|
||||||
type_(type),
|
type_(type),
|
||||||
index_(index),
|
index_(index),
|
||||||
offset_(offset),
|
offset_(offset),
|
||||||
align_(align),
|
align_(align),
|
||||||
size_(size) {}
|
size_(size),
|
||||||
|
location_(location) {}
|
||||||
|
|
||||||
StructMember::~StructMember() = default;
|
StructMember::~StructMember() = default;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -180,13 +181,15 @@ class StructMember final : public Castable<StructMember, Node> {
|
||||||
/// @param offset the byte offset from the base of the structure
|
/// @param offset the byte offset from the base of the structure
|
||||||
/// @param align the byte alignment of the member
|
/// @param align the byte alignment of the member
|
||||||
/// @param size the byte size of the member
|
/// @param size the byte size of the member
|
||||||
|
/// @param location the location attribute, if present
|
||||||
StructMember(const ast::StructMember* declaration,
|
StructMember(const ast::StructMember* declaration,
|
||||||
Symbol name,
|
Symbol name,
|
||||||
const sem::Type* type,
|
const sem::Type* type,
|
||||||
uint32_t index,
|
uint32_t index,
|
||||||
uint32_t offset,
|
uint32_t offset,
|
||||||
uint32_t align,
|
uint32_t align,
|
||||||
uint32_t size);
|
uint32_t size,
|
||||||
|
std::optional<uint32_t> location);
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~StructMember() override;
|
~StructMember() override;
|
||||||
|
@ -219,6 +222,9 @@ class StructMember final : public Castable<StructMember, Node> {
|
||||||
/// @returns byte size
|
/// @returns byte size
|
||||||
uint32_t Size() const { return size_; }
|
uint32_t Size() const { return size_; }
|
||||||
|
|
||||||
|
/// @returns the location, if set
|
||||||
|
std::optional<uint32_t> Location() const { return location_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ast::StructMember* const declaration_;
|
const ast::StructMember* const declaration_;
|
||||||
const Symbol name_;
|
const Symbol name_;
|
||||||
|
@ -228,6 +234,7 @@ class StructMember final : public Castable<StructMember, Node> {
|
||||||
const uint32_t offset_;
|
const uint32_t offset_;
|
||||||
const uint32_t align_;
|
const uint32_t align_;
|
||||||
const uint32_t size_;
|
const uint32_t size_;
|
||||||
|
const std::optional<uint32_t> location_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tint::sem
|
} // namespace tint::sem
|
||||||
|
|
|
@ -54,7 +54,8 @@ struct TypeTest : public TestHelper {
|
||||||
/* index */ 0u,
|
/* index */ 0u,
|
||||||
/* offset */ 0u,
|
/* offset */ 0u,
|
||||||
/* align */ 4u,
|
/* align */ 4u,
|
||||||
/* size */ 4u),
|
/* size */ 4u,
|
||||||
|
/* location */ std::nullopt),
|
||||||
},
|
},
|
||||||
/* align*/ 4u,
|
/* align*/ 4u,
|
||||||
/* size*/ 4u,
|
/* size*/ 4u,
|
||||||
|
|
Loading…
Reference in New Issue