diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc index 050fd1326d..795e16d7b8 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc @@ -597,7 +597,7 @@ bool Builder::GenerateGlobalVariable(ast::Variable* var) { Operand::Int(ConvertStorageClass(sc))}; if (var->has_constructor()) { ops.push_back(Operand::Int(init_id)); - } else { + } else if (!var->type()->IsTexture() && !var->type()->IsSampler()) { // If we don't have a constructor and we're an Output or Private variable // then WGSL requires an initializer. if (var->storage_class() == ast::StorageClass::kPrivate || diff --git a/src/writer/spirv/builder_intrinsic_test.cc b/src/writer/spirv/builder_intrinsic_test.cc index e950da416f..0efcdf3589 100644 --- a/src/writer/spirv/builder_intrinsic_test.cc +++ b/src/writer/spirv/builder_intrinsic_test.cc @@ -16,7 +16,10 @@ #include "gtest/gtest.h" #include "src/ast/call_expression.h" +#include "src/ast/float_literal.h" #include "src/ast/identifier_expression.h" +#include "src/ast/scalar_constructor_expression.h" +#include "src/ast/sint_literal.h" #include "src/ast/type/bool_type.h" #include "src/ast/type/depth_texture_type.h" #include "src/ast/type/f32_type.h" @@ -26,6 +29,7 @@ #include "src/ast/type/sampler_type.h" #include "src/ast/type/u32_type.h" #include "src/ast/type/vector_type.h" +#include "src/ast/type_constructor_expression.h" #include "src/ast/variable.h" #include "src/context.h" #include "src/type_determiner.h" @@ -413,860 +417,743 @@ TEST_F(BuilderTest, Call_Select) { )"); } -enum class TextureType { kF32, kI32, kU32 }; -inline std::ostream& operator<<(std::ostream& out, TextureType data) { - if (data == TextureType::kF32) { - out << "f32"; - } else if (data == TextureType::kI32) { - out << "i32"; - } else { - out << "u32"; - } - return out; -} - -struct TextureTestParams { - ast::type::TextureDimension dim; - TextureType type = TextureType::kF32; - ast::type::ImageFormat format = ast::type::ImageFormat::kR16Float; -}; -inline std::ostream& operator<<(std::ostream& out, TextureTestParams data) { - out << data.dim << "_" << data.type; - return out; -} - -class Builder_TextureOperation - : public testing::TestWithParam { - public: - Builder_TextureOperation() - : td_(std::make_unique(&ctx_, &mod_)), - b_(std::make_unique(&mod_)) {} - - TypeDeterminer* td() const { return td_.get(); } - Context* ctx() { return &ctx_; } - Builder* b() const { return b_.get(); } - - std::unique_ptr get_coords_type( - ast::type::TextureDimension dim, - ast::type::Type* type) { - if (dim == ast::type::TextureDimension::k1d) { - if (type->IsI32()) { - return std::make_unique(); - } else if (type->IsU32()) { - return std::make_unique(); - } else { - return std::make_unique(); - } - } else if (dim == ast::type::TextureDimension::k1dArray || - dim == ast::type::TextureDimension::k2d) { - return std::make_unique(type, 2); - } else if (dim == ast::type::TextureDimension::kCubeArray) { - return std::make_unique(type, 4); - } else { - return std::make_unique(type, 3); - } - } - - void add_call_param(std::string name, - ast::type::Type* type, - ast::ExpressionList* call_params) { - variables_.push_back( - std::make_unique(name, ast::StorageClass::kNone, type)); - td()->RegisterVariableForTesting(variables_.back().get()); - - call_params->push_back(std::make_unique(name)); - ASSERT_TRUE(b()->GenerateGlobalVariable(variables_.back().get())) - << b()->error(); - } - - std::unique_ptr subtype(TextureType type) { - if (type == TextureType::kF32) { - return std::make_unique(); - } - if (type == TextureType::kI32) { - return std::make_unique(); - } - return std::make_unique(); - } - - std::string texture_line( - ast::type::TextureDimension dim, - bool unknown_format, - TextureType type, - uint32_t depth_literal, - uint32_t sampled_literal, - ast::type::ImageFormat format = ast::type::ImageFormat::kR8Unorm) { - std::string res = "%6 = OpTypeImage "; - - if (type == TextureType::kF32) { - res += "%1 "; - } else if (type == TextureType::kU32) { - res += "%2 "; - } else { - res += "%3 "; - } - - if (dim == ast::type::TextureDimension::k1d || - dim == ast::type::TextureDimension::k1dArray) { - res += "1D "; - } else if (dim == ast::type::TextureDimension::k3d) { - res += "3D "; - } else if (dim == ast::type::TextureDimension::kCube || - dim == ast::type::TextureDimension::kCubeArray) { - res += "Cube "; - } else { - res += "2D "; - } - - res += std::to_string(depth_literal) + " "; - - if (dim == ast::type::TextureDimension::k1dArray || - dim == ast::type::TextureDimension::k2dArray || - dim == ast::type::TextureDimension::kCubeArray) { - res += "1 "; - } else { - res += "0 "; - } - - res += "0 "; - res += std::to_string(sampled_literal) + " "; - - if (unknown_format) { - res += "Unknown\n"; - } else if (format == ast::type::ImageFormat::kR16Float) { - res += "R16f\n"; - } else if (format == ast::type::ImageFormat::kR16Sint) { - res += "R16i\n"; - } else { - res += "R8\n"; - } - - return res; - } - - private: - Context ctx_; - ast::Module mod_; - std::unique_ptr td_; - std::unique_ptr b_; - std::vector> variables_; -}; - -class Builder_TextureLoad : public Builder_TextureOperation { - public: - std::string generate_type_str(ast::type::TextureDimension dim, - ast::type::ImageFormat format, - bool unknown_format, - TextureType type, - uint32_t depth_literal, - uint32_t sampled_literal, - uint32_t type_id, - uint32_t coords_length) { - std::string type_str = R"(%1 = OpTypeFloat 32 -%2 = OpTypeInt 32 0 -%3 = OpTypeInt 32 1 -)"; - - type_str += texture_line(dim, unknown_format, type, depth_literal, - sampled_literal, format); - - type_str += R"(%5 = OpTypePointer Private %6 -%7 = OpConstantNull %6 -%4 = OpVariable %5 Private %7 -)"; - - if (coords_length > 1) { - type_str += "%10 = OpTypeVector %3 " + std::to_string(coords_length) + - "\n" + - R"(%9 = OpTypePointer Private %10 -%11 = OpConstantNull %10 -%8 = OpVariable %9 Private %11 -%13 = OpTypePointer Private %3 -%14 = OpConstantNull %3 -%12 = OpVariable %13 Private %14 -%16 = OpTypeVector %)" + - std::to_string(type_id) + " 4\n"; - } else { - type_str += R"(%9 = OpTypePointer Private %3 -%10 = OpConstantNull %3 -%8 = OpVariable %9 Private %10 -%11 = OpVariable %9 Private %10 -%13 = OpTypeVector %)" + - std::to_string(type_id) + " 4\n"; - } - - return type_str; - } - - std::string generate_ops_str(uint32_t coords_length, std::string op_name) { - if (coords_length == 1) { - return R"(%14 = OpLoad %6 %4 -%15 = OpLoad %3 %8 -%16 = OpLoad %3 %11 -%12 = )" + op_name + - R"( %13 %14 %15 Lod %16 -)"; - } - - return R"(%17 = OpLoad %6 %4 -%18 = OpLoad %10 %8 -%19 = OpLoad %3 %12 -%15 = )" + op_name + - R"( %16 %17 %18 Lod %19 -)"; - } -}; - -TEST_P(Builder_TextureLoad, StorageReadonly) { - auto dim = GetParam().dim; - auto type = GetParam().type; - auto format = GetParam().format; - +TEST_F(BuilderTest, Call_TextureLoad_Storage_RO_1d) { ast::type::F32Type f32; - b()->GenerateTypeIfNeeded(&f32); - ast::type::U32Type u32; - b()->GenerateTypeIfNeeded(&u32); ast::type::I32Type i32; - b()->GenerateTypeIfNeeded(&i32); + ast::type::StorageTextureType s(ast::type::TextureDimension::k1d, + ast::type::StorageAccess::kRead, + ast::type::ImageFormat::kR16Float); - uint32_t type_id = 1; - if (type == TextureType::kU32) { - type_id = 2; - } else if (type == TextureType::kI32) { - type_id = 3; - } + Context ctx; + ast::Module mod; + TypeDeterminer td(&ctx, &mod); + Builder b(&mod); - auto coords_type = get_coords_type(dim, &i32); + ASSERT_TRUE(td.DetermineStorageTextureSubtype(&s)) << td.error(); - uint32_t coords_length = 1; - if (coords_type->IsVector()) { - coords_length = coords_type->AsVector()->size(); - } + b.push_function(Function{}); - auto* texture_type = - ctx()->type_mgr().Get(std::make_unique( - dim, ast::type::StorageAccess::kRead, format)); - - EXPECT_TRUE(td()->Determine()); + ast::Variable tex("texture", ast::StorageClass::kNone, &s); + td.RegisterVariableForTesting(&tex); + ASSERT_TRUE(b.GenerateGlobalVariable(&tex)) << b.error(); ast::ExpressionList call_params; - b()->push_function(Function{}); - - add_call_param("texture", texture_type, &call_params); - add_call_param("coords", coords_type.get(), &call_params); - add_call_param("lod", &i32, &call_params); + call_params.push_back(std::make_unique("texture")); + call_params.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); + call_params.push_back(std::make_unique( + std::make_unique(&i32, 2))); ast::CallExpression expr( std::make_unique("textureLoad"), std::move(call_params)); - EXPECT_TRUE(td()->DetermineResultType(&expr)); + EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); + EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error(); - if (coords_length > 1) { - EXPECT_EQ(b()->GenerateExpression(&expr), 15u) << b()->error(); - } else { - EXPECT_EQ(b()->GenerateExpression(&expr), 12u) << b()->error(); - } + EXPECT_EQ(DumpInstructions(b.types()), + R"(%4 = OpTypeFloat 32 +%3 = OpTypeImage %4 1D 0 0 0 2 R16f +%2 = OpTypePointer Private %3 +%1 = OpVariable %2 Private +%6 = OpTypeVector %4 4 +%8 = OpConstant %4 1 +%9 = OpTypeInt 32 1 +%10 = OpConstant %9 2 +)"); - EXPECT_EQ(DumpInstructions(b()->types()), - generate_type_str(dim, format, false, type, 0, 2, type_id, - coords_length)); - - EXPECT_EQ(DumpInstructions(b()->functions()[0].instructions()), - generate_ops_str(coords_length, "OpImageRead")); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(%7 = OpLoad %3 %1 +%5 = OpImageRead %6 %7 %8 Lod %10 +)"); } -TEST_P(Builder_TextureLoad, Sampled) { - auto dim = GetParam().dim; - auto type = GetParam().type; - auto format = GetParam().format; - +TEST_F(BuilderTest, Call_TextureLoad_Storage_RO_2d) { ast::type::F32Type f32; - b()->GenerateTypeIfNeeded(&f32); - ast::type::U32Type u32; - b()->GenerateTypeIfNeeded(&u32); ast::type::I32Type i32; - b()->GenerateTypeIfNeeded(&i32); + ast::type::VectorType vec2(&f32, 2); + ast::type::StorageTextureType s(ast::type::TextureDimension::k2d, + ast::type::StorageAccess::kRead, + ast::type::ImageFormat::kR16Float); - uint32_t type_id = 1; - if (type == TextureType::kU32) { - type_id = 2; - } else if (type == TextureType::kI32) { - type_id = 3; - } + Context ctx; + ast::Module mod; + TypeDeterminer td(&ctx, &mod); + Builder b(&mod); - auto coords_type = get_coords_type(dim, &i32); + ASSERT_TRUE(td.DetermineStorageTextureSubtype(&s)) << td.error(); - uint32_t coords_length = 1; - if (coords_type->IsVector()) { - coords_length = coords_type->AsVector()->size(); - } + b.push_function(Function{}); - std::unique_ptr s = subtype(type); - auto* texture_type = ctx()->type_mgr().Get( - std::make_unique(dim, s.get())); + ast::Variable tex("texture", ast::StorageClass::kNone, &s); + td.RegisterVariableForTesting(&tex); + ASSERT_TRUE(b.GenerateGlobalVariable(&tex)) << b.error(); - EXPECT_TRUE(td()->Determine()); + ast::ExpressionList vals; + vals.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); + vals.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); ast::ExpressionList call_params; - b()->push_function(Function{}); - - add_call_param("texture", texture_type, &call_params); - add_call_param("coords", coords_type.get(), &call_params); - add_call_param("lod", &i32, &call_params); + call_params.push_back(std::make_unique("texture")); + call_params.push_back( + std::make_unique(&vec2, std::move(vals))); + call_params.push_back(std::make_unique( + std::make_unique(&i32, 2))); ast::CallExpression expr( std::make_unique("textureLoad"), std::move(call_params)); - EXPECT_TRUE(td()->DetermineResultType(&expr)); + EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); + EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error(); - if (coords_length > 1) { - EXPECT_EQ(b()->GenerateExpression(&expr), 15u) << b()->error(); - } else { - EXPECT_EQ(b()->GenerateExpression(&expr), 12u) << b()->error(); - } + EXPECT_EQ(DumpInstructions(b.types()), + R"(%4 = OpTypeFloat 32 +%3 = OpTypeImage %4 2D 0 0 0 2 R16f +%2 = OpTypePointer Private %3 +%1 = OpVariable %2 Private +%6 = OpTypeVector %4 4 +%8 = OpTypeVector %4 2 +%9 = OpConstant %4 1 +%10 = OpConstant %4 2 +%11 = OpConstantComposite %8 %9 %10 +%12 = OpTypeInt 32 1 +%13 = OpConstant %12 2 +)"); - EXPECT_EQ( - DumpInstructions(b()->types()), - generate_type_str(dim, format, true, type, 0, 1, type_id, coords_length)); - - EXPECT_EQ(DumpInstructions(b()->functions()[0].instructions()), - generate_ops_str(coords_length, "OpImageFetch")); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(%7 = OpLoad %3 %1 +%5 = OpImageRead %6 %7 %11 Lod %13 +)"); } -INSTANTIATE_TEST_SUITE_P( - BuilderTest, - Builder_TextureLoad, - testing::Values( - TextureTestParams{ast::type::TextureDimension::k1d, TextureType::kF32, - ast::type::ImageFormat::kR16Float}, - TextureTestParams{ast::type::TextureDimension::k1d, TextureType::kI32, - ast::type::ImageFormat::kR16Sint}, - TextureTestParams{ast::type::TextureDimension::k1d, TextureType::kU32, - ast::type::ImageFormat::kR8Unorm}, - TextureTestParams{ast::type::TextureDimension::k1dArray, - TextureType::kF32, ast::type::ImageFormat::kR16Float}, - TextureTestParams{ast::type::TextureDimension::k1dArray, - TextureType::kI32, ast::type::ImageFormat::kR16Sint}, - TextureTestParams{ast::type::TextureDimension::k1dArray, - TextureType::kU32, ast::type::ImageFormat::kR8Unorm}, - TextureTestParams{ast::type::TextureDimension::k2d, TextureType::kF32, - ast::type::ImageFormat::kR16Float}, - TextureTestParams{ast::type::TextureDimension::k2d, TextureType::kI32, - ast::type::ImageFormat::kR16Sint}, - TextureTestParams{ast::type::TextureDimension::k2d, TextureType::kU32, - ast::type::ImageFormat::kR8Unorm}, - TextureTestParams{ast::type::TextureDimension::k2dArray, - TextureType::kF32, ast::type::ImageFormat::kR16Float}, - TextureTestParams{ast::type::TextureDimension::k2dArray, - TextureType::kI32, ast::type::ImageFormat::kR16Sint}, - TextureTestParams{ast::type::TextureDimension::k2dArray, - TextureType::kU32, ast::type::ImageFormat::kR8Unorm}, - TextureTestParams{ast::type::TextureDimension::k3d, TextureType::kF32, - ast::type::ImageFormat::kR16Float}, - TextureTestParams{ast::type::TextureDimension::k3d, TextureType::kI32, - ast::type::ImageFormat::kR16Sint}, - TextureTestParams{ast::type::TextureDimension::k3d, TextureType::kU32, - ast::type::ImageFormat::kR8Unorm})); - -class Builder_SampledTextureOperation : public Builder_TextureOperation { - public: - std::string generate_type_str(ast::type::TextureDimension dim, - bool unknown_format, - TextureType type, - uint32_t depth_literal, - uint32_t sampled_literal, - uint32_t type_id, - uint32_t coords_length, - bool optional_operand) { - std::string type_str = R"(%1 = OpTypeFloat 32 -%2 = OpTypeInt 32 0 -%3 = OpTypeInt 32 1 -)"; - - type_str += - texture_line(dim, unknown_format, type, depth_literal, sampled_literal); - - type_str += R"(%5 = OpTypePointer Private %6 -%7 = OpConstantNull %6 -%4 = OpVariable %5 Private %7 -%10 = OpTypeSampler -%9 = OpTypePointer Private %10 -%11 = OpConstantNull %10 -%8 = OpVariable %9 Private %11 -)"; - - if (coords_length > 1) { - type_str += "%14 = OpTypeVector %3 " + std::to_string(coords_length) + - R"( -%13 = OpTypePointer Private %14 -%15 = OpConstantNull %14 -%12 = OpVariable %13 Private %15 -)"; - - } else { - type_str += R"(%13 = OpTypePointer Private %3 -%14 = OpConstantNull %3 -%12 = OpVariable %13 Private %14 -)"; - } - - if (coords_length > 1 && optional_operand) { - type_str += R"(%17 = OpTypePointer Private %1 -%18 = OpConstantNull %1 -%16 = OpVariable %17 Private %18 -%20 = OpTypeVector %)" + - std::to_string(type_id) + R"( 4 -%25 = OpTypeSampledImage %6 -)"; - } else if (coords_length > 1 && !optional_operand) { - type_str += R"(%17 = OpTypeVector %)" + std::to_string(type_id) + R"( 4 -%21 = OpTypeSampledImage %6 -)"; - } else if (coords_length == 1 && optional_operand) { - type_str += R"(%16 = OpTypePointer Private %1 -%17 = OpConstantNull %1 -%15 = OpVariable %16 Private %17 -%19 = OpTypeVector %)" + - std::to_string(type_id) + R"( 4 -%24 = OpTypeSampledImage %6 -)"; - } else { - type_str += R"(%16 = OpTypeVector %)" + std::to_string(type_id) + R"( 4 -%20 = OpTypeSampledImage %6 -)"; - } - - return type_str; - } - - std::string generate_ops_str(uint32_t coords_length, - std::string op_name, - std::string optional_operand) { - if (coords_length > 1 && optional_operand == "") { - return R"(%18 = OpLoad %6 %4 -%19 = OpLoad %10 %8 -%20 = OpLoad %14 %12 -%22 = OpSampledImage %21 %18 %19 -%16 = )" + op_name + - R"( %17 %22 %20 -)"; - } - - if (coords_length == 1 && optional_operand == "") { - return R"(%17 = OpLoad %6 %4 -%18 = OpLoad %10 %8 -%19 = OpLoad %3 %12 -%21 = OpSampledImage %20 %17 %18 -%15 = )" + op_name + - R"( %16 %21 %19 -)"; - } - - if (coords_length > 1 && optional_operand != "") { - return R"(%21 = OpLoad %6 %4 -%22 = OpLoad %10 %8 -%23 = OpLoad %14 %12 -%24 = OpLoad %1 %16 -%26 = OpSampledImage %25 %21 %22 -%19 = )" + op_name + - " %20 %26 %23 " + optional_operand + " %24\n"; - } - - return R"(%20 = OpLoad %6 %4 -%21 = OpLoad %10 %8 -%22 = OpLoad %3 %12 -%23 = OpLoad %1 %15 -%25 = OpSampledImage %24 %20 %21 -%18 = )" + op_name + - " %19 %25 %22 " + optional_operand + " %23\n"; - } -}; - -TEST_P(Builder_SampledTextureOperation, TextureSample) { - auto dim = GetParam().dim; - auto type = GetParam().type; - +TEST_F(BuilderTest, Call_TextureLoad_Sampled_1d) { ast::type::F32Type f32; - b()->GenerateTypeIfNeeded(&f32); - ast::type::U32Type u32; - b()->GenerateTypeIfNeeded(&u32); ast::type::I32Type i32; - b()->GenerateTypeIfNeeded(&i32); + ast::type::SampledTextureType s(ast::type::TextureDimension::k1d, &f32); - uint32_t type_id = 1; - if (type == TextureType::kU32) { - type_id = 2; - } else if (type == TextureType::kI32) { - type_id = 3; - } + Context ctx; + ast::Module mod; + TypeDeterminer td(&ctx, &mod); + Builder b(&mod); - auto coords_type = get_coords_type(dim, &i32); + b.push_function(Function{}); - uint32_t coords_length = 1; - if (coords_type->IsVector()) { - coords_length = coords_type->AsVector()->size(); - } - - auto sampler_type = std::make_unique( - ast::type::SamplerKind::kSampler); - std::unique_ptr s = subtype(type); - auto* texture_type = ctx()->type_mgr().Get( - std::make_unique(dim, s.get())); - - EXPECT_TRUE(td()->Determine()); + ast::Variable tex("texture", ast::StorageClass::kNone, &s); + td.RegisterVariableForTesting(&tex); + ASSERT_TRUE(b.GenerateGlobalVariable(&tex)) << b.error(); ast::ExpressionList call_params; - b()->push_function(Function{}); + call_params.push_back(std::make_unique("texture")); + call_params.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); + call_params.push_back(std::make_unique( + std::make_unique(&i32, 2))); - add_call_param("texture", texture_type, &call_params); - add_call_param("sampler", sampler_type.get(), &call_params); - add_call_param("coords", coords_type.get(), &call_params); + ast::CallExpression expr( + std::make_unique("textureLoad"), + std::move(call_params)); + + EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); + EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error(); + + EXPECT_EQ(DumpInstructions(b.types()), + R"(%4 = OpTypeFloat 32 +%3 = OpTypeImage %4 1D 0 0 0 1 Unknown +%2 = OpTypePointer Private %3 +%1 = OpVariable %2 Private +%6 = OpTypeVector %4 4 +%8 = OpConstant %4 1 +%9 = OpTypeInt 32 1 +%10 = OpConstant %9 2 +)"); + + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(%7 = OpLoad %3 %1 +%5 = OpImageFetch %6 %7 %8 Lod %10 +)"); +} + +TEST_F(BuilderTest, Call_TextureLoad_Sampled_2d) { + ast::type::F32Type f32; + ast::type::I32Type i32; + ast::type::VectorType vec2(&f32, 2); + ast::type::SampledTextureType s(ast::type::TextureDimension::k2d, &f32); + + Context ctx; + ast::Module mod; + TypeDeterminer td(&ctx, &mod); + Builder b(&mod); + + b.push_function(Function{}); + + ast::Variable tex("texture", ast::StorageClass::kNone, &s); + td.RegisterVariableForTesting(&tex); + ASSERT_TRUE(b.GenerateGlobalVariable(&tex)) << b.error(); + + ast::ExpressionList vals; + vals.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); + vals.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); + + ast::ExpressionList call_params; + call_params.push_back(std::make_unique("texture")); + call_params.push_back( + std::make_unique(&vec2, std::move(vals))); + call_params.push_back(std::make_unique( + std::make_unique(&i32, 2))); + + ast::CallExpression expr( + std::make_unique("textureLoad"), + std::move(call_params)); + + EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); + EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error(); + + EXPECT_EQ(DumpInstructions(b.types()), + R"(%4 = OpTypeFloat 32 +%3 = OpTypeImage %4 2D 0 0 0 1 Unknown +%2 = OpTypePointer Private %3 +%1 = OpVariable %2 Private +%6 = OpTypeVector %4 4 +%8 = OpTypeVector %4 2 +%9 = OpConstant %4 1 +%10 = OpConstant %4 2 +%11 = OpConstantComposite %8 %9 %10 +%12 = OpTypeInt 32 1 +%13 = OpConstant %12 2 +)"); + + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(%7 = OpLoad %3 %1 +%5 = OpImageFetch %6 %7 %11 Lod %13 +)"); +} + +TEST_F(BuilderTest, Call_TextureSample_1d) { + ast::type::F32Type f32; + + ast::type::SamplerType s(ast::type::SamplerKind::kSampler); + ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, &s); + + Context ctx; + ast::Module mod; + TypeDeterminer td(&ctx, &mod); + Builder b(&mod); + + b.push_function(Function{}); + + ast::Variable tex("texture", ast::StorageClass::kNone, &t); + td.RegisterVariableForTesting(&tex); + ASSERT_TRUE(b.GenerateGlobalVariable(&tex)) << b.error(); + + ast::Variable sampler("sampler", ast::StorageClass::kNone, &s); + td.RegisterVariableForTesting(&sampler); + ASSERT_TRUE(b.GenerateGlobalVariable(&sampler)) << b.error(); + + ast::ExpressionList call_params; + call_params.push_back(std::make_unique("texture")); + call_params.push_back(std::make_unique("sampler")); + call_params.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); ast::CallExpression expr( std::make_unique("textureSample"), std::move(call_params)); - EXPECT_TRUE(td()->DetermineResultType(&expr)); + EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); + EXPECT_EQ(b.GenerateExpression(&expr), 7u) << b.error(); + EXPECT_EQ(DumpInstructions(b.types()), + R"(%4 = OpTypeSampler +%3 = OpTypeImage %4 1D 0 0 0 1 Unknown +%2 = OpTypePointer Private %3 +%1 = OpVariable %2 Private +%6 = OpTypePointer Private %4 +%5 = OpVariable %6 Private +%8 = OpTypeVector %4 4 +%11 = OpTypeFloat 32 +%12 = OpConstant %11 1 +%13 = OpTypeSampledImage %3 +)"); - if (coords_length > 1) { - EXPECT_EQ(b()->GenerateExpression(&expr), 16u) << b()->error(); - } else { - EXPECT_EQ(b()->GenerateExpression(&expr), 15u) << b()->error(); - } - - EXPECT_EQ( - DumpInstructions(b()->types()), - generate_type_str(dim, true, type, 0, 1, type_id, coords_length, false)); - - EXPECT_EQ(DumpInstructions(b()->functions()[0].instructions()), - generate_ops_str(coords_length, "OpImageSampleImplicitLod", "")); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(%9 = OpLoad %3 %1 +%10 = OpLoad %4 %5 +%14 = OpSampledImage %13 %9 %10 +%7 = OpImageSampleImplicitLod %8 %14 %12 +)"); } -TEST_P(Builder_SampledTextureOperation, TextureSampleLevel) { - auto dim = GetParam().dim; - auto type = GetParam().type; - +TEST_F(BuilderTest, Call_TextureSample_2d) { ast::type::F32Type f32; - b()->GenerateTypeIfNeeded(&f32); - ast::type::U32Type u32; - b()->GenerateTypeIfNeeded(&u32); - ast::type::I32Type i32; - b()->GenerateTypeIfNeeded(&i32); + ast::type::VectorType vec2(&f32, 2); - uint32_t type_id = 1; - if (type == TextureType::kU32) { - type_id = 2; - } else if (type == TextureType::kI32) { - type_id = 3; - } + ast::type::SamplerType s(ast::type::SamplerKind::kSampler); + ast::type::SampledTextureType t(ast::type::TextureDimension::k2d, &s); - auto coords_type = get_coords_type(dim, &i32); + Context ctx; + ast::Module mod; + TypeDeterminer td(&ctx, &mod); + Builder b(&mod); - uint32_t coords_length = 1; - if (coords_type->IsVector()) { - coords_length = coords_type->AsVector()->size(); - } + b.push_function(Function{}); - auto sampler_type = std::make_unique( - ast::type::SamplerKind::kSampler); - std::unique_ptr s = subtype(type); - auto* texture_type = ctx()->type_mgr().Get( - std::make_unique(dim, s.get())); + ast::Variable tex("texture", ast::StorageClass::kNone, &t); + td.RegisterVariableForTesting(&tex); + ASSERT_TRUE(b.GenerateGlobalVariable(&tex)) << b.error(); - EXPECT_TRUE(td()->Determine()); + ast::Variable sampler("sampler", ast::StorageClass::kNone, &s); + td.RegisterVariableForTesting(&sampler); + ASSERT_TRUE(b.GenerateGlobalVariable(&sampler)) << b.error(); + + ast::ExpressionList vals; + vals.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); + vals.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); ast::ExpressionList call_params; - b()->push_function(Function{}); + call_params.push_back(std::make_unique("texture")); + call_params.push_back(std::make_unique("sampler")); + call_params.push_back( + std::make_unique(&vec2, std::move(vals))); - add_call_param("texture", texture_type, &call_params); - add_call_param("sampler", sampler_type.get(), &call_params); - add_call_param("coords", coords_type.get(), &call_params); - add_call_param("lod", &f32, &call_params); + ast::CallExpression expr( + std::make_unique("textureSample"), + std::move(call_params)); + + EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); + EXPECT_EQ(b.GenerateExpression(&expr), 7u) << b.error(); + EXPECT_EQ(DumpInstructions(b.types()), + R"(%4 = OpTypeSampler +%3 = OpTypeImage %4 2D 0 0 0 1 Unknown +%2 = OpTypePointer Private %3 +%1 = OpVariable %2 Private +%6 = OpTypePointer Private %4 +%5 = OpVariable %6 Private +%8 = OpTypeVector %4 4 +%12 = OpTypeFloat 32 +%11 = OpTypeVector %12 2 +%13 = OpConstant %12 1 +%14 = OpConstant %12 2 +%15 = OpConstantComposite %11 %13 %14 +%16 = OpTypeSampledImage %3 +)"); + + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(%9 = OpLoad %3 %1 +%10 = OpLoad %4 %5 +%17 = OpSampledImage %16 %9 %10 +%7 = OpImageSampleImplicitLod %8 %17 %15 +)"); +} + +TEST_F(BuilderTest, Call_TextureSampleLevel_1d) { + ast::type::F32Type f32; + + ast::type::SamplerType s(ast::type::SamplerKind::kSampler); + ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, &f32); + + Context ctx; + ast::Module mod; + TypeDeterminer td(&ctx, &mod); + Builder b(&mod); + + b.push_function(Function{}); + + ast::Variable tex("texture", ast::StorageClass::kNone, &t); + td.RegisterVariableForTesting(&tex); + ASSERT_TRUE(b.GenerateGlobalVariable(&tex)) << b.error(); + + ast::Variable sampler("sampler", ast::StorageClass::kNone, &s); + td.RegisterVariableForTesting(&sampler); + ASSERT_TRUE(b.GenerateGlobalVariable(&sampler)) << b.error(); + + ast::ExpressionList call_params; + call_params.push_back(std::make_unique("texture")); + call_params.push_back(std::make_unique("sampler")); + call_params.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); + call_params.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); ast::CallExpression expr( std::make_unique("textureSampleLevel"), std::move(call_params)); - EXPECT_TRUE(td()->DetermineResultType(&expr)); + EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); + EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error(); - if (coords_length > 1) { - EXPECT_EQ(b()->GenerateExpression(&expr), 19u) << b()->error(); - } else { - EXPECT_EQ(b()->GenerateExpression(&expr), 18u) << b()->error(); - } + EXPECT_EQ(DumpInstructions(b.types()), + R"(%4 = OpTypeFloat 32 +%3 = OpTypeImage %4 1D 0 0 0 1 Unknown +%2 = OpTypePointer Private %3 +%1 = OpVariable %2 Private +%7 = OpTypeSampler +%6 = OpTypePointer Private %7 +%5 = OpVariable %6 Private +%9 = OpTypeVector %4 4 +%12 = OpConstant %4 1 +%13 = OpConstant %4 2 +%14 = OpTypeSampledImage %3 +)"); - EXPECT_EQ( - DumpInstructions(b()->types()), - generate_type_str(dim, true, type, 0, 1, type_id, coords_length, true)); - - EXPECT_EQ(DumpInstructions(b()->functions()[0].instructions()), - generate_ops_str(coords_length, "OpImageSampleExplicitLod", "Lod")); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(%10 = OpLoad %3 %1 +%11 = OpLoad %7 %5 +%15 = OpSampledImage %14 %10 %11 +%8 = OpImageSampleExplicitLod %9 %15 %12 Lod %13 +)"); } -TEST_P(Builder_SampledTextureOperation, TextureSampleBias) { - auto dim = GetParam().dim; - auto type = GetParam().type; - +TEST_F(BuilderTest, Call_TextureSampleLevel_2d) { ast::type::F32Type f32; - b()->GenerateTypeIfNeeded(&f32); - ast::type::U32Type u32; - b()->GenerateTypeIfNeeded(&u32); - ast::type::I32Type i32; - b()->GenerateTypeIfNeeded(&i32); + ast::type::VectorType vec2(&f32, 2); - uint32_t type_id = 1; - if (type == TextureType::kU32) { - type_id = 2; - } else if (type == TextureType::kI32) { - type_id = 3; - } + ast::type::SamplerType s(ast::type::SamplerKind::kSampler); + ast::type::SampledTextureType t(ast::type::TextureDimension::k2d, &f32); - auto coords_type = get_coords_type(dim, &i32); + Context ctx; + ast::Module mod; + TypeDeterminer td(&ctx, &mod); + Builder b(&mod); - uint32_t coords_length = 1; - if (coords_type->IsVector()) { - coords_length = coords_type->AsVector()->size(); - } + b.push_function(Function{}); - auto sampler_type = std::make_unique( - ast::type::SamplerKind::kSampler); - std::unique_ptr s = subtype(type); - auto* texture_type = ctx()->type_mgr().Get( - std::make_unique(dim, s.get())); + ast::Variable tex("texture", ast::StorageClass::kNone, &t); + td.RegisterVariableForTesting(&tex); + ASSERT_TRUE(b.GenerateGlobalVariable(&tex)) << b.error(); - EXPECT_TRUE(td()->Determine()); + ast::Variable sampler("sampler", ast::StorageClass::kNone, &s); + td.RegisterVariableForTesting(&sampler); + ASSERT_TRUE(b.GenerateGlobalVariable(&sampler)) << b.error(); + + ast::ExpressionList vals; + vals.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); + vals.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); ast::ExpressionList call_params; - b()->push_function(Function{}); + call_params.push_back(std::make_unique("texture")); + call_params.push_back(std::make_unique("sampler")); + call_params.push_back( + std::make_unique(&vec2, std::move(vals))); + call_params.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); - add_call_param("texture", texture_type, &call_params); - add_call_param("sampler", sampler_type.get(), &call_params); - add_call_param("coords", coords_type.get(), &call_params); - add_call_param("bias", &f32, &call_params); + ast::CallExpression expr( + std::make_unique("textureSampleLevel"), + std::move(call_params)); + + EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); + EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error(); + + EXPECT_EQ(DumpInstructions(b.types()), + R"(%4 = OpTypeFloat 32 +%3 = OpTypeImage %4 2D 0 0 0 1 Unknown +%2 = OpTypePointer Private %3 +%1 = OpVariable %2 Private +%7 = OpTypeSampler +%6 = OpTypePointer Private %7 +%5 = OpVariable %6 Private +%9 = OpTypeVector %4 4 +%12 = OpTypeVector %4 2 +%13 = OpConstant %4 1 +%14 = OpConstant %4 2 +%15 = OpConstantComposite %12 %13 %14 +%16 = OpTypeSampledImage %3 +)"); + + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(%10 = OpLoad %3 %1 +%11 = OpLoad %7 %5 +%17 = OpSampledImage %16 %10 %11 +%8 = OpImageSampleExplicitLod %9 %17 %15 Lod %14 +)"); +} + +TEST_F(BuilderTest, Call_TextureSampleBias_1d) { + ast::type::F32Type f32; + + ast::type::SamplerType s(ast::type::SamplerKind::kSampler); + ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, &f32); + + Context ctx; + ast::Module mod; + TypeDeterminer td(&ctx, &mod); + Builder b(&mod); + + b.push_function(Function{}); + + ast::Variable tex("texture", ast::StorageClass::kNone, &t); + td.RegisterVariableForTesting(&tex); + ASSERT_TRUE(b.GenerateGlobalVariable(&tex)) << b.error(); + + ast::Variable sampler("sampler", ast::StorageClass::kNone, &s); + td.RegisterVariableForTesting(&sampler); + ASSERT_TRUE(b.GenerateGlobalVariable(&sampler)) << b.error(); + + ast::ExpressionList call_params; + call_params.push_back(std::make_unique("texture")); + call_params.push_back(std::make_unique("sampler")); + call_params.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); + call_params.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); ast::CallExpression expr( std::make_unique("textureSampleBias"), std::move(call_params)); - EXPECT_TRUE(td()->DetermineResultType(&expr)); + EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); + EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error(); - if (coords_length > 1) { - EXPECT_EQ(b()->GenerateExpression(&expr), 19u) << b()->error(); - } else { - EXPECT_EQ(b()->GenerateExpression(&expr), 18u) << b()->error(); - } + EXPECT_EQ(DumpInstructions(b.types()), + R"(%4 = OpTypeFloat 32 +%3 = OpTypeImage %4 1D 0 0 0 1 Unknown +%2 = OpTypePointer Private %3 +%1 = OpVariable %2 Private +%7 = OpTypeSampler +%6 = OpTypePointer Private %7 +%5 = OpVariable %6 Private +%9 = OpTypeVector %4 4 +%12 = OpConstant %4 1 +%13 = OpConstant %4 2 +%14 = OpTypeSampledImage %3 +)"); - EXPECT_EQ( - DumpInstructions(b()->types()), - generate_type_str(dim, true, type, 0, 1, type_id, coords_length, true)); - - EXPECT_EQ( - DumpInstructions(b()->functions()[0].instructions()), - generate_ops_str(coords_length, "OpImageSampleImplicitLod", "Bias")); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(%10 = OpLoad %3 %1 +%11 = OpLoad %7 %5 +%15 = OpSampledImage %14 %10 %11 +%8 = OpImageSampleImplicitLod %9 %15 %12 Bias %13 +)"); } -INSTANTIATE_TEST_SUITE_P( - BuilderTest, - Builder_SampledTextureOperation, - testing::Values( - TextureTestParams{ast::type::TextureDimension::k1d, TextureType::kF32}, - TextureTestParams{ast::type::TextureDimension::k1d, TextureType::kI32}, - TextureTestParams{ast::type::TextureDimension::k1d, TextureType::kU32}, - TextureTestParams{ast::type::TextureDimension::k1dArray, - TextureType::kF32}, - TextureTestParams{ast::type::TextureDimension::k1dArray, - TextureType::kI32}, - TextureTestParams{ast::type::TextureDimension::k1dArray, - TextureType::kU32}, - TextureTestParams{ast::type::TextureDimension::k2d, TextureType::kF32}, - TextureTestParams{ast::type::TextureDimension::k2d, TextureType::kI32}, - TextureTestParams{ast::type::TextureDimension::k2d, TextureType::kU32}, - TextureTestParams{ast::type::TextureDimension::k2dArray, - TextureType::kF32}, - TextureTestParams{ast::type::TextureDimension::k2dArray, - TextureType::kI32}, - TextureTestParams{ast::type::TextureDimension::k2dArray, - TextureType::kU32}, - TextureTestParams{ast::type::TextureDimension::k3d, TextureType::kF32}, - TextureTestParams{ast::type::TextureDimension::k3d, TextureType::kI32}, - TextureTestParams{ast::type::TextureDimension::k3d, - TextureType::kU32})); - -class Builder_DepthTextureOperation : public Builder_TextureOperation { - public: - std::string generate_type_str(ast::type::TextureDimension dim, - uint32_t coords_length) { - std::string type_str = R"(%1 = OpTypeFloat 32 -%2 = OpTypeInt 32 0 -%3 = OpTypeInt 32 1 -)"; - - type_str += texture_line(dim, true, TextureType::kF32, 1, 1); - - type_str += R"(%5 = OpTypePointer Private %6 -%7 = OpConstantNull %6 -%4 = OpVariable %5 Private %7 -%10 = OpTypeSampler -%9 = OpTypePointer Private %10 -%11 = OpConstantNull %10 -%8 = OpVariable %9 Private %11 -%14 = OpTypeVector %1 )" + - std::to_string(coords_length) + R"( -%13 = OpTypePointer Private %14 -%15 = OpConstantNull %14 -%12 = OpVariable %13 Private %15 -%17 = OpTypePointer Private %1 -%18 = OpConstantNull %1 -%16 = OpVariable %17 Private %18 -%24 = OpTypeSampledImage %6 -%26 = OpConstant %1 0 -)"; - - return type_str; - } - - std::string generate_ops_str() { - return R"(%20 = OpLoad %6 %4 -%21 = OpLoad %10 %8 -%22 = OpLoad %14 %12 -%23 = OpLoad %1 %16 -%25 = OpSampledImage %24 %20 %21 -%19 = OpImageSampleDrefExplicitLod %1 %25 %22 %23 Lod %26 -)"; - } -}; - -TEST_P(Builder_DepthTextureOperation, TextureSampleCompare) { - auto dim = GetParam().dim; - auto type = GetParam().type; - +TEST_F(BuilderTest, Call_TextureSampleBias_2d) { ast::type::F32Type f32; - b()->GenerateTypeIfNeeded(&f32); - ast::type::U32Type u32; - b()->GenerateTypeIfNeeded(&u32); - ast::type::I32Type i32; - b()->GenerateTypeIfNeeded(&i32); + ast::type::VectorType vec2(&f32, 2); - auto coords_type = get_coords_type(dim, &f32); + ast::type::SamplerType s(ast::type::SamplerKind::kSampler); + ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, &f32); - uint32_t coords_length = coords_type->AsVector()->size(); + Context ctx; + ast::Module mod; + TypeDeterminer td(&ctx, &mod); + Builder b(&mod); - auto sampler_type = std::make_unique( - ast::type::SamplerKind::kComparisonSampler); - std::unique_ptr s = subtype(type); - auto* texture_type = - ctx()->type_mgr().Get(std::make_unique(dim)); + b.push_function(Function{}); + + ast::Variable tex("texture", ast::StorageClass::kNone, &t); + td.RegisterVariableForTesting(&tex); + ASSERT_TRUE(b.GenerateGlobalVariable(&tex)) << b.error(); + + ast::Variable sampler("sampler", ast::StorageClass::kNone, &s); + td.RegisterVariableForTesting(&sampler); + ASSERT_TRUE(b.GenerateGlobalVariable(&sampler)) << b.error(); + + ast::ExpressionList vals; + vals.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); + vals.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); ast::ExpressionList call_params; - b()->push_function(Function{}); + call_params.push_back(std::make_unique("texture")); + call_params.push_back(std::make_unique("sampler")); + call_params.push_back( + std::make_unique(&vec2, std::move(vals))); + call_params.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); - add_call_param("texture", texture_type, &call_params); - add_call_param("sampler", sampler_type.get(), &call_params); - add_call_param("coords", coords_type.get(), &call_params); - add_call_param("depth_reference", &f32, &call_params); + ast::CallExpression expr( + std::make_unique("textureSampleBias"), + std::move(call_params)); + + EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); + EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error(); + + EXPECT_EQ(DumpInstructions(b.types()), + R"(%4 = OpTypeFloat 32 +%3 = OpTypeImage %4 1D 0 0 0 1 Unknown +%2 = OpTypePointer Private %3 +%1 = OpVariable %2 Private +%7 = OpTypeSampler +%6 = OpTypePointer Private %7 +%5 = OpVariable %6 Private +%9 = OpTypeVector %4 4 +%12 = OpTypeVector %4 2 +%13 = OpConstant %4 1 +%14 = OpConstant %4 2 +%15 = OpConstantComposite %12 %13 %14 +%16 = OpTypeSampledImage %3 +)"); + + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(%10 = OpLoad %3 %1 +%11 = OpLoad %7 %5 +%17 = OpSampledImage %16 %10 %11 +%8 = OpImageSampleImplicitLod %9 %17 %15 Bias %14 +)"); +} + +TEST_F(BuilderTest, Call_TextureSampleCompare) { + ast::type::F32Type f32; + ast::type::VectorType vec2(&f32, 2); + + ast::type::SamplerType s(ast::type::SamplerKind::kComparisonSampler); + ast::type::DepthTextureType t(ast::type::TextureDimension::k2d); + + Context ctx; + ast::Module mod; + TypeDeterminer td(&ctx, &mod); + Builder b(&mod); + + b.push_function(Function{}); + + ast::Variable tex("texture", ast::StorageClass::kNone, &t); + td.RegisterVariableForTesting(&tex); + ASSERT_TRUE(b.GenerateGlobalVariable(&tex)) << b.error(); + + ast::Variable sampler("sampler", ast::StorageClass::kNone, &s); + td.RegisterVariableForTesting(&sampler); + ASSERT_TRUE(b.GenerateGlobalVariable(&sampler)) << b.error(); + + ast::ExpressionList vals; + vals.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); + vals.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); + + ast::ExpressionList call_params; + call_params.push_back(std::make_unique("texture")); + call_params.push_back(std::make_unique("sampler")); + call_params.push_back( + std::make_unique(&vec2, std::move(vals))); + call_params.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); ast::CallExpression expr( std::make_unique("textureSampleCompare"), std::move(call_params)); - EXPECT_TRUE(td()->DetermineResultType(&expr)); - - EXPECT_EQ(b()->GenerateExpression(&expr), 19u) << b()->error(); - - EXPECT_EQ(DumpInstructions(b()->types()), - generate_type_str(dim, coords_length)); - - EXPECT_EQ(DumpInstructions(b()->functions()[0].instructions()), - generate_ops_str()); -} - -INSTANTIATE_TEST_SUITE_P( - BuilderTest, - Builder_DepthTextureOperation, - testing::Values(TextureTestParams{ast::type::TextureDimension::k2d}, - TextureTestParams{ast::type::TextureDimension::k2dArray}, - TextureTestParams{ast::type::TextureDimension::kCube}, - TextureTestParams{ - ast::type::TextureDimension::kCubeArray})); - -// This tests that we do not push OpTypeSampledImage and float_0 type twice. -TEST_F(Builder_TextureOperation, TextureSampleCompareTwice) { - ast::type::F32Type f32; - b()->GenerateTypeIfNeeded(&f32); - - auto coords_type = get_coords_type(ast::type::TextureDimension::k2d, &f32); - auto sampler_type = std::make_unique( - ast::type::SamplerKind::kComparisonSampler); - auto* texture_type = - ctx()->type_mgr().Get(std::make_unique( - ast::type::TextureDimension::k2d)); - - b()->push_function(Function{}); - - ast::ExpressionList call_params_first; - add_call_param("texture", texture_type, &call_params_first); - add_call_param("sampler", sampler_type.get(), &call_params_first); - add_call_param("coords", coords_type.get(), &call_params_first); - add_call_param("depth_reference", &f32, &call_params_first); - - ast::ExpressionList call_params_second; - add_call_param("texture", texture_type, &call_params_second); - add_call_param("sampler", sampler_type.get(), &call_params_second); - add_call_param("coords", coords_type.get(), &call_params_second); - add_call_param("depth_reference", &f32, &call_params_second); - - ast::CallExpression expr_first( - std::make_unique("textureSampleCompare"), - std::move(call_params_first)); - ast::CallExpression expr_second( - std::make_unique("textureSampleCompare"), - std::move(call_params_second)); - - EXPECT_TRUE(td()->DetermineResultType(&expr_first)); - EXPECT_TRUE(td()->DetermineResultType(&expr_second)); - - EXPECT_EQ(b()->GenerateExpression(&expr_first), 21u) << b()->error(); - EXPECT_EQ(b()->GenerateExpression(&expr_second), 29u) << b()->error(); - - EXPECT_EQ(DumpInstructions(b()->types()), R"(%1 = OpTypeFloat 32 -%4 = OpTypeImage %1 2D 1 0 0 1 Unknown -%3 = OpTypePointer Private %4 -%5 = OpConstantNull %4 -%2 = OpVariable %3 Private %5 -%8 = OpTypeSampler -%7 = OpTypePointer Private %8 -%9 = OpConstantNull %8 -%6 = OpVariable %7 Private %9 -%12 = OpTypeVector %1 2 -%11 = OpTypePointer Private %12 -%13 = OpConstantNull %12 -%10 = OpVariable %11 Private %13 -%15 = OpTypePointer Private %1 -%16 = OpConstantNull %1 -%14 = OpVariable %15 Private %16 -%17 = OpVariable %3 Private %5 -%18 = OpVariable %7 Private %9 -%19 = OpVariable %11 Private %13 -%20 = OpVariable %15 Private %16 -%26 = OpTypeSampledImage %4 -%28 = OpConstant %1 0 + EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error(); + EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error(); + EXPECT_EQ(DumpInstructions(b.types()), + R"(%4 = OpTypeFloat 32 +%3 = OpTypeImage %4 2D 1 0 0 1 Unknown +%2 = OpTypePointer Private %3 +%1 = OpVariable %2 Private +%7 = OpTypeSampler +%6 = OpTypePointer Private %7 +%5 = OpVariable %6 Private +%11 = OpTypeVector %4 2 +%12 = OpConstant %4 1 +%13 = OpConstant %4 2 +%14 = OpConstantComposite %11 %12 %13 +%15 = OpTypeSampledImage %3 +%17 = OpConstant %4 0 )"); - EXPECT_EQ(DumpInstructions(b()->functions()[0].instructions()), - R"(%22 = OpLoad %4 %17 -%23 = OpLoad %8 %18 -%24 = OpLoad %12 %19 -%25 = OpLoad %1 %20 -%27 = OpSampledImage %26 %22 %23 -%21 = OpImageSampleDrefExplicitLod %1 %27 %24 %25 Lod %28 -%30 = OpLoad %4 %17 -%31 = OpLoad %8 %18 -%32 = OpLoad %12 %19 -%33 = OpLoad %1 %20 -%34 = OpSampledImage %26 %30 %31 -%29 = OpImageSampleDrefExplicitLod %1 %34 %32 %33 Lod %28 + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(%9 = OpLoad %3 %1 +%10 = OpLoad %7 %5 +%16 = OpSampledImage %15 %9 %10 +%8 = OpImageSampleDrefExplicitLod %4 %16 %14 %13 Lod %17 +)"); +} + +// This tests that we do not push OpTypeSampledImage and float_0 type twice. +TEST_F(BuilderTest, Call_TextureSampleCompare_Twice) { + ast::type::F32Type f32; + ast::type::VectorType vec2(&f32, 2); + + ast::type::SamplerType s(ast::type::SamplerKind::kComparisonSampler); + ast::type::DepthTextureType t(ast::type::TextureDimension::k2d); + + Context ctx; + ast::Module mod; + TypeDeterminer td(&ctx, &mod); + Builder b(&mod); + + b.push_function(Function{}); + + ast::Variable tex("texture", ast::StorageClass::kNone, &t); + td.RegisterVariableForTesting(&tex); + ASSERT_TRUE(b.GenerateGlobalVariable(&tex)) << b.error(); + + ast::Variable sampler("sampler", ast::StorageClass::kNone, &s); + td.RegisterVariableForTesting(&sampler); + ASSERT_TRUE(b.GenerateGlobalVariable(&sampler)) << b.error(); + + ast::ExpressionList vals; + vals.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); + vals.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); + + ast::ExpressionList call_params; + call_params.push_back(std::make_unique("texture")); + call_params.push_back(std::make_unique("sampler")); + call_params.push_back( + std::make_unique(&vec2, std::move(vals))); + call_params.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); + + ast::CallExpression expr1( + std::make_unique("textureSampleCompare"), + std::move(call_params)); + + vals.push_back(std::make_unique( + std::make_unique(&f32, 1.0))); + vals.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); + + call_params.push_back(std::make_unique("texture")); + call_params.push_back(std::make_unique("sampler")); + call_params.push_back( + std::make_unique(&vec2, std::move(vals))); + call_params.push_back(std::make_unique( + std::make_unique(&f32, 2.0))); + + ast::CallExpression expr2( + std::make_unique("textureSampleCompare"), + std::move(call_params)); + + EXPECT_TRUE(td.DetermineResultType(&expr1)) << td.error(); + EXPECT_TRUE(td.DetermineResultType(&expr2)) << td.error(); + + EXPECT_EQ(b.GenerateExpression(&expr1), 8u) << b.error(); + EXPECT_EQ(b.GenerateExpression(&expr2), 18u) << b.error(); + + EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32 +%3 = OpTypeImage %4 2D 1 0 0 1 Unknown +%2 = OpTypePointer Private %3 +%1 = OpVariable %2 Private +%7 = OpTypeSampler +%6 = OpTypePointer Private %7 +%5 = OpVariable %6 Private +%11 = OpTypeVector %4 2 +%12 = OpConstant %4 1 +%13 = OpConstant %4 2 +%14 = OpConstantComposite %11 %12 %13 +%15 = OpTypeSampledImage %3 +%17 = OpConstant %4 0 +)"); + + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), + R"(%9 = OpLoad %3 %1 +%10 = OpLoad %7 %5 +%16 = OpSampledImage %15 %9 %10 +%8 = OpImageSampleDrefExplicitLod %4 %16 %14 %13 Lod %17 +%19 = OpLoad %3 %1 +%20 = OpLoad %7 %5 +%21 = OpSampledImage %15 %19 %20 +%18 = OpImageSampleDrefExplicitLod %4 %21 %14 %13 Lod %17 )"); }