Validate scalar constructor and implement conversion to vecN<bool> in spir-v backend
After implementing validation and fairly exhaustive tests, discovered that conversion of scalar vector to bool vector did not work in the spir-v backend. For module scope variables, we use and rely on the FoldConstants transform to ensure no conversion needs to take place. This is necessary because we cannot easily introduce temporary values and refer to them when casting at module scope. Note that for the same reason, module-level conversions are always constant foldable, so this works. For function-level conversions, implemented support to emit a comparison against a zero value, and store the result in the bool vector. Bug: tint:865 Change-Id: I0528045e803f176e03428bc7eac31ae06920bbd7 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/54744 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
0507273047
commit
adbbd0ba66
|
@ -1988,6 +1988,9 @@ bool Resolver::Constructor(ast::ConstructorExpression* expr) {
|
||||||
if (auto* mat_type = type->As<sem::Matrix>()) {
|
if (auto* mat_type = type->As<sem::Matrix>()) {
|
||||||
return ValidateMatrixConstructor(type_ctor, mat_type);
|
return ValidateMatrixConstructor(type_ctor, mat_type);
|
||||||
}
|
}
|
||||||
|
if (type->is_scalar()) {
|
||||||
|
return ValidateScalarConstructor(type_ctor, type);
|
||||||
|
}
|
||||||
if (auto* arr_type = type->As<sem::Array>()) {
|
if (auto* arr_type = type->As<sem::Array>()) {
|
||||||
return ValidateArrayConstructor(type_ctor, arr_type);
|
return ValidateArrayConstructor(type_ctor, arr_type);
|
||||||
}
|
}
|
||||||
|
@ -2154,6 +2157,45 @@ bool Resolver::ValidateMatrixConstructor(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Resolver::ValidateScalarConstructor(
|
||||||
|
const ast::TypeConstructorExpression* ctor,
|
||||||
|
const sem::Type* type) {
|
||||||
|
if (ctor->values().size() == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (ctor->values().size() > 1) {
|
||||||
|
diagnostics_.add_error("expected zero or one value in constructor, got " +
|
||||||
|
std::to_string(ctor->values().size()),
|
||||||
|
ctor->source());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate constructor
|
||||||
|
auto* value = ctor->values()[0];
|
||||||
|
auto* value_type = TypeOf(value)->UnwrapRef();
|
||||||
|
|
||||||
|
using Bool = sem::Bool;
|
||||||
|
using I32 = sem::I32;
|
||||||
|
using U32 = sem::U32;
|
||||||
|
using F32 = sem::F32;
|
||||||
|
|
||||||
|
const bool is_valid =
|
||||||
|
(type->Is<Bool>() && value_type->IsAnyOf<Bool, I32, U32, F32>()) ||
|
||||||
|
(type->Is<I32>() && value_type->IsAnyOf<I32, U32, F32>()) ||
|
||||||
|
(type->Is<U32>() && value_type->IsAnyOf<I32, U32, F32>()) ||
|
||||||
|
(type->Is<F32>() && value_type->IsAnyOf<I32, U32, F32>());
|
||||||
|
if (!is_valid) {
|
||||||
|
diagnostics_.add_error("cannot construct '" + TypeNameOf(ctor) +
|
||||||
|
"' with a value of type '" + TypeNameOf(value) +
|
||||||
|
"'",
|
||||||
|
ctor->source());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Resolver::Identifier(ast::IdentifierExpression* expr) {
|
bool Resolver::Identifier(ast::IdentifierExpression* expr) {
|
||||||
auto symbol = expr->symbol();
|
auto symbol = expr->symbol();
|
||||||
VariableInfo* var;
|
VariableInfo* var;
|
||||||
|
|
|
@ -285,6 +285,8 @@ class Resolver {
|
||||||
const std::string& rhs_type_name);
|
const std::string& rhs_type_name);
|
||||||
bool ValidateVectorConstructor(const ast::TypeConstructorExpression* ctor,
|
bool ValidateVectorConstructor(const ast::TypeConstructorExpression* ctor,
|
||||||
const sem::Vector* vec_type);
|
const sem::Vector* vec_type);
|
||||||
|
bool ValidateScalarConstructor(const ast::TypeConstructorExpression* ctor,
|
||||||
|
const sem::Type* type);
|
||||||
bool ValidateArrayConstructor(const ast::TypeConstructorExpression* ctor,
|
bool ValidateArrayConstructor(const ast::TypeConstructorExpression* ctor,
|
||||||
const sem::Array* arr_type);
|
const sem::Array* arr_type);
|
||||||
bool ValidateTypeDecl(const ast::TypeDecl* named_type) const;
|
bool ValidateTypeDecl(const ast::TypeDecl* named_type) const;
|
||||||
|
|
|
@ -384,6 +384,23 @@ struct DataType<alias<T, ID>> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Struct of all creation pointer types
|
||||||
|
struct CreatePtrs {
|
||||||
|
/// ast node type create function
|
||||||
|
ast_type_func_ptr ast;
|
||||||
|
/// ast expression type create function
|
||||||
|
ast_expr_func_ptr expr;
|
||||||
|
/// sem type create function
|
||||||
|
sem_type_func_ptr sem;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Returns a CreatePtrs struct instance with all creation pointer types for
|
||||||
|
/// type `T`
|
||||||
|
template <typename T>
|
||||||
|
constexpr CreatePtrs CreatePtrsFor() {
|
||||||
|
return {DataType<T>::AST, DataType<T>::Expr, DataType<T>::Sem};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace builder
|
} // namespace builder
|
||||||
|
|
||||||
} // namespace resolver
|
} // namespace resolver
|
||||||
|
|
|
@ -20,31 +20,24 @@ namespace resolver {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Helpers and typedefs
|
// Helpers and typedefs
|
||||||
template <typename T>
|
using builder::alias;
|
||||||
using DataType = builder::DataType<T>;
|
using builder::alias1;
|
||||||
template <typename T>
|
using builder::alias2;
|
||||||
using vec2 = builder::vec2<T>;
|
using builder::alias3;
|
||||||
template <typename T>
|
using builder::CreatePtrs;
|
||||||
using vec3 = builder::vec3<T>;
|
using builder::CreatePtrsFor;
|
||||||
template <typename T>
|
using builder::DataType;
|
||||||
using vec4 = builder::vec4<T>;
|
using builder::f32;
|
||||||
template <typename T>
|
using builder::i32;
|
||||||
using mat2x2 = builder::mat2x2<T>;
|
using builder::mat2x2;
|
||||||
template <typename T>
|
using builder::mat2x3;
|
||||||
using mat3x3 = builder::mat3x3<T>;
|
using builder::mat3x2;
|
||||||
template <typename T>
|
using builder::mat3x3;
|
||||||
using mat4x4 = builder::mat4x4<T>;
|
using builder::mat4x4;
|
||||||
template <typename T>
|
using builder::u32;
|
||||||
using alias = builder::alias<T>;
|
using builder::vec2;
|
||||||
template <typename T>
|
using builder::vec3;
|
||||||
using alias1 = builder::alias1<T>;
|
using builder::vec4;
|
||||||
template <typename T>
|
|
||||||
using alias2 = builder::alias2<T>;
|
|
||||||
template <typename T>
|
|
||||||
using alias3 = builder::alias3<T>;
|
|
||||||
using f32 = builder::f32;
|
|
||||||
using i32 = builder::i32;
|
|
||||||
using u32 = builder::u32;
|
|
||||||
|
|
||||||
class ResolverTypeConstructorValidationTest : public resolver::TestHelper,
|
class ResolverTypeConstructorValidationTest : public resolver::TestHelper,
|
||||||
public testing::Test {};
|
public testing::Test {};
|
||||||
|
@ -235,6 +228,185 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeConstructorValidationTest,
|
||||||
|
|
||||||
} // namespace InferTypeTest
|
} // namespace InferTypeTest
|
||||||
|
|
||||||
|
namespace ConversionConstructorTest {
|
||||||
|
struct Params {
|
||||||
|
builder::ast_type_func_ptr lhs_type;
|
||||||
|
builder::ast_type_func_ptr rhs_type;
|
||||||
|
builder::ast_expr_func_ptr rhs_value_expr;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename LhsType, typename RhsType>
|
||||||
|
constexpr Params ParamsFor() {
|
||||||
|
return Params{DataType<LhsType>::AST, DataType<RhsType>::AST,
|
||||||
|
DataType<RhsType>::Expr};
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr Params valid_cases[] = {
|
||||||
|
// Direct init (non-conversions)
|
||||||
|
ParamsFor<bool, bool>(), //
|
||||||
|
ParamsFor<i32, i32>(), //
|
||||||
|
ParamsFor<u32, u32>(), //
|
||||||
|
ParamsFor<f32, f32>(), //
|
||||||
|
ParamsFor<vec3<bool>, vec3<bool>>(), //
|
||||||
|
ParamsFor<vec3<i32>, vec3<i32>>(), //
|
||||||
|
ParamsFor<vec3<u32>, vec3<u32>>(), //
|
||||||
|
ParamsFor<vec3<f32>, vec3<f32>>(), //
|
||||||
|
|
||||||
|
// Splat
|
||||||
|
ParamsFor<vec3<bool>, bool>(), //
|
||||||
|
ParamsFor<vec3<i32>, i32>(), //
|
||||||
|
ParamsFor<vec3<u32>, u32>(), //
|
||||||
|
ParamsFor<vec3<f32>, f32>(), //
|
||||||
|
|
||||||
|
// Conversion
|
||||||
|
ParamsFor<bool, u32>(), //
|
||||||
|
ParamsFor<bool, i32>(), //
|
||||||
|
ParamsFor<bool, f32>(), //
|
||||||
|
|
||||||
|
ParamsFor<i32, u32>(), //
|
||||||
|
ParamsFor<i32, f32>(), //
|
||||||
|
|
||||||
|
ParamsFor<u32, i32>(), //
|
||||||
|
ParamsFor<u32, f32>(), //
|
||||||
|
|
||||||
|
ParamsFor<f32, u32>(), //
|
||||||
|
ParamsFor<f32, i32>(), //
|
||||||
|
|
||||||
|
ParamsFor<vec3<bool>, vec3<u32>>(), //
|
||||||
|
ParamsFor<vec3<bool>, vec3<i32>>(), //
|
||||||
|
ParamsFor<vec3<bool>, vec3<f32>>(), //
|
||||||
|
|
||||||
|
ParamsFor<vec3<i32>, vec3<u32>>(), //
|
||||||
|
ParamsFor<vec3<i32>, vec3<f32>>(), //
|
||||||
|
|
||||||
|
ParamsFor<vec3<u32>, vec3<i32>>(), //
|
||||||
|
ParamsFor<vec3<u32>, vec3<f32>>(), //
|
||||||
|
|
||||||
|
ParamsFor<vec3<f32>, vec3<u32>>(), //
|
||||||
|
ParamsFor<vec3<f32>, vec3<i32>>(), //
|
||||||
|
};
|
||||||
|
|
||||||
|
using ConversionConstructorValidTest = ResolverTestWithParam<Params>;
|
||||||
|
TEST_P(ConversionConstructorValidTest, All) {
|
||||||
|
auto& params = GetParam();
|
||||||
|
|
||||||
|
// var a : <lhs_type1> = <lhs_type2>(<rhs_type>(<rhs_value_expr>));
|
||||||
|
auto* lhs_type1 = params.lhs_type(*this);
|
||||||
|
auto* lhs_type2 = params.lhs_type(*this);
|
||||||
|
auto* rhs_type = params.rhs_type(*this);
|
||||||
|
auto* rhs_value_expr = params.rhs_value_expr(*this, 0);
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << FriendlyName(lhs_type1) << " = " << FriendlyName(lhs_type2) << "("
|
||||||
|
<< FriendlyName(rhs_type) << "(<rhs value expr>))";
|
||||||
|
SCOPED_TRACE(ss.str());
|
||||||
|
|
||||||
|
auto* a = Var("a", lhs_type1, ast::StorageClass::kNone,
|
||||||
|
Construct(lhs_type2, Construct(rhs_type, rhs_value_expr)));
|
||||||
|
|
||||||
|
// Self-assign 'a' to force the expression to be resolved so we can test its
|
||||||
|
// type below
|
||||||
|
auto* a_ident = Expr("a");
|
||||||
|
WrapInFunction(Decl(a), Assign(a_ident, "a"));
|
||||||
|
|
||||||
|
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
}
|
||||||
|
INSTANTIATE_TEST_SUITE_P(ResolverTypeConstructorValidationTest,
|
||||||
|
ConversionConstructorValidTest,
|
||||||
|
testing::ValuesIn(valid_cases));
|
||||||
|
|
||||||
|
constexpr CreatePtrs all_types[] = {
|
||||||
|
CreatePtrsFor<bool>(), //
|
||||||
|
CreatePtrsFor<u32>(), //
|
||||||
|
CreatePtrsFor<i32>(), //
|
||||||
|
CreatePtrsFor<f32>(), //
|
||||||
|
CreatePtrsFor<vec3<bool>>(), //
|
||||||
|
CreatePtrsFor<vec3<i32>>(), //
|
||||||
|
CreatePtrsFor<vec3<u32>>(), //
|
||||||
|
CreatePtrsFor<vec3<f32>>(), //
|
||||||
|
CreatePtrsFor<mat3x3<i32>>(), //
|
||||||
|
CreatePtrsFor<mat3x3<u32>>(), //
|
||||||
|
CreatePtrsFor<mat3x3<f32>>(), //
|
||||||
|
CreatePtrsFor<mat2x3<i32>>(), //
|
||||||
|
CreatePtrsFor<mat2x3<u32>>(), //
|
||||||
|
CreatePtrsFor<mat2x3<f32>>(), //
|
||||||
|
CreatePtrsFor<mat3x2<i32>>(), //
|
||||||
|
CreatePtrsFor<mat3x2<u32>>(), //
|
||||||
|
CreatePtrsFor<mat3x2<f32>>() //
|
||||||
|
};
|
||||||
|
|
||||||
|
using ConversionConstructorInvalidTest =
|
||||||
|
ResolverTestWithParam<std::tuple<CreatePtrs, // lhs
|
||||||
|
CreatePtrs // rhs
|
||||||
|
>>;
|
||||||
|
TEST_P(ConversionConstructorInvalidTest, All) {
|
||||||
|
auto& params = GetParam();
|
||||||
|
|
||||||
|
auto& lhs_params = std::get<0>(params);
|
||||||
|
auto& rhs_params = std::get<1>(params);
|
||||||
|
|
||||||
|
// Skip test for valid cases
|
||||||
|
for (auto& v : valid_cases) {
|
||||||
|
if (v.lhs_type == lhs_params.ast && v.rhs_type == rhs_params.ast &&
|
||||||
|
v.rhs_value_expr == rhs_params.expr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Skip non-conversions
|
||||||
|
if (lhs_params.ast == rhs_params.ast) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// var a : <lhs_type1> = <lhs_type2>(<rhs_type>(<rhs_value_expr>));
|
||||||
|
auto* lhs_type1 = lhs_params.ast(*this);
|
||||||
|
auto* lhs_type2 = lhs_params.ast(*this);
|
||||||
|
auto* rhs_type = rhs_params.ast(*this);
|
||||||
|
auto* rhs_value_expr = rhs_params.expr(*this, 0);
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << FriendlyName(lhs_type1) << " = " << FriendlyName(lhs_type2) << "("
|
||||||
|
<< FriendlyName(rhs_type) << "(<rhs value expr>))";
|
||||||
|
SCOPED_TRACE(ss.str());
|
||||||
|
|
||||||
|
auto* a = Var("a", lhs_type1, ast::StorageClass::kNone,
|
||||||
|
Construct(lhs_type2, Construct(rhs_type, rhs_value_expr)));
|
||||||
|
|
||||||
|
// Self-assign 'a' to force the expression to be resolved so we can test its
|
||||||
|
// type below
|
||||||
|
auto* a_ident = Expr("a");
|
||||||
|
WrapInFunction(Decl(a), Assign(a_ident, "a"));
|
||||||
|
|
||||||
|
ASSERT_FALSE(r()->Resolve());
|
||||||
|
}
|
||||||
|
INSTANTIATE_TEST_SUITE_P(ResolverTypeConstructorValidationTest,
|
||||||
|
ConversionConstructorInvalidTest,
|
||||||
|
testing::Combine(testing::ValuesIn(all_types),
|
||||||
|
testing::ValuesIn(all_types)));
|
||||||
|
|
||||||
|
TEST_F(ResolverTypeConstructorValidationTest,
|
||||||
|
ConversionConstructorInvalid_TooManyInitializers) {
|
||||||
|
auto* a = Var("a", ty.f32(), ast::StorageClass::kNone,
|
||||||
|
Construct(Source{{12, 34}}, ty.f32(), Expr(1.0f), Expr(2.0f)));
|
||||||
|
WrapInFunction(a);
|
||||||
|
|
||||||
|
ASSERT_FALSE(r()->Resolve());
|
||||||
|
ASSERT_EQ(r()->error(),
|
||||||
|
"12:34 error: expected zero or one value in constructor, got 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverTypeConstructorValidationTest,
|
||||||
|
ConversionConstructorInvalid_InvalidInitializer) {
|
||||||
|
auto* a = Var("a", ty.f32(), ast::StorageClass::kNone,
|
||||||
|
Construct(Source{{12, 34}}, ty.f32(), Expr(true)));
|
||||||
|
WrapInFunction(a);
|
||||||
|
|
||||||
|
ASSERT_FALSE(r()->Resolve());
|
||||||
|
ASSERT_EQ(r()->error(),
|
||||||
|
"12:34 error: cannot construct 'f32' with a value of type 'bool'");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ConversionConstructorTest
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace resolver
|
} // namespace resolver
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "src/sem/struct.h"
|
#include "src/sem/struct.h"
|
||||||
#include "src/sem/variable.h"
|
#include "src/sem/variable.h"
|
||||||
#include "src/transform/external_texture_transform.h"
|
#include "src/transform/external_texture_transform.h"
|
||||||
|
#include "src/transform/fold_constants.h"
|
||||||
#include "src/transform/inline_pointer_lets.h"
|
#include "src/transform/inline_pointer_lets.h"
|
||||||
#include "src/transform/manager.h"
|
#include "src/transform/manager.h"
|
||||||
#include "src/transform/simplify.h"
|
#include "src/transform/simplify.h"
|
||||||
|
@ -43,6 +44,7 @@ Output Spirv::Run(const Program* in, const DataMap& data) {
|
||||||
Manager manager;
|
Manager manager;
|
||||||
manager.Add<InlinePointerLets>(); // Required for arrayLength()
|
manager.Add<InlinePointerLets>(); // Required for arrayLength()
|
||||||
manager.Add<Simplify>(); // Required for arrayLength()
|
manager.Add<Simplify>(); // Required for arrayLength()
|
||||||
|
manager.Add<FoldConstants>();
|
||||||
manager.Add<ExternalTextureTransform>();
|
manager.Add<ExternalTextureTransform>();
|
||||||
auto transformedInput = manager.Run(in, data);
|
auto transformedInput = manager.Run(in, data);
|
||||||
|
|
||||||
|
|
|
@ -1317,7 +1317,8 @@ uint32_t Builder::GenerateTypeConstructorExpression(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (can_cast_or_copy) {
|
if (can_cast_or_copy) {
|
||||||
return GenerateCastOrCopyOrPassthrough(result_type, values[0]);
|
return GenerateCastOrCopyOrPassthrough(result_type, values[0],
|
||||||
|
is_global_init);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto type_id = GenerateTypeIfNeeded(result_type);
|
auto type_id = GenerateTypeIfNeeded(result_type);
|
||||||
|
@ -1361,7 +1362,8 @@ uint32_t Builder::GenerateTypeConstructorExpression(
|
||||||
// Both scalars, but not the same type so we need to generate a conversion
|
// Both scalars, but not the same type so we need to generate a conversion
|
||||||
// of the value.
|
// of the value.
|
||||||
if (value_type->is_scalar() && result_type->is_scalar()) {
|
if (value_type->is_scalar() && result_type->is_scalar()) {
|
||||||
id = GenerateCastOrCopyOrPassthrough(result_type, values[0]);
|
id = GenerateCastOrCopyOrPassthrough(result_type, values[0],
|
||||||
|
is_global_init);
|
||||||
out << "_" << id;
|
out << "_" << id;
|
||||||
ops.push_back(Operand::Int(id));
|
ops.push_back(Operand::Int(id));
|
||||||
continue;
|
continue;
|
||||||
|
@ -1458,7 +1460,27 @@ uint32_t Builder::GenerateTypeConstructorExpression(
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Builder::GenerateCastOrCopyOrPassthrough(const sem::Type* to_type,
|
uint32_t Builder::GenerateCastOrCopyOrPassthrough(const sem::Type* to_type,
|
||||||
ast::Expression* from_expr) {
|
ast::Expression* from_expr,
|
||||||
|
bool is_global_init) {
|
||||||
|
// This should not happen as we rely on constant folding to obviate
|
||||||
|
// casts/conversions for module-scope variables
|
||||||
|
if (is_global_init) {
|
||||||
|
TINT_ICE(builder_.Diagnostics())
|
||||||
|
<< "Module-level conversions are not supported. Conversions should "
|
||||||
|
"have already been constant-folded by the FoldConstants transform.";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto elem_type_of = [](const sem::Type* t) -> const sem::Type* {
|
||||||
|
if (t->is_scalar()) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
if (auto* v = t->As<sem::Vector>()) {
|
||||||
|
return v->type();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
auto result = result_op();
|
auto result = result_op();
|
||||||
auto result_id = result.to_i();
|
auto result_id = result.to_i();
|
||||||
|
|
||||||
|
@ -1504,7 +1526,27 @@ uint32_t Builder::GenerateCastOrCopyOrPassthrough(const sem::Type* to_type,
|
||||||
(from_type->is_unsigned_integer_vector() &&
|
(from_type->is_unsigned_integer_vector() &&
|
||||||
to_type->is_integer_scalar_or_vector())) {
|
to_type->is_integer_scalar_or_vector())) {
|
||||||
op = spv::Op::OpBitcast;
|
op = spv::Op::OpBitcast;
|
||||||
|
} else if ((from_type->is_numeric_scalar() && to_type->Is<sem::Bool>()) ||
|
||||||
|
(from_type->is_numeric_vector() && to_type->is_bool_vector())) {
|
||||||
|
// Convert scalar (vector) to bool (vector)
|
||||||
|
|
||||||
|
// Return the result of comparing from_expr with zero
|
||||||
|
uint32_t zero = GenerateConstantNullIfNeeded(from_type);
|
||||||
|
const auto* from_elem_type = elem_type_of(from_type);
|
||||||
|
op = from_elem_type->is_integer_scalar() ? spv::Op::OpINotEqual
|
||||||
|
: spv::Op::OpFUnordNotEqual;
|
||||||
|
if (!push_function_inst(
|
||||||
|
op, {Operand::Int(result_type_id), Operand::Int(result_id),
|
||||||
|
Operand::Int(val_id), Operand::Int(zero)})) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result_id;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
TINT_ICE(builder_.Diagnostics()) << "Invalid from_type";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op == spv::Op::OpNop) {
|
if (op == spv::Op::OpNop) {
|
||||||
error_ = "unable to determine conversion type for cast, from: " +
|
error_ = "unable to determine conversion type for cast, from: " +
|
||||||
from_type->type_name() + " to: " + to_type->type_name();
|
from_type->type_name() + " to: " + to_type->type_name();
|
||||||
|
|
|
@ -382,9 +382,11 @@ class Builder {
|
||||||
/// of the right type.
|
/// of the right type.
|
||||||
/// @param to_type the type we're casting too
|
/// @param to_type the type we're casting too
|
||||||
/// @param from_expr the expression to cast
|
/// @param from_expr the expression to cast
|
||||||
|
/// @param is_global_init if this is a global initializer
|
||||||
/// @returns the expression ID on success or 0 otherwise
|
/// @returns the expression ID on success or 0 otherwise
|
||||||
uint32_t GenerateCastOrCopyOrPassthrough(const sem::Type* to_type,
|
uint32_t GenerateCastOrCopyOrPassthrough(const sem::Type* to_type,
|
||||||
ast::Expression* from_expr);
|
ast::Expression* from_expr,
|
||||||
|
bool is_global_init);
|
||||||
/// Generates a loop statement
|
/// Generates a loop statement
|
||||||
/// @param stmt the statement to generate
|
/// @param stmt the statement to generate
|
||||||
/// @returns true on successful generation
|
/// @returns true on successful generation
|
||||||
|
|
|
@ -637,50 +637,56 @@ TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec2_With_F32) {
|
||||||
|
|
||||||
TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec2_With_Vec2) {
|
TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec2_With_Vec2) {
|
||||||
auto* cast = vec2<f32>(vec2<f32>(2.0f, 2.0f));
|
auto* cast = vec2<f32>(vec2<f32>(2.0f, 2.0f));
|
||||||
WrapInFunction(cast);
|
GlobalConst("a", ty.vec2<f32>(), cast);
|
||||||
|
|
||||||
spirv::Builder& b = Build();
|
spirv::Builder& b = SanitizeAndBuild();
|
||||||
|
ASSERT_TRUE(b.Build());
|
||||||
|
|
||||||
b.push_function(Function{});
|
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
|
||||||
EXPECT_EQ(b.GenerateConstructorExpression(nullptr, cast, true), 5u);
|
%1 = OpTypeVector %2 2
|
||||||
|
%3 = OpConstant %2 2
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
|
%4 = OpConstantComposite %1 %3 %3
|
||||||
%2 = OpTypeVector %3 2
|
%6 = OpTypeVoid
|
||||||
%4 = OpConstant %3 2
|
%5 = OpTypeFunction %6
|
||||||
%5 = OpConstantComposite %2 %4 %4
|
|
||||||
)");
|
)");
|
||||||
|
|
||||||
|
Validate(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec3_With_Vec3) {
|
TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec3_With_Vec3) {
|
||||||
auto* cast = vec3<f32>(vec3<f32>(2.0f, 2.0f, 2.0f));
|
auto* cast = vec3<f32>(vec3<f32>(2.0f, 2.0f, 2.0f));
|
||||||
WrapInFunction(cast);
|
GlobalConst("a", ty.vec3<f32>(), cast);
|
||||||
|
|
||||||
spirv::Builder& b = Build();
|
spirv::Builder& b = SanitizeAndBuild();
|
||||||
|
ASSERT_TRUE(b.Build());
|
||||||
|
|
||||||
b.push_function(Function{});
|
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
|
||||||
EXPECT_EQ(b.GenerateConstructorExpression(nullptr, cast, true), 5u);
|
%1 = OpTypeVector %2 3
|
||||||
|
%3 = OpConstant %2 2
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
|
%4 = OpConstantComposite %1 %3 %3 %3
|
||||||
%2 = OpTypeVector %3 3
|
%6 = OpTypeVoid
|
||||||
%4 = OpConstant %3 2
|
%5 = OpTypeFunction %6
|
||||||
%5 = OpConstantComposite %2 %4 %4 %4
|
|
||||||
)");
|
)");
|
||||||
|
|
||||||
|
Validate(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec4_With_Vec4) {
|
TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec4_With_Vec4) {
|
||||||
auto* cast = vec4<f32>(vec4<f32>(2.0f, 2.0f, 2.0f, 2.0f));
|
auto* cast = vec4<f32>(vec4<f32>(2.0f, 2.0f, 2.0f, 2.0f));
|
||||||
WrapInFunction(cast);
|
GlobalConst("a", ty.vec4<f32>(), cast);
|
||||||
|
|
||||||
spirv::Builder& b = Build();
|
spirv::Builder& b = SanitizeAndBuild();
|
||||||
|
ASSERT_TRUE(b.Build());
|
||||||
|
|
||||||
b.push_function(Function{});
|
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
|
||||||
EXPECT_EQ(b.GenerateConstructorExpression(nullptr, cast, true), 5u);
|
%1 = OpTypeVector %2 4
|
||||||
|
%3 = OpConstant %2 2
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
|
%4 = OpConstantComposite %1 %3 %3 %3 %3
|
||||||
%2 = OpTypeVector %3 4
|
%6 = OpTypeVoid
|
||||||
%4 = OpConstant %3 2
|
%5 = OpTypeFunction %6
|
||||||
%5 = OpConstantComposite %2 %4 %4 %4 %4
|
|
||||||
)");
|
)");
|
||||||
|
|
||||||
|
Validate(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec3_With_F32) {
|
TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec3_With_F32) {
|
||||||
|
|
|
@ -65,6 +65,24 @@ struct ScalarConstant {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @param value the value of the constant
|
||||||
|
/// @returns a new ScalarConstant with the provided value and kind Kind::kI32
|
||||||
|
static inline ScalarConstant I32(int32_t value) {
|
||||||
|
ScalarConstant c;
|
||||||
|
c.value.i32 = value;
|
||||||
|
c.kind = Kind::kI32;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @param value the value of the constant
|
||||||
|
/// @returns a new ScalarConstant with the provided value and kind Kind::kI32
|
||||||
|
static inline ScalarConstant F32(float value) {
|
||||||
|
ScalarConstant c;
|
||||||
|
c.value.f32 = value;
|
||||||
|
c.kind = Kind::kF32;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
/// Equality operator
|
/// Equality operator
|
||||||
/// @param rhs the ScalarConstant to compare against
|
/// @param rhs the ScalarConstant to compare against
|
||||||
/// @returns true if this ScalarConstant is equal to `rhs`
|
/// @returns true if this ScalarConstant is equal to `rhs`
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
fn constant_with_non_constant() {
|
||||||
|
var a : f32 = f32();
|
||||||
|
var b : vec2<f32> = vec2<f32>(f32(i32(1)), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[stage(compute)]]
|
||||||
|
fn main() {
|
||||||
|
var bool_var1 : bool = bool(123u);
|
||||||
|
var bool_var2 : bool = bool(123);
|
||||||
|
var bool_var3 : bool = bool(123.0);
|
||||||
|
|
||||||
|
var i32_var1 : i32 = i32(123u);
|
||||||
|
var i32_var2 : i32 = i32(123.0);
|
||||||
|
|
||||||
|
var u32_var1 : u32 = u32(123);
|
||||||
|
var u32_var2 : u32 = u32(123.0);
|
||||||
|
|
||||||
|
var v3bool_var1 : vec3<bool> = vec3<bool>(vec3<u32>(123u));
|
||||||
|
var v3bool_var11 : vec3<bool> = vec3<bool>(vec3<u32>(1234u));
|
||||||
|
var v3bool_var2 : vec3<bool> = vec3<bool>(vec3<i32>(123));
|
||||||
|
var v3bool_var3 : vec3<bool> = vec3<bool>(vec3<f32>(123.0));
|
||||||
|
|
||||||
|
var v3i32_var1 : vec3<i32> = vec3<i32>(vec3<u32>(123u));
|
||||||
|
var v3i32_var2 : vec3<i32> = vec3<i32>(vec3<f32>(123.0));
|
||||||
|
|
||||||
|
var v3u32_var1 : vec3<u32> = vec3<u32>(vec3<i32>(123));
|
||||||
|
var v3u32_var2 : vec3<u32> = vec3<u32>(vec3<f32>(123.0));
|
||||||
|
|
||||||
|
var v3bool_var4 : vec3<bool> = vec3<bool>(vec2<bool>(vec2<f32>(123.0)), true);
|
||||||
|
var v4bool_var5 : vec4<bool> = vec4<bool>(vec2<bool>(vec2<f32>(123.0, 0.0)), vec2<bool>(true, bool(f32(0.0))));
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
void constant_with_non_constant() {
|
||||||
|
float a = 0.0f;
|
||||||
|
float2 b = float2(float(int(1)), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
[numthreads(1, 1, 1)]
|
||||||
|
void main() {
|
||||||
|
bool bool_var1 = bool(123u);
|
||||||
|
bool bool_var2 = bool(123);
|
||||||
|
bool bool_var3 = bool(123.0f);
|
||||||
|
int i32_var1 = int(123u);
|
||||||
|
int i32_var2 = int(123.0f);
|
||||||
|
uint u32_var1 = uint(123);
|
||||||
|
uint u32_var2 = uint(123.0f);
|
||||||
|
bool3 v3bool_var1 = bool3(uint3((123u).xxx));
|
||||||
|
bool3 v3bool_var11 = bool3(uint3((1234u).xxx));
|
||||||
|
bool3 v3bool_var2 = bool3(int3((123).xxx));
|
||||||
|
bool3 v3bool_var3 = bool3(float3((123.0f).xxx));
|
||||||
|
int3 v3i32_var1 = int3(uint3((123u).xxx));
|
||||||
|
int3 v3i32_var2 = int3(float3((123.0f).xxx));
|
||||||
|
uint3 v3u32_var1 = uint3(int3((123).xxx));
|
||||||
|
uint3 v3u32_var2 = uint3(float3((123.0f).xxx));
|
||||||
|
bool3 v3bool_var4 = bool3(bool2(float2((123.0f).xx)), true);
|
||||||
|
bool4 v4bool_var5 = bool4(bool2(float2(123.0f, 0.0f)), bool2(true, bool(float(0.0f))));
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
void constant_with_non_constant() {
|
||||||
|
float a = float();
|
||||||
|
float2 b = float2(float(int(1)), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
kernel void tint_symbol() {
|
||||||
|
bool bool_var1 = bool(123u);
|
||||||
|
bool bool_var2 = bool(123);
|
||||||
|
bool bool_var3 = bool(123.0f);
|
||||||
|
int i32_var1 = int(123u);
|
||||||
|
int i32_var2 = int(123.0f);
|
||||||
|
uint u32_var1 = uint(123);
|
||||||
|
uint u32_var2 = uint(123.0f);
|
||||||
|
bool3 v3bool_var1 = bool3(uint3(123u));
|
||||||
|
bool3 v3bool_var11 = bool3(uint3(1234u));
|
||||||
|
bool3 v3bool_var2 = bool3(int3(123));
|
||||||
|
bool3 v3bool_var3 = bool3(float3(123.0f));
|
||||||
|
int3 v3i32_var1 = int3(uint3(123u));
|
||||||
|
int3 v3i32_var2 = int3(float3(123.0f));
|
||||||
|
uint3 v3u32_var1 = uint3(int3(123));
|
||||||
|
uint3 v3u32_var2 = uint3(float3(123.0f));
|
||||||
|
bool3 v3bool_var4 = bool3(bool2(float2(123.0f)), true);
|
||||||
|
bool4 v4bool_var5 = bool4(bool2(float2(123.0f, 0.0f)), bool2(true, bool(float(0.0f))));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 65
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint GLCompute %main "main"
|
||||||
|
OpExecutionMode %main LocalSize 1 1 1
|
||||||
|
OpName %constant_with_non_constant "constant_with_non_constant"
|
||||||
|
OpName %a "a"
|
||||||
|
OpName %b "b"
|
||||||
|
OpName %main "main"
|
||||||
|
OpName %bool_var1 "bool_var1"
|
||||||
|
OpName %bool_var2 "bool_var2"
|
||||||
|
OpName %bool_var3 "bool_var3"
|
||||||
|
OpName %i32_var1 "i32_var1"
|
||||||
|
OpName %i32_var2 "i32_var2"
|
||||||
|
OpName %u32_var1 "u32_var1"
|
||||||
|
OpName %u32_var2 "u32_var2"
|
||||||
|
OpName %v3bool_var1 "v3bool_var1"
|
||||||
|
OpName %v3bool_var11 "v3bool_var11"
|
||||||
|
OpName %v3bool_var2 "v3bool_var2"
|
||||||
|
OpName %v3bool_var3 "v3bool_var3"
|
||||||
|
OpName %v3i32_var1 "v3i32_var1"
|
||||||
|
OpName %v3i32_var2 "v3i32_var2"
|
||||||
|
OpName %v3u32_var1 "v3u32_var1"
|
||||||
|
OpName %v3u32_var2 "v3u32_var2"
|
||||||
|
OpName %v3bool_var4 "v3bool_var4"
|
||||||
|
OpName %v4bool_var5 "v4bool_var5"
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%1 = OpTypeFunction %void
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%6 = OpConstantNull %float
|
||||||
|
%_ptr_Function_float = OpTypePointer Function %float
|
||||||
|
%v2float = OpTypeVector %float 2
|
||||||
|
%float_1 = OpConstant %float 1
|
||||||
|
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||||
|
%15 = OpConstantNull %v2float
|
||||||
|
%bool = OpTypeBool
|
||||||
|
%true = OpConstantTrue %bool
|
||||||
|
%_ptr_Function_bool = OpTypePointer Function %bool
|
||||||
|
%22 = OpConstantNull %bool
|
||||||
|
%int = OpTypeInt 32 1
|
||||||
|
%int_123 = OpConstant %int 123
|
||||||
|
%_ptr_Function_int = OpTypePointer Function %int
|
||||||
|
%29 = OpConstantNull %int
|
||||||
|
%uint = OpTypeInt 32 0
|
||||||
|
%uint_123 = OpConstant %uint 123
|
||||||
|
%_ptr_Function_uint = OpTypePointer Function %uint
|
||||||
|
%35 = OpConstantNull %uint
|
||||||
|
%v3bool = OpTypeVector %bool 3
|
||||||
|
%38 = OpConstantComposite %v3bool %true %true %true
|
||||||
|
%_ptr_Function_v3bool = OpTypePointer Function %v3bool
|
||||||
|
%41 = OpConstantNull %v3bool
|
||||||
|
%v3int = OpTypeVector %int 3
|
||||||
|
%46 = OpConstantComposite %v3int %int_123 %int_123 %int_123
|
||||||
|
%_ptr_Function_v3int = OpTypePointer Function %v3int
|
||||||
|
%49 = OpConstantNull %v3int
|
||||||
|
%v3uint = OpTypeVector %uint 3
|
||||||
|
%52 = OpConstantComposite %v3uint %uint_123 %uint_123 %uint_123
|
||||||
|
%_ptr_Function_v3uint = OpTypePointer Function %v3uint
|
||||||
|
%55 = OpConstantNull %v3uint
|
||||||
|
%57 = OpConstantComposite %v3bool %true %true %true
|
||||||
|
%v4bool = OpTypeVector %bool 4
|
||||||
|
%false = OpConstantFalse %bool
|
||||||
|
%61 = OpConstantComposite %v4bool %true %false %true %false
|
||||||
|
%_ptr_Function_v4bool = OpTypePointer Function %v4bool
|
||||||
|
%64 = OpConstantNull %v4bool
|
||||||
|
%constant_with_non_constant = OpFunction %void None %1
|
||||||
|
%4 = OpLabel
|
||||||
|
%a = OpVariable %_ptr_Function_float Function %6
|
||||||
|
%b = OpVariable %_ptr_Function_v2float Function %15
|
||||||
|
OpStore %a %6
|
||||||
|
%11 = OpLoad %float %a
|
||||||
|
%12 = OpCompositeConstruct %v2float %float_1 %11
|
||||||
|
OpStore %b %12
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%main = OpFunction %void None %1
|
||||||
|
%17 = OpLabel
|
||||||
|
%bool_var1 = OpVariable %_ptr_Function_bool Function %22
|
||||||
|
%bool_var2 = OpVariable %_ptr_Function_bool Function %22
|
||||||
|
%bool_var3 = OpVariable %_ptr_Function_bool Function %22
|
||||||
|
%i32_var1 = OpVariable %_ptr_Function_int Function %29
|
||||||
|
%i32_var2 = OpVariable %_ptr_Function_int Function %29
|
||||||
|
%u32_var1 = OpVariable %_ptr_Function_uint Function %35
|
||||||
|
%u32_var2 = OpVariable %_ptr_Function_uint Function %35
|
||||||
|
%v3bool_var1 = OpVariable %_ptr_Function_v3bool Function %41
|
||||||
|
%v3bool_var11 = OpVariable %_ptr_Function_v3bool Function %41
|
||||||
|
%v3bool_var2 = OpVariable %_ptr_Function_v3bool Function %41
|
||||||
|
%v3bool_var3 = OpVariable %_ptr_Function_v3bool Function %41
|
||||||
|
%v3i32_var1 = OpVariable %_ptr_Function_v3int Function %49
|
||||||
|
%v3i32_var2 = OpVariable %_ptr_Function_v3int Function %49
|
||||||
|
%v3u32_var1 = OpVariable %_ptr_Function_v3uint Function %55
|
||||||
|
%v3u32_var2 = OpVariable %_ptr_Function_v3uint Function %55
|
||||||
|
%v3bool_var4 = OpVariable %_ptr_Function_v3bool Function %41
|
||||||
|
%v4bool_var5 = OpVariable %_ptr_Function_v4bool Function %64
|
||||||
|
OpStore %bool_var1 %true
|
||||||
|
OpStore %bool_var2 %true
|
||||||
|
OpStore %bool_var3 %true
|
||||||
|
OpStore %i32_var1 %int_123
|
||||||
|
OpStore %i32_var2 %int_123
|
||||||
|
OpStore %u32_var1 %uint_123
|
||||||
|
OpStore %u32_var2 %uint_123
|
||||||
|
OpStore %v3bool_var1 %38
|
||||||
|
OpStore %v3bool_var11 %38
|
||||||
|
OpStore %v3bool_var2 %38
|
||||||
|
OpStore %v3bool_var3 %38
|
||||||
|
OpStore %v3i32_var1 %46
|
||||||
|
OpStore %v3i32_var2 %46
|
||||||
|
OpStore %v3u32_var1 %52
|
||||||
|
OpStore %v3u32_var2 %52
|
||||||
|
OpStore %v3bool_var4 %57
|
||||||
|
OpStore %v4bool_var5 %61
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,25 @@
|
||||||
|
fn constant_with_non_constant() {
|
||||||
|
var a : f32 = f32();
|
||||||
|
var b : vec2<f32> = vec2<f32>(f32(i32(1)), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[stage(compute)]]
|
||||||
|
fn main() {
|
||||||
|
var bool_var1 : bool = bool(123u);
|
||||||
|
var bool_var2 : bool = bool(123);
|
||||||
|
var bool_var3 : bool = bool(123.0);
|
||||||
|
var i32_var1 : i32 = i32(123u);
|
||||||
|
var i32_var2 : i32 = i32(123.0);
|
||||||
|
var u32_var1 : u32 = u32(123);
|
||||||
|
var u32_var2 : u32 = u32(123.0);
|
||||||
|
var v3bool_var1 : vec3<bool> = vec3<bool>(vec3<u32>(123u));
|
||||||
|
var v3bool_var11 : vec3<bool> = vec3<bool>(vec3<u32>(1234u));
|
||||||
|
var v3bool_var2 : vec3<bool> = vec3<bool>(vec3<i32>(123));
|
||||||
|
var v3bool_var3 : vec3<bool> = vec3<bool>(vec3<f32>(123.0));
|
||||||
|
var v3i32_var1 : vec3<i32> = vec3<i32>(vec3<u32>(123u));
|
||||||
|
var v3i32_var2 : vec3<i32> = vec3<i32>(vec3<f32>(123.0));
|
||||||
|
var v3u32_var1 : vec3<u32> = vec3<u32>(vec3<i32>(123));
|
||||||
|
var v3u32_var2 : vec3<u32> = vec3<u32>(vec3<f32>(123.0));
|
||||||
|
var v3bool_var4 : vec3<bool> = vec3<bool>(vec2<bool>(vec2<f32>(123.0)), true);
|
||||||
|
var v4bool_var5 : vec4<bool> = vec4<bool>(vec2<bool>(vec2<f32>(123.0, 0.0)), vec2<bool>(true, bool(f32(0.0))));
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
var<private> bool_var1 : bool = bool(1u);
|
||||||
|
var<private> bool_var2 : bool = bool(1);
|
||||||
|
var<private> bool_var3 : bool = bool(1.0);
|
||||||
|
|
||||||
|
var<private> i32_var1 : i32 = i32(1u);
|
||||||
|
var<private> i32_var2 : i32 = i32(1.0);
|
||||||
|
|
||||||
|
var<private> u32_var1 : u32 = u32(1);
|
||||||
|
var<private> u32_var2 : u32 = u32(1.0);
|
||||||
|
|
||||||
|
var<private> v3bool_var1 : vec3<bool> = vec3<bool>(vec3<u32>(1u));
|
||||||
|
var<private> v3bool_var2 : vec3<bool> = vec3<bool>(vec3<i32>(1));
|
||||||
|
var<private> v3bool_var3 : vec3<bool> = vec3<bool>(vec3<f32>(1.0));
|
||||||
|
|
||||||
|
var<private> v3i32_var1 : vec3<i32> = vec3<i32>(vec3<u32>(1u));
|
||||||
|
var<private> v3i32_var2 : vec3<i32> = vec3<i32>(vec3<f32>(1.0));
|
||||||
|
|
||||||
|
var<private> v3u32_var1 : vec3<u32> = vec3<u32>(vec3<i32>(1));
|
||||||
|
var<private> v3u32_var2 : vec3<u32> = vec3<u32>(vec3<f32>(1.0));
|
||||||
|
|
||||||
|
var<private> v3bool_var4 : vec3<bool> = vec3<bool>(vec2<bool>(vec2<f32>(123.0)), true);
|
||||||
|
var<private> v4bool_var5 : vec4<bool> = vec4<bool>(vec2<bool>(vec2<f32>(123.0, 0.0)), vec2<bool>(true, bool(f32(0.0))));
|
||||||
|
|
||||||
|
[[stage(compute)]]
|
||||||
|
fn main() {
|
||||||
|
// Reference the module-scope variables to stop them from being removed.
|
||||||
|
bool_var1 = bool();
|
||||||
|
bool_var2 = bool();
|
||||||
|
bool_var3 = bool();
|
||||||
|
i32_var1 = i32();
|
||||||
|
i32_var2 = i32();
|
||||||
|
u32_var1 = u32();
|
||||||
|
u32_var2 = u32();
|
||||||
|
v3bool_var1 = vec3<bool>();
|
||||||
|
v3bool_var2 = vec3<bool>();
|
||||||
|
v3bool_var3 = vec3<bool>();
|
||||||
|
v3bool_var4 = vec3<bool>();
|
||||||
|
v4bool_var5 = vec4<bool>();
|
||||||
|
v3i32_var1 = vec3<i32>();
|
||||||
|
v3i32_var2 = vec3<i32>();
|
||||||
|
v3u32_var1 = vec3<u32>();
|
||||||
|
v3u32_var2 = vec3<u32>();
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
static bool bool_var1 = bool(1u);
|
||||||
|
static bool bool_var2 = bool(1);
|
||||||
|
static bool bool_var3 = bool(1.0f);
|
||||||
|
static int i32_var1 = int(1u);
|
||||||
|
static int i32_var2 = int(1.0f);
|
||||||
|
static uint u32_var1 = uint(1);
|
||||||
|
static uint u32_var2 = uint(1.0f);
|
||||||
|
static bool3 v3bool_var1 = bool3(uint3((1u).xxx));
|
||||||
|
static bool3 v3bool_var2 = bool3(int3((1).xxx));
|
||||||
|
static bool3 v3bool_var3 = bool3(float3((1.0f).xxx));
|
||||||
|
static int3 v3i32_var1 = int3(uint3((1u).xxx));
|
||||||
|
static int3 v3i32_var2 = int3(float3((1.0f).xxx));
|
||||||
|
static uint3 v3u32_var1 = uint3(int3((1).xxx));
|
||||||
|
static uint3 v3u32_var2 = uint3(float3((1.0f).xxx));
|
||||||
|
static bool3 v3bool_var4 = bool3(bool2(float2((123.0f).xx)), true);
|
||||||
|
static bool4 v4bool_var5 = bool4(bool2(float2(123.0f, 0.0f)), bool2(true, bool(float(0.0f))));
|
||||||
|
|
||||||
|
[numthreads(1, 1, 1)]
|
||||||
|
void main() {
|
||||||
|
bool_var1 = false;
|
||||||
|
bool_var2 = false;
|
||||||
|
bool_var3 = false;
|
||||||
|
i32_var1 = 0;
|
||||||
|
i32_var2 = 0;
|
||||||
|
u32_var1 = 0u;
|
||||||
|
u32_var2 = 0u;
|
||||||
|
v3bool_var1 = bool3(false, false, false);
|
||||||
|
v3bool_var2 = bool3(false, false, false);
|
||||||
|
v3bool_var3 = bool3(false, false, false);
|
||||||
|
v3bool_var4 = bool3(false, false, false);
|
||||||
|
v4bool_var5 = bool4(false, false, false, false);
|
||||||
|
v3i32_var1 = int3(0, 0, 0);
|
||||||
|
v3i32_var2 = int3(0, 0, 0);
|
||||||
|
v3u32_var1 = uint3(0u, 0u, 0u);
|
||||||
|
v3u32_var2 = uint3(0u, 0u, 0u);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
kernel void tint_symbol() {
|
||||||
|
thread bool tint_symbol_1 = bool(1u);
|
||||||
|
thread bool tint_symbol_2 = bool(1);
|
||||||
|
thread bool tint_symbol_3 = bool(1.0f);
|
||||||
|
thread int tint_symbol_4 = int(1u);
|
||||||
|
thread int tint_symbol_5 = int(1.0f);
|
||||||
|
thread uint tint_symbol_6 = uint(1);
|
||||||
|
thread uint tint_symbol_7 = uint(1.0f);
|
||||||
|
thread bool3 tint_symbol_8 = bool3(uint3(1u));
|
||||||
|
thread bool3 tint_symbol_9 = bool3(int3(1));
|
||||||
|
thread bool3 tint_symbol_10 = bool3(float3(1.0f));
|
||||||
|
thread bool3 tint_symbol_11 = bool3(bool2(float2(123.0f)), true);
|
||||||
|
thread bool4 tint_symbol_12 = bool4(bool2(float2(123.0f, 0.0f)), bool2(true, bool(float(0.0f))));
|
||||||
|
thread int3 tint_symbol_13 = int3(uint3(1u));
|
||||||
|
thread int3 tint_symbol_14 = int3(float3(1.0f));
|
||||||
|
thread uint3 tint_symbol_15 = uint3(int3(1));
|
||||||
|
thread uint3 tint_symbol_16 = uint3(float3(1.0f));
|
||||||
|
tint_symbol_1 = bool();
|
||||||
|
tint_symbol_2 = bool();
|
||||||
|
tint_symbol_3 = bool();
|
||||||
|
tint_symbol_4 = int();
|
||||||
|
tint_symbol_5 = int();
|
||||||
|
tint_symbol_6 = uint();
|
||||||
|
tint_symbol_7 = uint();
|
||||||
|
tint_symbol_8 = bool3();
|
||||||
|
tint_symbol_9 = bool3();
|
||||||
|
tint_symbol_10 = bool3();
|
||||||
|
tint_symbol_11 = bool3();
|
||||||
|
tint_symbol_12 = bool4();
|
||||||
|
tint_symbol_13 = int3();
|
||||||
|
tint_symbol_14 = int3();
|
||||||
|
tint_symbol_15 = uint3();
|
||||||
|
tint_symbol_16 = uint3();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 51
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint GLCompute %main "main"
|
||||||
|
OpExecutionMode %main LocalSize 1 1 1
|
||||||
|
OpName %bool_var1 "bool_var1"
|
||||||
|
OpName %bool_var2 "bool_var2"
|
||||||
|
OpName %bool_var3 "bool_var3"
|
||||||
|
OpName %i32_var1 "i32_var1"
|
||||||
|
OpName %i32_var2 "i32_var2"
|
||||||
|
OpName %u32_var1 "u32_var1"
|
||||||
|
OpName %u32_var2 "u32_var2"
|
||||||
|
OpName %v3bool_var1 "v3bool_var1"
|
||||||
|
OpName %v3bool_var2 "v3bool_var2"
|
||||||
|
OpName %v3bool_var3 "v3bool_var3"
|
||||||
|
OpName %v3i32_var1 "v3i32_var1"
|
||||||
|
OpName %v3i32_var2 "v3i32_var2"
|
||||||
|
OpName %v3u32_var1 "v3u32_var1"
|
||||||
|
OpName %v3u32_var2 "v3u32_var2"
|
||||||
|
OpName %v3bool_var4 "v3bool_var4"
|
||||||
|
OpName %v4bool_var5 "v4bool_var5"
|
||||||
|
OpName %main "main"
|
||||||
|
%bool = OpTypeBool
|
||||||
|
%true = OpConstantTrue %bool
|
||||||
|
%_ptr_Private_bool = OpTypePointer Private %bool
|
||||||
|
%bool_var1 = OpVariable %_ptr_Private_bool Private %true
|
||||||
|
%bool_var2 = OpVariable %_ptr_Private_bool Private %true
|
||||||
|
%bool_var3 = OpVariable %_ptr_Private_bool Private %true
|
||||||
|
%int = OpTypeInt 32 1
|
||||||
|
%int_1 = OpConstant %int 1
|
||||||
|
%_ptr_Private_int = OpTypePointer Private %int
|
||||||
|
%i32_var1 = OpVariable %_ptr_Private_int Private %int_1
|
||||||
|
%i32_var2 = OpVariable %_ptr_Private_int Private %int_1
|
||||||
|
%uint = OpTypeInt 32 0
|
||||||
|
%uint_1 = OpConstant %uint 1
|
||||||
|
%_ptr_Private_uint = OpTypePointer Private %uint
|
||||||
|
%u32_var1 = OpVariable %_ptr_Private_uint Private %uint_1
|
||||||
|
%u32_var2 = OpVariable %_ptr_Private_uint Private %uint_1
|
||||||
|
%v3bool = OpTypeVector %bool 3
|
||||||
|
%18 = OpConstantComposite %v3bool %true %true %true
|
||||||
|
%_ptr_Private_v3bool = OpTypePointer Private %v3bool
|
||||||
|
%v3bool_var1 = OpVariable %_ptr_Private_v3bool Private %18
|
||||||
|
%v3bool_var2 = OpVariable %_ptr_Private_v3bool Private %18
|
||||||
|
%v3bool_var3 = OpVariable %_ptr_Private_v3bool Private %18
|
||||||
|
%v3int = OpTypeVector %int 3
|
||||||
|
%24 = OpConstantComposite %v3int %int_1 %int_1 %int_1
|
||||||
|
%_ptr_Private_v3int = OpTypePointer Private %v3int
|
||||||
|
%v3i32_var1 = OpVariable %_ptr_Private_v3int Private %24
|
||||||
|
%v3i32_var2 = OpVariable %_ptr_Private_v3int Private %24
|
||||||
|
%v3uint = OpTypeVector %uint 3
|
||||||
|
%29 = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
|
||||||
|
%_ptr_Private_v3uint = OpTypePointer Private %v3uint
|
||||||
|
%v3u32_var1 = OpVariable %_ptr_Private_v3uint Private %29
|
||||||
|
%v3u32_var2 = OpVariable %_ptr_Private_v3uint Private %29
|
||||||
|
%33 = OpConstantComposite %v3bool %true %true %true
|
||||||
|
%v3bool_var4 = OpVariable %_ptr_Private_v3bool Private %33
|
||||||
|
%v4bool = OpTypeVector %bool 4
|
||||||
|
%false = OpConstantFalse %bool
|
||||||
|
%37 = OpConstantComposite %v4bool %true %false %true %false
|
||||||
|
%_ptr_Private_v4bool = OpTypePointer Private %v4bool
|
||||||
|
%v4bool_var5 = OpVariable %_ptr_Private_v4bool Private %37
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%40 = OpTypeFunction %void
|
||||||
|
%44 = OpConstantNull %bool
|
||||||
|
%45 = OpConstantNull %int
|
||||||
|
%46 = OpConstantNull %uint
|
||||||
|
%47 = OpConstantNull %v3bool
|
||||||
|
%48 = OpConstantNull %v4bool
|
||||||
|
%49 = OpConstantNull %v3int
|
||||||
|
%50 = OpConstantNull %v3uint
|
||||||
|
%main = OpFunction %void None %40
|
||||||
|
%43 = OpLabel
|
||||||
|
OpStore %bool_var1 %44
|
||||||
|
OpStore %bool_var2 %44
|
||||||
|
OpStore %bool_var3 %44
|
||||||
|
OpStore %i32_var1 %45
|
||||||
|
OpStore %i32_var2 %45
|
||||||
|
OpStore %u32_var1 %46
|
||||||
|
OpStore %u32_var2 %46
|
||||||
|
OpStore %v3bool_var1 %47
|
||||||
|
OpStore %v3bool_var2 %47
|
||||||
|
OpStore %v3bool_var3 %47
|
||||||
|
OpStore %v3bool_var4 %47
|
||||||
|
OpStore %v4bool_var5 %48
|
||||||
|
OpStore %v3i32_var1 %49
|
||||||
|
OpStore %v3i32_var2 %49
|
||||||
|
OpStore %v3u32_var1 %50
|
||||||
|
OpStore %v3u32_var2 %50
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,51 @@
|
||||||
|
var<private> bool_var1 : bool = bool(1u);
|
||||||
|
|
||||||
|
var<private> bool_var2 : bool = bool(1);
|
||||||
|
|
||||||
|
var<private> bool_var3 : bool = bool(1.0);
|
||||||
|
|
||||||
|
var<private> i32_var1 : i32 = i32(1u);
|
||||||
|
|
||||||
|
var<private> i32_var2 : i32 = i32(1.0);
|
||||||
|
|
||||||
|
var<private> u32_var1 : u32 = u32(1);
|
||||||
|
|
||||||
|
var<private> u32_var2 : u32 = u32(1.0);
|
||||||
|
|
||||||
|
var<private> v3bool_var1 : vec3<bool> = vec3<bool>(vec3<u32>(1u));
|
||||||
|
|
||||||
|
var<private> v3bool_var2 : vec3<bool> = vec3<bool>(vec3<i32>(1));
|
||||||
|
|
||||||
|
var<private> v3bool_var3 : vec3<bool> = vec3<bool>(vec3<f32>(1.0));
|
||||||
|
|
||||||
|
var<private> v3i32_var1 : vec3<i32> = vec3<i32>(vec3<u32>(1u));
|
||||||
|
|
||||||
|
var<private> v3i32_var2 : vec3<i32> = vec3<i32>(vec3<f32>(1.0));
|
||||||
|
|
||||||
|
var<private> v3u32_var1 : vec3<u32> = vec3<u32>(vec3<i32>(1));
|
||||||
|
|
||||||
|
var<private> v3u32_var2 : vec3<u32> = vec3<u32>(vec3<f32>(1.0));
|
||||||
|
|
||||||
|
var<private> v3bool_var4 : vec3<bool> = vec3<bool>(vec2<bool>(vec2<f32>(123.0)), true);
|
||||||
|
|
||||||
|
var<private> v4bool_var5 : vec4<bool> = vec4<bool>(vec2<bool>(vec2<f32>(123.0, 0.0)), vec2<bool>(true, bool(f32(0.0))));
|
||||||
|
|
||||||
|
[[stage(compute)]]
|
||||||
|
fn main() {
|
||||||
|
bool_var1 = bool();
|
||||||
|
bool_var2 = bool();
|
||||||
|
bool_var3 = bool();
|
||||||
|
i32_var1 = i32();
|
||||||
|
i32_var2 = i32();
|
||||||
|
u32_var1 = u32();
|
||||||
|
u32_var2 = u32();
|
||||||
|
v3bool_var1 = vec3<bool>();
|
||||||
|
v3bool_var2 = vec3<bool>();
|
||||||
|
v3bool_var3 = vec3<bool>();
|
||||||
|
v3bool_var4 = vec3<bool>();
|
||||||
|
v4bool_var5 = vec4<bool>();
|
||||||
|
v3i32_var1 = vec3<i32>();
|
||||||
|
v3i32_var2 = vec3<i32>();
|
||||||
|
v3u32_var1 = vec3<u32>();
|
||||||
|
v3u32_var2 = vec3<u32>();
|
||||||
|
}
|
Loading…
Reference in New Issue