mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-07 20:49:25 +00:00
[ir][spirv-writer] Emit vector constants
Switch the constant map key to constant::Value. Bug: tint:1906 Change-Id: I71743cc8b47a5c703f6333371ed686cf70900f74 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/132742 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: James Price <jrprice@google.com>
This commit is contained in:
parent
f85dc40e67
commit
055de27441
@ -17,7 +17,7 @@
|
|||||||
namespace tint::writer::spirv {
|
namespace tint::writer::spirv {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
TEST_F(SpvGeneratorImplTest, Type_Bool) {
|
TEST_F(SpvGeneratorImplTest, Constant_Bool) {
|
||||||
generator_.Constant(b.Constant(true));
|
generator_.Constant(b.Constant(true));
|
||||||
generator_.Constant(b.Constant(false));
|
generator_.Constant(b.Constant(false));
|
||||||
EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeBool
|
EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeBool
|
||||||
@ -62,6 +62,89 @@ TEST_F(SpvGeneratorImplTest, Constant_F16) {
|
|||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvGeneratorImplTest, Constant_Vec4Bool) {
|
||||||
|
auto* t = b.Constant(true);
|
||||||
|
auto* f = b.Constant(false);
|
||||||
|
auto* v = mod.constants.Create<constant::Composite>(
|
||||||
|
mod.types.Get<type::Vector>(mod.types.Get<type::Bool>(), 4u),
|
||||||
|
utils::Vector{t->value, f->value, f->value, t->value}, false, true);
|
||||||
|
generator_.Constant(b.Constant(v));
|
||||||
|
EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeBool
|
||||||
|
%2 = OpTypeVector %3 4
|
||||||
|
%4 = OpConstantTrue %3
|
||||||
|
%5 = OpConstantFalse %3
|
||||||
|
%1 = OpConstantComposite %2 %4 %5 %5 %4
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvGeneratorImplTest, Constant_Vec2i) {
|
||||||
|
auto* i = mod.types.Get<type::I32>();
|
||||||
|
auto* i_42 = b.Constant(i32(42));
|
||||||
|
auto* i_n1 = b.Constant(i32(-1));
|
||||||
|
auto* v = mod.constants.Create<constant::Composite>(
|
||||||
|
mod.types.Get<type::Vector>(i, 2u), utils::Vector{i_42->value, i_n1->value}, false, false);
|
||||||
|
generator_.Constant(b.Constant(v));
|
||||||
|
EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeInt 32 1
|
||||||
|
%2 = OpTypeVector %3 2
|
||||||
|
%4 = OpConstant %3 42
|
||||||
|
%5 = OpConstant %3 -1
|
||||||
|
%1 = OpConstantComposite %2 %4 %5
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvGeneratorImplTest, Constant_Vec3u) {
|
||||||
|
auto* u = mod.types.Get<type::U32>();
|
||||||
|
auto* u_42 = b.Constant(u32(42));
|
||||||
|
auto* u_0 = b.Constant(u32(0));
|
||||||
|
auto* u_4b = b.Constant(u32(4000000000));
|
||||||
|
auto* v = mod.constants.Create<constant::Composite>(
|
||||||
|
mod.types.Get<type::Vector>(u, 3u), utils::Vector{u_42->value, u_0->value, u_4b->value},
|
||||||
|
false, true);
|
||||||
|
generator_.Constant(b.Constant(v));
|
||||||
|
EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeInt 32 0
|
||||||
|
%2 = OpTypeVector %3 3
|
||||||
|
%4 = OpConstant %3 42
|
||||||
|
%5 = OpConstant %3 0
|
||||||
|
%6 = OpConstant %3 4000000000
|
||||||
|
%1 = OpConstantComposite %2 %4 %5 %6
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvGeneratorImplTest, Constant_Vec4f) {
|
||||||
|
auto* f = mod.types.Get<type::F32>();
|
||||||
|
auto* f_42 = b.Constant(f32(42));
|
||||||
|
auto* f_0 = b.Constant(f32(0));
|
||||||
|
auto* f_q = b.Constant(f32(0.25));
|
||||||
|
auto* f_n1 = b.Constant(f32(-1));
|
||||||
|
auto* v = mod.constants.Create<constant::Composite>(
|
||||||
|
mod.types.Get<type::Vector>(f, 4u),
|
||||||
|
utils::Vector{f_42->value, f_0->value, f_q->value, f_n1->value}, false, true);
|
||||||
|
generator_.Constant(b.Constant(v));
|
||||||
|
EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeFloat 32
|
||||||
|
%2 = OpTypeVector %3 4
|
||||||
|
%4 = OpConstant %3 42
|
||||||
|
%5 = OpConstant %3 0
|
||||||
|
%6 = OpConstant %3 0.25
|
||||||
|
%7 = OpConstant %3 -1
|
||||||
|
%1 = OpConstantComposite %2 %4 %5 %6 %7
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvGeneratorImplTest, Constant_Vec2h) {
|
||||||
|
auto* h = mod.types.Get<type::F16>();
|
||||||
|
auto* h_42 = b.Constant(f16(42));
|
||||||
|
auto* h_q = b.Constant(f16(0.25));
|
||||||
|
auto* v = mod.constants.Create<constant::Composite>(
|
||||||
|
mod.types.Get<type::Vector>(h, 2u), utils::Vector{h_42->value, h_q->value}, false, false);
|
||||||
|
generator_.Constant(b.Constant(v));
|
||||||
|
EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeFloat 16
|
||||||
|
%2 = OpTypeVector %3 2
|
||||||
|
%4 = OpConstant %3 0x1.5p+5
|
||||||
|
%5 = OpConstant %3 0x1p-2
|
||||||
|
%1 = OpConstantComposite %2 %4 %5
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
// Test that we do not emit the same constant more than once.
|
// Test that we do not emit the same constant more than once.
|
||||||
TEST_F(SpvGeneratorImplTest, Constant_Deduplicate) {
|
TEST_F(SpvGeneratorImplTest, Constant_Deduplicate) {
|
||||||
generator_.Constant(b.Constant(i32(42)));
|
generator_.Constant(b.Constant(i32(42)));
|
||||||
|
@ -68,31 +68,41 @@ bool GeneratorImplIr::Generate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GeneratorImplIr::Constant(const ir::Constant* constant) {
|
uint32_t GeneratorImplIr::Constant(const ir::Constant* constant) {
|
||||||
|
return Constant(constant->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GeneratorImplIr::Constant(const constant::Value* constant) {
|
||||||
return constants_.GetOrCreate(constant, [&]() {
|
return constants_.GetOrCreate(constant, [&]() {
|
||||||
auto id = module_.NextId();
|
auto id = module_.NextId();
|
||||||
auto* ty = constant->Type();
|
auto* ty = constant->Type();
|
||||||
auto* value = constant->value;
|
|
||||||
Switch(
|
Switch(
|
||||||
ty, //
|
ty, //
|
||||||
[&](const type::Bool*) {
|
[&](const type::Bool*) {
|
||||||
module_.PushType(
|
module_.PushType(
|
||||||
value->ValueAs<bool>() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse,
|
constant->ValueAs<bool>() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse,
|
||||||
{Type(ty), id});
|
{Type(ty), id});
|
||||||
},
|
},
|
||||||
[&](const type::I32*) {
|
[&](const type::I32*) {
|
||||||
module_.PushType(spv::Op::OpConstant, {Type(ty), id, value->ValueAs<u32>()});
|
module_.PushType(spv::Op::OpConstant, {Type(ty), id, constant->ValueAs<u32>()});
|
||||||
},
|
},
|
||||||
[&](const type::U32*) {
|
[&](const type::U32*) {
|
||||||
module_.PushType(spv::Op::OpConstant,
|
module_.PushType(spv::Op::OpConstant,
|
||||||
{Type(ty), id, U32Operand(value->ValueAs<i32>())});
|
{Type(ty), id, U32Operand(constant->ValueAs<i32>())});
|
||||||
},
|
},
|
||||||
[&](const type::F32*) {
|
[&](const type::F32*) {
|
||||||
module_.PushType(spv::Op::OpConstant, {Type(ty), id, value->ValueAs<f32>()});
|
module_.PushType(spv::Op::OpConstant, {Type(ty), id, constant->ValueAs<f32>()});
|
||||||
},
|
},
|
||||||
[&](const type::F16*) {
|
[&](const type::F16*) {
|
||||||
module_.PushType(
|
module_.PushType(
|
||||||
spv::Op::OpConstant,
|
spv::Op::OpConstant,
|
||||||
{Type(ty), id, U32Operand(value->ValueAs<f16>().BitsRepresentation())});
|
{Type(ty), id, U32Operand(constant->ValueAs<f16>().BitsRepresentation())});
|
||||||
|
},
|
||||||
|
[&](const type::Vector* vec) {
|
||||||
|
OperandList operands = {Type(ty), id};
|
||||||
|
for (uint32_t i = 0; i < vec->Width(); i++) {
|
||||||
|
operands.push_back(Constant(constant->Index(i)));
|
||||||
|
}
|
||||||
|
module_.PushType(spv::Op::OpConstantComposite, operands);
|
||||||
},
|
},
|
||||||
[&](Default) {
|
[&](Default) {
|
||||||
TINT_ICE(Writer, diagnostics_) << "unhandled constant type: " << ty->FriendlyName();
|
TINT_ICE(Writer, diagnostics_) << "unhandled constant type: " << ty->FriendlyName();
|
||||||
|
@ -95,6 +95,11 @@ class GeneratorImplIr {
|
|||||||
uint32_t EmitBinary(const ir::Binary* binary);
|
uint32_t EmitBinary(const ir::Binary* binary);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Get the result ID of the constant `constant`, emitting its instruction if necessary.
|
||||||
|
/// @param constant the constant to get the ID for
|
||||||
|
/// @returns the result ID of the constant
|
||||||
|
uint32_t Constant(const constant::Value* constant);
|
||||||
|
|
||||||
const ir::Module* ir_;
|
const ir::Module* ir_;
|
||||||
spirv::Module module_;
|
spirv::Module module_;
|
||||||
BinaryWriter writer_;
|
BinaryWriter writer_;
|
||||||
@ -125,22 +130,22 @@ class GeneratorImplIr {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ConstantHasher provides a hash function for an ir::Constant pointer, hashing the value
|
/// ConstantHasher provides a hash function for a constant::Value pointer, hashing the value
|
||||||
/// instead of the pointer itself.
|
/// instead of the pointer itself.
|
||||||
struct ConstantHasher {
|
struct ConstantHasher {
|
||||||
/// @param c the ir::Constant pointer to create a hash for
|
/// @param c the constant::Value pointer to create a hash for
|
||||||
/// @return the hash value
|
/// @return the hash value
|
||||||
inline std::size_t operator()(const ir::Constant* c) const { return c->value->Hash(); }
|
inline std::size_t operator()(const constant::Value* c) const { return c->Hash(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ConstantEquals provides an equality function for two ir::Constant pointers, comparing their
|
/// ConstantEquals provides an equality function for two constant::Value pointers, comparing
|
||||||
/// values instead of the pointers.
|
/// their values instead of the pointers.
|
||||||
struct ConstantEquals {
|
struct ConstantEquals {
|
||||||
/// @param a the first ir::Constant pointer to compare
|
/// @param a the first constant::Value pointer to compare
|
||||||
/// @param b the second ir::Constant pointer to compare
|
/// @param b the second constant::Value pointer to compare
|
||||||
/// @return the hash value
|
/// @return the hash value
|
||||||
inline bool operator()(const ir::Constant* a, const ir::Constant* b) const {
|
inline bool operator()(const constant::Value* a, const constant::Value* b) const {
|
||||||
return a->value->Equal(b->value);
|
return a->Equal(b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -151,7 +156,7 @@ class GeneratorImplIr {
|
|||||||
utils::Hashmap<FunctionType, uint32_t, 8, FunctionType::Hasher> function_types_;
|
utils::Hashmap<FunctionType, uint32_t, 8, FunctionType::Hasher> function_types_;
|
||||||
|
|
||||||
/// The map of constants to their result IDs.
|
/// The map of constants to their result IDs.
|
||||||
utils::Hashmap<const ir::Constant*, uint32_t, 16, ConstantHasher, ConstantEquals> constants_;
|
utils::Hashmap<const constant::Value*, uint32_t, 16, ConstantHasher, ConstantEquals> constants_;
|
||||||
|
|
||||||
/// The map of instructions to their result IDs.
|
/// The map of instructions to their result IDs.
|
||||||
utils::Hashmap<const ir::Instruction*, uint32_t, 8> instructions_;
|
utils::Hashmap<const ir::Instruction*, uint32_t, 8> instructions_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user