Rename 'intrinsic' to 'builtin'
This matches the term used in the WGSL spec. Change-Id: I4603332b828450c126ef806f1064ed54f372013f Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/78787 Reviewed-by: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
a996ffbd1f
commit
b85e692aa7
|
@ -117,7 +117,7 @@ type nodes.
|
|||
|
||||
Semantic information is held by `sem::Node`s which describe the program at
|
||||
a higher / more abstract level than the AST. This includes information such as
|
||||
the resolved type of each expression, the resolved overload of an intrinsic
|
||||
the resolved type of each expression, the resolved overload of a builtin
|
||||
function call, and the module scoped variables used by each function.
|
||||
|
||||
Semantic information is generated by the `Resolver` when the `Program`
|
||||
|
|
18
src/BUILD.gn
18
src/BUILD.gn
|
@ -337,6 +337,9 @@ libtint_source_set("libtint_core_all_src") {
|
|||
"ast/workgroup_attribute.cc",
|
||||
"ast/workgroup_attribute.h",
|
||||
"block_allocator.h",
|
||||
"builtin_table.cc",
|
||||
"builtin_table.h",
|
||||
"builtin_table.inl",
|
||||
"castable.cc",
|
||||
"castable.h",
|
||||
"clone_context.cc",
|
||||
|
@ -359,9 +362,6 @@ libtint_source_set("libtint_core_all_src") {
|
|||
"inspector/resource_binding.h",
|
||||
"inspector/scalar.cc",
|
||||
"inspector/scalar.h",
|
||||
"intrinsic_table.cc",
|
||||
"intrinsic_table.h",
|
||||
"intrinsic_table.inl",
|
||||
"program.cc",
|
||||
"program.h",
|
||||
"program_builder.cc",
|
||||
|
@ -382,6 +382,8 @@ libtint_source_set("libtint_core_all_src") {
|
|||
"sem/behavior.h",
|
||||
"sem/binding_point.h",
|
||||
"sem/bool_type.h",
|
||||
"sem/builtin.h",
|
||||
"sem/builtin_type.h",
|
||||
"sem/call.h",
|
||||
"sem/call_target.h",
|
||||
"sem/constant.h",
|
||||
|
@ -394,8 +396,6 @@ libtint_source_set("libtint_core_all_src") {
|
|||
"sem/i32_type.h",
|
||||
"sem/if_statement.h",
|
||||
"sem/info.h",
|
||||
"sem/intrinsic.h",
|
||||
"sem/intrinsic_type.h",
|
||||
"sem/loop_statement.h",
|
||||
"sem/matrix_type.h",
|
||||
"sem/multisampled_texture_type.h",
|
||||
|
@ -536,6 +536,10 @@ libtint_source_set("libtint_sem_src") {
|
|||
"sem/block_statement.cc",
|
||||
"sem/bool_type.cc",
|
||||
"sem/bool_type.h",
|
||||
"sem/builtin.cc",
|
||||
"sem/builtin.h",
|
||||
"sem/builtin_type.cc",
|
||||
"sem/builtin_type.h",
|
||||
"sem/call.cc",
|
||||
"sem/call.h",
|
||||
"sem/call_target.cc",
|
||||
|
@ -561,10 +565,6 @@ libtint_source_set("libtint_sem_src") {
|
|||
"sem/if_statement.h",
|
||||
"sem/info.cc",
|
||||
"sem/info.h",
|
||||
"sem/intrinsic.cc",
|
||||
"sem/intrinsic.h",
|
||||
"sem/intrinsic_type.cc",
|
||||
"sem/intrinsic_type.h",
|
||||
"sem/loop_statement.cc",
|
||||
"sem/loop_statement.h",
|
||||
"sem/matrix_type.cc",
|
||||
|
|
|
@ -219,6 +219,9 @@ set(TINT_LIB_SRCS
|
|||
ast/workgroup_attribute.cc
|
||||
ast/workgroup_attribute.h
|
||||
block_allocator.h
|
||||
builtin_table.cc
|
||||
builtin_table.h
|
||||
builtin_table.inl
|
||||
castable.cc
|
||||
castable.h
|
||||
clone_context.cc
|
||||
|
@ -233,9 +236,6 @@ set(TINT_LIB_SRCS
|
|||
inspector/resource_binding.h
|
||||
inspector/scalar.cc
|
||||
inspector/scalar.h
|
||||
intrinsic_table.cc
|
||||
intrinsic_table.h
|
||||
intrinsic_table.inl
|
||||
program_builder.cc
|
||||
program_builder.h
|
||||
program_id.cc
|
||||
|
@ -260,6 +260,10 @@ set(TINT_LIB_SRCS
|
|||
sem/binding_point.h
|
||||
sem/block_statement.cc
|
||||
sem/block_statement.h
|
||||
sem/builtin_type.cc
|
||||
sem/builtin_type.h
|
||||
sem/builtin.cc
|
||||
sem/builtin.h
|
||||
sem/call_target.cc
|
||||
sem/call_target.h
|
||||
sem/call.cc
|
||||
|
@ -273,10 +277,6 @@ set(TINT_LIB_SRCS
|
|||
sem/function.cc
|
||||
sem/info.cc
|
||||
sem/info.h
|
||||
sem/intrinsic_type.cc
|
||||
sem/intrinsic_type.h
|
||||
sem/intrinsic.cc
|
||||
sem/intrinsic.h
|
||||
sem/member_accessor_expression.cc
|
||||
sem/parameter_usage.cc
|
||||
sem/parameter_usage.h
|
||||
|
@ -624,6 +624,8 @@ if(TINT_BUILD_TESTS)
|
|||
ast/bool_test.cc
|
||||
ast/break_statement_test.cc
|
||||
ast/builtin_attribute_test.cc
|
||||
ast/builtin_texture_helper_test.cc
|
||||
ast/builtin_texture_helper_test.h
|
||||
ast/call_expression_test.cc
|
||||
ast/call_statement_test.cc
|
||||
ast/case_statement_test.cc
|
||||
|
@ -645,8 +647,6 @@ if(TINT_BUILD_TESTS)
|
|||
ast/index_accessor_expression_test.cc
|
||||
ast/int_literal_expression_test.cc
|
||||
ast/interpolate_attribute_test.cc
|
||||
ast/intrinsic_texture_helper_test.cc
|
||||
ast/intrinsic_texture_helper_test.h
|
||||
ast/invariant_attribute_test.cc
|
||||
ast/location_attribute_test.cc
|
||||
ast/loop_statement_test.cc
|
||||
|
@ -682,6 +682,7 @@ if(TINT_BUILD_TESTS)
|
|||
ast/vector_test.cc
|
||||
ast/workgroup_attribute_test.cc
|
||||
block_allocator_test.cc
|
||||
builtin_table_test.cc
|
||||
castable_test.cc
|
||||
clone_context_test.cc
|
||||
debug_test.cc
|
||||
|
@ -689,7 +690,6 @@ if(TINT_BUILD_TESTS)
|
|||
diagnostic/diagnostic_test.cc
|
||||
diagnostic/formatter_test.cc
|
||||
diagnostic/printer_test.cc
|
||||
intrinsic_table_test.cc
|
||||
program_test.cc
|
||||
resolver/array_accessor_test.cc
|
||||
resolver/assignment_validation_test.cc
|
||||
|
@ -697,6 +697,8 @@ if(TINT_BUILD_TESTS)
|
|||
resolver/atomics_validation_test.cc
|
||||
resolver/bitcast_validation_test.cc
|
||||
resolver/builtins_validation_test.cc
|
||||
resolver/builtin_test.cc
|
||||
resolver/builtin_validation_test.cc
|
||||
resolver/call_test.cc
|
||||
resolver/call_validation_test.cc
|
||||
resolver/compound_statement_test.cc
|
||||
|
@ -707,8 +709,6 @@ if(TINT_BUILD_TESTS)
|
|||
resolver/function_validation_test.cc
|
||||
resolver/host_shareable_validation_test.cc
|
||||
resolver/inferred_type_test.cc
|
||||
resolver/intrinsic_test.cc
|
||||
resolver/intrinsic_validation_test.cc
|
||||
resolver/is_host_shareable_test.cc
|
||||
resolver/is_storeable_test.cc
|
||||
resolver/pipeline_overridable_constant_test.cc
|
||||
|
@ -732,12 +732,12 @@ if(TINT_BUILD_TESTS)
|
|||
scope_stack_test.cc
|
||||
sem/atomic_type_test.cc
|
||||
sem/bool_type_test.cc
|
||||
sem/builtin_test.cc
|
||||
sem/depth_multisampled_texture_type_test.cc
|
||||
sem/depth_texture_type_test.cc
|
||||
sem/external_texture_type_test.cc
|
||||
sem/f32_type_test.cc
|
||||
sem/i32_type_test.cc
|
||||
sem/intrinsic_test.cc
|
||||
sem/matrix_type_test.cc
|
||||
sem/multisampled_texture_type_test.cc
|
||||
sem/pointer_type_test.cc
|
||||
|
@ -911,6 +911,8 @@ if(TINT_BUILD_TESTS)
|
|||
writer/spirv/builder_binary_expression_test.cc
|
||||
writer/spirv/builder_bitcast_expression_test.cc
|
||||
writer/spirv/builder_block_test.cc
|
||||
writer/spirv/builder_builtin_test.cc
|
||||
writer/spirv/builder_builtin_texture_test.cc
|
||||
writer/spirv/builder_call_test.cc
|
||||
writer/spirv/builder_constructor_expression_test.cc
|
||||
writer/spirv/builder_discard_test.cc
|
||||
|
@ -922,8 +924,6 @@ if(TINT_BUILD_TESTS)
|
|||
writer/spirv/builder_global_variable_test.cc
|
||||
writer/spirv/builder_ident_expression_test.cc
|
||||
writer/spirv/builder_if_test.cc
|
||||
writer/spirv/builder_intrinsic_test.cc
|
||||
writer/spirv/builder_intrinsic_texture_test.cc
|
||||
writer/spirv/builder_literal_test.cc
|
||||
writer/spirv/builder_loop_test.cc
|
||||
writer/spirv/builder_return_test.cc
|
||||
|
@ -1020,6 +1020,8 @@ if(TINT_BUILD_TESTS)
|
|||
writer/msl/generator_impl_bitcast_test.cc
|
||||
writer/msl/generator_impl_block_test.cc
|
||||
writer/msl/generator_impl_break_test.cc
|
||||
writer/msl/generator_impl_builtin_test.cc
|
||||
writer/msl/generator_impl_builtin_texture_test.cc
|
||||
writer/msl/generator_impl_call_test.cc
|
||||
writer/msl/generator_impl_case_test.cc
|
||||
writer/msl/generator_impl_cast_test.cc
|
||||
|
@ -1030,8 +1032,6 @@ if(TINT_BUILD_TESTS)
|
|||
writer/msl/generator_impl_identifier_test.cc
|
||||
writer/msl/generator_impl_if_test.cc
|
||||
writer/msl/generator_impl_import_test.cc
|
||||
writer/msl/generator_impl_intrinsic_test.cc
|
||||
writer/msl/generator_impl_intrinsic_texture_test.cc
|
||||
writer/msl/generator_impl_loop_test.cc
|
||||
writer/msl/generator_impl_member_accessor_test.cc
|
||||
writer/msl/generator_impl_module_constant_test.cc
|
||||
|
@ -1054,6 +1054,8 @@ if(TINT_BUILD_TESTS)
|
|||
writer/glsl/generator_impl_bitcast_test.cc
|
||||
writer/glsl/generator_impl_block_test.cc
|
||||
writer/glsl/generator_impl_break_test.cc
|
||||
writer/glsl/generator_impl_builtin_test.cc
|
||||
writer/glsl/generator_impl_builtin_texture_test.cc
|
||||
writer/glsl/generator_impl_call_test.cc
|
||||
writer/glsl/generator_impl_case_test.cc
|
||||
writer/glsl/generator_impl_cast_test.cc
|
||||
|
@ -1063,8 +1065,6 @@ if(TINT_BUILD_TESTS)
|
|||
writer/glsl/generator_impl_function_test.cc
|
||||
writer/glsl/generator_impl_identifier_test.cc
|
||||
writer/glsl/generator_impl_if_test.cc
|
||||
writer/glsl/generator_impl_intrinsic_test.cc
|
||||
writer/glsl/generator_impl_intrinsic_texture_test.cc
|
||||
writer/glsl/generator_impl_import_test.cc
|
||||
writer/glsl/generator_impl_loop_test.cc
|
||||
writer/glsl/generator_impl_member_accessor_test.cc
|
||||
|
@ -1089,6 +1089,8 @@ if(TINT_BUILD_TESTS)
|
|||
writer/hlsl/generator_impl_bitcast_test.cc
|
||||
writer/hlsl/generator_impl_block_test.cc
|
||||
writer/hlsl/generator_impl_break_test.cc
|
||||
writer/hlsl/generator_impl_builtin_test.cc
|
||||
writer/hlsl/generator_impl_builtin_texture_test.cc
|
||||
writer/hlsl/generator_impl_call_test.cc
|
||||
writer/hlsl/generator_impl_case_test.cc
|
||||
writer/hlsl/generator_impl_cast_test.cc
|
||||
|
@ -1098,8 +1100,6 @@ if(TINT_BUILD_TESTS)
|
|||
writer/hlsl/generator_impl_function_test.cc
|
||||
writer/hlsl/generator_impl_identifier_test.cc
|
||||
writer/hlsl/generator_impl_if_test.cc
|
||||
writer/hlsl/generator_impl_intrinsic_test.cc
|
||||
writer/hlsl/generator_impl_intrinsic_texture_test.cc
|
||||
writer/hlsl/generator_impl_import_test.cc
|
||||
writer/hlsl/generator_impl_loop_test.cc
|
||||
writer/hlsl/generator_impl_member_accessor_test.cc
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/intrinsic_texture_helper_test.h"
|
||||
#include "src/ast/builtin_texture_helper_test.h"
|
||||
|
||||
#include "src/sem/depth_texture_type.h"
|
||||
#include "src/sem/multisampled_texture_type.h"
|
||||
|
@ -20,7 +20,7 @@
|
|||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
namespace intrinsic {
|
||||
namespace builtin {
|
||||
namespace test {
|
||||
|
||||
using u32 = ProgramBuilder::u32;
|
||||
|
@ -137,11 +137,11 @@ std::ostream& operator<<(std::ostream& out, const TextureOverloadCase& data) {
|
|||
const ast::Type* TextureOverloadCase::BuildResultVectorComponentType(
|
||||
ProgramBuilder* b) const {
|
||||
switch (texture_data_type) {
|
||||
case ast::intrinsic::test::TextureDataType::kF32:
|
||||
case ast::builtin::test::TextureDataType::kF32:
|
||||
return b->ty.f32();
|
||||
case ast::intrinsic::test::TextureDataType::kU32:
|
||||
case ast::builtin::test::TextureDataType::kU32:
|
||||
return b->ty.u32();
|
||||
case ast::intrinsic::test::TextureDataType::kI32:
|
||||
case ast::builtin::test::TextureDataType::kI32:
|
||||
return b->ty.i32();
|
||||
}
|
||||
|
||||
|
@ -156,29 +156,29 @@ const ast::Variable* TextureOverloadCase::BuildTextureVariable(
|
|||
b->create<ast::BindingAttribute>(0),
|
||||
};
|
||||
switch (texture_kind) {
|
||||
case ast::intrinsic::test::TextureKind::kRegular:
|
||||
case ast::builtin::test::TextureKind::kRegular:
|
||||
return b->Global("texture",
|
||||
b->ty.sampled_texture(texture_dimension,
|
||||
BuildResultVectorComponentType(b)),
|
||||
attrs);
|
||||
|
||||
case ast::intrinsic::test::TextureKind::kDepth:
|
||||
case ast::builtin::test::TextureKind::kDepth:
|
||||
return b->Global("texture", b->ty.depth_texture(texture_dimension),
|
||||
attrs);
|
||||
|
||||
case ast::intrinsic::test::TextureKind::kDepthMultisampled:
|
||||
case ast::builtin::test::TextureKind::kDepthMultisampled:
|
||||
return b->Global("texture",
|
||||
b->ty.depth_multisampled_texture(texture_dimension),
|
||||
attrs);
|
||||
|
||||
case ast::intrinsic::test::TextureKind::kMultisampled:
|
||||
case ast::builtin::test::TextureKind::kMultisampled:
|
||||
return b->Global(
|
||||
"texture",
|
||||
b->ty.multisampled_texture(texture_dimension,
|
||||
BuildResultVectorComponentType(b)),
|
||||
attrs);
|
||||
|
||||
case ast::intrinsic::test::TextureKind::kStorage: {
|
||||
case ast::builtin::test::TextureKind::kStorage: {
|
||||
auto* st = b->ty.storage_texture(texture_dimension, texel_format, access);
|
||||
return b->Global("texture", st, attrs);
|
||||
}
|
||||
|
@ -2281,6 +2281,6 @@ bool ReturnsVoid(ValidTextureOverload texture_overload) {
|
|||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace intrinsic
|
||||
} // namespace builtin
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_AST_INTRINSIC_TEXTURE_HELPER_TEST_H_
|
||||
#define SRC_AST_INTRINSIC_TEXTURE_HELPER_TEST_H_
|
||||
#ifndef SRC_AST_BUILTIN_TEXTURE_HELPER_TEST_H_
|
||||
#define SRC_AST_BUILTIN_TEXTURE_HELPER_TEST_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
|||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
namespace intrinsic {
|
||||
namespace builtin {
|
||||
namespace test {
|
||||
|
||||
enum class TextureKind {
|
||||
|
@ -181,10 +181,10 @@ enum class ValidTextureOverload {
|
|||
};
|
||||
|
||||
/// @param texture_overload the ValidTextureOverload
|
||||
/// @returns true if the ValidTextureOverload intrinsic returns no value.
|
||||
/// @returns true if the ValidTextureOverload builtin returns no value.
|
||||
bool ReturnsVoid(ValidTextureOverload texture_overload);
|
||||
|
||||
/// Describes a texture intrinsic overload
|
||||
/// Describes a texture builtin overload
|
||||
struct TextureOverloadCase {
|
||||
/// Constructor for textureSample...() functions
|
||||
TextureOverloadCase(ValidTextureOverload,
|
||||
|
@ -262,8 +262,8 @@ struct TextureOverloadCase {
|
|||
std::ostream& operator<<(std::ostream& out, const TextureOverloadCase& data);
|
||||
|
||||
} // namespace test
|
||||
} // namespace intrinsic
|
||||
} // namespace builtin
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_AST_INTRINSIC_TEXTURE_HELPER_TEST_H_
|
||||
#endif // SRC_AST_BUILTIN_TEXTURE_HELPER_TEST_H_
|
|
@ -26,7 +26,7 @@ class IdentifierExpression;
|
|||
|
||||
/// A call expression - represents either a:
|
||||
/// * sem::Function
|
||||
/// * sem::Intrinsic
|
||||
/// * sem::Builtin
|
||||
/// * sem::TypeConstructor
|
||||
/// * sem::TypeConversion
|
||||
class CallExpression : public Castable<CallExpression, Expression> {
|
||||
|
@ -64,7 +64,7 @@ class CallExpression : public Castable<CallExpression, Expression> {
|
|||
/// Target is either an identifier, or a Type.
|
||||
/// One of these must be nullptr and the other a non-nullptr.
|
||||
struct Target {
|
||||
/// name is a function or intrinsic to call, or type name to construct or
|
||||
/// name is a function or builtin to call, or type name to construct or
|
||||
/// cast-to
|
||||
const IdentifierExpression* name = nullptr;
|
||||
/// type to construct or cast-to
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/intrinsic_table.h"
|
||||
#include "src/builtin_table.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
@ -286,7 +286,7 @@ class OpenNumberMatcher : public NumberMatcher {
|
|||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Binding functions for use in the generated intrinsic_table.inl
|
||||
// Binding functions for use in the generated builtin_table.inl
|
||||
// TODO(bclayton): See if we can move more of this hand-rolled code to the
|
||||
// template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -793,19 +793,19 @@ struct OverloadInfo {
|
|||
bool is_deprecated;
|
||||
};
|
||||
|
||||
/// IntrinsicInfo describes an intrinsic function
|
||||
struct IntrinsicInfo {
|
||||
/// Number of overloads of the intrinsic function
|
||||
/// BuiltinInfo describes a builtin function
|
||||
struct BuiltinInfo {
|
||||
/// Number of overloads of the builtin function
|
||||
const uint8_t num_overloads;
|
||||
/// Pointer to the start of the overloads for the function
|
||||
OverloadInfo const* const overloads;
|
||||
};
|
||||
|
||||
#include "intrinsic_table.inl"
|
||||
#include "builtin_table.inl"
|
||||
|
||||
/// IntrinsicPrototype describes a fully matched intrinsic function, which is
|
||||
/// used as a lookup for building unique sem::Intrinsic instances.
|
||||
struct IntrinsicPrototype {
|
||||
/// BuiltinPrototype describes a fully matched builtin function, which is
|
||||
/// used as a lookup for building unique sem::Builtin instances.
|
||||
struct BuiltinPrototype {
|
||||
/// Parameter describes a single parameter
|
||||
struct Parameter {
|
||||
/// Parameter type
|
||||
|
@ -814,11 +814,11 @@ struct IntrinsicPrototype {
|
|||
ParameterUsage const usage = ParameterUsage::kNone;
|
||||
};
|
||||
|
||||
/// Hasher provides a hash function for the IntrinsicPrototype
|
||||
/// Hasher provides a hash function for the BuiltinPrototype
|
||||
struct Hasher {
|
||||
/// @param i the IntrinsicPrototype to create a hash for
|
||||
/// @param i the BuiltinPrototype to create a hash for
|
||||
/// @return the hash value
|
||||
inline std::size_t operator()(const IntrinsicPrototype& i) const {
|
||||
inline std::size_t operator()(const BuiltinPrototype& i) const {
|
||||
size_t hash = utils::Hash(i.parameters.size());
|
||||
for (auto& p : i.parameters) {
|
||||
utils::HashCombine(&hash, p.type, p.usage);
|
||||
|
@ -828,15 +828,15 @@ struct IntrinsicPrototype {
|
|||
}
|
||||
};
|
||||
|
||||
sem::IntrinsicType type = sem::IntrinsicType::kNone;
|
||||
sem::BuiltinType type = sem::BuiltinType::kNone;
|
||||
std::vector<Parameter> parameters;
|
||||
sem::Type const* return_type = nullptr;
|
||||
PipelineStageSet supported_stages;
|
||||
bool is_deprecated = false;
|
||||
};
|
||||
|
||||
/// Equality operator for IntrinsicPrototype
|
||||
bool operator==(const IntrinsicPrototype& a, const IntrinsicPrototype& b) {
|
||||
/// Equality operator for BuiltinPrototype
|
||||
bool operator==(const BuiltinPrototype& a, const BuiltinPrototype& b) {
|
||||
if (a.type != b.type || a.supported_stages != b.supported_stages ||
|
||||
a.return_type != b.return_type || a.is_deprecated != b.is_deprecated ||
|
||||
a.parameters.size() != b.parameters.size()) {
|
||||
|
@ -852,20 +852,20 @@ bool operator==(const IntrinsicPrototype& a, const IntrinsicPrototype& b) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Impl is the private implementation of the IntrinsicTable interface.
|
||||
class Impl : public IntrinsicTable {
|
||||
/// Impl is the private implementation of the BuiltinTable interface.
|
||||
class Impl : public BuiltinTable {
|
||||
public:
|
||||
explicit Impl(ProgramBuilder& builder);
|
||||
|
||||
const sem::Intrinsic* Lookup(sem::IntrinsicType intrinsic_type,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
const Source& source) override;
|
||||
const sem::Builtin* Lookup(sem::BuiltinType builtin_type,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
const Source& source) override;
|
||||
|
||||
private:
|
||||
const sem::Intrinsic* Match(sem::IntrinsicType intrinsic_type,
|
||||
const OverloadInfo& overload,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
int& match_score);
|
||||
const sem::Builtin* Match(sem::BuiltinType builtin_type,
|
||||
const OverloadInfo& overload,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
int& match_score);
|
||||
|
||||
MatchState Match(ClosedState& closed,
|
||||
const OverloadInfo& overload,
|
||||
|
@ -873,23 +873,21 @@ class Impl : public IntrinsicTable {
|
|||
|
||||
void PrintOverload(std::ostream& ss,
|
||||
const OverloadInfo& overload,
|
||||
sem::IntrinsicType intrinsic_type) const;
|
||||
sem::BuiltinType builtin_type) const;
|
||||
|
||||
ProgramBuilder& builder;
|
||||
Matchers matchers;
|
||||
std::unordered_map<IntrinsicPrototype,
|
||||
sem::Intrinsic*,
|
||||
IntrinsicPrototype::Hasher>
|
||||
intrinsics;
|
||||
std::unordered_map<BuiltinPrototype, sem::Builtin*, BuiltinPrototype::Hasher>
|
||||
builtins;
|
||||
};
|
||||
|
||||
/// @return a string representing a call to an intrinsic with the given argument
|
||||
/// @return a string representing a call to a builtin with the given argument
|
||||
/// types.
|
||||
std::string CallSignature(ProgramBuilder& builder,
|
||||
sem::IntrinsicType intrinsic_type,
|
||||
sem::BuiltinType builtin_type,
|
||||
const std::vector<const sem::Type*>& args) {
|
||||
std::stringstream ss;
|
||||
ss << sem::str(intrinsic_type) << "(";
|
||||
ss << sem::str(builtin_type) << "(";
|
||||
{
|
||||
bool first = true;
|
||||
for (auto* arg : args) {
|
||||
|
@ -915,9 +913,9 @@ std::string OpenNumberMatcher::String(MatchState& state) const {
|
|||
|
||||
Impl::Impl(ProgramBuilder& b) : builder(b) {}
|
||||
|
||||
const sem::Intrinsic* Impl::Lookup(sem::IntrinsicType intrinsic_type,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
const Source& source) {
|
||||
const sem::Builtin* Impl::Lookup(sem::BuiltinType builtin_type,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
const Source& source) {
|
||||
// Candidate holds information about a mismatched overload that could be what
|
||||
// the user intended to call.
|
||||
struct Candidate {
|
||||
|
@ -928,11 +926,11 @@ const sem::Intrinsic* Impl::Lookup(sem::IntrinsicType intrinsic_type,
|
|||
// The list of failed matches that had promise.
|
||||
std::vector<Candidate> candidates;
|
||||
|
||||
auto& intrinsic = kIntrinsics[static_cast<uint32_t>(intrinsic_type)];
|
||||
for (uint32_t o = 0; o < intrinsic.num_overloads; o++) {
|
||||
auto& builtin = kBuiltins[static_cast<uint32_t>(builtin_type)];
|
||||
for (uint32_t o = 0; o < builtin.num_overloads; o++) {
|
||||
int match_score = 1000;
|
||||
auto& overload = intrinsic.overloads[o];
|
||||
if (auto* match = Match(intrinsic_type, overload, args, match_score)) {
|
||||
auto& overload = builtin.overloads[o];
|
||||
if (auto* match = Match(builtin_type, overload, args, match_score)) {
|
||||
return match;
|
||||
}
|
||||
if (match_score > 0) {
|
||||
|
@ -947,7 +945,7 @@ const sem::Intrinsic* Impl::Lookup(sem::IntrinsicType intrinsic_type,
|
|||
|
||||
// Generate an error message
|
||||
std::stringstream ss;
|
||||
ss << "no matching call to " << CallSignature(builder, intrinsic_type, args)
|
||||
ss << "no matching call to " << CallSignature(builder, builtin_type, args)
|
||||
<< std::endl;
|
||||
if (!candidates.empty()) {
|
||||
ss << std::endl;
|
||||
|
@ -955,7 +953,7 @@ const sem::Intrinsic* Impl::Lookup(sem::IntrinsicType intrinsic_type,
|
|||
<< (candidates.size() > 1 ? "s:" : ":") << std::endl;
|
||||
for (auto& candidate : candidates) {
|
||||
ss << " ";
|
||||
PrintOverload(ss, *candidate.overload, intrinsic_type);
|
||||
PrintOverload(ss, *candidate.overload, builtin_type);
|
||||
ss << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -963,10 +961,10 @@ const sem::Intrinsic* Impl::Lookup(sem::IntrinsicType intrinsic_type,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const sem::Intrinsic* Impl::Match(sem::IntrinsicType intrinsic_type,
|
||||
const OverloadInfo& overload,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
int& match_score) {
|
||||
const sem::Builtin* Impl::Match(sem::BuiltinType builtin_type,
|
||||
const OverloadInfo& overload,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
int& match_score) {
|
||||
// Score wait for argument <-> parameter count matches / mismatches
|
||||
constexpr int kScorePerParamArgMismatch = -1;
|
||||
constexpr int kScorePerMatchedParam = 2;
|
||||
|
@ -987,7 +985,7 @@ const sem::Intrinsic* Impl::Match(sem::IntrinsicType intrinsic_type,
|
|||
|
||||
ClosedState closed(builder);
|
||||
|
||||
std::vector<IntrinsicPrototype::Parameter> parameters;
|
||||
std::vector<BuiltinPrototype::Parameter> parameters;
|
||||
|
||||
auto num_params = std::min(num_parameters, num_arguments);
|
||||
for (uint32_t p = 0; p < num_params; p++) {
|
||||
|
@ -996,7 +994,7 @@ const sem::Intrinsic* Impl::Match(sem::IntrinsicType intrinsic_type,
|
|||
auto* type = Match(closed, overload, indices).Type(args[p]->UnwrapRef());
|
||||
if (type) {
|
||||
parameters.emplace_back(
|
||||
IntrinsicPrototype::Parameter{type, parameter.usage});
|
||||
BuiltinPrototype::Parameter{type, parameter.usage});
|
||||
match_score += kScorePerMatchedParam;
|
||||
} else {
|
||||
overload_matched = false;
|
||||
|
@ -1044,7 +1042,7 @@ const sem::Intrinsic* Impl::Match(sem::IntrinsicType intrinsic_type,
|
|||
return_type = Match(closed, overload, indices).Type(&any);
|
||||
if (!return_type) {
|
||||
std::stringstream ss;
|
||||
PrintOverload(ss, overload, intrinsic_type);
|
||||
PrintOverload(ss, overload, builtin_type);
|
||||
TINT_ICE(Resolver, builder.Diagnostics())
|
||||
<< "MatchState.Match() returned null for " << ss.str();
|
||||
return nullptr;
|
||||
|
@ -1053,25 +1051,25 @@ const sem::Intrinsic* Impl::Match(sem::IntrinsicType intrinsic_type,
|
|||
return_type = builder.create<sem::Void>();
|
||||
}
|
||||
|
||||
IntrinsicPrototype intrinsic;
|
||||
intrinsic.type = intrinsic_type;
|
||||
intrinsic.return_type = return_type;
|
||||
intrinsic.parameters = std::move(parameters);
|
||||
intrinsic.supported_stages = overload.supported_stages;
|
||||
intrinsic.is_deprecated = overload.is_deprecated;
|
||||
BuiltinPrototype builtin;
|
||||
builtin.type = builtin_type;
|
||||
builtin.return_type = return_type;
|
||||
builtin.parameters = std::move(parameters);
|
||||
builtin.supported_stages = overload.supported_stages;
|
||||
builtin.is_deprecated = overload.is_deprecated;
|
||||
|
||||
// De-duplicate intrinsics that are identical.
|
||||
return utils::GetOrCreate(intrinsics, intrinsic, [&] {
|
||||
// De-duplicate builtins that are identical.
|
||||
return utils::GetOrCreate(builtins, builtin, [&] {
|
||||
std::vector<sem::Parameter*> params;
|
||||
params.reserve(intrinsic.parameters.size());
|
||||
for (auto& p : intrinsic.parameters) {
|
||||
params.reserve(builtin.parameters.size());
|
||||
for (auto& p : builtin.parameters) {
|
||||
params.emplace_back(builder.create<sem::Parameter>(
|
||||
nullptr, static_cast<uint32_t>(params.size()), p.type,
|
||||
ast::StorageClass::kNone, ast::Access::kUndefined, p.usage));
|
||||
}
|
||||
return builder.create<sem::Intrinsic>(
|
||||
intrinsic.type, intrinsic.return_type, std::move(params),
|
||||
intrinsic.supported_stages, intrinsic.is_deprecated);
|
||||
return builder.create<sem::Builtin>(
|
||||
builtin.type, builtin.return_type, std::move(params),
|
||||
builtin.supported_stages, builtin.is_deprecated);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1083,10 +1081,10 @@ MatchState Impl::Match(ClosedState& closed,
|
|||
|
||||
void Impl::PrintOverload(std::ostream& ss,
|
||||
const OverloadInfo& overload,
|
||||
sem::IntrinsicType intrinsic_type) const {
|
||||
sem::BuiltinType builtin_type) const {
|
||||
ClosedState closed(builder);
|
||||
|
||||
ss << intrinsic_type << "(";
|
||||
ss << builtin_type << "(";
|
||||
for (uint32_t p = 0; p < overload.num_parameters; p++) {
|
||||
auto& parameter = overload.parameters[p];
|
||||
if (p > 0) {
|
||||
|
@ -1156,12 +1154,11 @@ std::string MatchState::NumName() {
|
|||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<IntrinsicTable> IntrinsicTable::Create(
|
||||
ProgramBuilder& builder) {
|
||||
std::unique_ptr<BuiltinTable> BuiltinTable::Create(ProgramBuilder& builder) {
|
||||
return std::make_unique<Impl>(builder);
|
||||
}
|
||||
|
||||
IntrinsicTable::~IntrinsicTable() = default;
|
||||
BuiltinTable::~BuiltinTable() = default;
|
||||
|
||||
/// TypeInfo for the Any type declared in the anonymous namespace above
|
||||
TINT_INSTANTIATE_TYPEINFO(Any);
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_BUILTIN_TABLE_H_
|
||||
#define SRC_BUILTIN_TABLE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "src/sem/builtin.h"
|
||||
|
||||
namespace tint {
|
||||
|
||||
// Forward declarations
|
||||
class ProgramBuilder;
|
||||
|
||||
/// BuiltinTable is a lookup table of all the WGSL builtin functions
|
||||
class BuiltinTable {
|
||||
public:
|
||||
/// @param builder the program builder
|
||||
/// @return a pointer to a newly created BuiltinTable
|
||||
static std::unique_ptr<BuiltinTable> Create(ProgramBuilder& builder);
|
||||
|
||||
/// Destructor
|
||||
virtual ~BuiltinTable();
|
||||
|
||||
/// Lookup looks for the builtin overload with the given signature, raising
|
||||
/// an error diagnostic if the builtin was not found.
|
||||
/// @param type the builtin type
|
||||
/// @param args the argument types passed to the builtin function
|
||||
/// @param source the source of the builtin call
|
||||
/// @return the semantic builtin if found, otherwise nullptr
|
||||
virtual const sem::Builtin* Lookup(sem::BuiltinType type,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
const Source& source) = 0;
|
||||
};
|
||||
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_BUILTIN_TABLE_H_
|
|
@ -13,11 +13,11 @@
|
|||
// limitations under the License.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// File generated by tools/intrinsic-gen
|
||||
// File generated by tools/builtin-gen
|
||||
// using the template:
|
||||
// src/intrinsic_table.inl.tmpl
|
||||
// and the intrinsic defintion file:
|
||||
// src/intrinsics.def
|
||||
// src/builtin_table.inl.tmpl
|
||||
// and the builtin defintion file:
|
||||
// src/builtins.def
|
||||
//
|
||||
// Do not modify this file directly
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -25,7 +25,7 @@
|
|||
// clang-format off
|
||||
|
||||
/// TypeMatcher for 'type bool'
|
||||
/// @see src/intrinsics.def:68:6
|
||||
/// @see src/builtins.def:68:6
|
||||
class Bool : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -52,7 +52,7 @@ std::string Bool::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type f32'
|
||||
/// @see src/intrinsics.def:69:6
|
||||
/// @see src/builtins.def:69:6
|
||||
class F32 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -79,7 +79,7 @@ std::string F32::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type i32'
|
||||
/// @see src/intrinsics.def:70:6
|
||||
/// @see src/builtins.def:70:6
|
||||
class I32 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -106,7 +106,7 @@ std::string I32::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type u32'
|
||||
/// @see src/intrinsics.def:71:6
|
||||
/// @see src/builtins.def:71:6
|
||||
class U32 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -133,7 +133,7 @@ std::string U32::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type vec2'
|
||||
/// @see src/intrinsics.def:72:6
|
||||
/// @see src/builtins.def:72:6
|
||||
class Vec2 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -166,7 +166,7 @@ std::string Vec2::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type vec3'
|
||||
/// @see src/intrinsics.def:73:6
|
||||
/// @see src/builtins.def:73:6
|
||||
class Vec3 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -199,7 +199,7 @@ std::string Vec3::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type vec4'
|
||||
/// @see src/intrinsics.def:74:6
|
||||
/// @see src/builtins.def:74:6
|
||||
class Vec4 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -232,7 +232,7 @@ std::string Vec4::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type vec'
|
||||
/// @see src/intrinsics.def:75:37
|
||||
/// @see src/builtins.def:75:37
|
||||
class Vec : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -273,7 +273,7 @@ std::string Vec::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type mat'
|
||||
/// @see src/intrinsics.def:76:37
|
||||
/// @see src/builtins.def:76:37
|
||||
class Mat : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -320,7 +320,7 @@ std::string Mat::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type ptr'
|
||||
/// @see src/intrinsics.def:77:6
|
||||
/// @see src/builtins.def:77:6
|
||||
class Ptr : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -365,7 +365,7 @@ std::string Ptr::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type atomic'
|
||||
/// @see src/intrinsics.def:78:6
|
||||
/// @see src/builtins.def:78:6
|
||||
class Atomic : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -398,7 +398,7 @@ std::string Atomic::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type array'
|
||||
/// @see src/intrinsics.def:79:6
|
||||
/// @see src/builtins.def:79:6
|
||||
class Array : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -431,7 +431,7 @@ std::string Array::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type sampler'
|
||||
/// @see src/intrinsics.def:80:6
|
||||
/// @see src/builtins.def:80:6
|
||||
class Sampler : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -458,7 +458,7 @@ std::string Sampler::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type sampler_comparison'
|
||||
/// @see src/intrinsics.def:81:6
|
||||
/// @see src/builtins.def:81:6
|
||||
class SamplerComparison : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -485,7 +485,7 @@ std::string SamplerComparison::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_1d'
|
||||
/// @see src/intrinsics.def:82:6
|
||||
/// @see src/builtins.def:82:6
|
||||
class Texture1D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -518,7 +518,7 @@ std::string Texture1D::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_2d'
|
||||
/// @see src/intrinsics.def:83:6
|
||||
/// @see src/builtins.def:83:6
|
||||
class Texture2D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -551,7 +551,7 @@ std::string Texture2D::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_2d_array'
|
||||
/// @see src/intrinsics.def:84:6
|
||||
/// @see src/builtins.def:84:6
|
||||
class Texture2DArray : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -584,7 +584,7 @@ std::string Texture2DArray::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_3d'
|
||||
/// @see src/intrinsics.def:85:6
|
||||
/// @see src/builtins.def:85:6
|
||||
class Texture3D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -617,7 +617,7 @@ std::string Texture3D::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_cube'
|
||||
/// @see src/intrinsics.def:86:6
|
||||
/// @see src/builtins.def:86:6
|
||||
class TextureCube : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -650,7 +650,7 @@ std::string TextureCube::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_cube_array'
|
||||
/// @see src/intrinsics.def:87:6
|
||||
/// @see src/builtins.def:87:6
|
||||
class TextureCubeArray : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -683,7 +683,7 @@ std::string TextureCubeArray::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_multisampled_2d'
|
||||
/// @see src/intrinsics.def:88:6
|
||||
/// @see src/builtins.def:88:6
|
||||
class TextureMultisampled2D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -716,7 +716,7 @@ std::string TextureMultisampled2D::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_depth_2d'
|
||||
/// @see src/intrinsics.def:89:6
|
||||
/// @see src/builtins.def:89:6
|
||||
class TextureDepth2D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -743,7 +743,7 @@ std::string TextureDepth2D::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_depth_2d_array'
|
||||
/// @see src/intrinsics.def:90:6
|
||||
/// @see src/builtins.def:90:6
|
||||
class TextureDepth2DArray : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -770,7 +770,7 @@ std::string TextureDepth2DArray::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_depth_cube'
|
||||
/// @see src/intrinsics.def:91:6
|
||||
/// @see src/builtins.def:91:6
|
||||
class TextureDepthCube : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -797,7 +797,7 @@ std::string TextureDepthCube::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_depth_cube_array'
|
||||
/// @see src/intrinsics.def:92:6
|
||||
/// @see src/builtins.def:92:6
|
||||
class TextureDepthCubeArray : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -824,7 +824,7 @@ std::string TextureDepthCubeArray::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_depth_multisampled_2d'
|
||||
/// @see src/intrinsics.def:93:6
|
||||
/// @see src/builtins.def:93:6
|
||||
class TextureDepthMultisampled2D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -851,7 +851,7 @@ std::string TextureDepthMultisampled2D::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_storage_1d'
|
||||
/// @see src/intrinsics.def:94:6
|
||||
/// @see src/builtins.def:94:6
|
||||
class TextureStorage1D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -890,7 +890,7 @@ std::string TextureStorage1D::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_storage_2d'
|
||||
/// @see src/intrinsics.def:95:6
|
||||
/// @see src/builtins.def:95:6
|
||||
class TextureStorage2D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -929,7 +929,7 @@ std::string TextureStorage2D::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_storage_2d_array'
|
||||
/// @see src/intrinsics.def:96:6
|
||||
/// @see src/builtins.def:96:6
|
||||
class TextureStorage2DArray : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -968,7 +968,7 @@ std::string TextureStorage2DArray::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_storage_3d'
|
||||
/// @see src/intrinsics.def:97:6
|
||||
/// @see src/builtins.def:97:6
|
||||
class TextureStorage3D : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -1007,7 +1007,7 @@ std::string TextureStorage3D::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type texture_external'
|
||||
/// @see src/intrinsics.def:98:6
|
||||
/// @see src/builtins.def:98:6
|
||||
class TextureExternal : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -1034,7 +1034,7 @@ std::string TextureExternal::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type __modf_result'
|
||||
/// @see src/intrinsics.def:100:6
|
||||
/// @see src/builtins.def:100:6
|
||||
class ModfResult : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -1061,7 +1061,7 @@ std::string ModfResult::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type __modf_result_vec'
|
||||
/// @see src/intrinsics.def:101:42
|
||||
/// @see src/builtins.def:101:42
|
||||
class ModfResultVec : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -1096,7 +1096,7 @@ std::string ModfResultVec::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type __frexp_result'
|
||||
/// @see src/intrinsics.def:102:6
|
||||
/// @see src/builtins.def:102:6
|
||||
class FrexpResult : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -1123,7 +1123,7 @@ std::string FrexpResult::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'type __frexp_result_vec'
|
||||
/// @see src/intrinsics.def:103:43
|
||||
/// @see src/builtins.def:103:43
|
||||
class FrexpResultVec : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules.
|
||||
|
@ -1158,7 +1158,7 @@ std::string FrexpResultVec::String(MatchState& state) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'match fiu32'
|
||||
/// @see src/intrinsics.def:111:7
|
||||
/// @see src/builtins.def:111:7
|
||||
class Fiu32 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
|
@ -1192,7 +1192,7 @@ std::string Fiu32::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'match iu32'
|
||||
/// @see src/intrinsics.def:112:7
|
||||
/// @see src/builtins.def:112:7
|
||||
class Iu32 : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
|
@ -1223,7 +1223,7 @@ std::string Iu32::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// TypeMatcher for 'match scalar'
|
||||
/// @see src/intrinsics.def:113:7
|
||||
/// @see src/builtins.def:113:7
|
||||
class Scalar : public TypeMatcher {
|
||||
public:
|
||||
/// Checks whether the given type matches the matcher rules, and returns the
|
||||
|
@ -1260,7 +1260,7 @@ std::string Scalar::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// EnumMatcher for 'match f32_texel_format'
|
||||
/// @see src/intrinsics.def:124:7
|
||||
/// @see src/builtins.def:124:7
|
||||
class F32TexelFormat : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
|
@ -1293,7 +1293,7 @@ std::string F32TexelFormat::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// EnumMatcher for 'match i32_texel_format'
|
||||
/// @see src/intrinsics.def:126:7
|
||||
/// @see src/builtins.def:126:7
|
||||
class I32TexelFormat : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
|
@ -1325,7 +1325,7 @@ std::string I32TexelFormat::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// EnumMatcher for 'match u32_texel_format'
|
||||
/// @see src/intrinsics.def:128:7
|
||||
/// @see src/builtins.def:128:7
|
||||
class U32TexelFormat : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
|
@ -1357,7 +1357,7 @@ std::string U32TexelFormat::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// EnumMatcher for 'match write_only'
|
||||
/// @see src/intrinsics.def:131:7
|
||||
/// @see src/builtins.def:131:7
|
||||
class WriteOnly : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
|
@ -1383,7 +1383,7 @@ std::string WriteOnly::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// EnumMatcher for 'match function_private_workgroup'
|
||||
/// @see src/intrinsics.def:133:7
|
||||
/// @see src/builtins.def:133:7
|
||||
class FunctionPrivateWorkgroup : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
|
@ -1413,7 +1413,7 @@ std::string FunctionPrivateWorkgroup::String(MatchState&) const {
|
|||
}
|
||||
|
||||
/// EnumMatcher for 'match workgroup_or_storage'
|
||||
/// @see src/intrinsics.def:134:7
|
||||
/// @see src/builtins.def:134:7
|
||||
class WorkgroupOrStorage : public NumberMatcher {
|
||||
public:
|
||||
/// Checks whether the given number matches the enum matcher rules.
|
||||
|
@ -8642,7 +8642,7 @@ constexpr OverloadInfo kOverloads[] = {
|
|||
},
|
||||
};
|
||||
|
||||
constexpr IntrinsicInfo kIntrinsics[] = {
|
||||
constexpr BuiltinInfo kBuiltins[] = {
|
||||
{
|
||||
/* [0] */
|
||||
/* fn abs<T : fiu32>(T) -> T */
|
|
@ -1,10 +1,10 @@
|
|||
{{- /*
|
||||
--------------------------------------------------------------------------------
|
||||
Template file for use with tools/intrinsic-gen to generate intrinsic_table.inl
|
||||
Used by IntrinsicTable.cc for intrinsic overload resolution.
|
||||
Template file for use with tools/builtin-gen to generate builtin_table.inl
|
||||
Used by BuiltinTable.cc for builtin overload resolution.
|
||||
|
||||
See:
|
||||
* tools/cmd/intrinsic-gen/gen for structures used by this template
|
||||
* tools/cmd/builtin-gen/gen for structures used by this template
|
||||
* https://golang.org/pkg/text/template/ for documentation on the template syntax
|
||||
--------------------------------------------------------------------------------
|
||||
*/ -}}
|
||||
|
@ -23,7 +23,7 @@ See:
|
|||
{{ end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- with IntrinsicTable -}}
|
||||
{{- with BuiltinTable -}}
|
||||
{{- template "Matchers" . }}
|
||||
|
||||
constexpr MatcherIndex kMatcherIndices[] = {
|
||||
|
@ -106,7 +106,7 @@ constexpr OverloadInfo kOverloads[] = {
|
|||
{{- end }}
|
||||
};
|
||||
|
||||
constexpr IntrinsicInfo kIntrinsics[] = {
|
||||
constexpr BuiltinInfo kBuiltins[] = {
|
||||
{{- range $i, $f := .Functions }}
|
||||
{
|
||||
/* [{{$i}}] */
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/intrinsic_table.h"
|
||||
#include "src/builtin_table.h"
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/program_builder.h"
|
||||
|
@ -30,65 +30,63 @@ namespace {
|
|||
|
||||
using ::testing::HasSubstr;
|
||||
|
||||
using IntrinsicType = sem::IntrinsicType;
|
||||
using BuiltinType = sem::BuiltinType;
|
||||
using Parameter = sem::Parameter;
|
||||
using ParameterUsage = sem::ParameterUsage;
|
||||
|
||||
class IntrinsicTableTest : public testing::Test, public ProgramBuilder {
|
||||
class BuiltinTableTest : public testing::Test, public ProgramBuilder {
|
||||
public:
|
||||
std::unique_ptr<IntrinsicTable> table = IntrinsicTable::Create(*this);
|
||||
std::unique_ptr<BuiltinTable> table = BuiltinTable::Create(*this);
|
||||
};
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchF32) {
|
||||
TEST_F(BuiltinTableTest, MatchF32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* result = table->Lookup(IntrinsicType::kCos, {f32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kCos, {f32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kCos);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kCos);
|
||||
EXPECT_EQ(result->ReturnType(), f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 1u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), f32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchF32) {
|
||||
TEST_F(BuiltinTableTest, MismatchF32) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* result = table->Lookup(IntrinsicType::kCos, {i32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kCos, {i32}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchU32) {
|
||||
TEST_F(BuiltinTableTest, MatchU32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(f32, 2);
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kUnpack2x16float, {u32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kUnpack2x16float, {u32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kUnpack2x16float);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kUnpack2x16float);
|
||||
EXPECT_EQ(result->ReturnType(), vec2_f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 1u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), u32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchU32) {
|
||||
TEST_F(BuiltinTableTest, MismatchU32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kUnpack2x16float, {f32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kUnpack2x16float, {f32}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchI32) {
|
||||
TEST_F(BuiltinTableTest, MatchI32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* vec4_f32 = create<sem::Vector>(f32, 4);
|
||||
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k1d, f32);
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kTextureLoad, {tex, i32, i32}, Source{});
|
||||
table->Lookup(BuiltinType::kTextureLoad, {tex, i32, i32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kTextureLoad);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
|
||||
EXPECT_EQ(result->ReturnType(), vec4_f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 3u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), tex);
|
||||
|
@ -99,51 +97,49 @@ TEST_F(IntrinsicTableTest, MatchI32) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kLevel);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchI32) {
|
||||
TEST_F(BuiltinTableTest, MismatchI32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k1d, f32);
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kTextureLoad, {tex, f32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kTextureLoad, {tex, f32}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchIU32AsI32) {
|
||||
TEST_F(BuiltinTableTest, MatchIU32AsI32) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* result = table->Lookup(IntrinsicType::kCountOneBits, {i32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kCountOneBits, {i32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kCountOneBits);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kCountOneBits);
|
||||
EXPECT_EQ(result->ReturnType(), i32);
|
||||
ASSERT_EQ(result->Parameters().size(), 1u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), i32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchIU32AsU32) {
|
||||
TEST_F(BuiltinTableTest, MatchIU32AsU32) {
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto* result = table->Lookup(IntrinsicType::kCountOneBits, {u32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kCountOneBits, {u32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kCountOneBits);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kCountOneBits);
|
||||
EXPECT_EQ(result->ReturnType(), u32);
|
||||
ASSERT_EQ(result->Parameters().size(), 1u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), u32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchIU32) {
|
||||
TEST_F(BuiltinTableTest, MismatchIU32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* result = table->Lookup(IntrinsicType::kCountOneBits, {f32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kCountOneBits, {f32}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchFIU32AsI32) {
|
||||
TEST_F(BuiltinTableTest, MatchFIU32AsI32) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kClamp, {i32, i32, i32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kClamp, {i32, i32, i32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kClamp);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kClamp);
|
||||
EXPECT_EQ(result->ReturnType(), i32);
|
||||
ASSERT_EQ(result->Parameters().size(), 3u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), i32);
|
||||
|
@ -151,13 +147,12 @@ TEST_F(IntrinsicTableTest, MatchFIU32AsI32) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Type(), i32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchFIU32AsU32) {
|
||||
TEST_F(BuiltinTableTest, MatchFIU32AsU32) {
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kClamp, {u32, u32, u32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kClamp, {u32, u32, u32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kClamp);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kClamp);
|
||||
EXPECT_EQ(result->ReturnType(), u32);
|
||||
ASSERT_EQ(result->Parameters().size(), 3u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), u32);
|
||||
|
@ -165,13 +160,12 @@ TEST_F(IntrinsicTableTest, MatchFIU32AsU32) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Type(), u32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchFIU32AsF32) {
|
||||
TEST_F(BuiltinTableTest, MatchFIU32AsF32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kClamp, {f32, f32, f32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kClamp, {f32, f32, f32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kClamp);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kClamp);
|
||||
EXPECT_EQ(result->ReturnType(), f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 3u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), f32);
|
||||
|
@ -179,22 +173,22 @@ TEST_F(IntrinsicTableTest, MatchFIU32AsF32) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Type(), f32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchFIU32) {
|
||||
TEST_F(BuiltinTableTest, MismatchFIU32) {
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kClamp, {bool_, bool_, bool_}, Source{});
|
||||
table->Lookup(BuiltinType::kClamp, {bool_, bool_, bool_}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchBool) {
|
||||
TEST_F(BuiltinTableTest, MatchBool) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kSelect, {f32, f32, bool_}, Source{});
|
||||
table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kSelect);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kSelect);
|
||||
EXPECT_EQ(result->ReturnType(), f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 3u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), f32);
|
||||
|
@ -202,46 +196,43 @@ TEST_F(IntrinsicTableTest, MatchBool) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Type(), bool_);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchBool) {
|
||||
TEST_F(BuiltinTableTest, MismatchBool) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kSelect, {f32, f32, f32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kSelect, {f32, f32, f32}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchPointer) {
|
||||
TEST_F(BuiltinTableTest, MatchPointer) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* atomicI32 = create<sem::Atomic>(i32);
|
||||
auto* ptr = create<sem::Pointer>(atomicI32, ast::StorageClass::kWorkgroup,
|
||||
ast::Access::kReadWrite);
|
||||
auto* result = table->Lookup(IntrinsicType::kAtomicLoad, {ptr}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kAtomicLoad, {ptr}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kAtomicLoad);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kAtomicLoad);
|
||||
EXPECT_EQ(result->ReturnType(), i32);
|
||||
ASSERT_EQ(result->Parameters().size(), 1u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), ptr);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchPointer) {
|
||||
TEST_F(BuiltinTableTest, MismatchPointer) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* atomicI32 = create<sem::Atomic>(i32);
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kAtomicLoad, {atomicI32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kAtomicLoad, {atomicI32}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchArray) {
|
||||
TEST_F(BuiltinTableTest, MatchArray) {
|
||||
auto* arr = create<sem::Array>(create<sem::U32>(), 0, 4, 4, 4, 4);
|
||||
auto* arr_ptr = create<sem::Pointer>(arr, ast::StorageClass::kStorage,
|
||||
ast::Access::kReadWrite);
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kArrayLength, {arr_ptr}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kArrayLength, {arr_ptr}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kArrayLength);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kArrayLength);
|
||||
EXPECT_TRUE(result->ReturnType()->Is<sem::U32>());
|
||||
ASSERT_EQ(result->Parameters().size(), 1u);
|
||||
auto* param_type = result->Parameters()[0]->Type();
|
||||
|
@ -249,24 +240,24 @@ TEST_F(IntrinsicTableTest, MatchArray) {
|
|||
EXPECT_TRUE(param_type->As<sem::Pointer>()->StoreType()->Is<sem::Array>());
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchArray) {
|
||||
TEST_F(BuiltinTableTest, MismatchArray) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* result = table->Lookup(IntrinsicType::kArrayLength, {f32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kArrayLength, {f32}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchSampler) {
|
||||
TEST_F(BuiltinTableTest, MatchSampler) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(f32, 2);
|
||||
auto* vec4_f32 = create<sem::Vector>(f32, 4);
|
||||
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
|
||||
auto* sampler = create<sem::Sampler>(ast::SamplerKind::kSampler);
|
||||
auto* result = table->Lookup(IntrinsicType::kTextureSample,
|
||||
auto* result = table->Lookup(BuiltinType::kTextureSample,
|
||||
{tex, sampler, vec2_f32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kTextureSample);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kTextureSample);
|
||||
EXPECT_EQ(result->ReturnType(), vec4_f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 3u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), tex);
|
||||
|
@ -277,27 +268,27 @@ TEST_F(IntrinsicTableTest, MatchSampler) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kCoords);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchSampler) {
|
||||
TEST_F(BuiltinTableTest, MismatchSampler) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(f32, 2);
|
||||
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
|
||||
auto* result = table->Lookup(IntrinsicType::kTextureSample,
|
||||
auto* result = table->Lookup(BuiltinType::kTextureSample,
|
||||
{tex, f32, vec2_f32}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchSampledTexture) {
|
||||
TEST_F(BuiltinTableTest, MatchSampledTexture) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* vec2_i32 = create<sem::Vector>(i32, 2);
|
||||
auto* vec4_f32 = create<sem::Vector>(f32, 4);
|
||||
auto* tex = create<sem::SampledTexture>(ast::TextureDimension::k2d, f32);
|
||||
auto* result = table->Lookup(IntrinsicType::kTextureLoad,
|
||||
{tex, vec2_i32, i32}, Source{});
|
||||
auto* result =
|
||||
table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kTextureLoad);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
|
||||
EXPECT_EQ(result->ReturnType(), vec4_f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 3u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), tex);
|
||||
|
@ -308,17 +299,17 @@ TEST_F(IntrinsicTableTest, MatchSampledTexture) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kLevel);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchMultisampledTexture) {
|
||||
TEST_F(BuiltinTableTest, MatchMultisampledTexture) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* vec2_i32 = create<sem::Vector>(i32, 2);
|
||||
auto* vec4_f32 = create<sem::Vector>(f32, 4);
|
||||
auto* tex = create<sem::MultisampledTexture>(ast::TextureDimension::k2d, f32);
|
||||
auto* result = table->Lookup(IntrinsicType::kTextureLoad,
|
||||
{tex, vec2_i32, i32}, Source{});
|
||||
auto* result =
|
||||
table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kTextureLoad);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
|
||||
EXPECT_EQ(result->ReturnType(), vec4_f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 3u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), tex);
|
||||
|
@ -329,16 +320,16 @@ TEST_F(IntrinsicTableTest, MatchMultisampledTexture) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kSampleIndex);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchDepthTexture) {
|
||||
TEST_F(BuiltinTableTest, MatchDepthTexture) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* vec2_i32 = create<sem::Vector>(i32, 2);
|
||||
auto* tex = create<sem::DepthTexture>(ast::TextureDimension::k2d);
|
||||
auto* result = table->Lookup(IntrinsicType::kTextureLoad,
|
||||
{tex, vec2_i32, i32}, Source{});
|
||||
auto* result =
|
||||
table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kTextureLoad);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
|
||||
EXPECT_EQ(result->ReturnType(), f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 3u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), tex);
|
||||
|
@ -349,16 +340,16 @@ TEST_F(IntrinsicTableTest, MatchDepthTexture) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kLevel);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchDepthMultisampledTexture) {
|
||||
TEST_F(BuiltinTableTest, MatchDepthMultisampledTexture) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* vec2_i32 = create<sem::Vector>(i32, 2);
|
||||
auto* tex = create<sem::DepthMultisampledTexture>(ast::TextureDimension::k2d);
|
||||
auto* result = table->Lookup(IntrinsicType::kTextureLoad,
|
||||
{tex, vec2_i32, i32}, Source{});
|
||||
auto* result =
|
||||
table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32, i32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kTextureLoad);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
|
||||
EXPECT_EQ(result->ReturnType(), f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 3u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), tex);
|
||||
|
@ -369,17 +360,17 @@ TEST_F(IntrinsicTableTest, MatchDepthMultisampledTexture) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kSampleIndex);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchExternalTexture) {
|
||||
TEST_F(BuiltinTableTest, MatchExternalTexture) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* vec2_i32 = create<sem::Vector>(i32, 2);
|
||||
auto* vec4_f32 = create<sem::Vector>(f32, 4);
|
||||
auto* tex = create<sem::ExternalTexture>();
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kTextureLoad, {tex, vec2_i32}, Source{});
|
||||
table->Lookup(BuiltinType::kTextureLoad, {tex, vec2_i32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kTextureLoad);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kTextureLoad);
|
||||
EXPECT_EQ(result->ReturnType(), vec4_f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 2u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), tex);
|
||||
|
@ -388,7 +379,7 @@ TEST_F(IntrinsicTableTest, MatchExternalTexture) {
|
|||
EXPECT_EQ(result->Parameters()[1]->Usage(), ParameterUsage::kCoords);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchWOStorageTexture) {
|
||||
TEST_F(BuiltinTableTest, MatchWOStorageTexture) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* vec2_i32 = create<sem::Vector>(i32, 2);
|
||||
|
@ -399,11 +390,11 @@ TEST_F(IntrinsicTableTest, MatchWOStorageTexture) {
|
|||
ast::TexelFormat::kR32Float,
|
||||
ast::Access::kWrite, subtype);
|
||||
|
||||
auto* result = table->Lookup(IntrinsicType::kTextureStore,
|
||||
auto* result = table->Lookup(BuiltinType::kTextureStore,
|
||||
{tex, vec2_i32, vec4_f32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kTextureStore);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kTextureStore);
|
||||
EXPECT_TRUE(result->ReturnType()->Is<sem::Void>());
|
||||
ASSERT_EQ(result->Parameters().size(), 3u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), tex);
|
||||
|
@ -414,61 +405,59 @@ TEST_F(IntrinsicTableTest, MatchWOStorageTexture) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Usage(), ParameterUsage::kValue);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchTexture) {
|
||||
TEST_F(BuiltinTableTest, MismatchTexture) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* i32 = create<sem::I32>();
|
||||
auto* vec2_i32 = create<sem::Vector>(i32, 2);
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kTextureLoad, {f32, vec2_i32}, Source{});
|
||||
table->Lookup(BuiltinType::kTextureLoad, {f32, vec2_i32}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) {
|
||||
TEST_F(BuiltinTableTest, ImplicitLoadOnReference) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kCos,
|
||||
table->Lookup(BuiltinType::kCos,
|
||||
{create<sem::Reference>(f32, ast::StorageClass::kFunction,
|
||||
ast::Access::kReadWrite)},
|
||||
Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kCos);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kCos);
|
||||
EXPECT_EQ(result->ReturnType(), f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 1u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), f32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchOpenType) {
|
||||
TEST_F(BuiltinTableTest, MatchOpenType) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kClamp, {f32, f32, f32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kClamp, {f32, f32, f32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kClamp);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kClamp);
|
||||
EXPECT_EQ(result->ReturnType(), f32);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), f32);
|
||||
EXPECT_EQ(result->Parameters()[1]->Type(), f32);
|
||||
EXPECT_EQ(result->Parameters()[2]->Type(), f32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchOpenType) {
|
||||
TEST_F(BuiltinTableTest, MismatchOpenType) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kClamp, {f32, u32, f32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kClamp, {f32, u32, f32}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchOpenSizeVector) {
|
||||
TEST_F(BuiltinTableTest, MatchOpenSizeVector) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(f32, 2);
|
||||
auto* result = table->Lookup(IntrinsicType::kClamp,
|
||||
auto* result = table->Lookup(BuiltinType::kClamp,
|
||||
{vec2_f32, vec2_f32, vec2_f32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kClamp);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kClamp);
|
||||
EXPECT_EQ(result->ReturnType(), vec2_f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 3u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), vec2_f32);
|
||||
|
@ -476,45 +465,44 @@ TEST_F(IntrinsicTableTest, MatchOpenSizeVector) {
|
|||
EXPECT_EQ(result->Parameters()[2]->Type(), vec2_f32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchOpenSizeVector) {
|
||||
TEST_F(BuiltinTableTest, MismatchOpenSizeVector) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* u32 = create<sem::U32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(f32, 2);
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kClamp, {vec2_f32, u32, vec2_f32}, Source{});
|
||||
table->Lookup(BuiltinType::kClamp, {vec2_f32, u32, vec2_f32}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MatchOpenSizeMatrix) {
|
||||
TEST_F(BuiltinTableTest, MatchOpenSizeMatrix) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* vec3_f32 = create<sem::Vector>(f32, 3);
|
||||
auto* mat3_f32 = create<sem::Matrix>(vec3_f32, 3);
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kDeterminant, {mat3_f32}, Source{});
|
||||
auto* result = table->Lookup(BuiltinType::kDeterminant, {mat3_f32}, Source{});
|
||||
ASSERT_NE(result, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
EXPECT_EQ(result->Type(), IntrinsicType::kDeterminant);
|
||||
EXPECT_EQ(result->Type(), BuiltinType::kDeterminant);
|
||||
EXPECT_EQ(result->ReturnType(), f32);
|
||||
ASSERT_EQ(result->Parameters().size(), 1u);
|
||||
EXPECT_EQ(result->Parameters()[0]->Type(), mat3_f32);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, MismatchOpenSizeMatrix) {
|
||||
TEST_F(BuiltinTableTest, MismatchOpenSizeMatrix) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(f32, 2);
|
||||
auto* mat3x2_f32 = create<sem::Matrix>(vec2_f32, 3);
|
||||
auto* result =
|
||||
table->Lookup(IntrinsicType::kDeterminant, {mat3x2_f32}, Source{});
|
||||
table->Lookup(BuiltinType::kDeterminant, {mat3x2_f32}, Source{});
|
||||
ASSERT_EQ(result, nullptr);
|
||||
ASSERT_THAT(Diagnostics().str(), HasSubstr("no matching call"));
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, OverloadOrderByNumberOfParameters) {
|
||||
TEST_F(BuiltinTableTest, OverloadOrderByNumberOfParameters) {
|
||||
// None of the arguments match, so expect the overloads with 2 parameters to
|
||||
// come first
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
table->Lookup(IntrinsicType::kTextureDimensions, {bool_, bool_}, Source{});
|
||||
table->Lookup(BuiltinType::kTextureDimensions, {bool_, bool_}, Source{});
|
||||
ASSERT_EQ(Diagnostics().str(),
|
||||
R"(error: no matching call to textureDimensions(bool, bool)
|
||||
|
||||
|
@ -549,10 +537,10 @@ TEST_F(IntrinsicTableTest, OverloadOrderByNumberOfParameters) {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, OverloadOrderByMatchingParameter) {
|
||||
TEST_F(BuiltinTableTest, OverloadOrderByMatchingParameter) {
|
||||
auto* tex = create<sem::DepthTexture>(ast::TextureDimension::k2d);
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
table->Lookup(IntrinsicType::kTextureDimensions, {tex, bool_}, Source{});
|
||||
table->Lookup(BuiltinType::kTextureDimensions, {tex, bool_}, Source{});
|
||||
ASSERT_EQ(
|
||||
Diagnostics().str(),
|
||||
R"(error: no matching call to textureDimensions(texture_depth_2d, bool)
|
||||
|
@ -588,18 +576,18 @@ TEST_F(IntrinsicTableTest, OverloadOrderByMatchingParameter) {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicTableTest, SameOverloadReturnsSameIntrinsicPointer) {
|
||||
TEST_F(BuiltinTableTest, SameOverloadReturnsSameBuiltinPointer) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* vec2_f32 = create<sem::Vector>(create<sem::F32>(), 2);
|
||||
auto* bool_ = create<sem::Bool>();
|
||||
auto* a = table->Lookup(IntrinsicType::kSelect, {f32, f32, bool_}, Source{});
|
||||
auto* a = table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
|
||||
ASSERT_NE(a, nullptr) << Diagnostics().str();
|
||||
|
||||
auto* b = table->Lookup(IntrinsicType::kSelect, {f32, f32, bool_}, Source{});
|
||||
auto* b = table->Lookup(BuiltinType::kSelect, {f32, f32, bool_}, Source{});
|
||||
ASSERT_NE(b, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
||||
|
||||
auto* c = table->Lookup(IntrinsicType::kSelect, {vec2_f32, vec2_f32, bool_},
|
||||
auto* c = table->Lookup(BuiltinType::kSelect, {vec2_f32, vec2_f32, bool_},
|
||||
Source{});
|
||||
ASSERT_NE(c, nullptr) << Diagnostics().str();
|
||||
ASSERT_EQ(Diagnostics().str(), "");
|
|
@ -13,9 +13,9 @@
|
|||
// limitations under the License.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// WGSL intrinsic definition file //
|
||||
// WGSL builtin definition file //
|
||||
// //
|
||||
// This file is used to generate parts of the Tint IntrinsicTable, various //
|
||||
// This file is used to generate parts of the Tint BuiltinTable, various //
|
||||
// enum definition files, as well as test .wgsl files. //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -134,10 +134,10 @@ match function_private_workgroup: function | private | workgroup
|
|||
match workgroup_or_storage: workgroup | storage
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Intrinsic Functions //
|
||||
// Builtin Functions //
|
||||
// //
|
||||
// The intrinsic function declarations below declare all the built-in //
|
||||
// functions supported by the WGSL language. This intrinsic definition //
|
||||
// The builtin function declarations below declare all the built-in //
|
||||
// functions supported by the WGSL language. This builtin definition //
|
||||
// language supports simple static-type function declarations, as well as //
|
||||
// single overload declarations that can match a number of different //
|
||||
// argument types via the use of 'open-types' and 'open-numbers'. //
|
||||
|
@ -150,7 +150,7 @@ match workgroup_or_storage: workgroup | storage
|
|||
// parameter of type 'f32' and returns a 'bool'. //
|
||||
// //
|
||||
// An 'open-type' can be thought as a template type that is determined by the //
|
||||
// arguments to the intrinsic. //
|
||||
// arguments to the builtin. //
|
||||
// //
|
||||
// * Open-type example without constraint: //
|
||||
// //
|
||||
|
@ -170,7 +170,7 @@ match workgroup_or_storage: workgroup | storage
|
|||
// same argument type. //
|
||||
// //
|
||||
// Similarly an 'open-number' can be thought as a template number or //
|
||||
// enumerator that is determined by the arguments to the intrinsic. //
|
||||
// enumerator that is determined by the arguments to the builtin. //
|
||||
// //
|
||||
// * Open-number example: //
|
||||
// //
|
||||
|
@ -239,7 +239,7 @@ match workgroup_or_storage: workgroup | storage
|
|||
// fn F(USAGE : f32) //
|
||||
// - Single parameter with name USAGE. //
|
||||
// Note: Parameter names are used by Tint to infer parameter order for //
|
||||
// some intrinsic functions //
|
||||
// some builtin functions //
|
||||
// //
|
||||
// fn F<T>(T) //
|
||||
// - Single parameter of unconstrained open-type T (any type) //
|
|
@ -785,7 +785,7 @@ void Inspector::GenerateSamplerTargets() {
|
|||
continue;
|
||||
}
|
||||
|
||||
auto* i = call->Target()->As<sem::Intrinsic>();
|
||||
auto* i = call->Target()->As<sem::Builtin>();
|
||||
if (!i) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_INTRINSIC_TABLE_H_
|
||||
#define SRC_INTRINSIC_TABLE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "src/sem/intrinsic.h"
|
||||
|
||||
namespace tint {
|
||||
|
||||
// Forward declarations
|
||||
class ProgramBuilder;
|
||||
|
||||
/// IntrinsicTable is a lookup table of all the WGSL intrinsic functions
|
||||
class IntrinsicTable {
|
||||
public:
|
||||
/// @param builder the program builder
|
||||
/// @return a pointer to a newly created IntrinsicTable
|
||||
static std::unique_ptr<IntrinsicTable> Create(ProgramBuilder& builder);
|
||||
|
||||
/// Destructor
|
||||
virtual ~IntrinsicTable();
|
||||
|
||||
/// Lookup looks for the intrinsic overload with the given signature, raising
|
||||
/// an error diagnostic if the intrinsic was not found.
|
||||
/// @param type the intrinsic type
|
||||
/// @param args the argument types passed to the intrinsic function
|
||||
/// @param source the source of the intrinsic call
|
||||
/// @return the semantic intrinsic if found, otherwise nullptr
|
||||
virtual const sem::Intrinsic* Lookup(
|
||||
sem::IntrinsicType type,
|
||||
const std::vector<const sem::Type*>& args,
|
||||
const Source& source) = 0;
|
||||
};
|
||||
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_INTRINSIC_TABLE_H_
|
|
@ -33,8 +33,8 @@
|
|||
#include "src/ast/switch_statement.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/ast/variable_decl_statement.h"
|
||||
#include "src/sem/builtin_type.h"
|
||||
#include "src/sem/depth_texture_type.h"
|
||||
#include "src/sem/intrinsic_type.h"
|
||||
#include "src/sem/sampled_texture_type.h"
|
||||
|
||||
// Terms:
|
||||
|
@ -437,38 +437,38 @@ std::string GetGlslStd450FuncName(uint32_t ext_opcode) {
|
|||
return "";
|
||||
}
|
||||
|
||||
// Returns the WGSL standard library function intrinsic for the
|
||||
// given instruction, or sem::IntrinsicType::kNone
|
||||
sem::IntrinsicType GetIntrinsic(SpvOp opcode) {
|
||||
// Returns the WGSL standard library function builtin for the
|
||||
// given instruction, or sem::BuiltinType::kNone
|
||||
sem::BuiltinType GetBuiltin(SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpBitCount:
|
||||
return sem::IntrinsicType::kCountOneBits;
|
||||
return sem::BuiltinType::kCountOneBits;
|
||||
case SpvOpBitReverse:
|
||||
return sem::IntrinsicType::kReverseBits;
|
||||
return sem::BuiltinType::kReverseBits;
|
||||
case SpvOpDot:
|
||||
return sem::IntrinsicType::kDot;
|
||||
return sem::BuiltinType::kDot;
|
||||
case SpvOpDPdx:
|
||||
return sem::IntrinsicType::kDpdx;
|
||||
return sem::BuiltinType::kDpdx;
|
||||
case SpvOpDPdy:
|
||||
return sem::IntrinsicType::kDpdy;
|
||||
return sem::BuiltinType::kDpdy;
|
||||
case SpvOpFwidth:
|
||||
return sem::IntrinsicType::kFwidth;
|
||||
return sem::BuiltinType::kFwidth;
|
||||
case SpvOpDPdxFine:
|
||||
return sem::IntrinsicType::kDpdxFine;
|
||||
return sem::BuiltinType::kDpdxFine;
|
||||
case SpvOpDPdyFine:
|
||||
return sem::IntrinsicType::kDpdyFine;
|
||||
return sem::BuiltinType::kDpdyFine;
|
||||
case SpvOpFwidthFine:
|
||||
return sem::IntrinsicType::kFwidthFine;
|
||||
return sem::BuiltinType::kFwidthFine;
|
||||
case SpvOpDPdxCoarse:
|
||||
return sem::IntrinsicType::kDpdxCoarse;
|
||||
return sem::BuiltinType::kDpdxCoarse;
|
||||
case SpvOpDPdyCoarse:
|
||||
return sem::IntrinsicType::kDpdyCoarse;
|
||||
return sem::BuiltinType::kDpdyCoarse;
|
||||
case SpvOpFwidthCoarse:
|
||||
return sem::IntrinsicType::kFwidthCoarse;
|
||||
return sem::BuiltinType::kFwidthCoarse;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return sem::IntrinsicType::kNone;
|
||||
return sem::BuiltinType::kNone;
|
||||
}
|
||||
|
||||
// @param opcode a SPIR-V opcode
|
||||
|
@ -3888,9 +3888,9 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
|
|||
std::move(params))};
|
||||
}
|
||||
|
||||
const auto intrinsic = GetIntrinsic(opcode);
|
||||
if (intrinsic != sem::IntrinsicType::kNone) {
|
||||
return MakeIntrinsicCall(inst);
|
||||
const auto builtin = GetBuiltin(opcode);
|
||||
if (builtin != sem::BuiltinType::kNone) {
|
||||
return MakeBuiltinCall(inst);
|
||||
}
|
||||
|
||||
if (opcode == SpvOpFMod) {
|
||||
|
@ -5081,10 +5081,10 @@ bool FunctionEmitter::EmitControlBarrier(
|
|||
return true;
|
||||
}
|
||||
|
||||
TypedExpression FunctionEmitter::MakeIntrinsicCall(
|
||||
TypedExpression FunctionEmitter::MakeBuiltinCall(
|
||||
const spvtools::opt::Instruction& inst) {
|
||||
const auto intrinsic = GetIntrinsic(inst.opcode());
|
||||
auto* name = sem::str(intrinsic);
|
||||
const auto builtin = GetBuiltin(inst.opcode());
|
||||
auto* name = sem::str(builtin);
|
||||
auto* ident = create<ast::IdentifierExpression>(
|
||||
Source{}, builder_.Symbols().Register(name));
|
||||
|
||||
|
@ -5864,7 +5864,7 @@ TypedExpression FunctionEmitter::MakeArrayLength(
|
|||
auto* member_access = create<ast::MemberAccessorExpression>(
|
||||
Source{}, member_expr.expr, member_ident);
|
||||
|
||||
// Generate the intrinsic function call.
|
||||
// Generate the builtin function call.
|
||||
auto* call_expr =
|
||||
builder_.Call(Source{}, "arrayLength", builder_.AddressOf(member_access));
|
||||
|
||||
|
|
|
@ -995,17 +995,17 @@ class FunctionEmitter {
|
|||
/// @returns false if emission failed
|
||||
bool EmitFunctionCall(const spvtools::opt::Instruction& inst);
|
||||
|
||||
/// Emits a control barrier intrinsic. On failure, emits a diagnostic and
|
||||
/// Emits a control barrier builtin. On failure, emits a diagnostic and
|
||||
/// returns false.
|
||||
/// @param inst the SPIR-V control barrier instruction
|
||||
/// @returns false if emission failed
|
||||
bool EmitControlBarrier(const spvtools::opt::Instruction& inst);
|
||||
|
||||
/// Returns an expression for a SPIR-V instruction that maps to a WGSL
|
||||
/// intrinsic function call.
|
||||
/// builtin function call.
|
||||
/// @param inst the SPIR-V instruction
|
||||
/// @returns an expression
|
||||
TypedExpression MakeIntrinsicCall(const spvtools::opt::Instruction& inst);
|
||||
TypedExpression MakeBuiltinCall(const spvtools::opt::Instruction& inst);
|
||||
|
||||
/// Returns an expression for a SPIR-V OpArrayLength instruction.
|
||||
/// @param inst the SPIR-V instruction
|
||||
|
|
|
@ -935,11 +935,11 @@ TEST_F(SpvBinaryArithTestBasic, OuterProduct) {
|
|||
<< got;
|
||||
}
|
||||
|
||||
struct IntrinsicData {
|
||||
struct BuiltinData {
|
||||
const std::string spirv;
|
||||
const std::string wgsl;
|
||||
};
|
||||
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
|
||||
inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
|
||||
out << "OpData{" << data.spirv << "," << data.wgsl << "}";
|
||||
return out;
|
||||
}
|
||||
|
@ -955,10 +955,10 @@ inline std::ostream& operator<<(std::ostream& out, ArgAndTypeData data) {
|
|||
}
|
||||
|
||||
using SpvBinaryDerivativeTest = SpvParserTestBase<
|
||||
::testing::TestWithParam<std::tuple<IntrinsicData, ArgAndTypeData>>>;
|
||||
::testing::TestWithParam<std::tuple<BuiltinData, ArgAndTypeData>>>;
|
||||
|
||||
TEST_P(SpvBinaryDerivativeTest, Derivatives) {
|
||||
auto& intrinsic = std::get<0>(GetParam());
|
||||
auto& builtin = std::get<0>(GetParam());
|
||||
auto& arg = std::get<1>(GetParam());
|
||||
|
||||
const auto assembly = R"(
|
||||
|
@ -968,7 +968,7 @@ TEST_P(SpvBinaryDerivativeTest, Derivatives) {
|
|||
%entry = OpLabel
|
||||
%1 = OpCopyObject %)" +
|
||||
arg.spirv_type + " %" + arg.spirv_arg + R"(
|
||||
%2 = )" + intrinsic.spirv +
|
||||
%2 = )" + builtin.spirv +
|
||||
" %" + arg.spirv_type + R"( %1
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
@ -979,24 +979,24 @@ TEST_P(SpvBinaryDerivativeTest, Derivatives) {
|
|||
auto fe = p->function_emitter(100);
|
||||
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||
auto ast_body = fe.ast_body();
|
||||
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
||||
HasSubstr("let x_2 : " + arg.ast_type + " = " + intrinsic.wgsl +
|
||||
"(x_1);"));
|
||||
EXPECT_THAT(
|
||||
test::ToString(p->program(), ast_body),
|
||||
HasSubstr("let x_2 : " + arg.ast_type + " = " + builtin.wgsl + "(x_1);"));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
SpvBinaryDerivativeTest,
|
||||
SpvBinaryDerivativeTest,
|
||||
testing::Combine(
|
||||
::testing::Values(IntrinsicData{"OpDPdx", "dpdx"},
|
||||
IntrinsicData{"OpDPdy", "dpdy"},
|
||||
IntrinsicData{"OpFwidth", "fwidth"},
|
||||
IntrinsicData{"OpDPdxFine", "dpdxFine"},
|
||||
IntrinsicData{"OpDPdyFine", "dpdyFine"},
|
||||
IntrinsicData{"OpFwidthFine", "fwidthFine"},
|
||||
IntrinsicData{"OpDPdxCoarse", "dpdxCoarse"},
|
||||
IntrinsicData{"OpDPdyCoarse", "dpdyCoarse"},
|
||||
IntrinsicData{"OpFwidthCoarse", "fwidthCoarse"}),
|
||||
::testing::Values(BuiltinData{"OpDPdx", "dpdx"},
|
||||
BuiltinData{"OpDPdy", "dpdy"},
|
||||
BuiltinData{"OpFwidth", "fwidth"},
|
||||
BuiltinData{"OpDPdxFine", "dpdxFine"},
|
||||
BuiltinData{"OpDPdyFine", "dpdyFine"},
|
||||
BuiltinData{"OpFwidthFine", "fwidthFine"},
|
||||
BuiltinData{"OpDPdxCoarse", "dpdxCoarse"},
|
||||
BuiltinData{"OpDPdyCoarse", "dpdyCoarse"},
|
||||
BuiltinData{"OpFwidthCoarse", "fwidthCoarse"}),
|
||||
::testing::Values(
|
||||
ArgAndTypeData{"float", "float_50", "f32"},
|
||||
ArgAndTypeData{"v2float", "v2float_50_60", "vec2<f32>"},
|
||||
|
|
|
@ -74,9 +74,9 @@ TEST_F(SpvParserTest, WorkgroupBarrier) {
|
|||
EXPECT_EQ(call->expr->args.size(), 0u);
|
||||
auto* sem_call = program.Sem().Get(call->expr);
|
||||
ASSERT_NE(sem_call, nullptr);
|
||||
auto* intrinsic = sem_call->Target()->As<sem::Intrinsic>();
|
||||
ASSERT_NE(intrinsic, nullptr);
|
||||
EXPECT_EQ(intrinsic->Type(), sem::IntrinsicType::kWorkgroupBarrier);
|
||||
auto* builtin = sem_call->Target()->As<sem::Builtin>();
|
||||
ASSERT_NE(builtin, nullptr);
|
||||
EXPECT_EQ(builtin->Type(), sem::BuiltinType::kWorkgroupBarrier);
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest, StorageBarrier) {
|
||||
|
@ -108,9 +108,9 @@ TEST_F(SpvParserTest, StorageBarrier) {
|
|||
EXPECT_EQ(call->expr->args.size(), 0u);
|
||||
auto* sem_call = program.Sem().Get(call->expr);
|
||||
ASSERT_NE(sem_call, nullptr);
|
||||
auto* intrinsic = sem_call->Target()->As<sem::Intrinsic>();
|
||||
ASSERT_NE(intrinsic, nullptr);
|
||||
EXPECT_EQ(intrinsic->Type(), sem::IntrinsicType::kStorageBarrier);
|
||||
auto* builtin = sem_call->Target()->As<sem::Builtin>();
|
||||
ASSERT_NE(builtin, nullptr);
|
||||
EXPECT_EQ(builtin->Type(), sem::BuiltinType::kStorageBarrier);
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest, ErrBarrierInvalidExecution) {
|
||||
|
|
|
@ -114,7 +114,7 @@ fn f() { a = 1 }
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplErrorTest, AssignmentStmtInvalidLHS_IntrinsicFunctionName) {
|
||||
TEST_F(ParserImplErrorTest, AssignmentStmtInvalidLHS_BuiltinFunctionName) {
|
||||
EXPECT("normalize = 5;",
|
||||
R"(test.wgsl:1:1 error: statement found outside of function body
|
||||
normalize = 5;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,16 +12,16 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/intrinsic_texture_helper_test.h"
|
||||
#include "src/ast/builtin_texture_helper_test.h"
|
||||
#include "src/resolver/resolver_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace resolver {
|
||||
namespace {
|
||||
|
||||
using ResolverIntrinsicValidationTest = ResolverTest;
|
||||
using ResolverBuiltinValidationTest = ResolverTest;
|
||||
|
||||
TEST_F(ResolverIntrinsicValidationTest,
|
||||
TEST_F(ResolverBuiltinValidationTest,
|
||||
FunctionTypeMustMatchReturnStatementType_void_fail) {
|
||||
// fn func { return workgroupBarrier(); }
|
||||
Func("func", {}, ty.void_(),
|
||||
|
@ -30,12 +30,11 @@ TEST_F(ResolverIntrinsicValidationTest,
|
|||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
"12:34 error: intrinsic 'workgroupBarrier' does not return a value");
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: builtin 'workgroupBarrier' does not return a value");
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageDirect) {
|
||||
TEST_F(ResolverBuiltinValidationTest, InvalidPipelineStageDirect) {
|
||||
// @stage(compute) @workgroup_size(1) fn func { return dpdx(1.0); }
|
||||
|
||||
auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"),
|
||||
|
@ -49,7 +48,7 @@ TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageDirect) {
|
|||
"3:4 error: built-in cannot be used by compute pipeline stage");
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageIndirect) {
|
||||
TEST_F(ResolverBuiltinValidationTest, InvalidPipelineStageIndirect) {
|
||||
// fn f0 { return dpdx(1.0); }
|
||||
// fn f1 { f0(); }
|
||||
// fn f2 { f1(); }
|
||||
|
@ -75,7 +74,7 @@ TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageIndirect) {
|
|||
7:8 note: called by entry point 'main')");
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsFunction) {
|
||||
TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsFunction) {
|
||||
Func(Source{{12, 34}}, "mix", {}, ty.i32(), {});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
@ -84,7 +83,7 @@ TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsFunction) {
|
|||
R"(12:34 error: 'mix' is a builtin and cannot be redeclared as a function)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsGlobalLet) {
|
||||
TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsGlobalLet) {
|
||||
GlobalConst(Source{{12, 34}}, "mix", ty.i32(), Expr(1));
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
@ -93,7 +92,7 @@ TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsGlobalLet) {
|
|||
R"(12:34 error: 'mix' is a builtin and cannot be redeclared as a module-scope let)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsGlobalVar) {
|
||||
TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsGlobalVar) {
|
||||
Global(Source{{12, 34}}, "mix", ty.i32(), Expr(1),
|
||||
ast::StorageClass::kPrivate);
|
||||
|
||||
|
@ -103,7 +102,7 @@ TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsGlobalVar) {
|
|||
R"(12:34 error: 'mix' is a builtin and cannot be redeclared as a module-scope var)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsAlias) {
|
||||
TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsAlias) {
|
||||
Alias(Source{{12, 34}}, "mix", ty.i32());
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
@ -112,7 +111,7 @@ TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsAlias) {
|
|||
R"(12:34 error: 'mix' is a builtin and cannot be redeclared as an alias)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsStruct) {
|
||||
TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsStruct) {
|
||||
Structure(Source{{12, 34}}, "mix", {Member("m", ty.i32())});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
@ -123,10 +122,10 @@ TEST_F(ResolverIntrinsicValidationTest, IntrinsicRedeclaredAsStruct) {
|
|||
|
||||
namespace texture_constexpr_args {
|
||||
|
||||
using TextureOverloadCase = ast::intrinsic::test::TextureOverloadCase;
|
||||
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
|
||||
using TextureKind = ast::intrinsic::test::TextureKind;
|
||||
using TextureDataType = ast::intrinsic::test::TextureDataType;
|
||||
using TextureOverloadCase = ast::builtin::test::TextureOverloadCase;
|
||||
using ValidTextureOverload = ast::builtin::test::ValidTextureOverload;
|
||||
using TextureKind = ast::builtin::test::TextureKind;
|
||||
using TextureDataType = ast::builtin::test::TextureDataType;
|
||||
using u32 = ProgramBuilder::u32;
|
||||
using i32 = ProgramBuilder::i32;
|
||||
using f32 = ProgramBuilder::f32;
|
||||
|
@ -229,10 +228,10 @@ static std::ostream& operator<<(std::ostream& out, Constexpr expr) {
|
|||
return out;
|
||||
}
|
||||
|
||||
using IntrinsicTextureConstExprArgValidationTest = ResolverTestWithParam<
|
||||
using BuiltinTextureConstExprArgValidationTest = ResolverTestWithParam<
|
||||
std::tuple<TextureOverloadCase, Parameter, Constexpr>>;
|
||||
|
||||
TEST_P(IntrinsicTextureConstExprArgValidationTest, Immediate) {
|
||||
TEST_P(BuiltinTextureConstExprArgValidationTest, Immediate) {
|
||||
auto& p = GetParam();
|
||||
auto overload = std::get<0>(p);
|
||||
auto param = std::get<1>(p);
|
||||
|
@ -255,7 +254,7 @@ TEST_P(IntrinsicTextureConstExprArgValidationTest, Immediate) {
|
|||
|
||||
arg_to_replace = expr(Source{{12, 34}}, *this);
|
||||
|
||||
// Call the intrinsic with the constexpr argument replaced
|
||||
// Call the builtin with the constexpr argument replaced
|
||||
Func("func", {}, ty.void_(), {CallStmt(Call(overload.function, args))},
|
||||
{Stage(ast::PipelineStage::kFragment)});
|
||||
|
||||
|
@ -279,7 +278,7 @@ TEST_P(IntrinsicTextureConstExprArgValidationTest, Immediate) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_P(IntrinsicTextureConstExprArgValidationTest, GlobalConst) {
|
||||
TEST_P(BuiltinTextureConstExprArgValidationTest, GlobalConst) {
|
||||
auto& p = GetParam();
|
||||
auto overload = std::get<0>(p);
|
||||
auto param = std::get<1>(p);
|
||||
|
@ -302,7 +301,7 @@ TEST_P(IntrinsicTextureConstExprArgValidationTest, GlobalConst) {
|
|||
|
||||
arg_to_replace = Expr(Source{{12, 34}}, "G");
|
||||
|
||||
// Call the intrinsic with the constexpr argument replaced
|
||||
// Call the builtin with the constexpr argument replaced
|
||||
Func("func", {}, ty.void_(), {CallStmt(Call(overload.function, args))},
|
||||
{Stage(ast::PipelineStage::kFragment)});
|
||||
|
||||
|
@ -315,7 +314,7 @@ TEST_P(IntrinsicTextureConstExprArgValidationTest, GlobalConst) {
|
|||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Offset2D,
|
||||
IntrinsicTextureConstExprArgValidationTest,
|
||||
BuiltinTextureConstExprArgValidationTest,
|
||||
testing::Combine(
|
||||
testing::ValuesIn(TextureCases({
|
||||
ValidTextureOverload::kSample2dOffsetF32,
|
||||
|
@ -349,7 +348,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Offset3D,
|
||||
IntrinsicTextureConstExprArgValidationTest,
|
||||
BuiltinTextureConstExprArgValidationTest,
|
||||
testing::Combine(
|
||||
testing::ValuesIn(TextureCases({
|
||||
ValidTextureOverload::kSample3dOffsetF32,
|
||||
|
@ -377,7 +376,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Component,
|
||||
IntrinsicTextureConstExprArgValidationTest,
|
||||
BuiltinTextureConstExprArgValidationTest,
|
||||
testing::Combine(
|
||||
testing::ValuesIn(
|
||||
TextureCases({ValidTextureOverload::kGather2dF32,
|
|
@ -24,7 +24,7 @@
|
|||
#include "src/ast/fallthrough_statement.h"
|
||||
#include "src/ast/traverse_expressions.h"
|
||||
#include "src/scope_stack.h"
|
||||
#include "src/sem/intrinsic.h"
|
||||
#include "src/sem/builtin.h"
|
||||
#include "src/utils/defer.h"
|
||||
#include "src/utils/map.h"
|
||||
#include "src/utils/scoped_assignment.h"
|
||||
|
@ -297,7 +297,7 @@ class DependencyScanner {
|
|||
if (auto* ident = expr->As<ast::IdentifierExpression>()) {
|
||||
auto* node = scope_stack_.Get(ident->symbol);
|
||||
if (node == nullptr) {
|
||||
if (!IsIntrinsic(ident->symbol)) {
|
||||
if (!IsBuiltin(ident->symbol)) {
|
||||
UnknownSymbol(ident->symbol, ident->source, "identifier");
|
||||
}
|
||||
return ast::TraverseAction::Descend;
|
||||
|
@ -313,7 +313,7 @@ class DependencyScanner {
|
|||
}
|
||||
if (auto* call = expr->As<ast::CallExpression>()) {
|
||||
if (call->target.name) {
|
||||
if (!IsIntrinsic(call->target.name->symbol)) {
|
||||
if (!IsBuiltin(call->target.name->symbol)) {
|
||||
AddGlobalDependency(call->target.name,
|
||||
call->target.name->symbol, "function",
|
||||
"calls");
|
||||
|
@ -436,10 +436,10 @@ class DependencyScanner {
|
|||
}
|
||||
}
|
||||
|
||||
/// @returns true if `name` is the name of an intrinsic function
|
||||
bool IsIntrinsic(Symbol name) const {
|
||||
return sem::ParseIntrinsicType(symbols_.NameFor(name)) !=
|
||||
sem::IntrinsicType::kNone;
|
||||
/// @returns true if `name` is the name of a builtin function
|
||||
bool IsBuiltin(Symbol name) const {
|
||||
return sem::ParseBuiltinType(symbols_.NameFor(name)) !=
|
||||
sem::BuiltinType::kNone;
|
||||
}
|
||||
|
||||
/// Appends an error to the diagnostics that the given symbol cannot be
|
||||
|
|
|
@ -84,7 +84,7 @@ namespace resolver {
|
|||
Resolver::Resolver(ProgramBuilder* builder)
|
||||
: builder_(builder),
|
||||
diagnostics_(builder->Diagnostics()),
|
||||
intrinsic_table_(IntrinsicTable::Create(*builder)) {}
|
||||
builtin_table_(BuiltinTable::Create(*builder)) {}
|
||||
|
||||
Resolver::~Resolver() = default;
|
||||
|
||||
|
@ -1354,10 +1354,9 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
}
|
||||
|
||||
auto name = builder_->Symbols().NameFor(ident->symbol);
|
||||
auto intrinsic_type = sem::ParseIntrinsicType(name);
|
||||
if (intrinsic_type != sem::IntrinsicType::kNone) {
|
||||
return IntrinsicCall(expr, intrinsic_type, std::move(args),
|
||||
std::move(arg_tys));
|
||||
auto builtin_type = sem::ParseBuiltinType(name);
|
||||
if (builtin_type != sem::BuiltinType::kNone) {
|
||||
return BuiltinCall(expr, builtin_type, std::move(args), std::move(arg_tys));
|
||||
}
|
||||
|
||||
TINT_ICE(Resolver, diagnostics_)
|
||||
|
@ -1368,36 +1367,35 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
sem::Call* Resolver::IntrinsicCall(
|
||||
const ast::CallExpression* expr,
|
||||
sem::IntrinsicType intrinsic_type,
|
||||
const std::vector<const sem::Expression*> args,
|
||||
const std::vector<const sem::Type*> arg_tys) {
|
||||
auto* intrinsic = intrinsic_table_->Lookup(intrinsic_type, std::move(arg_tys),
|
||||
expr->source);
|
||||
if (!intrinsic) {
|
||||
sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
||||
sem::BuiltinType builtin_type,
|
||||
const std::vector<const sem::Expression*> args,
|
||||
const std::vector<const sem::Type*> arg_tys) {
|
||||
auto* builtin =
|
||||
builtin_table_->Lookup(builtin_type, std::move(arg_tys), expr->source);
|
||||
if (!builtin) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (intrinsic->IsDeprecated()) {
|
||||
AddWarning("use of deprecated intrinsic", expr->source);
|
||||
if (builtin->IsDeprecated()) {
|
||||
AddWarning("use of deprecated builtin", expr->source);
|
||||
}
|
||||
|
||||
auto* call = builder_->create<sem::Call>(expr, intrinsic, std::move(args),
|
||||
auto* call = builder_->create<sem::Call>(expr, builtin, std::move(args),
|
||||
current_statement_, sem::Constant{});
|
||||
|
||||
current_function_->AddDirectlyCalledIntrinsic(intrinsic);
|
||||
current_function_->AddDirectlyCalledBuiltin(builtin);
|
||||
|
||||
if (IsTextureIntrinsic(intrinsic_type)) {
|
||||
if (!ValidateTextureIntrinsicFunction(call)) {
|
||||
if (IsTextureBuiltin(builtin_type)) {
|
||||
if (!ValidateTextureBuiltinFunction(call)) {
|
||||
return nullptr;
|
||||
}
|
||||
// Collect a texture/sampler pair for this intrinsic.
|
||||
const auto& signature = intrinsic->Signature();
|
||||
// Collect a texture/sampler pair for this builtin.
|
||||
const auto& signature = builtin->Signature();
|
||||
int texture_index = signature.IndexOf(sem::ParameterUsage::kTexture);
|
||||
if (texture_index == -1) {
|
||||
TINT_ICE(Resolver, diagnostics_)
|
||||
<< "texture intrinsic without texture parameter";
|
||||
<< "texture builtin without texture parameter";
|
||||
}
|
||||
|
||||
auto* texture = args[texture_index]->As<sem::VariableUser>()->Variable();
|
||||
|
@ -1409,7 +1407,7 @@ sem::Call* Resolver::IntrinsicCall(
|
|||
current_function_->AddTextureSamplerPair(texture, sampler);
|
||||
}
|
||||
|
||||
if (!ValidateIntrinsicCall(call)) {
|
||||
if (!ValidateBuiltinCall(call)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1662,8 +1660,8 @@ sem::Expression* Resolver::Identifier(const ast::IdentifierExpression* expr) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (IsIntrinsic(symbol)) {
|
||||
AddError("missing '(' for intrinsic call", expr->source.End());
|
||||
if (IsBuiltin(symbol)) {
|
||||
AddError("missing '(' for builtin call", expr->source.End());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -2786,9 +2784,9 @@ bool Resolver::IsHostShareable(const sem::Type* type) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Resolver::IsIntrinsic(Symbol symbol) const {
|
||||
bool Resolver::IsBuiltin(Symbol symbol) const {
|
||||
std::string name = builder_->Symbols().NameFor(symbol);
|
||||
return sem::ParseIntrinsicType(name) != sem::IntrinsicType::kNone;
|
||||
return sem::ParseBuiltinType(name) != sem::BuiltinType::kNone;
|
||||
}
|
||||
|
||||
bool Resolver::IsCallStatement(const ast::Expression* expr) const {
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "src/intrinsic_table.h"
|
||||
#include "src/builtin_table.h"
|
||||
#include "src/program_builder.h"
|
||||
#include "src/resolver/dependency_graph.h"
|
||||
#include "src/scope_stack.h"
|
||||
|
@ -59,11 +59,11 @@ namespace sem {
|
|||
class Array;
|
||||
class Atomic;
|
||||
class BlockStatement;
|
||||
class Builtin;
|
||||
class CaseStatement;
|
||||
class ElseStatement;
|
||||
class ForLoopStatement;
|
||||
class IfStatement;
|
||||
class Intrinsic;
|
||||
class LoopStatement;
|
||||
class Statement;
|
||||
class SwitchStatement;
|
||||
|
@ -191,10 +191,10 @@ class Resolver {
|
|||
const std::vector<const sem::Expression*> args,
|
||||
sem::Behaviors arg_behaviors);
|
||||
sem::Expression* Identifier(const ast::IdentifierExpression*);
|
||||
sem::Call* IntrinsicCall(const ast::CallExpression*,
|
||||
sem::IntrinsicType,
|
||||
const std::vector<const sem::Expression*> args,
|
||||
const std::vector<const sem::Type*> arg_tys);
|
||||
sem::Call* BuiltinCall(const ast::CallExpression*,
|
||||
sem::BuiltinType,
|
||||
const std::vector<const sem::Expression*> args,
|
||||
const std::vector<const sem::Type*> arg_tys);
|
||||
sem::Expression* Literal(const ast::LiteralExpression*);
|
||||
sem::Expression* MemberAccessor(const ast::MemberAccessorExpression*);
|
||||
sem::Call* TypeConversion(const ast::CallExpression* expr,
|
||||
|
@ -258,7 +258,7 @@ class Resolver {
|
|||
bool ValidateIfStatement(const sem::IfStatement* stmt);
|
||||
bool ValidateInterpolateAttribute(const ast::InterpolateAttribute* attr,
|
||||
const sem::Type* storage_type);
|
||||
bool ValidateIntrinsicCall(const sem::Call* call);
|
||||
bool ValidateBuiltinCall(const sem::Call* call);
|
||||
bool ValidateLocationAttribute(const ast::LocationAttribute* location,
|
||||
const sem::Type* type,
|
||||
std::unordered_set<uint32_t>& locations,
|
||||
|
@ -290,7 +290,7 @@ class Resolver {
|
|||
const sem::Type* type);
|
||||
bool ValidateArrayConstructorOrCast(const ast::CallExpression* ctor,
|
||||
const sem::Array* arr_type);
|
||||
bool ValidateTextureIntrinsicFunction(const sem::Call* call);
|
||||
bool ValidateTextureBuiltinFunction(const sem::Call* call);
|
||||
bool ValidateNoDuplicateAttributes(const ast::AttributeList& attributes);
|
||||
bool ValidateStorageClassLayout(const sem::Type* type,
|
||||
ast::StorageClass sc,
|
||||
|
@ -462,9 +462,8 @@ class Resolver {
|
|||
return const_cast<T*>(As<T>(sem));
|
||||
}
|
||||
|
||||
/// @returns true if the symbol is the name of an intrinsic (builtin)
|
||||
/// function.
|
||||
bool IsIntrinsic(Symbol) const;
|
||||
/// @returns true if the symbol is the name of a builtin function.
|
||||
bool IsBuiltin(Symbol) const;
|
||||
|
||||
/// @returns true if `expr` is the current CallStatement's CallExpression
|
||||
bool IsCallStatement(const ast::Expression* expr) const;
|
||||
|
@ -520,7 +519,7 @@ class Resolver {
|
|||
|
||||
ProgramBuilder* const builder_;
|
||||
diag::List& diagnostics_;
|
||||
std::unique_ptr<IntrinsicTable> const intrinsic_table_;
|
||||
std::unique_ptr<BuiltinTable> const builtin_table_;
|
||||
DependencyGraph dependencies_;
|
||||
std::vector<sem::Function*> entry_points_;
|
||||
std::unordered_map<const sem::Type*, const Source&> atomic_composite_info_;
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
#include "src/ast/assignment_statement.h"
|
||||
#include "src/ast/bitcast_expression.h"
|
||||
#include "src/ast/break_statement.h"
|
||||
#include "src/ast/builtin_texture_helper_test.h"
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/continue_statement.h"
|
||||
#include "src/ast/float_literal_expression.h"
|
||||
#include "src/ast/if_statement.h"
|
||||
#include "src/ast/intrinsic_texture_helper_test.h"
|
||||
#include "src/ast/loop_statement.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/return_statement.h"
|
||||
|
@ -535,7 +535,7 @@ TEST_F(ResolverTest, Expr_Call_WithParams) {
|
|||
EXPECT_TRUE(TypeOf(param)->Is<sem::F32>());
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Expr_Call_Intrinsic) {
|
||||
TEST_F(ResolverTest, Expr_Call_Builtin) {
|
||||
auto* call = Call("round", 2.4f);
|
||||
WrapInFunction(call);
|
||||
|
||||
|
|
|
@ -560,7 +560,7 @@ bool Resolver::ValidateVariable(const sem::Variable* var) {
|
|||
|
||||
if (var->Is<sem::GlobalVariable>()) {
|
||||
auto name = builder_->Symbols().NameFor(decl->symbol);
|
||||
if (sem::ParseIntrinsicType(name) != sem::IntrinsicType::kNone) {
|
||||
if (sem::ParseBuiltinType(name) != sem::BuiltinType::kNone) {
|
||||
auto* kind = var->Declaration()->is_const ? "let" : "var";
|
||||
AddError(
|
||||
"'" + name +
|
||||
|
@ -840,7 +840,7 @@ bool Resolver::ValidateFunction(const sem::Function* func) {
|
|||
auto* decl = func->Declaration();
|
||||
|
||||
auto name = builder_->Symbols().NameFor(decl->symbol);
|
||||
if (sem::ParseIntrinsicType(name) != sem::IntrinsicType::kNone) {
|
||||
if (sem::ParseBuiltinType(name) != sem::BuiltinType::kNone) {
|
||||
AddError(
|
||||
"'" + name + "' is a builtin and cannot be redeclared as a function",
|
||||
decl->source);
|
||||
|
@ -1369,7 +1369,7 @@ bool Resolver::ValidateIfStatement(const sem::IfStatement* stmt) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Resolver::ValidateIntrinsicCall(const sem::Call* call) {
|
||||
bool Resolver::ValidateBuiltinCall(const sem::Call* call) {
|
||||
if (call->Type()->Is<sem::Void>()) {
|
||||
bool is_call_statement = false;
|
||||
if (auto* call_stmt = As<ast::CallStatement>(call->Stmt()->Declaration())) {
|
||||
|
@ -1383,7 +1383,7 @@ bool Resolver::ValidateIntrinsicCall(const sem::Call* call) {
|
|||
// statement should be used instead.
|
||||
auto* ident = call->Declaration()->target.name;
|
||||
auto name = builder_->Symbols().NameFor(ident->symbol);
|
||||
AddError("intrinsic '" + name + "' does not return a value",
|
||||
AddError("builtin '" + name + "' does not return a value",
|
||||
call->Declaration()->source);
|
||||
return false;
|
||||
}
|
||||
|
@ -1392,14 +1392,14 @@ bool Resolver::ValidateIntrinsicCall(const sem::Call* call) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Resolver::ValidateTextureIntrinsicFunction(const sem::Call* call) {
|
||||
auto* intrinsic = call->Target()->As<sem::Intrinsic>();
|
||||
if (!intrinsic) {
|
||||
bool Resolver::ValidateTextureBuiltinFunction(const sem::Call* call) {
|
||||
auto* builtin = call->Target()->As<sem::Builtin>();
|
||||
if (!builtin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string func_name = intrinsic->str();
|
||||
auto& signature = intrinsic->Signature();
|
||||
std::string func_name = builtin->str();
|
||||
auto& signature = builtin->Signature();
|
||||
|
||||
auto check_arg_is_constexpr = [&](sem::ParameterUsage usage, int min,
|
||||
int max) {
|
||||
|
@ -1431,7 +1431,7 @@ bool Resolver::ValidateTextureIntrinsicFunction(const sem::Call* call) {
|
|||
return ast::TraverseAction::Stop;
|
||||
});
|
||||
if (is_const_expr) {
|
||||
auto vector = intrinsic->Parameters()[index]->Type()->Is<sem::Vector>();
|
||||
auto vector = builtin->Parameters()[index]->Type()->Is<sem::Vector>();
|
||||
for (size_t i = 0; i < values.Elements().size(); i++) {
|
||||
auto value = values.Elements()[i].i32;
|
||||
if (value < min || value > max) {
|
||||
|
@ -1895,12 +1895,12 @@ bool Resolver::ValidatePipelineStages() {
|
|||
}
|
||||
}
|
||||
|
||||
auto check_intrinsic_calls = [&](const sem::Function* func,
|
||||
const sem::Function* entry_point) {
|
||||
auto check_builtin_calls = [&](const sem::Function* func,
|
||||
const sem::Function* entry_point) {
|
||||
auto stage = entry_point->Declaration()->PipelineStage();
|
||||
for (auto* intrinsic : func->DirectlyCalledIntrinsics()) {
|
||||
if (!intrinsic->SupportedStages().Contains(stage)) {
|
||||
auto* call = func->FindDirectCallTo(intrinsic);
|
||||
for (auto* builtin : func->DirectlyCalledBuiltins()) {
|
||||
if (!builtin->SupportedStages().Contains(stage)) {
|
||||
auto* call = func->FindDirectCallTo(builtin);
|
||||
std::stringstream err;
|
||||
err << "built-in cannot be used by " << stage << " pipeline stage";
|
||||
AddError(err.str(), call ? call->Declaration()->source
|
||||
|
@ -1927,11 +1927,11 @@ bool Resolver::ValidatePipelineStages() {
|
|||
};
|
||||
|
||||
for (auto* entry_point : entry_points_) {
|
||||
if (!check_intrinsic_calls(entry_point, entry_point)) {
|
||||
if (!check_builtin_calls(entry_point, entry_point)) {
|
||||
return false;
|
||||
}
|
||||
for (auto* func : entry_point->TransitivelyCalledFunctions()) {
|
||||
if (!check_intrinsic_calls(func, entry_point)) {
|
||||
if (!check_builtin_calls(func, entry_point)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1974,7 +1974,7 @@ bool Resolver::ValidateArrayStrideAttribute(const ast::StrideAttribute* attr,
|
|||
|
||||
bool Resolver::ValidateAlias(const ast::Alias* alias) {
|
||||
auto name = builder_->Symbols().NameFor(alias->name);
|
||||
if (sem::ParseIntrinsicType(name) != sem::IntrinsicType::kNone) {
|
||||
if (sem::ParseBuiltinType(name) != sem::BuiltinType::kNone) {
|
||||
AddError("'" + name + "' is a builtin and cannot be redeclared as an alias",
|
||||
alias->source);
|
||||
return false;
|
||||
|
@ -1985,7 +1985,7 @@ bool Resolver::ValidateAlias(const ast::Alias* alias) {
|
|||
|
||||
bool Resolver::ValidateStructure(const sem::Struct* str) {
|
||||
auto name = builder_->Symbols().NameFor(str->Declaration()->name);
|
||||
if (sem::ParseIntrinsicType(name) != sem::IntrinsicType::kNone) {
|
||||
if (sem::ParseBuiltinType(name) != sem::BuiltinType::kNone) {
|
||||
AddError("'" + name + "' is a builtin and cannot be redeclared as a struct",
|
||||
str->Declaration()->source);
|
||||
return false;
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
#include "src/ast/assignment_statement.h"
|
||||
#include "src/ast/bitcast_expression.h"
|
||||
#include "src/ast/break_statement.h"
|
||||
#include "src/ast/builtin_texture_helper_test.h"
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/continue_statement.h"
|
||||
#include "src/ast/discard_statement.h"
|
||||
#include "src/ast/if_statement.h"
|
||||
#include "src/ast/intrinsic_texture_helper_test.h"
|
||||
#include "src/ast/loop_statement.h"
|
||||
#include "src/ast/return_statement.h"
|
||||
#include "src/ast/stage_attribute.h"
|
||||
|
@ -156,11 +156,11 @@ TEST_F(ResolverValidationTest, Expr_DontCall_Function) {
|
|||
EXPECT_EQ(r()->error(), "3:8 error: missing '(' for function call");
|
||||
}
|
||||
|
||||
TEST_F(ResolverValidationTest, Expr_DontCall_Intrinsic) {
|
||||
TEST_F(ResolverValidationTest, Expr_DontCall_Builtin) {
|
||||
WrapInFunction(Expr(Source{{{3, 3}, {3, 8}}}, "round"));
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(), "3:8 error: missing '(' for intrinsic call");
|
||||
EXPECT_EQ(r()->error(), "3:8 error: missing '(' for builtin call");
|
||||
}
|
||||
|
||||
TEST_F(ResolverValidationTest, Expr_DontCall_Type) {
|
||||
|
@ -172,8 +172,7 @@ TEST_F(ResolverValidationTest, Expr_DontCall_Type) {
|
|||
"3:8 error: missing '(' for type constructor or cast");
|
||||
}
|
||||
|
||||
TEST_F(ResolverValidationTest,
|
||||
AssignmentStmt_InvalidLHS_IntrinsicFunctionName) {
|
||||
TEST_F(ResolverValidationTest, AssignmentStmt_InvalidLHS_BuiltinFunctionName) {
|
||||
// normalize = 2;
|
||||
|
||||
auto* lhs = Expr(Source{{12, 34}}, "normalize");
|
||||
|
@ -182,7 +181,7 @@ TEST_F(ResolverValidationTest,
|
|||
WrapInFunction(assign);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(), "12:34 error: missing '(' for intrinsic call");
|
||||
EXPECT_EQ(r()->error(), "12:34 error: missing '(' for builtin call");
|
||||
}
|
||||
|
||||
TEST_F(ResolverValidationTest, UsingUndefinedVariable_Fail) {
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
// Copyright 2020 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Doxygen seems to trip over this file for some unknown reason. Disable.
|
||||
//! @cond Doxygen_Suppress
|
||||
|
||||
#include "src/sem/builtin.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/utils/to_const_ptr_vec.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::sem::Builtin);
|
||||
|
||||
namespace tint {
|
||||
namespace sem {
|
||||
|
||||
const char* Builtin::str() const {
|
||||
return sem::str(type_);
|
||||
}
|
||||
|
||||
bool IsCoarseDerivativeBuiltin(BuiltinType i) {
|
||||
return i == BuiltinType::kDpdxCoarse || i == BuiltinType::kDpdyCoarse ||
|
||||
i == BuiltinType::kFwidthCoarse;
|
||||
}
|
||||
|
||||
bool IsFineDerivativeBuiltin(BuiltinType i) {
|
||||
return i == BuiltinType::kDpdxFine || i == BuiltinType::kDpdyFine ||
|
||||
i == BuiltinType::kFwidthFine;
|
||||
}
|
||||
|
||||
bool IsDerivativeBuiltin(BuiltinType i) {
|
||||
return i == BuiltinType::kDpdx || i == BuiltinType::kDpdy ||
|
||||
i == BuiltinType::kFwidth || IsCoarseDerivativeBuiltin(i) ||
|
||||
IsFineDerivativeBuiltin(i);
|
||||
}
|
||||
|
||||
bool IsFloatClassificationBuiltin(BuiltinType i) {
|
||||
return i == BuiltinType::kIsFinite || i == BuiltinType::kIsInf ||
|
||||
i == BuiltinType::kIsNan || i == BuiltinType::kIsNormal;
|
||||
}
|
||||
|
||||
bool IsTextureBuiltin(BuiltinType i) {
|
||||
return IsImageQueryBuiltin(i) || i == BuiltinType::kTextureLoad ||
|
||||
i == BuiltinType::kTextureGather ||
|
||||
i == BuiltinType::kTextureGatherCompare ||
|
||||
i == BuiltinType::kTextureSample ||
|
||||
i == BuiltinType::kTextureSampleLevel ||
|
||||
i == BuiltinType::kTextureSampleBias ||
|
||||
i == BuiltinType::kTextureSampleCompare ||
|
||||
i == BuiltinType::kTextureSampleCompareLevel ||
|
||||
i == BuiltinType::kTextureSampleGrad ||
|
||||
i == BuiltinType::kTextureStore;
|
||||
}
|
||||
|
||||
bool IsImageQueryBuiltin(BuiltinType i) {
|
||||
return i == BuiltinType::kTextureDimensions ||
|
||||
i == BuiltinType::kTextureNumLayers ||
|
||||
i == BuiltinType::kTextureNumLevels ||
|
||||
i == BuiltinType::kTextureNumSamples;
|
||||
}
|
||||
|
||||
bool IsDataPackingBuiltin(BuiltinType i) {
|
||||
return i == BuiltinType::kPack4x8snorm || i == BuiltinType::kPack4x8unorm ||
|
||||
i == BuiltinType::kPack2x16snorm || i == BuiltinType::kPack2x16unorm ||
|
||||
i == BuiltinType::kPack2x16float;
|
||||
}
|
||||
|
||||
bool IsDataUnpackingBuiltin(BuiltinType i) {
|
||||
return i == BuiltinType::kUnpack4x8snorm ||
|
||||
i == BuiltinType::kUnpack4x8unorm ||
|
||||
i == BuiltinType::kUnpack2x16snorm ||
|
||||
i == BuiltinType::kUnpack2x16unorm ||
|
||||
i == BuiltinType::kUnpack2x16float;
|
||||
}
|
||||
|
||||
bool IsBarrierBuiltin(BuiltinType i) {
|
||||
return i == BuiltinType::kWorkgroupBarrier ||
|
||||
i == BuiltinType::kStorageBarrier;
|
||||
}
|
||||
|
||||
bool IsAtomicBuiltin(BuiltinType i) {
|
||||
return i == sem::BuiltinType::kAtomicLoad ||
|
||||
i == sem::BuiltinType::kAtomicStore ||
|
||||
i == sem::BuiltinType::kAtomicAdd ||
|
||||
i == sem::BuiltinType::kAtomicSub ||
|
||||
i == sem::BuiltinType::kAtomicMax ||
|
||||
i == sem::BuiltinType::kAtomicMin ||
|
||||
i == sem::BuiltinType::kAtomicAnd ||
|
||||
i == sem::BuiltinType::kAtomicOr ||
|
||||
i == sem::BuiltinType::kAtomicXor ||
|
||||
i == sem::BuiltinType::kAtomicExchange ||
|
||||
i == sem::BuiltinType::kAtomicCompareExchangeWeak;
|
||||
}
|
||||
|
||||
Builtin::Builtin(BuiltinType type,
|
||||
const sem::Type* return_type,
|
||||
std::vector<Parameter*> parameters,
|
||||
PipelineStageSet supported_stages,
|
||||
bool is_deprecated)
|
||||
: Base(return_type, utils::ToConstPtrVec(parameters)),
|
||||
type_(type),
|
||||
supported_stages_(supported_stages),
|
||||
is_deprecated_(is_deprecated) {
|
||||
for (auto* parameter : parameters) {
|
||||
parameter->SetOwner(this);
|
||||
}
|
||||
}
|
||||
|
||||
Builtin::~Builtin() = default;
|
||||
|
||||
bool Builtin::IsCoarseDerivative() const {
|
||||
return IsCoarseDerivativeBuiltin(type_);
|
||||
}
|
||||
|
||||
bool Builtin::IsFineDerivative() const {
|
||||
return IsFineDerivativeBuiltin(type_);
|
||||
}
|
||||
|
||||
bool Builtin::IsDerivative() const {
|
||||
return IsDerivativeBuiltin(type_);
|
||||
}
|
||||
|
||||
bool Builtin::IsFloatClassification() const {
|
||||
return IsFloatClassificationBuiltin(type_);
|
||||
}
|
||||
|
||||
bool Builtin::IsTexture() const {
|
||||
return IsTextureBuiltin(type_);
|
||||
}
|
||||
|
||||
bool Builtin::IsImageQuery() const {
|
||||
return IsImageQueryBuiltin(type_);
|
||||
}
|
||||
|
||||
bool Builtin::IsDataPacking() const {
|
||||
return IsDataPackingBuiltin(type_);
|
||||
}
|
||||
|
||||
bool Builtin::IsDataUnpacking() const {
|
||||
return IsDataUnpackingBuiltin(type_);
|
||||
}
|
||||
|
||||
bool Builtin::IsBarrier() const {
|
||||
return IsBarrierBuiltin(type_);
|
||||
}
|
||||
|
||||
bool Builtin::IsAtomic() const {
|
||||
return IsAtomicBuiltin(type_);
|
||||
}
|
||||
|
||||
} // namespace sem
|
||||
} // namespace tint
|
||||
|
||||
//! @endcond
|
|
@ -0,0 +1,173 @@
|
|||
// Copyright 2020 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_SEM_BUILTIN_H_
|
||||
#define SRC_SEM_BUILTIN_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "src/sem/builtin_type.h"
|
||||
#include "src/sem/call_target.h"
|
||||
#include "src/sem/pipeline_stage_set.h"
|
||||
#include "src/utils/hash.h"
|
||||
|
||||
namespace tint {
|
||||
namespace sem {
|
||||
|
||||
/// Determines if the given `i` is a coarse derivative
|
||||
/// @param i the builtin type
|
||||
/// @returns true if the given derivative is coarse.
|
||||
bool IsCoarseDerivativeBuiltin(BuiltinType i);
|
||||
|
||||
/// Determines if the given `i` is a fine derivative
|
||||
/// @param i the builtin type
|
||||
/// @returns true if the given derivative is fine.
|
||||
bool IsFineDerivativeBuiltin(BuiltinType i);
|
||||
|
||||
/// Determine if the given `i` is a derivative builtin
|
||||
/// @param i the builtin type
|
||||
/// @returns true if the given `i` is a derivative builtin
|
||||
bool IsDerivativeBuiltin(BuiltinType i);
|
||||
|
||||
/// Determines if the given `i` is a float classification builtin
|
||||
/// @param i the builtin type
|
||||
/// @returns true if the given `i` is a float builtin
|
||||
bool IsFloatClassificationBuiltin(BuiltinType i);
|
||||
|
||||
/// Determines if the given `i` is a texture operation builtin
|
||||
/// @param i the builtin type
|
||||
/// @returns true if the given `i` is a texture operation builtin
|
||||
bool IsTextureBuiltin(BuiltinType i);
|
||||
|
||||
/// Determines if the given `i` is a image query builtin
|
||||
/// @param i the builtin type
|
||||
/// @returns true if the given `i` is a image query builtin
|
||||
bool IsImageQueryBuiltin(BuiltinType i);
|
||||
|
||||
/// Determines if the given `i` is a data packing builtin
|
||||
/// @param i the builtin
|
||||
/// @returns true if the given `i` is a data packing builtin
|
||||
bool IsDataPackingBuiltin(BuiltinType i);
|
||||
|
||||
/// Determines if the given `i` is a data unpacking builtin
|
||||
/// @param i the builtin
|
||||
/// @returns true if the given `i` is a data unpacking builtin
|
||||
bool IsDataUnpackingBuiltin(BuiltinType i);
|
||||
|
||||
/// Determines if the given `i` is a barrier builtin
|
||||
/// @param i the builtin
|
||||
/// @returns true if the given `i` is a barrier builtin
|
||||
bool IsBarrierBuiltin(BuiltinType i);
|
||||
|
||||
/// Determines if the given `i` is a atomic builtin
|
||||
/// @param i the builtin
|
||||
/// @returns true if the given `i` is a atomic builtin
|
||||
bool IsAtomicBuiltin(BuiltinType i);
|
||||
|
||||
/// Builtin holds the semantic information for a builtin function.
|
||||
class Builtin : public Castable<Builtin, CallTarget> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param type the builtin type
|
||||
/// @param return_type the return type for the builtin call
|
||||
/// @param parameters the parameters for the builtin overload
|
||||
/// @param supported_stages the pipeline stages that this builtin can be
|
||||
/// used in
|
||||
/// @param is_deprecated true if the particular overload is considered
|
||||
/// deprecated
|
||||
Builtin(BuiltinType type,
|
||||
const sem::Type* return_type,
|
||||
std::vector<Parameter*> parameters,
|
||||
PipelineStageSet supported_stages,
|
||||
bool is_deprecated);
|
||||
|
||||
/// Destructor
|
||||
~Builtin() override;
|
||||
|
||||
/// @return the type of the builtin
|
||||
BuiltinType Type() const { return type_; }
|
||||
|
||||
/// @return the pipeline stages that this builtin can be used in
|
||||
PipelineStageSet SupportedStages() const { return supported_stages_; }
|
||||
|
||||
/// @return true if the builtin overload is considered deprecated
|
||||
bool IsDeprecated() const { return is_deprecated_; }
|
||||
|
||||
/// @returns the name of the builtin function type. The spelling, including
|
||||
/// case, matches the name in the WGSL spec.
|
||||
const char* str() const;
|
||||
|
||||
/// @returns true if builtin is a coarse derivative builtin
|
||||
bool IsCoarseDerivative() const;
|
||||
|
||||
/// @returns true if builtin is a fine a derivative builtin
|
||||
bool IsFineDerivative() const;
|
||||
|
||||
/// @returns true if builtin is a derivative builtin
|
||||
bool IsDerivative() const;
|
||||
|
||||
/// @returns true if builtin is a float builtin
|
||||
bool IsFloatClassification() const;
|
||||
|
||||
/// @returns true if builtin is a texture operation builtin
|
||||
bool IsTexture() const;
|
||||
|
||||
/// @returns true if builtin is a image query builtin
|
||||
bool IsImageQuery() const;
|
||||
|
||||
/// @returns true if builtin is a data packing builtin
|
||||
bool IsDataPacking() const;
|
||||
|
||||
/// @returns true if builtin is a data unpacking builtin
|
||||
bool IsDataUnpacking() const;
|
||||
|
||||
/// @returns true if builtin is a barrier builtin
|
||||
bool IsBarrier() const;
|
||||
|
||||
/// @returns true if builtin is a atomic builtin
|
||||
bool IsAtomic() const;
|
||||
|
||||
private:
|
||||
const BuiltinType type_;
|
||||
const PipelineStageSet supported_stages_;
|
||||
const bool is_deprecated_;
|
||||
};
|
||||
|
||||
/// Constant value used by the degrees() builtin
|
||||
static constexpr double kRadToDeg = 57.295779513082322865;
|
||||
|
||||
/// Constant value used by the radians() builtin
|
||||
static constexpr double kDegToRad = 0.017453292519943295474;
|
||||
|
||||
} // namespace sem
|
||||
} // namespace tint
|
||||
|
||||
namespace std {
|
||||
|
||||
/// Custom std::hash specialization for tint::sem::Builtin
|
||||
template <>
|
||||
class hash<tint::sem::Builtin> {
|
||||
public:
|
||||
/// @param i the Builtin to create a hash for
|
||||
/// @return the hash value
|
||||
inline std::size_t operator()(const tint::sem::Builtin& i) const {
|
||||
return tint::utils::Hash(i.Type(), i.SupportedStages(), i.ReturnType(),
|
||||
i.Parameters(), i.IsDeprecated());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // SRC_SEM_BUILTIN_H_
|
|
@ -0,0 +1,131 @@
|
|||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/sem/builtin.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace tint {
|
||||
namespace sem {
|
||||
namespace {
|
||||
|
||||
struct BuiltinData {
|
||||
const char* name;
|
||||
BuiltinType builtin;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
|
||||
out << data.name;
|
||||
return out;
|
||||
}
|
||||
|
||||
using BuiltinTypeTest = testing::TestWithParam<BuiltinData>;
|
||||
|
||||
TEST_P(BuiltinTypeTest, Parse) {
|
||||
auto param = GetParam();
|
||||
EXPECT_EQ(ParseBuiltinType(param.name), param.builtin);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
BuiltinTypeTest,
|
||||
BuiltinTypeTest,
|
||||
testing::Values(
|
||||
BuiltinData{"abs", BuiltinType::kAbs},
|
||||
BuiltinData{"acos", BuiltinType::kAcos},
|
||||
BuiltinData{"all", BuiltinType::kAll},
|
||||
BuiltinData{"any", BuiltinType::kAny},
|
||||
BuiltinData{"arrayLength", BuiltinType::kArrayLength},
|
||||
BuiltinData{"asin", BuiltinType::kAsin},
|
||||
BuiltinData{"atan", BuiltinType::kAtan},
|
||||
BuiltinData{"atan2", BuiltinType::kAtan2},
|
||||
BuiltinData{"ceil", BuiltinType::kCeil},
|
||||
BuiltinData{"clamp", BuiltinType::kClamp},
|
||||
BuiltinData{"cos", BuiltinType::kCos},
|
||||
BuiltinData{"cosh", BuiltinType::kCosh},
|
||||
BuiltinData{"countOneBits", BuiltinType::kCountOneBits},
|
||||
BuiltinData{"cross", BuiltinType::kCross},
|
||||
BuiltinData{"determinant", BuiltinType::kDeterminant},
|
||||
BuiltinData{"distance", BuiltinType::kDistance},
|
||||
BuiltinData{"dot", BuiltinType::kDot},
|
||||
BuiltinData{"dpdx", BuiltinType::kDpdx},
|
||||
BuiltinData{"dpdxCoarse", BuiltinType::kDpdxCoarse},
|
||||
BuiltinData{"dpdxFine", BuiltinType::kDpdxFine},
|
||||
BuiltinData{"dpdy", BuiltinType::kDpdy},
|
||||
BuiltinData{"dpdyCoarse", BuiltinType::kDpdyCoarse},
|
||||
BuiltinData{"dpdyFine", BuiltinType::kDpdyFine},
|
||||
BuiltinData{"exp", BuiltinType::kExp},
|
||||
BuiltinData{"exp2", BuiltinType::kExp2},
|
||||
BuiltinData{"faceForward", BuiltinType::kFaceForward},
|
||||
BuiltinData{"floor", BuiltinType::kFloor},
|
||||
BuiltinData{"fma", BuiltinType::kFma},
|
||||
BuiltinData{"fract", BuiltinType::kFract},
|
||||
BuiltinData{"frexp", BuiltinType::kFrexp},
|
||||
BuiltinData{"fwidth", BuiltinType::kFwidth},
|
||||
BuiltinData{"fwidthCoarse", BuiltinType::kFwidthCoarse},
|
||||
BuiltinData{"fwidthFine", BuiltinType::kFwidthFine},
|
||||
BuiltinData{"inverseSqrt", BuiltinType::kInverseSqrt},
|
||||
BuiltinData{"isFinite", BuiltinType::kIsFinite},
|
||||
BuiltinData{"isInf", BuiltinType::kIsInf},
|
||||
BuiltinData{"isNan", BuiltinType::kIsNan},
|
||||
BuiltinData{"isNormal", BuiltinType::kIsNormal},
|
||||
BuiltinData{"ldexp", BuiltinType::kLdexp},
|
||||
BuiltinData{"length", BuiltinType::kLength},
|
||||
BuiltinData{"log", BuiltinType::kLog},
|
||||
BuiltinData{"log2", BuiltinType::kLog2},
|
||||
BuiltinData{"max", BuiltinType::kMax},
|
||||
BuiltinData{"min", BuiltinType::kMin},
|
||||
BuiltinData{"mix", BuiltinType::kMix},
|
||||
BuiltinData{"modf", BuiltinType::kModf},
|
||||
BuiltinData{"normalize", BuiltinType::kNormalize},
|
||||
BuiltinData{"pow", BuiltinType::kPow},
|
||||
BuiltinData{"reflect", BuiltinType::kReflect},
|
||||
BuiltinData{"reverseBits", BuiltinType::kReverseBits},
|
||||
BuiltinData{"round", BuiltinType::kRound},
|
||||
BuiltinData{"select", BuiltinType::kSelect},
|
||||
BuiltinData{"sign", BuiltinType::kSign},
|
||||
BuiltinData{"sin", BuiltinType::kSin},
|
||||
BuiltinData{"sinh", BuiltinType::kSinh},
|
||||
BuiltinData{"smoothStep", BuiltinType::kSmoothStep},
|
||||
BuiltinData{"sqrt", BuiltinType::kSqrt},
|
||||
BuiltinData{"step", BuiltinType::kStep},
|
||||
BuiltinData{"storageBarrier", BuiltinType::kStorageBarrier},
|
||||
BuiltinData{"tan", BuiltinType::kTan},
|
||||
BuiltinData{"tanh", BuiltinType::kTanh},
|
||||
BuiltinData{"textureDimensions", BuiltinType::kTextureDimensions},
|
||||
BuiltinData{"textureLoad", BuiltinType::kTextureLoad},
|
||||
BuiltinData{"textureNumLayers", BuiltinType::kTextureNumLayers},
|
||||
BuiltinData{"textureNumLevels", BuiltinType::kTextureNumLevels},
|
||||
BuiltinData{"textureNumSamples", BuiltinType::kTextureNumSamples},
|
||||
BuiltinData{"textureSample", BuiltinType::kTextureSample},
|
||||
BuiltinData{"textureSampleBias", BuiltinType::kTextureSampleBias},
|
||||
BuiltinData{"textureSampleCompare", BuiltinType::kTextureSampleCompare},
|
||||
BuiltinData{"textureSampleCompareLevel",
|
||||
BuiltinType::kTextureSampleCompareLevel},
|
||||
BuiltinData{"textureSampleGrad", BuiltinType::kTextureSampleGrad},
|
||||
BuiltinData{"textureSampleLevel", BuiltinType::kTextureSampleLevel},
|
||||
BuiltinData{"trunc", BuiltinType::kTrunc},
|
||||
BuiltinData{"unpack2x16float", BuiltinType::kUnpack2x16float},
|
||||
BuiltinData{"unpack2x16snorm", BuiltinType::kUnpack2x16snorm},
|
||||
BuiltinData{"unpack2x16unorm", BuiltinType::kUnpack2x16unorm},
|
||||
BuiltinData{"unpack4x8snorm", BuiltinType::kUnpack4x8snorm},
|
||||
BuiltinData{"unpack4x8unorm", BuiltinType::kUnpack4x8unorm},
|
||||
BuiltinData{"workgroupBarrier", BuiltinType::kWorkgroupBarrier}));
|
||||
|
||||
TEST_F(BuiltinTypeTest, ParseNoMatch) {
|
||||
EXPECT_EQ(ParseBuiltinType("not_builtin"), BuiltinType::kNone);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace sem
|
||||
} // namespace tint
|
|
@ -0,0 +1,560 @@
|
|||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// File generated by tools/builtin-gen
|
||||
// using the template:
|
||||
// src/sem/builtin_type.cc.tmpl
|
||||
// and the builtin defintion file:
|
||||
// src/builtins.def
|
||||
//
|
||||
// Do not modify this file directly
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "src/sem/builtin_type.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace tint {
|
||||
namespace sem {
|
||||
|
||||
BuiltinType ParseBuiltinType(const std::string& name) {
|
||||
if (name == "abs") {
|
||||
return BuiltinType::kAbs;
|
||||
}
|
||||
if (name == "acos") {
|
||||
return BuiltinType::kAcos;
|
||||
}
|
||||
if (name == "all") {
|
||||
return BuiltinType::kAll;
|
||||
}
|
||||
if (name == "any") {
|
||||
return BuiltinType::kAny;
|
||||
}
|
||||
if (name == "arrayLength") {
|
||||
return BuiltinType::kArrayLength;
|
||||
}
|
||||
if (name == "asin") {
|
||||
return BuiltinType::kAsin;
|
||||
}
|
||||
if (name == "atan") {
|
||||
return BuiltinType::kAtan;
|
||||
}
|
||||
if (name == "atan2") {
|
||||
return BuiltinType::kAtan2;
|
||||
}
|
||||
if (name == "ceil") {
|
||||
return BuiltinType::kCeil;
|
||||
}
|
||||
if (name == "clamp") {
|
||||
return BuiltinType::kClamp;
|
||||
}
|
||||
if (name == "cos") {
|
||||
return BuiltinType::kCos;
|
||||
}
|
||||
if (name == "cosh") {
|
||||
return BuiltinType::kCosh;
|
||||
}
|
||||
if (name == "countOneBits") {
|
||||
return BuiltinType::kCountOneBits;
|
||||
}
|
||||
if (name == "cross") {
|
||||
return BuiltinType::kCross;
|
||||
}
|
||||
if (name == "degrees") {
|
||||
return BuiltinType::kDegrees;
|
||||
}
|
||||
if (name == "determinant") {
|
||||
return BuiltinType::kDeterminant;
|
||||
}
|
||||
if (name == "distance") {
|
||||
return BuiltinType::kDistance;
|
||||
}
|
||||
if (name == "dot") {
|
||||
return BuiltinType::kDot;
|
||||
}
|
||||
if (name == "dpdx") {
|
||||
return BuiltinType::kDpdx;
|
||||
}
|
||||
if (name == "dpdxCoarse") {
|
||||
return BuiltinType::kDpdxCoarse;
|
||||
}
|
||||
if (name == "dpdxFine") {
|
||||
return BuiltinType::kDpdxFine;
|
||||
}
|
||||
if (name == "dpdy") {
|
||||
return BuiltinType::kDpdy;
|
||||
}
|
||||
if (name == "dpdyCoarse") {
|
||||
return BuiltinType::kDpdyCoarse;
|
||||
}
|
||||
if (name == "dpdyFine") {
|
||||
return BuiltinType::kDpdyFine;
|
||||
}
|
||||
if (name == "exp") {
|
||||
return BuiltinType::kExp;
|
||||
}
|
||||
if (name == "exp2") {
|
||||
return BuiltinType::kExp2;
|
||||
}
|
||||
if (name == "faceForward") {
|
||||
return BuiltinType::kFaceForward;
|
||||
}
|
||||
if (name == "floor") {
|
||||
return BuiltinType::kFloor;
|
||||
}
|
||||
if (name == "fma") {
|
||||
return BuiltinType::kFma;
|
||||
}
|
||||
if (name == "fract") {
|
||||
return BuiltinType::kFract;
|
||||
}
|
||||
if (name == "frexp") {
|
||||
return BuiltinType::kFrexp;
|
||||
}
|
||||
if (name == "fwidth") {
|
||||
return BuiltinType::kFwidth;
|
||||
}
|
||||
if (name == "fwidthCoarse") {
|
||||
return BuiltinType::kFwidthCoarse;
|
||||
}
|
||||
if (name == "fwidthFine") {
|
||||
return BuiltinType::kFwidthFine;
|
||||
}
|
||||
if (name == "inverseSqrt") {
|
||||
return BuiltinType::kInverseSqrt;
|
||||
}
|
||||
if (name == "isFinite") {
|
||||
return BuiltinType::kIsFinite;
|
||||
}
|
||||
if (name == "isInf") {
|
||||
return BuiltinType::kIsInf;
|
||||
}
|
||||
if (name == "isNan") {
|
||||
return BuiltinType::kIsNan;
|
||||
}
|
||||
if (name == "isNormal") {
|
||||
return BuiltinType::kIsNormal;
|
||||
}
|
||||
if (name == "ldexp") {
|
||||
return BuiltinType::kLdexp;
|
||||
}
|
||||
if (name == "length") {
|
||||
return BuiltinType::kLength;
|
||||
}
|
||||
if (name == "log") {
|
||||
return BuiltinType::kLog;
|
||||
}
|
||||
if (name == "log2") {
|
||||
return BuiltinType::kLog2;
|
||||
}
|
||||
if (name == "max") {
|
||||
return BuiltinType::kMax;
|
||||
}
|
||||
if (name == "min") {
|
||||
return BuiltinType::kMin;
|
||||
}
|
||||
if (name == "mix") {
|
||||
return BuiltinType::kMix;
|
||||
}
|
||||
if (name == "modf") {
|
||||
return BuiltinType::kModf;
|
||||
}
|
||||
if (name == "normalize") {
|
||||
return BuiltinType::kNormalize;
|
||||
}
|
||||
if (name == "pack2x16float") {
|
||||
return BuiltinType::kPack2x16float;
|
||||
}
|
||||
if (name == "pack2x16snorm") {
|
||||
return BuiltinType::kPack2x16snorm;
|
||||
}
|
||||
if (name == "pack2x16unorm") {
|
||||
return BuiltinType::kPack2x16unorm;
|
||||
}
|
||||
if (name == "pack4x8snorm") {
|
||||
return BuiltinType::kPack4x8snorm;
|
||||
}
|
||||
if (name == "pack4x8unorm") {
|
||||
return BuiltinType::kPack4x8unorm;
|
||||
}
|
||||
if (name == "pow") {
|
||||
return BuiltinType::kPow;
|
||||
}
|
||||
if (name == "radians") {
|
||||
return BuiltinType::kRadians;
|
||||
}
|
||||
if (name == "reflect") {
|
||||
return BuiltinType::kReflect;
|
||||
}
|
||||
if (name == "refract") {
|
||||
return BuiltinType::kRefract;
|
||||
}
|
||||
if (name == "reverseBits") {
|
||||
return BuiltinType::kReverseBits;
|
||||
}
|
||||
if (name == "round") {
|
||||
return BuiltinType::kRound;
|
||||
}
|
||||
if (name == "select") {
|
||||
return BuiltinType::kSelect;
|
||||
}
|
||||
if (name == "sign") {
|
||||
return BuiltinType::kSign;
|
||||
}
|
||||
if (name == "sin") {
|
||||
return BuiltinType::kSin;
|
||||
}
|
||||
if (name == "sinh") {
|
||||
return BuiltinType::kSinh;
|
||||
}
|
||||
if (name == "smoothStep") {
|
||||
return BuiltinType::kSmoothStep;
|
||||
}
|
||||
if (name == "sqrt") {
|
||||
return BuiltinType::kSqrt;
|
||||
}
|
||||
if (name == "step") {
|
||||
return BuiltinType::kStep;
|
||||
}
|
||||
if (name == "storageBarrier") {
|
||||
return BuiltinType::kStorageBarrier;
|
||||
}
|
||||
if (name == "tan") {
|
||||
return BuiltinType::kTan;
|
||||
}
|
||||
if (name == "tanh") {
|
||||
return BuiltinType::kTanh;
|
||||
}
|
||||
if (name == "transpose") {
|
||||
return BuiltinType::kTranspose;
|
||||
}
|
||||
if (name == "trunc") {
|
||||
return BuiltinType::kTrunc;
|
||||
}
|
||||
if (name == "unpack2x16float") {
|
||||
return BuiltinType::kUnpack2x16float;
|
||||
}
|
||||
if (name == "unpack2x16snorm") {
|
||||
return BuiltinType::kUnpack2x16snorm;
|
||||
}
|
||||
if (name == "unpack2x16unorm") {
|
||||
return BuiltinType::kUnpack2x16unorm;
|
||||
}
|
||||
if (name == "unpack4x8snorm") {
|
||||
return BuiltinType::kUnpack4x8snorm;
|
||||
}
|
||||
if (name == "unpack4x8unorm") {
|
||||
return BuiltinType::kUnpack4x8unorm;
|
||||
}
|
||||
if (name == "workgroupBarrier") {
|
||||
return BuiltinType::kWorkgroupBarrier;
|
||||
}
|
||||
if (name == "textureDimensions") {
|
||||
return BuiltinType::kTextureDimensions;
|
||||
}
|
||||
if (name == "textureGather") {
|
||||
return BuiltinType::kTextureGather;
|
||||
}
|
||||
if (name == "textureGatherCompare") {
|
||||
return BuiltinType::kTextureGatherCompare;
|
||||
}
|
||||
if (name == "textureNumLayers") {
|
||||
return BuiltinType::kTextureNumLayers;
|
||||
}
|
||||
if (name == "textureNumLevels") {
|
||||
return BuiltinType::kTextureNumLevels;
|
||||
}
|
||||
if (name == "textureNumSamples") {
|
||||
return BuiltinType::kTextureNumSamples;
|
||||
}
|
||||
if (name == "textureSample") {
|
||||
return BuiltinType::kTextureSample;
|
||||
}
|
||||
if (name == "textureSampleBias") {
|
||||
return BuiltinType::kTextureSampleBias;
|
||||
}
|
||||
if (name == "textureSampleCompare") {
|
||||
return BuiltinType::kTextureSampleCompare;
|
||||
}
|
||||
if (name == "textureSampleCompareLevel") {
|
||||
return BuiltinType::kTextureSampleCompareLevel;
|
||||
}
|
||||
if (name == "textureSampleGrad") {
|
||||
return BuiltinType::kTextureSampleGrad;
|
||||
}
|
||||
if (name == "textureSampleLevel") {
|
||||
return BuiltinType::kTextureSampleLevel;
|
||||
}
|
||||
if (name == "textureStore") {
|
||||
return BuiltinType::kTextureStore;
|
||||
}
|
||||
if (name == "textureLoad") {
|
||||
return BuiltinType::kTextureLoad;
|
||||
}
|
||||
if (name == "atomicLoad") {
|
||||
return BuiltinType::kAtomicLoad;
|
||||
}
|
||||
if (name == "atomicStore") {
|
||||
return BuiltinType::kAtomicStore;
|
||||
}
|
||||
if (name == "atomicAdd") {
|
||||
return BuiltinType::kAtomicAdd;
|
||||
}
|
||||
if (name == "atomicSub") {
|
||||
return BuiltinType::kAtomicSub;
|
||||
}
|
||||
if (name == "atomicMax") {
|
||||
return BuiltinType::kAtomicMax;
|
||||
}
|
||||
if (name == "atomicMin") {
|
||||
return BuiltinType::kAtomicMin;
|
||||
}
|
||||
if (name == "atomicAnd") {
|
||||
return BuiltinType::kAtomicAnd;
|
||||
}
|
||||
if (name == "atomicOr") {
|
||||
return BuiltinType::kAtomicOr;
|
||||
}
|
||||
if (name == "atomicXor") {
|
||||
return BuiltinType::kAtomicXor;
|
||||
}
|
||||
if (name == "atomicExchange") {
|
||||
return BuiltinType::kAtomicExchange;
|
||||
}
|
||||
if (name == "atomicCompareExchangeWeak") {
|
||||
return BuiltinType::kAtomicCompareExchangeWeak;
|
||||
}
|
||||
return BuiltinType::kNone;
|
||||
}
|
||||
|
||||
const char* str(BuiltinType i) {
|
||||
switch (i) {
|
||||
case BuiltinType::kNone:
|
||||
return "<none>";
|
||||
case BuiltinType::kAbs:
|
||||
return "abs";
|
||||
case BuiltinType::kAcos:
|
||||
return "acos";
|
||||
case BuiltinType::kAll:
|
||||
return "all";
|
||||
case BuiltinType::kAny:
|
||||
return "any";
|
||||
case BuiltinType::kArrayLength:
|
||||
return "arrayLength";
|
||||
case BuiltinType::kAsin:
|
||||
return "asin";
|
||||
case BuiltinType::kAtan:
|
||||
return "atan";
|
||||
case BuiltinType::kAtan2:
|
||||
return "atan2";
|
||||
case BuiltinType::kCeil:
|
||||
return "ceil";
|
||||
case BuiltinType::kClamp:
|
||||
return "clamp";
|
||||
case BuiltinType::kCos:
|
||||
return "cos";
|
||||
case BuiltinType::kCosh:
|
||||
return "cosh";
|
||||
case BuiltinType::kCountOneBits:
|
||||
return "countOneBits";
|
||||
case BuiltinType::kCross:
|
||||
return "cross";
|
||||
case BuiltinType::kDegrees:
|
||||
return "degrees";
|
||||
case BuiltinType::kDeterminant:
|
||||
return "determinant";
|
||||
case BuiltinType::kDistance:
|
||||
return "distance";
|
||||
case BuiltinType::kDot:
|
||||
return "dot";
|
||||
case BuiltinType::kDpdx:
|
||||
return "dpdx";
|
||||
case BuiltinType::kDpdxCoarse:
|
||||
return "dpdxCoarse";
|
||||
case BuiltinType::kDpdxFine:
|
||||
return "dpdxFine";
|
||||
case BuiltinType::kDpdy:
|
||||
return "dpdy";
|
||||
case BuiltinType::kDpdyCoarse:
|
||||
return "dpdyCoarse";
|
||||
case BuiltinType::kDpdyFine:
|
||||
return "dpdyFine";
|
||||
case BuiltinType::kExp:
|
||||
return "exp";
|
||||
case BuiltinType::kExp2:
|
||||
return "exp2";
|
||||
case BuiltinType::kFaceForward:
|
||||
return "faceForward";
|
||||
case BuiltinType::kFloor:
|
||||
return "floor";
|
||||
case BuiltinType::kFma:
|
||||
return "fma";
|
||||
case BuiltinType::kFract:
|
||||
return "fract";
|
||||
case BuiltinType::kFrexp:
|
||||
return "frexp";
|
||||
case BuiltinType::kFwidth:
|
||||
return "fwidth";
|
||||
case BuiltinType::kFwidthCoarse:
|
||||
return "fwidthCoarse";
|
||||
case BuiltinType::kFwidthFine:
|
||||
return "fwidthFine";
|
||||
case BuiltinType::kInverseSqrt:
|
||||
return "inverseSqrt";
|
||||
case BuiltinType::kIsFinite:
|
||||
return "isFinite";
|
||||
case BuiltinType::kIsInf:
|
||||
return "isInf";
|
||||
case BuiltinType::kIsNan:
|
||||
return "isNan";
|
||||
case BuiltinType::kIsNormal:
|
||||
return "isNormal";
|
||||
case BuiltinType::kLdexp:
|
||||
return "ldexp";
|
||||
case BuiltinType::kLength:
|
||||
return "length";
|
||||
case BuiltinType::kLog:
|
||||
return "log";
|
||||
case BuiltinType::kLog2:
|
||||
return "log2";
|
||||
case BuiltinType::kMax:
|
||||
return "max";
|
||||
case BuiltinType::kMin:
|
||||
return "min";
|
||||
case BuiltinType::kMix:
|
||||
return "mix";
|
||||
case BuiltinType::kModf:
|
||||
return "modf";
|
||||
case BuiltinType::kNormalize:
|
||||
return "normalize";
|
||||
case BuiltinType::kPack2x16float:
|
||||
return "pack2x16float";
|
||||
case BuiltinType::kPack2x16snorm:
|
||||
return "pack2x16snorm";
|
||||
case BuiltinType::kPack2x16unorm:
|
||||
return "pack2x16unorm";
|
||||
case BuiltinType::kPack4x8snorm:
|
||||
return "pack4x8snorm";
|
||||
case BuiltinType::kPack4x8unorm:
|
||||
return "pack4x8unorm";
|
||||
case BuiltinType::kPow:
|
||||
return "pow";
|
||||
case BuiltinType::kRadians:
|
||||
return "radians";
|
||||
case BuiltinType::kReflect:
|
||||
return "reflect";
|
||||
case BuiltinType::kRefract:
|
||||
return "refract";
|
||||
case BuiltinType::kReverseBits:
|
||||
return "reverseBits";
|
||||
case BuiltinType::kRound:
|
||||
return "round";
|
||||
case BuiltinType::kSelect:
|
||||
return "select";
|
||||
case BuiltinType::kSign:
|
||||
return "sign";
|
||||
case BuiltinType::kSin:
|
||||
return "sin";
|
||||
case BuiltinType::kSinh:
|
||||
return "sinh";
|
||||
case BuiltinType::kSmoothStep:
|
||||
return "smoothStep";
|
||||
case BuiltinType::kSqrt:
|
||||
return "sqrt";
|
||||
case BuiltinType::kStep:
|
||||
return "step";
|
||||
case BuiltinType::kStorageBarrier:
|
||||
return "storageBarrier";
|
||||
case BuiltinType::kTan:
|
||||
return "tan";
|
||||
case BuiltinType::kTanh:
|
||||
return "tanh";
|
||||
case BuiltinType::kTranspose:
|
||||
return "transpose";
|
||||
case BuiltinType::kTrunc:
|
||||
return "trunc";
|
||||
case BuiltinType::kUnpack2x16float:
|
||||
return "unpack2x16float";
|
||||
case BuiltinType::kUnpack2x16snorm:
|
||||
return "unpack2x16snorm";
|
||||
case BuiltinType::kUnpack2x16unorm:
|
||||
return "unpack2x16unorm";
|
||||
case BuiltinType::kUnpack4x8snorm:
|
||||
return "unpack4x8snorm";
|
||||
case BuiltinType::kUnpack4x8unorm:
|
||||
return "unpack4x8unorm";
|
||||
case BuiltinType::kWorkgroupBarrier:
|
||||
return "workgroupBarrier";
|
||||
case BuiltinType::kTextureDimensions:
|
||||
return "textureDimensions";
|
||||
case BuiltinType::kTextureGather:
|
||||
return "textureGather";
|
||||
case BuiltinType::kTextureGatherCompare:
|
||||
return "textureGatherCompare";
|
||||
case BuiltinType::kTextureNumLayers:
|
||||
return "textureNumLayers";
|
||||
case BuiltinType::kTextureNumLevels:
|
||||
return "textureNumLevels";
|
||||
case BuiltinType::kTextureNumSamples:
|
||||
return "textureNumSamples";
|
||||
case BuiltinType::kTextureSample:
|
||||
return "textureSample";
|
||||
case BuiltinType::kTextureSampleBias:
|
||||
return "textureSampleBias";
|
||||
case BuiltinType::kTextureSampleCompare:
|
||||
return "textureSampleCompare";
|
||||
case BuiltinType::kTextureSampleCompareLevel:
|
||||
return "textureSampleCompareLevel";
|
||||
case BuiltinType::kTextureSampleGrad:
|
||||
return "textureSampleGrad";
|
||||
case BuiltinType::kTextureSampleLevel:
|
||||
return "textureSampleLevel";
|
||||
case BuiltinType::kTextureStore:
|
||||
return "textureStore";
|
||||
case BuiltinType::kTextureLoad:
|
||||
return "textureLoad";
|
||||
case BuiltinType::kAtomicLoad:
|
||||
return "atomicLoad";
|
||||
case BuiltinType::kAtomicStore:
|
||||
return "atomicStore";
|
||||
case BuiltinType::kAtomicAdd:
|
||||
return "atomicAdd";
|
||||
case BuiltinType::kAtomicSub:
|
||||
return "atomicSub";
|
||||
case BuiltinType::kAtomicMax:
|
||||
return "atomicMax";
|
||||
case BuiltinType::kAtomicMin:
|
||||
return "atomicMin";
|
||||
case BuiltinType::kAtomicAnd:
|
||||
return "atomicAnd";
|
||||
case BuiltinType::kAtomicOr:
|
||||
return "atomicOr";
|
||||
case BuiltinType::kAtomicXor:
|
||||
return "atomicXor";
|
||||
case BuiltinType::kAtomicExchange:
|
||||
return "atomicExchange";
|
||||
case BuiltinType::kAtomicCompareExchangeWeak:
|
||||
return "atomicCompareExchangeWeak";
|
||||
}
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, BuiltinType i) {
|
||||
out << str(i);
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace sem
|
||||
} // namespace tint
|
|
@ -1,42 +1,42 @@
|
|||
{{- /*
|
||||
--------------------------------------------------------------------------------
|
||||
Template file for use with tools/intrinsic-gen to generate intrinsic_type.cc
|
||||
Template file for use with tools/builtin-gen to generate builtin_type.cc
|
||||
|
||||
See:
|
||||
* tools/cmd/intrinsic-gen/gen for structures used by this template
|
||||
* tools/cmd/builtin-gen/gen for structures used by this template
|
||||
* https://golang.org/pkg/text/template/ for documentation on the template syntax
|
||||
--------------------------------------------------------------------------------
|
||||
*/ -}}
|
||||
|
||||
#include "src/sem/intrinsic_type.h"
|
||||
#include "src/sem/builtin_type.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace tint {
|
||||
namespace sem {
|
||||
|
||||
IntrinsicType ParseIntrinsicType(const std::string& name) {
|
||||
BuiltinType ParseBuiltinType(const std::string& name) {
|
||||
{{- range .Sem.Functions }}
|
||||
if (name == "{{.Name}}") {
|
||||
return IntrinsicType::k{{Title .Name}};
|
||||
return BuiltinType::k{{Title .Name}};
|
||||
}
|
||||
{{- end }}
|
||||
return IntrinsicType::kNone;
|
||||
return BuiltinType::kNone;
|
||||
}
|
||||
|
||||
const char* str(IntrinsicType i) {
|
||||
const char* str(BuiltinType i) {
|
||||
switch (i) {
|
||||
case IntrinsicType::kNone:
|
||||
case BuiltinType::kNone:
|
||||
return "<none>";
|
||||
{{- range .Sem.Functions }}
|
||||
case IntrinsicType::k{{Title .Name}}:
|
||||
case BuiltinType::k{{Title .Name}}:
|
||||
return "{{.Name}}";
|
||||
{{- end }}
|
||||
}
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, IntrinsicType i) {
|
||||
std::ostream& operator<<(std::ostream& out, BuiltinType i) {
|
||||
out << str(i);
|
||||
return out;
|
||||
}
|
|
@ -13,17 +13,17 @@
|
|||
// limitations under the License.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// File generated by tools/intrinsic-gen
|
||||
// File generated by tools/builtin-gen
|
||||
// using the template:
|
||||
// src/sem/intrinsic_type.h.tmpl
|
||||
// and the intrinsic defintion file:
|
||||
// src/intrinsics.def
|
||||
// src/sem/builtin_type.h.tmpl
|
||||
// and the builtin defintion file:
|
||||
// src/builtins.def
|
||||
//
|
||||
// Do not modify this file directly
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SRC_SEM_INTRINSIC_TYPE_H_
|
||||
#define SRC_SEM_INTRINSIC_TYPE_H_
|
||||
#ifndef SRC_SEM_BUILTIN_TYPE_H_
|
||||
#define SRC_SEM_BUILTIN_TYPE_H_
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
@ -31,8 +31,8 @@
|
|||
namespace tint {
|
||||
namespace sem {
|
||||
|
||||
/// Enumerator of all intrinsic functions
|
||||
enum class IntrinsicType {
|
||||
/// Enumerator of all builtin functions
|
||||
enum class BuiltinType {
|
||||
kNone = -1,
|
||||
kAbs,
|
||||
kAcos,
|
||||
|
@ -138,21 +138,21 @@ enum class IntrinsicType {
|
|||
kAtomicCompareExchangeWeak,
|
||||
};
|
||||
|
||||
/// Matches the IntrinsicType by name
|
||||
/// @param name the intrinsic name to parse
|
||||
/// @returns the parsed IntrinsicType, or IntrinsicType::kNone if `name` did not
|
||||
/// match any intrinsic.
|
||||
IntrinsicType ParseIntrinsicType(const std::string& name);
|
||||
/// Matches the BuiltinType by name
|
||||
/// @param name the builtin name to parse
|
||||
/// @returns the parsed BuiltinType, or BuiltinType::kNone if `name` did not
|
||||
/// match any builtin.
|
||||
BuiltinType ParseBuiltinType(const std::string& name);
|
||||
|
||||
/// @returns the name of the intrinsic function type. The spelling, including
|
||||
/// @returns the name of the builtin function type. The spelling, including
|
||||
/// case, matches the name in the WGSL spec.
|
||||
const char* str(IntrinsicType i);
|
||||
const char* str(BuiltinType i);
|
||||
|
||||
/// Emits the name of the intrinsic function type. The spelling, including case,
|
||||
/// Emits the name of the builtin function type. The spelling, including case,
|
||||
/// matches the name in the WGSL spec.
|
||||
std::ostream& operator<<(std::ostream& out, IntrinsicType i);
|
||||
std::ostream& operator<<(std::ostream& out, BuiltinType i);
|
||||
|
||||
} // namespace sem
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_SEM_INTRINSIC_TYPE_H_
|
||||
#endif // SRC_SEM_BUILTIN_TYPE_H_
|
|
@ -0,0 +1,45 @@
|
|||
{{- /*
|
||||
--------------------------------------------------------------------------------
|
||||
Template file for use with tools/builtin-gen to generate builtin_type.h
|
||||
|
||||
See:
|
||||
* tools/cmd/builtin-gen/gen for structures used by this template
|
||||
* https://golang.org/pkg/text/template/ for documentation on the template syntax
|
||||
--------------------------------------------------------------------------------
|
||||
*/ -}}
|
||||
|
||||
#ifndef SRC_SEM_BUILTIN_TYPE_H_
|
||||
#define SRC_SEM_BUILTIN_TYPE_H_
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace tint {
|
||||
namespace sem {
|
||||
|
||||
/// Enumerator of all builtin functions
|
||||
enum class BuiltinType {
|
||||
kNone = -1,
|
||||
{{- range .Sem.Functions }}
|
||||
k{{Title .Name}},
|
||||
{{- end }}
|
||||
};
|
||||
|
||||
/// Matches the BuiltinType by name
|
||||
/// @param name the builtin name to parse
|
||||
/// @returns the parsed BuiltinType, or BuiltinType::kNone if `name` did not
|
||||
/// match any builtin.
|
||||
BuiltinType ParseBuiltinType(const std::string& name);
|
||||
|
||||
/// @returns the name of the builtin function type. The spelling, including
|
||||
/// case, matches the name in the WGSL spec.
|
||||
const char* str(BuiltinType i);
|
||||
|
||||
/// Emits the name of the builtin function type. The spelling, including case,
|
||||
/// matches the name in the WGSL spec.
|
||||
std::ostream& operator<<(std::ostream& out, BuiltinType i);
|
||||
|
||||
} // namespace sem
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_SEM_BUILTIN_TYPE_H_
|
|
@ -17,8 +17,8 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include "src/sem/builtin.h"
|
||||
#include "src/sem/expression.h"
|
||||
#include "src/sem/intrinsic.h"
|
||||
|
||||
namespace tint {
|
||||
namespace sem {
|
||||
|
|
|
@ -56,7 +56,7 @@ struct CallTargetSignature {
|
|||
int IndexOf(ParameterUsage usage) const;
|
||||
};
|
||||
|
||||
/// CallTarget is the base for callable functions, intrinsics, type constructors
|
||||
/// CallTarget is the base for callable functions, builtins, type constructors
|
||||
/// and type casts.
|
||||
class CallTarget : public Castable<CallTarget, Node> {
|
||||
public:
|
||||
|
|
|
@ -35,7 +35,7 @@ class ReturnStatement;
|
|||
|
||||
namespace sem {
|
||||
|
||||
class Intrinsic;
|
||||
class Builtin;
|
||||
class Variable;
|
||||
|
||||
/// WorkgroupDimension describes the size of a single dimension of an entry
|
||||
|
@ -120,16 +120,15 @@ class Function : public Castable<Function, CallTarget> {
|
|||
transitively_called_functions_.add(function);
|
||||
}
|
||||
|
||||
/// @returns the list of intrinsics that this function directly calls.
|
||||
const utils::UniqueVector<const Intrinsic*>& DirectlyCalledIntrinsics()
|
||||
const {
|
||||
return directly_called_intrinsics_;
|
||||
/// @returns the list of builtins that this function directly calls.
|
||||
const utils::UniqueVector<const Builtin*>& DirectlyCalledBuiltins() const {
|
||||
return directly_called_builtins_;
|
||||
}
|
||||
|
||||
/// Records that this function transitively calls `intrinsic`.
|
||||
/// @param intrinsic the intrinsic this function directly calls
|
||||
void AddDirectlyCalledIntrinsic(const Intrinsic* intrinsic) {
|
||||
directly_called_intrinsics_.add(intrinsic);
|
||||
/// Records that this function transitively calls `builtin`.
|
||||
/// @param builtin the builtin this function directly calls
|
||||
void AddDirectlyCalledBuiltin(const Builtin* builtin) {
|
||||
directly_called_builtins_.add(builtin);
|
||||
}
|
||||
|
||||
/// Adds the given texture/sampler pair to the list of unique pairs
|
||||
|
@ -149,13 +148,13 @@ class Function : public Castable<Function, CallTarget> {
|
|||
return texture_sampler_pairs_;
|
||||
}
|
||||
|
||||
/// @returns the list of direct calls to functions / intrinsics made by this
|
||||
/// @returns the list of direct calls to functions / builtins made by this
|
||||
/// function
|
||||
std::vector<const Call*> DirectCallStatements() const {
|
||||
return direct_calls_;
|
||||
}
|
||||
|
||||
/// Adds a record of the direct function / intrinsic calls made by this
|
||||
/// Adds a record of the direct function / builtin calls made by this
|
||||
/// function
|
||||
/// @param call the call
|
||||
void AddDirectCall(const Call* call) { direct_calls_.emplace_back(call); }
|
||||
|
@ -275,7 +274,7 @@ class Function : public Castable<Function, CallTarget> {
|
|||
utils::UniqueVector<const GlobalVariable*> directly_referenced_globals_;
|
||||
utils::UniqueVector<const GlobalVariable*> transitively_referenced_globals_;
|
||||
utils::UniqueVector<const Function*> transitively_called_functions_;
|
||||
utils::UniqueVector<const Intrinsic*> directly_called_intrinsics_;
|
||||
utils::UniqueVector<const Builtin*> directly_called_builtins_;
|
||||
utils::UniqueVector<VariablePair> texture_sampler_pairs_;
|
||||
std::vector<const Call*> direct_calls_;
|
||||
std::vector<const Call*> callsites_;
|
||||
|
|
|
@ -1,163 +0,0 @@
|
|||
// Copyright 2020 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/sem/intrinsic.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/utils/to_const_ptr_vec.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::sem::Intrinsic);
|
||||
|
||||
namespace tint {
|
||||
namespace sem {
|
||||
|
||||
const char* Intrinsic::str() const {
|
||||
return sem::str(type_);
|
||||
}
|
||||
|
||||
bool IsCoarseDerivativeIntrinsic(IntrinsicType i) {
|
||||
return i == IntrinsicType::kDpdxCoarse || i == IntrinsicType::kDpdyCoarse ||
|
||||
i == IntrinsicType::kFwidthCoarse;
|
||||
}
|
||||
|
||||
bool IsFineDerivativeIntrinsic(IntrinsicType i) {
|
||||
return i == IntrinsicType::kDpdxFine || i == IntrinsicType::kDpdyFine ||
|
||||
i == IntrinsicType::kFwidthFine;
|
||||
}
|
||||
|
||||
bool IsDerivativeIntrinsic(IntrinsicType i) {
|
||||
return i == IntrinsicType::kDpdx || i == IntrinsicType::kDpdy ||
|
||||
i == IntrinsicType::kFwidth || IsCoarseDerivativeIntrinsic(i) ||
|
||||
IsFineDerivativeIntrinsic(i);
|
||||
}
|
||||
|
||||
bool IsFloatClassificationIntrinsic(IntrinsicType i) {
|
||||
return i == IntrinsicType::kIsFinite || i == IntrinsicType::kIsInf ||
|
||||
i == IntrinsicType::kIsNan || i == IntrinsicType::kIsNormal;
|
||||
}
|
||||
|
||||
bool IsTextureIntrinsic(IntrinsicType i) {
|
||||
return IsImageQueryIntrinsic(i) || i == IntrinsicType::kTextureLoad ||
|
||||
i == IntrinsicType::kTextureGather ||
|
||||
i == IntrinsicType::kTextureGatherCompare ||
|
||||
i == IntrinsicType::kTextureSample ||
|
||||
i == IntrinsicType::kTextureSampleLevel ||
|
||||
i == IntrinsicType::kTextureSampleBias ||
|
||||
i == IntrinsicType::kTextureSampleCompare ||
|
||||
i == IntrinsicType::kTextureSampleCompareLevel ||
|
||||
i == IntrinsicType::kTextureSampleGrad ||
|
||||
i == IntrinsicType::kTextureStore;
|
||||
}
|
||||
|
||||
bool IsImageQueryIntrinsic(IntrinsicType i) {
|
||||
return i == IntrinsicType::kTextureDimensions ||
|
||||
i == IntrinsicType::kTextureNumLayers ||
|
||||
i == IntrinsicType::kTextureNumLevels ||
|
||||
i == IntrinsicType::kTextureNumSamples;
|
||||
}
|
||||
|
||||
bool IsDataPackingIntrinsic(IntrinsicType i) {
|
||||
return i == IntrinsicType::kPack4x8snorm ||
|
||||
i == IntrinsicType::kPack4x8unorm ||
|
||||
i == IntrinsicType::kPack2x16snorm ||
|
||||
i == IntrinsicType::kPack2x16unorm ||
|
||||
i == IntrinsicType::kPack2x16float;
|
||||
}
|
||||
|
||||
bool IsDataUnpackingIntrinsic(IntrinsicType i) {
|
||||
return i == IntrinsicType::kUnpack4x8snorm ||
|
||||
i == IntrinsicType::kUnpack4x8unorm ||
|
||||
i == IntrinsicType::kUnpack2x16snorm ||
|
||||
i == IntrinsicType::kUnpack2x16unorm ||
|
||||
i == IntrinsicType::kUnpack2x16float;
|
||||
}
|
||||
|
||||
bool IsBarrierIntrinsic(IntrinsicType i) {
|
||||
return i == IntrinsicType::kWorkgroupBarrier ||
|
||||
i == IntrinsicType::kStorageBarrier;
|
||||
}
|
||||
|
||||
bool IsAtomicIntrinsic(IntrinsicType i) {
|
||||
return i == sem::IntrinsicType::kAtomicLoad ||
|
||||
i == sem::IntrinsicType::kAtomicStore ||
|
||||
i == sem::IntrinsicType::kAtomicAdd ||
|
||||
i == sem::IntrinsicType::kAtomicSub ||
|
||||
i == sem::IntrinsicType::kAtomicMax ||
|
||||
i == sem::IntrinsicType::kAtomicMin ||
|
||||
i == sem::IntrinsicType::kAtomicAnd ||
|
||||
i == sem::IntrinsicType::kAtomicOr ||
|
||||
i == sem::IntrinsicType::kAtomicXor ||
|
||||
i == sem::IntrinsicType::kAtomicExchange ||
|
||||
i == sem::IntrinsicType::kAtomicCompareExchangeWeak;
|
||||
}
|
||||
|
||||
Intrinsic::Intrinsic(IntrinsicType type,
|
||||
const sem::Type* return_type,
|
||||
std::vector<Parameter*> parameters,
|
||||
PipelineStageSet supported_stages,
|
||||
bool is_deprecated)
|
||||
: Base(return_type, utils::ToConstPtrVec(parameters)),
|
||||
type_(type),
|
||||
supported_stages_(supported_stages),
|
||||
is_deprecated_(is_deprecated) {
|
||||
for (auto* parameter : parameters) {
|
||||
parameter->SetOwner(this);
|
||||
}
|
||||
}
|
||||
|
||||
Intrinsic::~Intrinsic() = default;
|
||||
|
||||
bool Intrinsic::IsCoarseDerivative() const {
|
||||
return IsCoarseDerivativeIntrinsic(type_);
|
||||
}
|
||||
|
||||
bool Intrinsic::IsFineDerivative() const {
|
||||
return IsFineDerivativeIntrinsic(type_);
|
||||
}
|
||||
|
||||
bool Intrinsic::IsDerivative() const {
|
||||
return IsDerivativeIntrinsic(type_);
|
||||
}
|
||||
|
||||
bool Intrinsic::IsFloatClassification() const {
|
||||
return IsFloatClassificationIntrinsic(type_);
|
||||
}
|
||||
|
||||
bool Intrinsic::IsTexture() const {
|
||||
return IsTextureIntrinsic(type_);
|
||||
}
|
||||
|
||||
bool Intrinsic::IsImageQuery() const {
|
||||
return IsImageQueryIntrinsic(type_);
|
||||
}
|
||||
|
||||
bool Intrinsic::IsDataPacking() const {
|
||||
return IsDataPackingIntrinsic(type_);
|
||||
}
|
||||
|
||||
bool Intrinsic::IsDataUnpacking() const {
|
||||
return IsDataUnpackingIntrinsic(type_);
|
||||
}
|
||||
|
||||
bool Intrinsic::IsBarrier() const {
|
||||
return IsBarrierIntrinsic(type_);
|
||||
}
|
||||
|
||||
bool Intrinsic::IsAtomic() const {
|
||||
return IsAtomicIntrinsic(type_);
|
||||
}
|
||||
|
||||
} // namespace sem
|
||||
} // namespace tint
|
|
@ -1,173 +0,0 @@
|
|||
// Copyright 2020 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_SEM_INTRINSIC_H_
|
||||
#define SRC_SEM_INTRINSIC_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "src/sem/call_target.h"
|
||||
#include "src/sem/intrinsic_type.h"
|
||||
#include "src/sem/pipeline_stage_set.h"
|
||||
#include "src/utils/hash.h"
|
||||
|
||||
namespace tint {
|
||||
namespace sem {
|
||||
|
||||
/// Determines if the given `i` is a coarse derivative
|
||||
/// @param i the intrinsic type
|
||||
/// @returns true if the given derivative is coarse.
|
||||
bool IsCoarseDerivativeIntrinsic(IntrinsicType i);
|
||||
|
||||
/// Determines if the given `i` is a fine derivative
|
||||
/// @param i the intrinsic type
|
||||
/// @returns true if the given derivative is fine.
|
||||
bool IsFineDerivativeIntrinsic(IntrinsicType i);
|
||||
|
||||
/// Determine if the given `i` is a derivative intrinsic
|
||||
/// @param i the intrinsic type
|
||||
/// @returns true if the given `i` is a derivative intrinsic
|
||||
bool IsDerivativeIntrinsic(IntrinsicType i);
|
||||
|
||||
/// Determines if the given `i` is a float classification intrinsic
|
||||
/// @param i the intrinsic type
|
||||
/// @returns true if the given `i` is a float intrinsic
|
||||
bool IsFloatClassificationIntrinsic(IntrinsicType i);
|
||||
|
||||
/// Determines if the given `i` is a texture operation intrinsic
|
||||
/// @param i the intrinsic type
|
||||
/// @returns true if the given `i` is a texture operation intrinsic
|
||||
bool IsTextureIntrinsic(IntrinsicType i);
|
||||
|
||||
/// Determines if the given `i` is a image query intrinsic
|
||||
/// @param i the intrinsic type
|
||||
/// @returns true if the given `i` is a image query intrinsic
|
||||
bool IsImageQueryIntrinsic(IntrinsicType i);
|
||||
|
||||
/// Determines if the given `i` is a data packing intrinsic
|
||||
/// @param i the intrinsic
|
||||
/// @returns true if the given `i` is a data packing intrinsic
|
||||
bool IsDataPackingIntrinsic(IntrinsicType i);
|
||||
|
||||
/// Determines if the given `i` is a data unpacking intrinsic
|
||||
/// @param i the intrinsic
|
||||
/// @returns true if the given `i` is a data unpacking intrinsic
|
||||
bool IsDataUnpackingIntrinsic(IntrinsicType i);
|
||||
|
||||
/// Determines if the given `i` is a barrier intrinsic
|
||||
/// @param i the intrinsic
|
||||
/// @returns true if the given `i` is a barrier intrinsic
|
||||
bool IsBarrierIntrinsic(IntrinsicType i);
|
||||
|
||||
/// Determines if the given `i` is a atomic intrinsic
|
||||
/// @param i the intrinsic
|
||||
/// @returns true if the given `i` is a atomic intrinsic
|
||||
bool IsAtomicIntrinsic(IntrinsicType i);
|
||||
|
||||
/// Intrinsic holds the semantic information for an intrinsic function.
|
||||
class Intrinsic : public Castable<Intrinsic, CallTarget> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param type the intrinsic type
|
||||
/// @param return_type the return type for the intrinsic call
|
||||
/// @param parameters the parameters for the intrinsic overload
|
||||
/// @param supported_stages the pipeline stages that this intrinsic can be
|
||||
/// used in
|
||||
/// @param is_deprecated true if the particular overload is considered
|
||||
/// deprecated
|
||||
Intrinsic(IntrinsicType type,
|
||||
const sem::Type* return_type,
|
||||
std::vector<Parameter*> parameters,
|
||||
PipelineStageSet supported_stages,
|
||||
bool is_deprecated);
|
||||
|
||||
/// Destructor
|
||||
~Intrinsic() override;
|
||||
|
||||
/// @return the type of the intrinsic
|
||||
IntrinsicType Type() const { return type_; }
|
||||
|
||||
/// @return the pipeline stages that this intrinsic can be used in
|
||||
PipelineStageSet SupportedStages() const { return supported_stages_; }
|
||||
|
||||
/// @return true if the intrinsic overload is considered deprecated
|
||||
bool IsDeprecated() const { return is_deprecated_; }
|
||||
|
||||
/// @returns the name of the intrinsic function type. The spelling, including
|
||||
/// case, matches the name in the WGSL spec.
|
||||
const char* str() const;
|
||||
|
||||
/// @returns true if intrinsic is a coarse derivative intrinsic
|
||||
bool IsCoarseDerivative() const;
|
||||
|
||||
/// @returns true if intrinsic is a fine a derivative intrinsic
|
||||
bool IsFineDerivative() const;
|
||||
|
||||
/// @returns true if intrinsic is a derivative intrinsic
|
||||
bool IsDerivative() const;
|
||||
|
||||
/// @returns true if intrinsic is a float intrinsic
|
||||
bool IsFloatClassification() const;
|
||||
|
||||
/// @returns true if intrinsic is a texture operation intrinsic
|
||||
bool IsTexture() const;
|
||||
|
||||
/// @returns true if intrinsic is a image query intrinsic
|
||||
bool IsImageQuery() const;
|
||||
|
||||
/// @returns true if intrinsic is a data packing intrinsic
|
||||
bool IsDataPacking() const;
|
||||
|
||||
/// @returns true if intrinsic is a data unpacking intrinsic
|
||||
bool IsDataUnpacking() const;
|
||||
|
||||
/// @returns true if intrinsic is a barrier intrinsic
|
||||
bool IsBarrier() const;
|
||||
|
||||
/// @returns true if intrinsic is a atomic intrinsic
|
||||
bool IsAtomic() const;
|
||||
|
||||
private:
|
||||
const IntrinsicType type_;
|
||||
const PipelineStageSet supported_stages_;
|
||||
const bool is_deprecated_;
|
||||
};
|
||||
|
||||
/// Constant value used by the degrees() intrinsic
|
||||
static constexpr double kRadToDeg = 57.295779513082322865;
|
||||
|
||||
/// Constant value used by the radians() intrinsic
|
||||
static constexpr double kDegToRad = 0.017453292519943295474;
|
||||
|
||||
} // namespace sem
|
||||
} // namespace tint
|
||||
|
||||
namespace std {
|
||||
|
||||
/// Custom std::hash specialization for tint::sem::Intrinsic
|
||||
template <>
|
||||
class hash<tint::sem::Intrinsic> {
|
||||
public:
|
||||
/// @param i the Intrinsic to create a hash for
|
||||
/// @return the hash value
|
||||
inline std::size_t operator()(const tint::sem::Intrinsic& i) const {
|
||||
return tint::utils::Hash(i.Type(), i.SupportedStages(), i.ReturnType(),
|
||||
i.Parameters(), i.IsDeprecated());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // SRC_SEM_INTRINSIC_H_
|
|
@ -1,132 +0,0 @@
|
|||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/sem/intrinsic.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace tint {
|
||||
namespace sem {
|
||||
namespace {
|
||||
|
||||
struct IntrinsicData {
|
||||
const char* name;
|
||||
IntrinsicType intrinsic;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
|
||||
out << data.name;
|
||||
return out;
|
||||
}
|
||||
|
||||
using IntrinsicTypeTest = testing::TestWithParam<IntrinsicData>;
|
||||
|
||||
TEST_P(IntrinsicTypeTest, Parse) {
|
||||
auto param = GetParam();
|
||||
EXPECT_EQ(ParseIntrinsicType(param.name), param.intrinsic);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IntrinsicTypeTest,
|
||||
IntrinsicTypeTest,
|
||||
testing::Values(
|
||||
IntrinsicData{"abs", IntrinsicType::kAbs},
|
||||
IntrinsicData{"acos", IntrinsicType::kAcos},
|
||||
IntrinsicData{"all", IntrinsicType::kAll},
|
||||
IntrinsicData{"any", IntrinsicType::kAny},
|
||||
IntrinsicData{"arrayLength", IntrinsicType::kArrayLength},
|
||||
IntrinsicData{"asin", IntrinsicType::kAsin},
|
||||
IntrinsicData{"atan", IntrinsicType::kAtan},
|
||||
IntrinsicData{"atan2", IntrinsicType::kAtan2},
|
||||
IntrinsicData{"ceil", IntrinsicType::kCeil},
|
||||
IntrinsicData{"clamp", IntrinsicType::kClamp},
|
||||
IntrinsicData{"cos", IntrinsicType::kCos},
|
||||
IntrinsicData{"cosh", IntrinsicType::kCosh},
|
||||
IntrinsicData{"countOneBits", IntrinsicType::kCountOneBits},
|
||||
IntrinsicData{"cross", IntrinsicType::kCross},
|
||||
IntrinsicData{"determinant", IntrinsicType::kDeterminant},
|
||||
IntrinsicData{"distance", IntrinsicType::kDistance},
|
||||
IntrinsicData{"dot", IntrinsicType::kDot},
|
||||
IntrinsicData{"dpdx", IntrinsicType::kDpdx},
|
||||
IntrinsicData{"dpdxCoarse", IntrinsicType::kDpdxCoarse},
|
||||
IntrinsicData{"dpdxFine", IntrinsicType::kDpdxFine},
|
||||
IntrinsicData{"dpdy", IntrinsicType::kDpdy},
|
||||
IntrinsicData{"dpdyCoarse", IntrinsicType::kDpdyCoarse},
|
||||
IntrinsicData{"dpdyFine", IntrinsicType::kDpdyFine},
|
||||
IntrinsicData{"exp", IntrinsicType::kExp},
|
||||
IntrinsicData{"exp2", IntrinsicType::kExp2},
|
||||
IntrinsicData{"faceForward", IntrinsicType::kFaceForward},
|
||||
IntrinsicData{"floor", IntrinsicType::kFloor},
|
||||
IntrinsicData{"fma", IntrinsicType::kFma},
|
||||
IntrinsicData{"fract", IntrinsicType::kFract},
|
||||
IntrinsicData{"frexp", IntrinsicType::kFrexp},
|
||||
IntrinsicData{"fwidth", IntrinsicType::kFwidth},
|
||||
IntrinsicData{"fwidthCoarse", IntrinsicType::kFwidthCoarse},
|
||||
IntrinsicData{"fwidthFine", IntrinsicType::kFwidthFine},
|
||||
IntrinsicData{"inverseSqrt", IntrinsicType::kInverseSqrt},
|
||||
IntrinsicData{"isFinite", IntrinsicType::kIsFinite},
|
||||
IntrinsicData{"isInf", IntrinsicType::kIsInf},
|
||||
IntrinsicData{"isNan", IntrinsicType::kIsNan},
|
||||
IntrinsicData{"isNormal", IntrinsicType::kIsNormal},
|
||||
IntrinsicData{"ldexp", IntrinsicType::kLdexp},
|
||||
IntrinsicData{"length", IntrinsicType::kLength},
|
||||
IntrinsicData{"log", IntrinsicType::kLog},
|
||||
IntrinsicData{"log2", IntrinsicType::kLog2},
|
||||
IntrinsicData{"max", IntrinsicType::kMax},
|
||||
IntrinsicData{"min", IntrinsicType::kMin},
|
||||
IntrinsicData{"mix", IntrinsicType::kMix},
|
||||
IntrinsicData{"modf", IntrinsicType::kModf},
|
||||
IntrinsicData{"normalize", IntrinsicType::kNormalize},
|
||||
IntrinsicData{"pow", IntrinsicType::kPow},
|
||||
IntrinsicData{"reflect", IntrinsicType::kReflect},
|
||||
IntrinsicData{"reverseBits", IntrinsicType::kReverseBits},
|
||||
IntrinsicData{"round", IntrinsicType::kRound},
|
||||
IntrinsicData{"select", IntrinsicType::kSelect},
|
||||
IntrinsicData{"sign", IntrinsicType::kSign},
|
||||
IntrinsicData{"sin", IntrinsicType::kSin},
|
||||
IntrinsicData{"sinh", IntrinsicType::kSinh},
|
||||
IntrinsicData{"smoothStep", IntrinsicType::kSmoothStep},
|
||||
IntrinsicData{"sqrt", IntrinsicType::kSqrt},
|
||||
IntrinsicData{"step", IntrinsicType::kStep},
|
||||
IntrinsicData{"storageBarrier", IntrinsicType::kStorageBarrier},
|
||||
IntrinsicData{"tan", IntrinsicType::kTan},
|
||||
IntrinsicData{"tanh", IntrinsicType::kTanh},
|
||||
IntrinsicData{"textureDimensions", IntrinsicType::kTextureDimensions},
|
||||
IntrinsicData{"textureLoad", IntrinsicType::kTextureLoad},
|
||||
IntrinsicData{"textureNumLayers", IntrinsicType::kTextureNumLayers},
|
||||
IntrinsicData{"textureNumLevels", IntrinsicType::kTextureNumLevels},
|
||||
IntrinsicData{"textureNumSamples", IntrinsicType::kTextureNumSamples},
|
||||
IntrinsicData{"textureSample", IntrinsicType::kTextureSample},
|
||||
IntrinsicData{"textureSampleBias", IntrinsicType::kTextureSampleBias},
|
||||
IntrinsicData{"textureSampleCompare",
|
||||
IntrinsicType::kTextureSampleCompare},
|
||||
IntrinsicData{"textureSampleCompareLevel",
|
||||
IntrinsicType::kTextureSampleCompareLevel},
|
||||
IntrinsicData{"textureSampleGrad", IntrinsicType::kTextureSampleGrad},
|
||||
IntrinsicData{"textureSampleLevel", IntrinsicType::kTextureSampleLevel},
|
||||
IntrinsicData{"trunc", IntrinsicType::kTrunc},
|
||||
IntrinsicData{"unpack2x16float", IntrinsicType::kUnpack2x16float},
|
||||
IntrinsicData{"unpack2x16snorm", IntrinsicType::kUnpack2x16snorm},
|
||||
IntrinsicData{"unpack2x16unorm", IntrinsicType::kUnpack2x16unorm},
|
||||
IntrinsicData{"unpack4x8snorm", IntrinsicType::kUnpack4x8snorm},
|
||||
IntrinsicData{"unpack4x8unorm", IntrinsicType::kUnpack4x8unorm},
|
||||
IntrinsicData{"workgroupBarrier", IntrinsicType::kWorkgroupBarrier}));
|
||||
|
||||
TEST_F(IntrinsicTypeTest, ParseNoMatch) {
|
||||
EXPECT_EQ(ParseIntrinsicType("not_intrinsic"), IntrinsicType::kNone);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace sem
|
||||
} // namespace tint
|
|
@ -1,560 +0,0 @@
|
|||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// File generated by tools/intrinsic-gen
|
||||
// using the template:
|
||||
// src/sem/intrinsic_type.cc.tmpl
|
||||
// and the intrinsic defintion file:
|
||||
// src/intrinsics.def
|
||||
//
|
||||
// Do not modify this file directly
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "src/sem/intrinsic_type.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace tint {
|
||||
namespace sem {
|
||||
|
||||
IntrinsicType ParseIntrinsicType(const std::string& name) {
|
||||
if (name == "abs") {
|
||||
return IntrinsicType::kAbs;
|
||||
}
|
||||
if (name == "acos") {
|
||||
return IntrinsicType::kAcos;
|
||||
}
|
||||
if (name == "all") {
|
||||
return IntrinsicType::kAll;
|
||||
}
|
||||
if (name == "any") {
|
||||
return IntrinsicType::kAny;
|
||||
}
|
||||
if (name == "arrayLength") {
|
||||
return IntrinsicType::kArrayLength;
|
||||
}
|
||||
if (name == "asin") {
|
||||
return IntrinsicType::kAsin;
|
||||
}
|
||||
if (name == "atan") {
|
||||
return IntrinsicType::kAtan;
|
||||
}
|
||||
if (name == "atan2") {
|
||||
return IntrinsicType::kAtan2;
|
||||
}
|
||||
if (name == "ceil") {
|
||||
return IntrinsicType::kCeil;
|
||||
}
|
||||
if (name == "clamp") {
|
||||
return IntrinsicType::kClamp;
|
||||
}
|
||||
if (name == "cos") {
|
||||
return IntrinsicType::kCos;
|
||||
}
|
||||
if (name == "cosh") {
|
||||
return IntrinsicType::kCosh;
|
||||
}
|
||||
if (name == "countOneBits") {
|
||||
return IntrinsicType::kCountOneBits;
|
||||
}
|
||||
if (name == "cross") {
|
||||
return IntrinsicType::kCross;
|
||||
}
|
||||
if (name == "degrees") {
|
||||
return IntrinsicType::kDegrees;
|
||||
}
|
||||
if (name == "determinant") {
|
||||
return IntrinsicType::kDeterminant;
|
||||
}
|
||||
if (name == "distance") {
|
||||
return IntrinsicType::kDistance;
|
||||
}
|
||||
if (name == "dot") {
|
||||
return IntrinsicType::kDot;
|
||||
}
|
||||
if (name == "dpdx") {
|
||||
return IntrinsicType::kDpdx;
|
||||
}
|
||||
if (name == "dpdxCoarse") {
|
||||
return IntrinsicType::kDpdxCoarse;
|
||||
}
|
||||
if (name == "dpdxFine") {
|
||||
return IntrinsicType::kDpdxFine;
|
||||
}
|
||||
if (name == "dpdy") {
|
||||
return IntrinsicType::kDpdy;
|
||||
}
|
||||
if (name == "dpdyCoarse") {
|
||||
return IntrinsicType::kDpdyCoarse;
|
||||
}
|
||||
if (name == "dpdyFine") {
|
||||
return IntrinsicType::kDpdyFine;
|
||||
}
|
||||
if (name == "exp") {
|
||||
return IntrinsicType::kExp;
|
||||
}
|
||||
if (name == "exp2") {
|
||||
return IntrinsicType::kExp2;
|
||||
}
|
||||
if (name == "faceForward") {
|
||||
return IntrinsicType::kFaceForward;
|
||||
}
|
||||
if (name == "floor") {
|
||||
return IntrinsicType::kFloor;
|
||||
}
|
||||
if (name == "fma") {
|
||||
return IntrinsicType::kFma;
|
||||
}
|
||||
if (name == "fract") {
|
||||
return IntrinsicType::kFract;
|
||||
}
|
||||
if (name == "frexp") {
|
||||
return IntrinsicType::kFrexp;
|
||||
}
|
||||
if (name == "fwidth") {
|
||||
return IntrinsicType::kFwidth;
|
||||
}
|
||||
if (name == "fwidthCoarse") {
|
||||
return IntrinsicType::kFwidthCoarse;
|
||||
}
|
||||
if (name == "fwidthFine") {
|
||||
return IntrinsicType::kFwidthFine;
|
||||
}
|
||||
if (name == "inverseSqrt") {
|
||||
return IntrinsicType::kInverseSqrt;
|
||||
}
|
||||
if (name == "isFinite") {
|
||||
return IntrinsicType::kIsFinite;
|
||||
}
|
||||
if (name == "isInf") {
|
||||
return IntrinsicType::kIsInf;
|
||||
}
|
||||
if (name == "isNan") {
|
||||
return IntrinsicType::kIsNan;
|
||||
}
|
||||
if (name == "isNormal") {
|
||||
return IntrinsicType::kIsNormal;
|
||||
}
|
||||
if (name == "ldexp") {
|
||||
return IntrinsicType::kLdexp;
|
||||
}
|
||||
if (name == "length") {
|
||||
return IntrinsicType::kLength;
|
||||
}
|
||||
if (name == "log") {
|
||||
return IntrinsicType::kLog;
|
||||
}
|
||||
if (name == "log2") {
|
||||
return IntrinsicType::kLog2;
|
||||
}
|
||||
if (name == "max") {
|
||||
return IntrinsicType::kMax;
|
||||
}
|
||||
if (name == "min") {
|
||||
return IntrinsicType::kMin;
|
||||
}
|
||||
if (name == "mix") {
|
||||
return IntrinsicType::kMix;
|
||||
}
|
||||
if (name == "modf") {
|
||||
return IntrinsicType::kModf;
|
||||
}
|
||||
if (name == "normalize") {
|
||||
return IntrinsicType::kNormalize;
|
||||
}
|
||||
if (name == "pack2x16float") {
|
||||
return IntrinsicType::kPack2x16float;
|
||||
}
|
||||
if (name == "pack2x16snorm") {
|
||||
return IntrinsicType::kPack2x16snorm;
|
||||
}
|
||||
if (name == "pack2x16unorm") {
|
||||
return IntrinsicType::kPack2x16unorm;
|
||||
}
|
||||
if (name == "pack4x8snorm") {
|
||||
return IntrinsicType::kPack4x8snorm;
|
||||
}
|
||||
if (name == "pack4x8unorm") {
|
||||
return IntrinsicType::kPack4x8unorm;
|
||||
}
|
||||
if (name == "pow") {
|
||||
return IntrinsicType::kPow;
|
||||
}
|
||||
if (name == "radians") {
|
||||
return IntrinsicType::kRadians;
|
||||
}
|
||||
if (name == "reflect") {
|
||||
return IntrinsicType::kReflect;
|
||||
}
|
||||
if (name == "refract") {
|
||||
return IntrinsicType::kRefract;
|
||||
}
|
||||
if (name == "reverseBits") {
|
||||
return IntrinsicType::kReverseBits;
|
||||
}
|
||||
if (name == "round") {
|
||||
return IntrinsicType::kRound;
|
||||
}
|
||||
if (name == "select") {
|
||||
return IntrinsicType::kSelect;
|
||||
}
|
||||
if (name == "sign") {
|
||||
return IntrinsicType::kSign;
|
||||
}
|
||||
if (name == "sin") {
|
||||
return IntrinsicType::kSin;
|
||||
}
|
||||
if (name == "sinh") {
|
||||
return IntrinsicType::kSinh;
|
||||
}
|
||||
if (name == "smoothStep") {
|
||||
return IntrinsicType::kSmoothStep;
|
||||
}
|
||||
if (name == "sqrt") {
|
||||
return IntrinsicType::kSqrt;
|
||||
}
|
||||
if (name == "step") {
|
||||
return IntrinsicType::kStep;
|
||||
}
|
||||
if (name == "storageBarrier") {
|
||||
return IntrinsicType::kStorageBarrier;
|
||||
}
|
||||
if (name == "tan") {
|
||||
return IntrinsicType::kTan;
|
||||
}
|
||||
if (name == "tanh") {
|
||||
return IntrinsicType::kTanh;
|
||||
}
|
||||
if (name == "transpose") {
|
||||
return IntrinsicType::kTranspose;
|
||||
}
|
||||
if (name == "trunc") {
|
||||
return IntrinsicType::kTrunc;
|
||||
}
|
||||
if (name == "unpack2x16float") {
|
||||
return IntrinsicType::kUnpack2x16float;
|
||||
}
|
||||
if (name == "unpack2x16snorm") {
|
||||
return IntrinsicType::kUnpack2x16snorm;
|
||||
}
|
||||
if (name == "unpack2x16unorm") {
|
||||
return IntrinsicType::kUnpack2x16unorm;
|
||||
}
|
||||
if (name == "unpack4x8snorm") {
|
||||
return IntrinsicType::kUnpack4x8snorm;
|
||||
}
|
||||
if (name == "unpack4x8unorm") {
|
||||
return IntrinsicType::kUnpack4x8unorm;
|
||||
}
|
||||
if (name == "workgroupBarrier") {
|
||||
return IntrinsicType::kWorkgroupBarrier;
|
||||
}
|
||||
if (name == "textureDimensions") {
|
||||
return IntrinsicType::kTextureDimensions;
|
||||
}
|
||||
if (name == "textureGather") {
|
||||
return IntrinsicType::kTextureGather;
|
||||
}
|
||||
if (name == "textureGatherCompare") {
|
||||
return IntrinsicType::kTextureGatherCompare;
|
||||
}
|
||||
if (name == "textureNumLayers") {
|
||||
return IntrinsicType::kTextureNumLayers;
|
||||
}
|
||||
if (name == "textureNumLevels") {
|
||||
return IntrinsicType::kTextureNumLevels;
|
||||
}
|
||||
if (name == "textureNumSamples") {
|
||||
return IntrinsicType::kTextureNumSamples;
|
||||
}
|
||||
if (name == "textureSample") {
|
||||
return IntrinsicType::kTextureSample;
|
||||
}
|
||||
if (name == "textureSampleBias") {
|
||||
return IntrinsicType::kTextureSampleBias;
|
||||
}
|
||||
if (name == "textureSampleCompare") {
|
||||
return IntrinsicType::kTextureSampleCompare;
|
||||
}
|
||||
if (name == "textureSampleCompareLevel") {
|
||||
return IntrinsicType::kTextureSampleCompareLevel;
|
||||
}
|
||||
if (name == "textureSampleGrad") {
|
||||
return IntrinsicType::kTextureSampleGrad;
|
||||
}
|
||||
if (name == "textureSampleLevel") {
|
||||
return IntrinsicType::kTextureSampleLevel;
|
||||
}
|
||||
if (name == "textureStore") {
|
||||
return IntrinsicType::kTextureStore;
|
||||
}
|
||||
if (name == "textureLoad") {
|
||||
return IntrinsicType::kTextureLoad;
|
||||
}
|
||||
if (name == "atomicLoad") {
|
||||
return IntrinsicType::kAtomicLoad;
|
||||
}
|
||||
if (name == "atomicStore") {
|
||||
return IntrinsicType::kAtomicStore;
|
||||
}
|
||||
if (name == "atomicAdd") {
|
||||
return IntrinsicType::kAtomicAdd;
|
||||
}
|
||||
if (name == "atomicSub") {
|
||||
return IntrinsicType::kAtomicSub;
|
||||
}
|
||||
if (name == "atomicMax") {
|
||||
return IntrinsicType::kAtomicMax;
|
||||
}
|
||||
if (name == "atomicMin") {
|
||||
return IntrinsicType::kAtomicMin;
|
||||
}
|
||||
if (name == "atomicAnd") {
|
||||
return IntrinsicType::kAtomicAnd;
|
||||
}
|
||||
if (name == "atomicOr") {
|
||||
return IntrinsicType::kAtomicOr;
|
||||
}
|
||||
if (name == "atomicXor") {
|
||||
return IntrinsicType::kAtomicXor;
|
||||
}
|
||||
if (name == "atomicExchange") {
|
||||
return IntrinsicType::kAtomicExchange;
|
||||
}
|
||||
if (name == "atomicCompareExchangeWeak") {
|
||||
return IntrinsicType::kAtomicCompareExchangeWeak;
|
||||
}
|
||||
return IntrinsicType::kNone;
|
||||
}
|
||||
|
||||
const char* str(IntrinsicType i) {
|
||||
switch (i) {
|
||||
case IntrinsicType::kNone:
|
||||
return "<none>";
|
||||
case IntrinsicType::kAbs:
|
||||
return "abs";
|
||||
case IntrinsicType::kAcos:
|
||||
return "acos";
|
||||
case IntrinsicType::kAll:
|
||||
return "all";
|
||||
case IntrinsicType::kAny:
|
||||
return "any";
|
||||
case IntrinsicType::kArrayLength:
|
||||
return "arrayLength";
|
||||
case IntrinsicType::kAsin:
|
||||
return "asin";
|
||||
case IntrinsicType::kAtan:
|
||||
return "atan";
|
||||
case IntrinsicType::kAtan2:
|
||||
return "atan2";
|
||||
case IntrinsicType::kCeil:
|
||||
return "ceil";
|
||||
case IntrinsicType::kClamp:
|
||||
return "clamp";
|
||||
case IntrinsicType::kCos:
|
||||
return "cos";
|
||||
case IntrinsicType::kCosh:
|
||||
return "cosh";
|
||||
case IntrinsicType::kCountOneBits:
|
||||
return "countOneBits";
|
||||
case IntrinsicType::kCross:
|
||||
return "cross";
|
||||
case IntrinsicType::kDegrees:
|
||||
return "degrees";
|
||||
case IntrinsicType::kDeterminant:
|
||||
return "determinant";
|
||||
case IntrinsicType::kDistance:
|
||||
return "distance";
|
||||
case IntrinsicType::kDot:
|
||||
return "dot";
|
||||
case IntrinsicType::kDpdx:
|
||||
return "dpdx";
|
||||
case IntrinsicType::kDpdxCoarse:
|
||||
return "dpdxCoarse";
|
||||
case IntrinsicType::kDpdxFine:
|
||||
return "dpdxFine";
|
||||
case IntrinsicType::kDpdy:
|
||||
return "dpdy";
|
||||
case IntrinsicType::kDpdyCoarse:
|
||||
return "dpdyCoarse";
|
||||
case IntrinsicType::kDpdyFine:
|
||||
return "dpdyFine";
|
||||
case IntrinsicType::kExp:
|
||||
return "exp";
|
||||
case IntrinsicType::kExp2:
|
||||
return "exp2";
|
||||
case IntrinsicType::kFaceForward:
|
||||
return "faceForward";
|
||||
case IntrinsicType::kFloor:
|
||||
return "floor";
|
||||
case IntrinsicType::kFma:
|
||||
return "fma";
|
||||
case IntrinsicType::kFract:
|
||||
return "fract";
|
||||
case IntrinsicType::kFrexp:
|
||||
return "frexp";
|
||||
case IntrinsicType::kFwidth:
|
||||
return "fwidth";
|
||||
case IntrinsicType::kFwidthCoarse:
|
||||
return "fwidthCoarse";
|
||||
case IntrinsicType::kFwidthFine:
|
||||
return "fwidthFine";
|
||||
case IntrinsicType::kInverseSqrt:
|
||||
return "inverseSqrt";
|
||||
case IntrinsicType::kIsFinite:
|
||||
return "isFinite";
|
||||
case IntrinsicType::kIsInf:
|
||||
return "isInf";
|
||||
case IntrinsicType::kIsNan:
|
||||
return "isNan";
|
||||
case IntrinsicType::kIsNormal:
|
||||
return "isNormal";
|
||||
case IntrinsicType::kLdexp:
|
||||
return "ldexp";
|
||||
case IntrinsicType::kLength:
|
||||
return "length";
|
||||
case IntrinsicType::kLog:
|
||||
return "log";
|
||||
case IntrinsicType::kLog2:
|
||||
return "log2";
|
||||
case IntrinsicType::kMax:
|
||||
return "max";
|
||||
case IntrinsicType::kMin:
|
||||
return "min";
|
||||
case IntrinsicType::kMix:
|
||||
return "mix";
|
||||
case IntrinsicType::kModf:
|
||||
return "modf";
|
||||
case IntrinsicType::kNormalize:
|
||||
return "normalize";
|
||||
case IntrinsicType::kPack2x16float:
|
||||
return "pack2x16float";
|
||||
case IntrinsicType::kPack2x16snorm:
|
||||
return "pack2x16snorm";
|
||||
case IntrinsicType::kPack2x16unorm:
|
||||
return "pack2x16unorm";
|
||||
case IntrinsicType::kPack4x8snorm:
|
||||
return "pack4x8snorm";
|
||||
case IntrinsicType::kPack4x8unorm:
|
||||
return "pack4x8unorm";
|
||||
case IntrinsicType::kPow:
|
||||
return "pow";
|
||||
case IntrinsicType::kRadians:
|
||||
return "radians";
|
||||
case IntrinsicType::kReflect:
|
||||
return "reflect";
|
||||
case IntrinsicType::kRefract:
|
||||
return "refract";
|
||||
case IntrinsicType::kReverseBits:
|
||||
return "reverseBits";
|
||||
case IntrinsicType::kRound:
|
||||
return "round";
|
||||
case IntrinsicType::kSelect:
|
||||
return "select";
|
||||
case IntrinsicType::kSign:
|
||||
return "sign";
|
||||
case IntrinsicType::kSin:
|
||||
return "sin";
|
||||
case IntrinsicType::kSinh:
|
||||
return "sinh";
|
||||
case IntrinsicType::kSmoothStep:
|
||||
return "smoothStep";
|
||||
case IntrinsicType::kSqrt:
|
||||
return "sqrt";
|
||||
case IntrinsicType::kStep:
|
||||
return "step";
|
||||
case IntrinsicType::kStorageBarrier:
|
||||
return "storageBarrier";
|
||||
case IntrinsicType::kTan:
|
||||
return "tan";
|
||||
case IntrinsicType::kTanh:
|
||||
return "tanh";
|
||||
case IntrinsicType::kTranspose:
|
||||
return "transpose";
|
||||
case IntrinsicType::kTrunc:
|
||||
return "trunc";
|
||||
case IntrinsicType::kUnpack2x16float:
|
||||
return "unpack2x16float";
|
||||
case IntrinsicType::kUnpack2x16snorm:
|
||||
return "unpack2x16snorm";
|
||||
case IntrinsicType::kUnpack2x16unorm:
|
||||
return "unpack2x16unorm";
|
||||
case IntrinsicType::kUnpack4x8snorm:
|
||||
return "unpack4x8snorm";
|
||||
case IntrinsicType::kUnpack4x8unorm:
|
||||
return "unpack4x8unorm";
|
||||
case IntrinsicType::kWorkgroupBarrier:
|
||||
return "workgroupBarrier";
|
||||
case IntrinsicType::kTextureDimensions:
|
||||
return "textureDimensions";
|
||||
case IntrinsicType::kTextureGather:
|
||||
return "textureGather";
|
||||
case IntrinsicType::kTextureGatherCompare:
|
||||
return "textureGatherCompare";
|
||||
case IntrinsicType::kTextureNumLayers:
|
||||
return "textureNumLayers";
|
||||
case IntrinsicType::kTextureNumLevels:
|
||||
return "textureNumLevels";
|
||||
case IntrinsicType::kTextureNumSamples:
|
||||
return "textureNumSamples";
|
||||
case IntrinsicType::kTextureSample:
|
||||
return "textureSample";
|
||||
case IntrinsicType::kTextureSampleBias:
|
||||
return "textureSampleBias";
|
||||
case IntrinsicType::kTextureSampleCompare:
|
||||
return "textureSampleCompare";
|
||||
case IntrinsicType::kTextureSampleCompareLevel:
|
||||
return "textureSampleCompareLevel";
|
||||
case IntrinsicType::kTextureSampleGrad:
|
||||
return "textureSampleGrad";
|
||||
case IntrinsicType::kTextureSampleLevel:
|
||||
return "textureSampleLevel";
|
||||
case IntrinsicType::kTextureStore:
|
||||
return "textureStore";
|
||||
case IntrinsicType::kTextureLoad:
|
||||
return "textureLoad";
|
||||
case IntrinsicType::kAtomicLoad:
|
||||
return "atomicLoad";
|
||||
case IntrinsicType::kAtomicStore:
|
||||
return "atomicStore";
|
||||
case IntrinsicType::kAtomicAdd:
|
||||
return "atomicAdd";
|
||||
case IntrinsicType::kAtomicSub:
|
||||
return "atomicSub";
|
||||
case IntrinsicType::kAtomicMax:
|
||||
return "atomicMax";
|
||||
case IntrinsicType::kAtomicMin:
|
||||
return "atomicMin";
|
||||
case IntrinsicType::kAtomicAnd:
|
||||
return "atomicAnd";
|
||||
case IntrinsicType::kAtomicOr:
|
||||
return "atomicOr";
|
||||
case IntrinsicType::kAtomicXor:
|
||||
return "atomicXor";
|
||||
case IntrinsicType::kAtomicExchange:
|
||||
return "atomicExchange";
|
||||
case IntrinsicType::kAtomicCompareExchangeWeak:
|
||||
return "atomicCompareExchangeWeak";
|
||||
}
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, IntrinsicType i) {
|
||||
out << str(i);
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace sem
|
||||
} // namespace tint
|
|
@ -1,45 +0,0 @@
|
|||
{{- /*
|
||||
--------------------------------------------------------------------------------
|
||||
Template file for use with tools/intrinsic-gen to generate intrinsic_type.h
|
||||
|
||||
See:
|
||||
* tools/cmd/intrinsic-gen/gen for structures used by this template
|
||||
* https://golang.org/pkg/text/template/ for documentation on the template syntax
|
||||
--------------------------------------------------------------------------------
|
||||
*/ -}}
|
||||
|
||||
#ifndef SRC_SEM_INTRINSIC_TYPE_H_
|
||||
#define SRC_SEM_INTRINSIC_TYPE_H_
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace tint {
|
||||
namespace sem {
|
||||
|
||||
/// Enumerator of all intrinsic functions
|
||||
enum class IntrinsicType {
|
||||
kNone = -1,
|
||||
{{- range .Sem.Functions }}
|
||||
k{{Title .Name}},
|
||||
{{- end }}
|
||||
};
|
||||
|
||||
/// Matches the IntrinsicType by name
|
||||
/// @param name the intrinsic name to parse
|
||||
/// @returns the parsed IntrinsicType, or IntrinsicType::kNone if `name` did not
|
||||
/// match any intrinsic.
|
||||
IntrinsicType ParseIntrinsicType(const std::string& name);
|
||||
|
||||
/// @returns the name of the intrinsic function type. The spelling, including
|
||||
/// case, matches the name in the WGSL spec.
|
||||
const char* str(IntrinsicType i);
|
||||
|
||||
/// Emits the name of the intrinsic function type. The spelling, including case,
|
||||
/// matches the name in the WGSL spec.
|
||||
std::ostream& operator<<(std::ostream& out, IntrinsicType i);
|
||||
|
||||
} // namespace sem
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_SEM_INTRINSIC_TYPE_H_
|
|
@ -13,11 +13,11 @@
|
|||
// limitations under the License.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// File generated by tools/intrinsic-gen
|
||||
// File generated by tools/builtin-gen
|
||||
// using the template:
|
||||
// src/sem/parameter_usage.cc.tmpl
|
||||
// and the intrinsic defintion file:
|
||||
// src/intrinsics.def
|
||||
// and the builtin defintion file:
|
||||
// src/builtins.def
|
||||
//
|
||||
// Do not modify this file directly
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{{- /*
|
||||
--------------------------------------------------------------------------------
|
||||
Template file for use with tools/intrinsic-gen to generate parameter_usage.cc
|
||||
Template file for use with tools/builtin-gen to generate parameter_usage.cc
|
||||
|
||||
See:
|
||||
* tools/cmd/intrinsic-gen/gen for structures used by this template
|
||||
* tools/cmd/builtin-gen/gen for structures used by this template
|
||||
* https://golang.org/pkg/text/template/ for documentation on the template syntax
|
||||
--------------------------------------------------------------------------------
|
||||
*/ -}}
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
// limitations under the License.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// File generated by tools/intrinsic-gen
|
||||
// File generated by tools/builtin-gen
|
||||
// using the template:
|
||||
// src/sem/parameter_usage.h.tmpl
|
||||
// and the intrinsic defintion file:
|
||||
// src/intrinsics.def
|
||||
// and the builtin defintion file:
|
||||
// src/builtins.def
|
||||
//
|
||||
// Do not modify this file directly
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{{- /*
|
||||
--------------------------------------------------------------------------------
|
||||
Template file for use with tools/intrinsic-gen to generate parameter_usage.h
|
||||
Template file for use with tools/builtin-gen to generate parameter_usage.h
|
||||
|
||||
See:
|
||||
* tools/cmd/intrinsic-gen/gen for structures used by this template
|
||||
* tools/cmd/builtin-gen/gen for structures used by this template
|
||||
* https://golang.org/pkg/text/template/ for documentation on the template syntax
|
||||
--------------------------------------------------------------------------------
|
||||
*/ -}}
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace transform {
|
|||
ArrayLengthFromUniform::ArrayLengthFromUniform() = default;
|
||||
ArrayLengthFromUniform::~ArrayLengthFromUniform() = default;
|
||||
|
||||
/// Iterate over all arrayLength() intrinsics that operate on
|
||||
/// Iterate over all arrayLength() builtins that operate on
|
||||
/// storage buffer variables.
|
||||
/// @param ctx the CloneContext.
|
||||
/// @param functor of type void(const ast::CallExpression*, const
|
||||
|
@ -46,7 +46,7 @@ template <typename F>
|
|||
static void IterateArrayLengthOnStorageVar(CloneContext& ctx, F&& functor) {
|
||||
auto& sem = ctx.src->Sem();
|
||||
|
||||
// Find all calls to the arrayLength() intrinsic.
|
||||
// Find all calls to the arrayLength() builtin.
|
||||
for (auto* node : ctx.src->ASTNodes().Objects()) {
|
||||
auto* call_expr = node->As<ast::CallExpression>();
|
||||
if (!call_expr) {
|
||||
|
@ -54,8 +54,8 @@ static void IterateArrayLengthOnStorageVar(CloneContext& ctx, F&& functor) {
|
|||
}
|
||||
|
||||
auto* call = sem.Get(call_expr);
|
||||
auto* intrinsic = call->Target()->As<sem::Intrinsic>();
|
||||
if (!intrinsic || intrinsic->Type() != sem::IntrinsicType::kArrayLength) {
|
||||
auto* builtin = call->Target()->As<sem::Builtin>();
|
||||
if (!builtin || builtin->Type() != sem::BuiltinType::kArrayLength) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -98,8 +98,8 @@ bool ArrayLengthFromUniform::ShouldRun(const Program* program,
|
|||
const DataMap&) const {
|
||||
for (auto* fn : program->AST().Functions()) {
|
||||
if (auto* sem_fn = program->Sem().Get(fn)) {
|
||||
for (auto* intrinsic : sem_fn->DirectlyCalledIntrinsics()) {
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kArrayLength) {
|
||||
for (auto* builtin : sem_fn->DirectlyCalledBuiltins()) {
|
||||
if (builtin->Type() == sem::BuiltinType::kArrayLength) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ class ArrayLengthFromUniform
|
|||
};
|
||||
|
||||
/// Information produced about what the transform did.
|
||||
/// If there were no calls to the arrayLength() intrinsic, then no Result will
|
||||
/// If there were no calls to the arrayLength() builtin, then no Result will
|
||||
/// be emitted.
|
||||
struct Result : public Castable<Result, transform::Data> {
|
||||
/// Constructor
|
||||
|
|
|
@ -76,8 +76,8 @@ bool CalculateArrayLength::ShouldRun(const Program* program,
|
|||
const DataMap&) const {
|
||||
for (auto* fn : program->AST().Functions()) {
|
||||
if (auto* sem_fn = program->Sem().Get(fn)) {
|
||||
for (auto* intrinsic : sem_fn->DirectlyCalledIntrinsics()) {
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kArrayLength) {
|
||||
for (auto* builtin : sem_fn->DirectlyCalledBuiltins()) {
|
||||
if (builtin->Type() == sem::BuiltinType::kArrayLength) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -143,8 +143,8 @@ void CalculateArrayLength::Run(CloneContext& ctx,
|
|||
for (auto* node : ctx.src->ASTNodes().Objects()) {
|
||||
if (auto* call_expr = node->As<ast::CallExpression>()) {
|
||||
auto* call = sem.Get(call_expr);
|
||||
if (auto* intrinsic = call->Target()->As<sem::Intrinsic>()) {
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kArrayLength) {
|
||||
if (auto* builtin = call->Target()->As<sem::Builtin>()) {
|
||||
if (builtin->Type() == sem::BuiltinType::kArrayLength) {
|
||||
// We're dealing with an arrayLength() call
|
||||
|
||||
// A runtime-sized array can only appear as the store type of a
|
||||
|
|
|
@ -71,7 +71,7 @@ struct CombineSamplers::State {
|
|||
|
||||
/// Placeholder global samplers used when a function contains texture-only
|
||||
/// references (one comparison sampler, one regular). These are also used as
|
||||
/// temporary sampler parameters to the texture intrinsics to satsify the WGSL
|
||||
/// temporary sampler parameters to the texture builtins to satisfy the WGSL
|
||||
/// resolver, but are then ignored and removed by the GLSL writer.
|
||||
const ast::Variable* placeholder_samplers_[2] = {};
|
||||
|
||||
|
@ -210,9 +210,9 @@ struct CombineSamplers::State {
|
|||
-> const ast::Expression* {
|
||||
if (auto* call = sem.Get(expr)) {
|
||||
ast::ExpressionList args;
|
||||
// Replace all texture intrinsic calls.
|
||||
if (auto* intrinsic = call->Target()->As<sem::Intrinsic>()) {
|
||||
const auto& signature = intrinsic->Signature();
|
||||
// Replace all texture builtin calls.
|
||||
if (auto* builtin = call->Target()->As<sem::Builtin>()) {
|
||||
const auto& signature = builtin->Signature();
|
||||
int sampler_index = signature.IndexOf(sem::ParameterUsage::kSampler);
|
||||
int texture_index = signature.IndexOf(sem::ParameterUsage::kTexture);
|
||||
if (texture_index == -1) {
|
||||
|
|
|
@ -38,9 +38,9 @@ namespace transform {
|
|||
/// parameter. In this case, a new parameter is added to the function
|
||||
/// signature. All separate texture/sampler parameters are removed.
|
||||
///
|
||||
/// All texture intrinsic callsites are modified to pass the combined
|
||||
/// All texture builtin callsites are modified to pass the combined
|
||||
/// texture/sampler as the first argument, and separate texture/sampler
|
||||
/// arugments are removed.
|
||||
/// arguments are removed.
|
||||
///
|
||||
/// Note that the sampler may be null, indicating that only a texture
|
||||
/// reference was required (e.g., textureLoad). In this case, a
|
||||
|
|
|
@ -115,7 +115,7 @@ struct LoadStoreKey {
|
|||
struct AtomicKey {
|
||||
sem::Type const* buf_ty = nullptr; // buffer type
|
||||
sem::Type const* el_ty = nullptr; // element type
|
||||
sem::IntrinsicType const op; // atomic op
|
||||
sem::BuiltinType const op; // atomic op
|
||||
bool operator==(const AtomicKey& rhs) const {
|
||||
return buf_ty == rhs.buf_ty && el_ty == rhs.el_ty && op == rhs.op;
|
||||
}
|
||||
|
@ -224,41 +224,41 @@ DecomposeMemoryAccess::Intrinsic* IntrinsicStoreFor(
|
|||
/// @returns a DecomposeMemoryAccess::Intrinsic attribute that can be applied
|
||||
/// to a stub function for the atomic op and the type `ty`.
|
||||
DecomposeMemoryAccess::Intrinsic* IntrinsicAtomicFor(ProgramBuilder* builder,
|
||||
sem::IntrinsicType ity,
|
||||
sem::BuiltinType ity,
|
||||
const sem::Type* ty) {
|
||||
auto op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicLoad;
|
||||
switch (ity) {
|
||||
case sem::IntrinsicType::kAtomicLoad:
|
||||
case sem::BuiltinType::kAtomicLoad:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicLoad;
|
||||
break;
|
||||
case sem::IntrinsicType::kAtomicStore:
|
||||
case sem::BuiltinType::kAtomicStore:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicStore;
|
||||
break;
|
||||
case sem::IntrinsicType::kAtomicAdd:
|
||||
case sem::BuiltinType::kAtomicAdd:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicAdd;
|
||||
break;
|
||||
case sem::IntrinsicType::kAtomicSub:
|
||||
case sem::BuiltinType::kAtomicSub:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicSub;
|
||||
break;
|
||||
case sem::IntrinsicType::kAtomicMax:
|
||||
case sem::BuiltinType::kAtomicMax:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicMax;
|
||||
break;
|
||||
case sem::IntrinsicType::kAtomicMin:
|
||||
case sem::BuiltinType::kAtomicMin:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicMin;
|
||||
break;
|
||||
case sem::IntrinsicType::kAtomicAnd:
|
||||
case sem::BuiltinType::kAtomicAnd:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicAnd;
|
||||
break;
|
||||
case sem::IntrinsicType::kAtomicOr:
|
||||
case sem::BuiltinType::kAtomicOr:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicOr;
|
||||
break;
|
||||
case sem::IntrinsicType::kAtomicXor:
|
||||
case sem::BuiltinType::kAtomicXor:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicXor;
|
||||
break;
|
||||
case sem::IntrinsicType::kAtomicExchange:
|
||||
case sem::BuiltinType::kAtomicExchange:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicExchange;
|
||||
break;
|
||||
case sem::IntrinsicType::kAtomicCompareExchangeWeak:
|
||||
case sem::BuiltinType::kAtomicCompareExchangeWeak:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicCompareExchangeWeak;
|
||||
break;
|
||||
default:
|
||||
|
@ -641,7 +641,7 @@ struct DecomposeMemoryAccess::State {
|
|||
/// @return the name of the function that performs the load
|
||||
Symbol AtomicFunc(const sem::Type* buf_ty,
|
||||
const sem::Type* el_ty,
|
||||
const sem::Intrinsic* intrinsic,
|
||||
const sem::Builtin* intrinsic,
|
||||
const sem::VariableUser* var_user) {
|
||||
auto op = intrinsic->Type();
|
||||
return utils::GetOrCreate(atomic_funcs, AtomicKey{buf_ty, el_ty, op}, [&] {
|
||||
|
@ -921,15 +921,15 @@ void DecomposeMemoryAccess::Run(CloneContext& ctx,
|
|||
|
||||
if (auto* call_expr = node->As<ast::CallExpression>()) {
|
||||
auto* call = sem.Get(call_expr);
|
||||
if (auto* intrinsic = call->Target()->As<sem::Intrinsic>()) {
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kArrayLength) {
|
||||
if (auto* builtin = call->Target()->As<sem::Builtin>()) {
|
||||
if (builtin->Type() == sem::BuiltinType::kArrayLength) {
|
||||
// arrayLength(X)
|
||||
// Don't convert X into a load, this intrinsic actually requires the
|
||||
// Don't convert X into a load, this builtin actually requires the
|
||||
// real pointer.
|
||||
state.TakeAccess(call_expr->args[0]);
|
||||
continue;
|
||||
}
|
||||
if (intrinsic->IsAtomic()) {
|
||||
if (builtin->IsAtomic()) {
|
||||
if (auto access = state.TakeAccess(call_expr->args[0])) {
|
||||
// atomic___(X)
|
||||
ctx.Replace(call_expr, [=, &ctx, &state] {
|
||||
|
@ -937,9 +937,8 @@ void DecomposeMemoryAccess::Run(CloneContext& ctx,
|
|||
auto* offset = access.offset->Build(ctx);
|
||||
auto* buf_ty = access.var->Type()->UnwrapRef();
|
||||
auto* el_ty = access.type->UnwrapRef()->As<sem::Atomic>()->Type();
|
||||
Symbol func =
|
||||
state.AtomicFunc(buf_ty, el_ty, intrinsic,
|
||||
access.var->As<sem::VariableUser>());
|
||||
Symbol func = state.AtomicFunc(
|
||||
buf_ty, el_ty, builtin, access.var->As<sem::VariableUser>());
|
||||
|
||||
ast::ExpressionList args{ctx.Clone(buf), offset};
|
||||
for (size_t i = 1; i < call_expr->args.size(); i++) {
|
||||
|
|
|
@ -46,10 +46,9 @@ void ExternalTextureTransform::Run(CloneContext& ctx,
|
|||
// Scan the AST nodes for calls to textureLoad or textureSampleLevel.
|
||||
for (auto* node : ctx.src->ASTNodes().Objects()) {
|
||||
if (auto* call_expr = node->As<ast::CallExpression>()) {
|
||||
if (auto* intrinsic =
|
||||
sem.Get(call_expr)->Target()->As<sem::Intrinsic>()) {
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad ||
|
||||
intrinsic->Type() == sem::IntrinsicType::kTextureSampleLevel) {
|
||||
if (auto* builtin = sem.Get(call_expr)->Target()->As<sem::Builtin>()) {
|
||||
if (builtin->Type() == sem::BuiltinType::kTextureLoad ||
|
||||
builtin->Type() == sem::BuiltinType::kTextureSampleLevel) {
|
||||
// When a textureLoad or textureSampleLevel has been identified, check
|
||||
// if the first parameter is an external texture.
|
||||
if (auto* var =
|
||||
|
@ -58,7 +57,7 @@ void ExternalTextureTransform::Run(CloneContext& ctx,
|
|||
->Type()
|
||||
->UnwrapRef()
|
||||
->Is<sem::ExternalTexture>()) {
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad &&
|
||||
if (builtin->Type() == sem::BuiltinType::kTextureLoad &&
|
||||
call_expr->args.size() != 2) {
|
||||
TINT_ICE(Transform, ctx.dst->Diagnostics())
|
||||
<< "expected textureLoad call with a texture_external to "
|
||||
|
@ -66,8 +65,7 @@ void ExternalTextureTransform::Run(CloneContext& ctx,
|
|||
<< call_expr->args.size() << " parameters";
|
||||
}
|
||||
|
||||
if (intrinsic->Type() ==
|
||||
sem::IntrinsicType::kTextureSampleLevel &&
|
||||
if (builtin->Type() == sem::BuiltinType::kTextureSampleLevel &&
|
||||
call_expr->args.size() != 3) {
|
||||
TINT_ICE(Transform, ctx.dst->Diagnostics())
|
||||
<< "expected textureSampleLevel call with a "
|
||||
|
@ -82,12 +80,12 @@ void ExternalTextureTransform::Run(CloneContext& ctx,
|
|||
auto* externalTextureParam = ctx.Clone(call_expr->args[0]);
|
||||
|
||||
ast::ExpressionList params;
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad) {
|
||||
if (builtin->Type() == sem::BuiltinType::kTextureLoad) {
|
||||
auto* coordsParam = ctx.Clone(call_expr->args[1]);
|
||||
auto* levelParam = ctx.dst->Expr(0);
|
||||
params = {externalTextureParam, coordsParam, levelParam};
|
||||
} else if (intrinsic->Type() ==
|
||||
sem::IntrinsicType::kTextureSampleLevel) {
|
||||
} else if (builtin->Type() ==
|
||||
sem::BuiltinType::kTextureSampleLevel) {
|
||||
auto* samplerParam = ctx.Clone(call_expr->args[1]);
|
||||
auto* coordsParam = ctx.Clone(call_expr->args[2]);
|
||||
auto* levelParam = ctx.dst->Expr(0.0f);
|
||||
|
|
|
@ -148,11 +148,11 @@ struct MultiplanarExternalTexture::State {
|
|||
// textureLoadExternal and textureSampleExternal calls.
|
||||
ctx.ReplaceAll(
|
||||
[&](const ast::CallExpression* expr) -> const ast::CallExpression* {
|
||||
auto* intrinsic = sem.Get(expr)->Target()->As<sem::Intrinsic>();
|
||||
auto* builtin = sem.Get(expr)->Target()->As<sem::Builtin>();
|
||||
|
||||
if (intrinsic && !intrinsic->Parameters().empty() &&
|
||||
intrinsic->Parameters()[0]->Type()->Is<sem::ExternalTexture>() &&
|
||||
intrinsic->Type() != sem::IntrinsicType::kTextureDimensions) {
|
||||
if (builtin && !builtin->Parameters().empty() &&
|
||||
builtin->Parameters()[0]->Type()->Is<sem::ExternalTexture>() &&
|
||||
builtin->Type() != sem::BuiltinType::kTextureDimensions) {
|
||||
auto it = new_binding_symbols.find(
|
||||
expr->args[0]->As<ast::IdentifierExpression>()->symbol);
|
||||
if (it == new_binding_symbols.end()) {
|
||||
|
@ -164,11 +164,11 @@ struct MultiplanarExternalTexture::State {
|
|||
}
|
||||
auto& syms = it->second;
|
||||
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad) {
|
||||
if (builtin->Type() == sem::BuiltinType::kTextureLoad) {
|
||||
return createTexLdExt(expr, syms);
|
||||
}
|
||||
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kTextureSampleLevel) {
|
||||
if (builtin->Type() == sem::BuiltinType::kTextureSampleLevel) {
|
||||
return createTexSmpExt(expr, syms);
|
||||
}
|
||||
|
||||
|
@ -248,12 +248,12 @@ struct MultiplanarExternalTexture::State {
|
|||
/// bodies of the textureSampleExternal and textureLoadExternal functions.
|
||||
/// @param call_type determines which function body to generate
|
||||
/// @returns a statement list that makes of the body of the chosen function
|
||||
ast::StatementList createTexFnExtStatementList(sem::IntrinsicType call_type) {
|
||||
ast::StatementList createTexFnExtStatementList(sem::BuiltinType call_type) {
|
||||
using f32 = ProgramBuilder::f32;
|
||||
const ast::CallExpression* single_plane_call = nullptr;
|
||||
const ast::CallExpression* plane_0_call = nullptr;
|
||||
const ast::CallExpression* plane_1_call = nullptr;
|
||||
if (call_type == sem::IntrinsicType::kTextureSampleLevel) {
|
||||
if (call_type == sem::BuiltinType::kTextureSampleLevel) {
|
||||
// textureSampleLevel(plane0, smp, coord.xy, 0.0);
|
||||
single_plane_call =
|
||||
b.Call("textureSampleLevel", "plane0", "smp", "coord", 0.0f);
|
||||
|
@ -263,7 +263,7 @@ struct MultiplanarExternalTexture::State {
|
|||
// textureSampleLevel(plane1, smp, coord.xy, 0.0);
|
||||
plane_1_call =
|
||||
b.Call("textureSampleLevel", "plane1", "smp", "coord", 0.0f);
|
||||
} else if (call_type == sem::IntrinsicType::kTextureLoad) {
|
||||
} else if (call_type == sem::BuiltinType::kTextureLoad) {
|
||||
// textureLoad(plane0, coords.xy, 0);
|
||||
single_plane_call = b.Call("textureLoad", "plane0", "coord", 0);
|
||||
// textureLoad(plane0, coords.xy, 0);
|
||||
|
@ -272,7 +272,7 @@ struct MultiplanarExternalTexture::State {
|
|||
plane_1_call = b.Call("textureLoad", "plane1", "coord", 0);
|
||||
} else {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "unhandled intrinsic: " << call_type;
|
||||
<< "unhandled builtin: " << call_type;
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -343,7 +343,7 @@ struct MultiplanarExternalTexture::State {
|
|||
b.Param("params", b.ty.type_name(params_struct_sym))};
|
||||
|
||||
ast::StatementList statementList =
|
||||
createTexFnExtStatementList(sem::IntrinsicType::kTextureSampleLevel);
|
||||
createTexFnExtStatementList(sem::BuiltinType::kTextureSampleLevel);
|
||||
|
||||
b.Func(texture_sample_external_sym, varList, b.ty.vec4(b.ty.f32()),
|
||||
statementList, {});
|
||||
|
@ -386,7 +386,7 @@ struct MultiplanarExternalTexture::State {
|
|||
b.Param("params", b.ty.type_name(params_struct_sym))};
|
||||
|
||||
ast::StatementList statement_list =
|
||||
createTexFnExtStatementList(sem::IntrinsicType::kTextureLoad);
|
||||
createTexFnExtStatementList(sem::BuiltinType::kTextureLoad);
|
||||
|
||||
b.Func(texture_load_external_sym, var_list, b.ty.vec4(b.ty.f32()),
|
||||
statement_list, {});
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include "src/ast/struct_member.h"
|
||||
#include "src/sem/binding_point.h"
|
||||
#include "src/sem/intrinsic_type.h"
|
||||
#include "src/sem/builtin_type.h"
|
||||
#include "src/transform/transform.h"
|
||||
|
||||
namespace tint {
|
||||
|
|
|
@ -89,12 +89,12 @@ void RemovePhonies::Run(CloneContext& ctx, const DataMap&, DataMap&) const {
|
|||
if (!ast::TraverseExpressions(
|
||||
stmt->rhs, ctx.dst->Diagnostics(),
|
||||
[&](const ast::CallExpression* call) {
|
||||
// ast::CallExpression may map to a function or intrinsic call
|
||||
// ast::CallExpression may map to a function or builtin call
|
||||
// (both may have side-effects), or a type constructor or
|
||||
// type conversion (both do not have side effects).
|
||||
if (sem.Get(call)
|
||||
->Target()
|
||||
->IsAnyOf<sem::Function, sem::Intrinsic>()) {
|
||||
->IsAnyOf<sem::Function, sem::Builtin>()) {
|
||||
side_effects.push_back(call);
|
||||
return ast::TraverseAction::Skip;
|
||||
}
|
||||
|
|
|
@ -1257,7 +1257,7 @@ Output Renamer::Run(const Program* in, const DataMap& inputs) const {
|
|||
// Disable auto-cloning of symbols, since we want to rename them.
|
||||
CloneContext ctx(&out, in, false);
|
||||
|
||||
// Swizzles, intrinsic calls and builtin structure members need to keep their
|
||||
// Swizzles, builtin calls and builtin structure members need to keep their
|
||||
// symbols preserved.
|
||||
std::unordered_set<const ast::IdentifierExpression*> preserve;
|
||||
for (auto* node : in->ASTNodes().Objects()) {
|
||||
|
@ -1284,7 +1284,7 @@ Output Renamer::Run(const Program* in, const DataMap& inputs) const {
|
|||
<< "CallExpression has no semantic info";
|
||||
continue;
|
||||
}
|
||||
if (sem->Target()->Is<sem::Intrinsic>()) {
|
||||
if (sem->Target()->Is<sem::Builtin>()) {
|
||||
preserve.emplace(call->target.name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ fn tint_symbol() -> @builtin(position) vec4<f32> {
|
|||
EXPECT_THAT(data->remappings, ContainerEq(expected_remappings));
|
||||
}
|
||||
|
||||
TEST_F(RenamerTest, PreserveIntrinsics) {
|
||||
TEST_F(RenamerTest, PreserveBuiltins) {
|
||||
auto* src = R"(
|
||||
@stage(vertex)
|
||||
fn entry() -> @builtin(position) vec4<f32> {
|
||||
|
@ -666,20 +666,20 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
"VPOS",
|
||||
"VertexShader",
|
||||
"abort",
|
||||
// "abs", // WGSL intrinsic
|
||||
// "acos", // WGSL intrinsic
|
||||
// "all", // WGSL intrinsic
|
||||
// "abs", // WGSL builtin
|
||||
// "acos", // WGSL builtin
|
||||
// "all", // WGSL builtin
|
||||
"allow_uav_condition",
|
||||
// "any", // WGSL intrinsic
|
||||
// "any", // WGSL builtin
|
||||
"asdouble",
|
||||
"asfloat",
|
||||
// "asin", // WGSL intrinsic
|
||||
// "asin", // WGSL builtin
|
||||
"asint",
|
||||
// "asm", // WGSL keyword
|
||||
"asm_fragment",
|
||||
"asuint",
|
||||
// "atan", // WGSL intrinsic
|
||||
// "atan2", // WGSL intrinsic
|
||||
// "atan", // WGSL builtin
|
||||
// "atan2", // WGSL builtin
|
||||
"auto",
|
||||
// "bool", // WGSL keyword
|
||||
"bool1",
|
||||
|
@ -704,14 +704,14 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
"bool4x4",
|
||||
"branch",
|
||||
// "break", // WGSL keyword
|
||||
// "call", // WGSL intrinsic
|
||||
// "call", // WGSL builtin
|
||||
// "case", // WGSL keyword
|
||||
"catch",
|
||||
"cbuffer",
|
||||
// "ceil", // WGSL intrinsic
|
||||
// "ceil", // WGSL builtin
|
||||
"centroid",
|
||||
"char",
|
||||
// "clamp", // WGSL intrinsic
|
||||
// "clamp", // WGSL builtin
|
||||
"class",
|
||||
"clip",
|
||||
"column_major",
|
||||
|
@ -720,10 +720,10 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
// "const", // WGSL keyword
|
||||
"const_cast",
|
||||
// "continue", // WGSL keyword
|
||||
// "cos", // WGSL intrinsic
|
||||
// "cosh", // WGSL intrinsic
|
||||
// "cos", // WGSL builtin
|
||||
// "cosh", // WGSL builtin
|
||||
"countbits",
|
||||
// "cross", // WGSL intrinsic
|
||||
// "cross", // WGSL builtin
|
||||
"ddx",
|
||||
"ddx_coarse",
|
||||
"ddx_fine",
|
||||
|
@ -733,11 +733,11 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
// "default", // WGSL keyword
|
||||
"degrees",
|
||||
"delete",
|
||||
// "determinant", // WGSL intrinsic
|
||||
// "determinant", // WGSL builtin
|
||||
// "discard", // WGSL keyword
|
||||
// "distance", // WGSL intrinsic
|
||||
// "distance", // WGSL builtin
|
||||
// "do", // WGSL keyword
|
||||
// "dot", // WGSL intrinsic
|
||||
// "dot", // WGSL builtin
|
||||
"double",
|
||||
"double1",
|
||||
"double1x1",
|
||||
|
@ -785,14 +785,14 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
// "else", // WGSL keyword
|
||||
// "enum", // WGSL keyword
|
||||
"errorf",
|
||||
// "exp", // WGSL intrinsic
|
||||
// "exp2", // WGSL intrinsic
|
||||
// "exp", // WGSL builtin
|
||||
// "exp2", // WGSL builtin
|
||||
"explicit",
|
||||
"export",
|
||||
"extern",
|
||||
"f16to32",
|
||||
"f32tof16",
|
||||
// "faceforward", // WGSL intrinsic
|
||||
// "faceforward", // WGSL builtin
|
||||
// "false", // WGSL keyword
|
||||
"fastopt",
|
||||
"firstbithigh",
|
||||
|
@ -819,15 +819,15 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
"float4x2",
|
||||
"float4x3",
|
||||
"float4x4",
|
||||
// "floor", // WGSL intrinsic
|
||||
// "fma", // WGSL intrinsic
|
||||
// "floor", // WGSL builtin
|
||||
// "fma", // WGSL builtin
|
||||
"fmod",
|
||||
// "for", // WGSL keyword
|
||||
"forcecase",
|
||||
"frac",
|
||||
// "frexp", // WGSL intrinsic
|
||||
// "frexp", // WGSL builtin
|
||||
"friend",
|
||||
// "fwidth", // WGSL intrinsic
|
||||
// "fwidth", // WGSL builtin
|
||||
"fxgroup",
|
||||
"goto",
|
||||
"groupshared",
|
||||
|
@ -881,22 +881,22 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
"isfinite",
|
||||
"isinf",
|
||||
"isnan",
|
||||
// "ldexp", // WGSL intrinsic
|
||||
// "length", // WGSL intrinsic
|
||||
// "ldexp", // WGSL builtin
|
||||
// "length", // WGSL builtin
|
||||
"lerp",
|
||||
"line",
|
||||
"lineadj",
|
||||
"linear",
|
||||
"lit",
|
||||
// "log", // WGSL intrinsic
|
||||
// "log", // WGSL builtin
|
||||
"log10",
|
||||
// "log2", // WGSL intrinsic
|
||||
// "log2", // WGSL builtin
|
||||
"long",
|
||||
// "loop", // WGSL keyword
|
||||
"mad",
|
||||
"matrix",
|
||||
// "max", // WGSL intrinsic
|
||||
// "min", // WGSL intrinsic
|
||||
// "max", // WGSL builtin
|
||||
// "min", // WGSL builtin
|
||||
"min10float",
|
||||
"min10float1",
|
||||
"min10float1x1",
|
||||
|
@ -1002,7 +1002,7 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
"min16uint4x2",
|
||||
"min16uint4x3",
|
||||
"min16uint4x4",
|
||||
// "modf", // WGSL intrinsic
|
||||
// "modf", // WGSL builtin
|
||||
"msad4",
|
||||
"mul",
|
||||
"mutable",
|
||||
|
@ -1011,7 +1011,7 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
"nointerpolation",
|
||||
"noise",
|
||||
"noperspective",
|
||||
// "normalize", // WGSL intrinsic
|
||||
// "normalize", // WGSL builtin
|
||||
"numthreads",
|
||||
"operator",
|
||||
// "out", // WGSL keyword
|
||||
|
@ -1020,7 +1020,7 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
"pixelfragment",
|
||||
"pixelshader",
|
||||
"point",
|
||||
// "pow", // WGSL intrinsic
|
||||
// "pow", // WGSL builtin
|
||||
"precise",
|
||||
"printf",
|
||||
// "private", // WGSL keyword
|
||||
|
@ -1028,13 +1028,13 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
"public",
|
||||
"radians",
|
||||
"rcp",
|
||||
// "reflect", // WGSL intrinsic
|
||||
// "reflect", // WGSL builtin
|
||||
"refract",
|
||||
"register",
|
||||
"reinterpret_cast",
|
||||
// "return", // WGSL keyword
|
||||
// "reversebits", // WGSL intrinsic
|
||||
// "round", // WGSL intrinsic
|
||||
// "reversebits", // WGSL builtin
|
||||
// "round", // WGSL builtin
|
||||
"row_major",
|
||||
"rsqrt",
|
||||
"sample",
|
||||
|
@ -1046,25 +1046,25 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
"saturate",
|
||||
"shared",
|
||||
"short",
|
||||
// "sign", // WGSL intrinsic
|
||||
// "sign", // WGSL builtin
|
||||
"signed",
|
||||
// "sin", // WGSL intrinsic
|
||||
// "sin", // WGSL builtin
|
||||
"sincos",
|
||||
// "sinh", // WGSL intrinsic
|
||||
// "sinh", // WGSL builtin
|
||||
"sizeof",
|
||||
// "smoothstep", // WGSL intrinsic
|
||||
// "smoothstep", // WGSL builtin
|
||||
"snorm",
|
||||
// "sqrt", // WGSL intrinsic
|
||||
// "sqrt", // WGSL builtin
|
||||
"stateblock",
|
||||
"stateblock_state",
|
||||
"static",
|
||||
"static_cast",
|
||||
// "step", // WGSL intrinsic
|
||||
// "step", // WGSL builtin
|
||||
"string",
|
||||
// "struct", // WGSL keyword
|
||||
// "switch", // WGSL keyword
|
||||
// "tan", // WGSL intrinsic
|
||||
// "tanh", // WGSL intrinsic
|
||||
// "tan", // WGSL builtin
|
||||
// "tanh", // WGSL builtin
|
||||
"tbuffer",
|
||||
"technique",
|
||||
"technique10",
|
||||
|
@ -1106,7 +1106,7 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestHlsl,
|
|||
"triangle",
|
||||
"triangleadj",
|
||||
// "true", // WGSL keyword
|
||||
// "trunc", // WGSL intrinsic
|
||||
// "trunc", // WGSL builtin
|
||||
"try",
|
||||
// "typedef", // WGSL keyword
|
||||
"typename",
|
||||
|
|
|
@ -200,24 +200,24 @@ struct Robustness::State {
|
|||
return b.IndexAccessor(src, obj, idx.expr);
|
||||
}
|
||||
|
||||
/// @param type intrinsic type
|
||||
/// @returns true if the given intrinsic is a texture function that requires
|
||||
/// @param type builtin type
|
||||
/// @returns true if the given builtin is a texture function that requires
|
||||
/// argument clamping,
|
||||
bool TextureIntrinsicNeedsClamping(sem::IntrinsicType type) {
|
||||
return type == sem::IntrinsicType::kTextureLoad ||
|
||||
type == sem::IntrinsicType::kTextureStore;
|
||||
bool TextureBuiltinNeedsClamping(sem::BuiltinType type) {
|
||||
return type == sem::BuiltinType::kTextureLoad ||
|
||||
type == sem::BuiltinType::kTextureStore;
|
||||
}
|
||||
|
||||
/// Apply bounds clamping to the coordinates, array index and level arguments
|
||||
/// of the `textureLoad()` and `textureStore()` intrinsics.
|
||||
/// @param expr the intrinsic call expression
|
||||
/// of the `textureLoad()` and `textureStore()` builtins.
|
||||
/// @param expr the builtin call expression
|
||||
/// @return the clamped replacement call expression, or nullptr if `expr`
|
||||
/// should be cloned without changes.
|
||||
const ast::CallExpression* Transform(const ast::CallExpression* expr) {
|
||||
auto* call = ctx.src->Sem().Get(expr);
|
||||
auto* call_target = call->Target();
|
||||
auto* intrinsic = call_target->As<sem::Intrinsic>();
|
||||
if (!intrinsic || !TextureIntrinsicNeedsClamping(intrinsic->Type())) {
|
||||
auto* builtin = call_target->As<sem::Builtin>();
|
||||
if (!builtin || !TextureBuiltinNeedsClamping(builtin->Type())) {
|
||||
return nullptr; // No transform, just clone.
|
||||
}
|
||||
|
||||
|
@ -225,7 +225,7 @@ struct Robustness::State {
|
|||
|
||||
// Indices of the mandatory texture and coords parameters, and the optional
|
||||
// array and level parameters.
|
||||
auto& signature = intrinsic->Signature();
|
||||
auto& signature = builtin->Signature();
|
||||
auto texture_idx = signature.IndexOf(sem::ParameterUsage::kTexture);
|
||||
auto coords_idx = signature.IndexOf(sem::ParameterUsage::kCoords);
|
||||
auto array_idx = signature.IndexOf(sem::ParameterUsage::kArrayIndex);
|
||||
|
@ -233,7 +233,7 @@ struct Robustness::State {
|
|||
|
||||
auto* texture_arg = expr->args[texture_idx];
|
||||
auto* coords_arg = expr->args[coords_idx];
|
||||
auto* coords_ty = intrinsic->Parameters()[coords_idx]->Type();
|
||||
auto* coords_ty = builtin->Parameters()[coords_idx]->Type();
|
||||
|
||||
// If the level is provided, then we need to clamp this. As the level is
|
||||
// used by textureDimensions() and the texture[Load|Store]() calls, we need
|
||||
|
|
|
@ -444,8 +444,8 @@ bool GeneratorImpl::EmitCall(std::ostream& out,
|
|||
if (auto* func = target->As<sem::Function>()) {
|
||||
return EmitFunctionCall(out, call, func);
|
||||
}
|
||||
if (auto* intrinsic = target->As<sem::Intrinsic>()) {
|
||||
return EmitIntrinsicCall(out, call, intrinsic);
|
||||
if (auto* builtin = target->As<sem::Builtin>()) {
|
||||
return EmitBuiltinCall(out, call, builtin);
|
||||
}
|
||||
if (auto* cast = target->As<sem::TypeConversion>()) {
|
||||
return EmitTypeConversion(out, call, cast);
|
||||
|
@ -501,47 +501,47 @@ bool GeneratorImpl::EmitFunctionCall(std::ostream& out,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
bool GeneratorImpl::EmitBuiltinCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Builtin* builtin) {
|
||||
auto* expr = call->Declaration();
|
||||
if (intrinsic->IsTexture()) {
|
||||
return EmitTextureCall(out, call, intrinsic);
|
||||
if (builtin->IsTexture()) {
|
||||
return EmitTextureCall(out, call, builtin);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kSelect) {
|
||||
if (builtin->Type() == sem::BuiltinType::kSelect) {
|
||||
return EmitSelectCall(out, expr);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kDot) {
|
||||
return EmitDotCall(out, expr, intrinsic);
|
||||
if (builtin->Type() == sem::BuiltinType::kDot) {
|
||||
return EmitDotCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kModf) {
|
||||
return EmitModfCall(out, expr, intrinsic);
|
||||
if (builtin->Type() == sem::BuiltinType::kModf) {
|
||||
return EmitModfCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kFrexp) {
|
||||
return EmitFrexpCall(out, expr, intrinsic);
|
||||
if (builtin->Type() == sem::BuiltinType::kFrexp) {
|
||||
return EmitFrexpCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kIsNormal) {
|
||||
return EmitIsNormalCall(out, expr, intrinsic);
|
||||
if (builtin->Type() == sem::BuiltinType::kIsNormal) {
|
||||
return EmitIsNormalCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kDegrees) {
|
||||
return EmitDegreesCall(out, expr, intrinsic);
|
||||
if (builtin->Type() == sem::BuiltinType::kDegrees) {
|
||||
return EmitDegreesCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kRadians) {
|
||||
return EmitRadiansCall(out, expr, intrinsic);
|
||||
if (builtin->Type() == sem::BuiltinType::kRadians) {
|
||||
return EmitRadiansCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->IsDataPacking()) {
|
||||
return EmitDataPackingCall(out, expr, intrinsic);
|
||||
if (builtin->IsDataPacking()) {
|
||||
return EmitDataPackingCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->IsDataUnpacking()) {
|
||||
return EmitDataUnpackingCall(out, expr, intrinsic);
|
||||
if (builtin->IsDataUnpacking()) {
|
||||
return EmitDataUnpackingCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->IsBarrier()) {
|
||||
return EmitBarrierCall(out, intrinsic);
|
||||
if (builtin->IsBarrier()) {
|
||||
return EmitBarrierCall(out, builtin);
|
||||
}
|
||||
if (intrinsic->IsAtomic()) {
|
||||
return EmitWorkgroupAtomicCall(out, expr, intrinsic);
|
||||
if (builtin->IsAtomic()) {
|
||||
return EmitWorkgroupAtomicCall(out, expr, builtin);
|
||||
}
|
||||
auto name = generate_builtin_name(intrinsic);
|
||||
auto name = generate_builtin_name(builtin);
|
||||
if (name.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -621,7 +621,7 @@ bool GeneratorImpl::EmitTypeConstructor(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
const sem::Builtin* builtin) {
|
||||
auto call = [&](const char* name) {
|
||||
out << name;
|
||||
{
|
||||
|
@ -639,8 +639,8 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
|||
return true;
|
||||
};
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kAtomicLoad: {
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kAtomicLoad: {
|
||||
// GLSL does not have an atomicLoad, so we emulate it with
|
||||
// atomicOr using 0 as the OR value
|
||||
out << "atomicOr";
|
||||
|
@ -650,19 +650,19 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
|||
return false;
|
||||
}
|
||||
out << ", 0";
|
||||
if (intrinsic->ReturnType()->Is<sem::U32>()) {
|
||||
if (builtin->ReturnType()->Is<sem::U32>()) {
|
||||
out << "u";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case sem::IntrinsicType::kAtomicCompareExchangeWeak: {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
case sem::BuiltinType::kAtomicCompareExchangeWeak: {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
{
|
||||
auto pre = line(b);
|
||||
if (!EmitTypeAndName(pre, intrinsic->ReturnType(),
|
||||
if (!EmitTypeAndName(pre, builtin->ReturnType(),
|
||||
ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, "result")) {
|
||||
return false;
|
||||
|
@ -694,27 +694,27 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
|||
});
|
||||
}
|
||||
|
||||
case sem::IntrinsicType::kAtomicAdd:
|
||||
case sem::IntrinsicType::kAtomicSub:
|
||||
case sem::BuiltinType::kAtomicAdd:
|
||||
case sem::BuiltinType::kAtomicSub:
|
||||
return call("atomicAdd");
|
||||
|
||||
case sem::IntrinsicType::kAtomicMax:
|
||||
case sem::BuiltinType::kAtomicMax:
|
||||
return call("atomicMax");
|
||||
|
||||
case sem::IntrinsicType::kAtomicMin:
|
||||
case sem::BuiltinType::kAtomicMin:
|
||||
return call("atomicMin");
|
||||
|
||||
case sem::IntrinsicType::kAtomicAnd:
|
||||
case sem::BuiltinType::kAtomicAnd:
|
||||
return call("atomicAnd");
|
||||
|
||||
case sem::IntrinsicType::kAtomicOr:
|
||||
case sem::BuiltinType::kAtomicOr:
|
||||
return call("atomicOr");
|
||||
|
||||
case sem::IntrinsicType::kAtomicXor:
|
||||
case sem::BuiltinType::kAtomicXor:
|
||||
return call("atomicXor");
|
||||
|
||||
case sem::IntrinsicType::kAtomicExchange:
|
||||
case sem::IntrinsicType::kAtomicStore:
|
||||
case sem::BuiltinType::kAtomicExchange:
|
||||
case sem::BuiltinType::kAtomicStore:
|
||||
// GLSL does not have an atomicStore, so we emulate it with
|
||||
// atomicExchange.
|
||||
return call("atomicExchange");
|
||||
|
@ -724,7 +724,7 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
|||
}
|
||||
|
||||
TINT_UNREACHABLE(Writer, diagnostics_)
|
||||
<< "unsupported atomic intrinsic: " << intrinsic->Type();
|
||||
<< "unsupported atomic builtin: " << builtin->Type();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -755,8 +755,8 @@ bool GeneratorImpl::EmitSelectCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitDotCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
auto* vec_ty = intrinsic->Parameters()[0]->Type()->As<sem::Vector>();
|
||||
const sem::Builtin* builtin) {
|
||||
auto* vec_ty = builtin->Parameters()[0]->Type()->As<sem::Vector>();
|
||||
std::string fn = "dot";
|
||||
if (vec_ty->type()->is_integer_scalar()) {
|
||||
// GLSL does not have a builtin for dot() with integer vector types.
|
||||
|
@ -827,12 +827,12 @@ bool GeneratorImpl::EmitDotCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitModfCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
const sem::Builtin* builtin) {
|
||||
if (expr->args.size() == 1) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
auto* ty = intrinsic->Parameters()[0]->Type();
|
||||
auto* ty = builtin->Parameters()[0]->Type();
|
||||
auto in = params[0];
|
||||
|
||||
std::string width;
|
||||
|
@ -843,7 +843,7 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
|
|||
// Emit the builtin return type unique to this overload. This does not
|
||||
// exist in the AST, so it will not be generated in Generate().
|
||||
if (!EmitStructType(&helpers_,
|
||||
intrinsic->ReturnType()->As<sem::Struct>())) {
|
||||
builtin->ReturnType()->As<sem::Struct>())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -851,7 +851,7 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
|
|||
line(b) << "float" << width << " fract = modf(" << in << ", whole);";
|
||||
{
|
||||
auto l = line(b);
|
||||
if (!EmitType(l, intrinsic->ReturnType(), ast::StorageClass::kNone,
|
||||
if (!EmitType(l, builtin->ReturnType(), ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, "")) {
|
||||
return false;
|
||||
}
|
||||
|
@ -877,12 +877,12 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
const sem::Builtin* builtin) {
|
||||
if (expr->args.size() == 1) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
auto* ty = intrinsic->Parameters()[0]->Type();
|
||||
auto* ty = builtin->Parameters()[0]->Type();
|
||||
auto in = params[0];
|
||||
|
||||
std::string width;
|
||||
|
@ -893,7 +893,7 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
|||
// Emit the builtin return type unique to this overload. This does not
|
||||
// exist in the AST, so it will not be generated in Generate().
|
||||
if (!EmitStructType(&helpers_,
|
||||
intrinsic->ReturnType()->As<sem::Struct>())) {
|
||||
builtin->ReturnType()->As<sem::Struct>())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -901,7 +901,7 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
|||
line(b) << "float" << width << " sig = frexp(" << in << ", exp);";
|
||||
{
|
||||
auto l = line(b);
|
||||
if (!EmitType(l, intrinsic->ReturnType(), ast::StorageClass::kNone,
|
||||
if (!EmitType(l, builtin->ReturnType(), ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, "")) {
|
||||
return false;
|
||||
}
|
||||
|
@ -914,12 +914,12 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
|||
// DEPRECATED
|
||||
// Exponent is an integer in WGSL, but HLSL wants a float.
|
||||
// We need to make the call with a temporary float, and then cast.
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
auto* significand_ty = intrinsic->Parameters()[0]->Type();
|
||||
auto* significand_ty = builtin->Parameters()[0]->Type();
|
||||
auto significand = params[0];
|
||||
auto* exponent_ty = intrinsic->Parameters()[1]->Type();
|
||||
auto* exponent_ty = builtin->Parameters()[1]->Type();
|
||||
auto exponent = params[1];
|
||||
|
||||
std::string width;
|
||||
|
@ -948,12 +948,12 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitIsNormalCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
// GLSL doesn't have a isNormal intrinsic, we need to emulate
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
// GLSL doesn't have a isNormal builtin, we need to emulate
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
auto* input_ty = intrinsic->Parameters()[0]->Type();
|
||||
auto* input_ty = builtin->Parameters()[0]->Type();
|
||||
|
||||
std::string width;
|
||||
if (auto* vec = input_ty->As<sem::Vector>()) {
|
||||
|
@ -976,9 +976,9 @@ bool GeneratorImpl::EmitIsNormalCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
line(b) << "return " << params[0] << " * " << std::setprecision(20)
|
||||
<< sem::kRadToDeg << ";";
|
||||
|
@ -988,9 +988,9 @@ bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
line(b) << "return " << params[0] << " * " << std::setprecision(20)
|
||||
<< sem::kDegToRad << ";";
|
||||
|
@ -1000,28 +1000,28 @@ bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
uint32_t dims = 2;
|
||||
bool is_signed = false;
|
||||
uint32_t scale = 65535;
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kPack4x8snorm ||
|
||||
intrinsic->Type() == sem::IntrinsicType::kPack4x8unorm) {
|
||||
if (builtin->Type() == sem::BuiltinType::kPack4x8snorm ||
|
||||
builtin->Type() == sem::BuiltinType::kPack4x8unorm) {
|
||||
dims = 4;
|
||||
scale = 255;
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kPack4x8snorm ||
|
||||
intrinsic->Type() == sem::IntrinsicType::kPack2x16snorm) {
|
||||
if (builtin->Type() == sem::BuiltinType::kPack4x8snorm ||
|
||||
builtin->Type() == sem::BuiltinType::kPack2x16snorm) {
|
||||
is_signed = true;
|
||||
scale = (scale - 1) / 2;
|
||||
}
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kPack4x8snorm:
|
||||
case sem::IntrinsicType::kPack4x8unorm:
|
||||
case sem::IntrinsicType::kPack2x16snorm:
|
||||
case sem::IntrinsicType::kPack2x16unorm: {
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kPack4x8snorm:
|
||||
case sem::BuiltinType::kPack4x8unorm:
|
||||
case sem::BuiltinType::kPack2x16snorm:
|
||||
case sem::BuiltinType::kPack2x16unorm: {
|
||||
{
|
||||
auto l = line(b);
|
||||
l << (is_signed ? "" : "u") << "int" << dims
|
||||
|
@ -1048,7 +1048,7 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case sem::IntrinsicType::kPack2x16float: {
|
||||
case sem::BuiltinType::kPack2x16float: {
|
||||
line(b) << "uint2 i = f32tof16(" << params[0] << ");";
|
||||
line(b) << "return i.x | (i.y << 16);";
|
||||
break;
|
||||
|
@ -1056,7 +1056,7 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
|
|||
default:
|
||||
diagnostics_.add_error(
|
||||
diag::System::Writer,
|
||||
"Internal error: unhandled data packing intrinsic");
|
||||
"Internal error: unhandled data packing builtin");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1066,26 +1066,26 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
uint32_t dims = 2;
|
||||
bool is_signed = false;
|
||||
uint32_t scale = 65535;
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kUnpack4x8snorm ||
|
||||
intrinsic->Type() == sem::IntrinsicType::kUnpack4x8unorm) {
|
||||
if (builtin->Type() == sem::BuiltinType::kUnpack4x8snorm ||
|
||||
builtin->Type() == sem::BuiltinType::kUnpack4x8unorm) {
|
||||
dims = 4;
|
||||
scale = 255;
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kUnpack4x8snorm ||
|
||||
intrinsic->Type() == sem::IntrinsicType::kUnpack2x16snorm) {
|
||||
if (builtin->Type() == sem::BuiltinType::kUnpack4x8snorm ||
|
||||
builtin->Type() == sem::BuiltinType::kUnpack2x16snorm) {
|
||||
is_signed = true;
|
||||
scale = (scale - 1) / 2;
|
||||
}
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kUnpack4x8snorm:
|
||||
case sem::IntrinsicType::kUnpack2x16snorm: {
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kUnpack4x8snorm:
|
||||
case sem::BuiltinType::kUnpack2x16snorm: {
|
||||
line(b) << "int j = int(" << params[0] << ");";
|
||||
{ // Perform sign extension on the converted values.
|
||||
auto l = line(b);
|
||||
|
@ -1101,8 +1101,8 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
|
|||
<< ".0, " << (is_signed ? "-1.0" : "0.0") << ", 1.0);";
|
||||
break;
|
||||
}
|
||||
case sem::IntrinsicType::kUnpack4x8unorm:
|
||||
case sem::IntrinsicType::kUnpack2x16unorm: {
|
||||
case sem::BuiltinType::kUnpack4x8unorm:
|
||||
case sem::BuiltinType::kUnpack2x16unorm: {
|
||||
line(b) << "uint j = " << params[0] << ";";
|
||||
{
|
||||
auto l = line(b);
|
||||
|
@ -1119,14 +1119,14 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
|
|||
line(b) << "return float" << dims << "(i) / " << scale << ".0;";
|
||||
break;
|
||||
}
|
||||
case sem::IntrinsicType::kUnpack2x16float:
|
||||
case sem::BuiltinType::kUnpack2x16float:
|
||||
line(b) << "uint i = " << params[0] << ";";
|
||||
line(b) << "return f16tof32(uint2(i & 0xffff, i >> 16));";
|
||||
break;
|
||||
default:
|
||||
diagnostics_.add_error(
|
||||
diag::System::Writer,
|
||||
"Internal error: unhandled data packing intrinsic");
|
||||
"Internal error: unhandled data packing builtin");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1135,16 +1135,16 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
|
|||
}
|
||||
|
||||
bool GeneratorImpl::EmitBarrierCall(std::ostream& out,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
const sem::Builtin* builtin) {
|
||||
// TODO(crbug.com/tint/661): Combine sequential barriers to a single
|
||||
// instruction.
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kWorkgroupBarrier) {
|
||||
if (builtin->Type() == sem::BuiltinType::kWorkgroupBarrier) {
|
||||
out << "memoryBarrierShared()";
|
||||
} else if (intrinsic->Type() == sem::IntrinsicType::kStorageBarrier) {
|
||||
} else if (builtin->Type() == sem::BuiltinType::kStorageBarrier) {
|
||||
out << "memoryBarrierBuffer()";
|
||||
} else {
|
||||
TINT_UNREACHABLE(Writer, diagnostics_)
|
||||
<< "unexpected barrier intrinsic type " << sem::str(intrinsic->Type());
|
||||
<< "unexpected barrier builtin type " << sem::str(builtin->Type());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -1152,10 +1152,10 @@ bool GeneratorImpl::EmitBarrierCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
const sem::Builtin* builtin) {
|
||||
using Usage = sem::ParameterUsage;
|
||||
|
||||
auto& signature = intrinsic->Signature();
|
||||
auto& signature = builtin->Signature();
|
||||
auto* expr = call->Declaration();
|
||||
auto arguments = expr->args;
|
||||
|
||||
|
@ -1173,8 +1173,8 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
|
||||
auto* texture_type = TypeOf(texture)->UnwrapRef()->As<sem::Texture>();
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kTextureDimensions: {
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kTextureDimensions: {
|
||||
if (texture_type->Is<sem::StorageTexture>()) {
|
||||
out << "imageSize(";
|
||||
} else {
|
||||
|
@ -1207,8 +1207,8 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
return true;
|
||||
}
|
||||
// TODO(senorblanco): determine if this works for array textures
|
||||
case sem::IntrinsicType::kTextureNumLayers:
|
||||
case sem::IntrinsicType::kTextureNumLevels: {
|
||||
case sem::BuiltinType::kTextureNumLayers:
|
||||
case sem::BuiltinType::kTextureNumLevels: {
|
||||
out << "textureQueryLevels(";
|
||||
if (!EmitExpression(out, texture)) {
|
||||
return false;
|
||||
|
@ -1216,7 +1216,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
out << ");";
|
||||
return true;
|
||||
}
|
||||
case sem::IntrinsicType::kTextureNumSamples: {
|
||||
case sem::BuiltinType::kTextureNumSamples: {
|
||||
out << "textureSamples(";
|
||||
if (!EmitExpression(out, texture)) {
|
||||
return false;
|
||||
|
@ -1231,44 +1231,44 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
uint32_t glsl_ret_width = 4u;
|
||||
bool is_depth = texture_type->Is<sem::DepthTexture>();
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kTextureSample:
|
||||
case sem::IntrinsicType::kTextureSampleBias:
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kTextureSample:
|
||||
case sem::BuiltinType::kTextureSampleBias:
|
||||
out << "texture";
|
||||
if (is_depth) {
|
||||
glsl_ret_width = 1u;
|
||||
}
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureSampleLevel:
|
||||
case sem::BuiltinType::kTextureSampleLevel:
|
||||
out << "textureLod";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureGather:
|
||||
case sem::IntrinsicType::kTextureGatherCompare:
|
||||
case sem::BuiltinType::kTextureGather:
|
||||
case sem::BuiltinType::kTextureGatherCompare:
|
||||
out << "textureGather";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureSampleGrad:
|
||||
case sem::BuiltinType::kTextureSampleGrad:
|
||||
out << "textureGrad";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureSampleCompare:
|
||||
case sem::IntrinsicType::kTextureSampleCompareLevel:
|
||||
case sem::BuiltinType::kTextureSampleCompare:
|
||||
case sem::BuiltinType::kTextureSampleCompareLevel:
|
||||
out << "texture";
|
||||
glsl_ret_width = 1;
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureLoad:
|
||||
case sem::BuiltinType::kTextureLoad:
|
||||
out << "texelFetch";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureStore:
|
||||
case sem::BuiltinType::kTextureStore:
|
||||
out << "imageStore";
|
||||
break;
|
||||
default:
|
||||
diagnostics_.add_error(
|
||||
diag::System::Writer,
|
||||
"Internal compiler error: Unhandled texture intrinsic '" +
|
||||
std::string(intrinsic->str()) + "'");
|
||||
"Internal compiler error: Unhandled texture builtin '" +
|
||||
std::string(builtin->str()) + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (intrinsic->Signature().IndexOf(sem::ParameterUsage::kOffset) >= 0) {
|
||||
if (builtin->Signature().IndexOf(sem::ParameterUsage::kOffset) >= 0) {
|
||||
out << "Offset";
|
||||
}
|
||||
|
||||
|
@ -1299,7 +1299,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
if (auto* depth_ref = arg(Usage::kDepthRef)) {
|
||||
param_coords =
|
||||
AppendVector(&builder_, param_coords, depth_ref)->Declaration();
|
||||
} else if (intrinsic->Type() == sem::IntrinsicType::kTextureSample) {
|
||||
} else if (builtin->Type() == sem::BuiltinType::kTextureSample) {
|
||||
// Sampling a depth texture in GLSL always requires a depth reference, so
|
||||
// append zero here.
|
||||
auto* f32 = builder_.create<sem::F32>();
|
||||
|
@ -1327,7 +1327,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
}
|
||||
|
||||
// GLSL's textureGather always requires a refZ parameter.
|
||||
if (is_depth && intrinsic->Type() == sem::IntrinsicType::kTextureGather) {
|
||||
if (is_depth && builtin->Type() == sem::BuiltinType::kTextureGather) {
|
||||
out << ", 0.0";
|
||||
}
|
||||
|
||||
|
@ -1347,21 +1347,21 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
if (!EmitExpression(out, e)) {
|
||||
return false;
|
||||
}
|
||||
} else if (intrinsic->Type() == sem::IntrinsicType::kTextureSample) {
|
||||
} else if (builtin->Type() == sem::BuiltinType::kTextureSample) {
|
||||
out << ", 0.0f";
|
||||
}
|
||||
}
|
||||
|
||||
out << ")";
|
||||
|
||||
if (intrinsic->ReturnType()->Is<sem::Void>()) {
|
||||
if (builtin->ReturnType()->Is<sem::Void>()) {
|
||||
return true;
|
||||
}
|
||||
// If the intrinsic return type does not match the number of elements of the
|
||||
// GLSL intrinsic, we need to swizzle the expression to generate the correct
|
||||
// If the builtin return type does not match the number of elements of the
|
||||
// GLSL builtin, we need to swizzle the expression to generate the correct
|
||||
// number of components.
|
||||
uint32_t wgsl_ret_width = 1;
|
||||
if (auto* vec = intrinsic->ReturnType()->As<sem::Vector>()) {
|
||||
if (auto* vec = builtin->ReturnType()->As<sem::Vector>()) {
|
||||
wgsl_ret_width = vec->Width();
|
||||
}
|
||||
if (wgsl_ret_width < glsl_ret_width) {
|
||||
|
@ -1374,100 +1374,99 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
TINT_ICE(Writer, diagnostics_)
|
||||
<< "WGSL return width (" << wgsl_ret_width
|
||||
<< ") is wider than GLSL return width (" << glsl_ret_width << ") for "
|
||||
<< intrinsic->Type();
|
||||
<< builtin->Type();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string GeneratorImpl::generate_builtin_name(
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kAbs:
|
||||
case sem::IntrinsicType::kAcos:
|
||||
case sem::IntrinsicType::kAll:
|
||||
case sem::IntrinsicType::kAny:
|
||||
case sem::IntrinsicType::kAsin:
|
||||
case sem::IntrinsicType::kAtan:
|
||||
case sem::IntrinsicType::kCeil:
|
||||
case sem::IntrinsicType::kClamp:
|
||||
case sem::IntrinsicType::kCos:
|
||||
case sem::IntrinsicType::kCosh:
|
||||
case sem::IntrinsicType::kCross:
|
||||
case sem::IntrinsicType::kDeterminant:
|
||||
case sem::IntrinsicType::kDistance:
|
||||
case sem::IntrinsicType::kDot:
|
||||
case sem::IntrinsicType::kExp:
|
||||
case sem::IntrinsicType::kExp2:
|
||||
case sem::IntrinsicType::kFloor:
|
||||
case sem::IntrinsicType::kFrexp:
|
||||
case sem::IntrinsicType::kLdexp:
|
||||
case sem::IntrinsicType::kLength:
|
||||
case sem::IntrinsicType::kLog:
|
||||
case sem::IntrinsicType::kLog2:
|
||||
case sem::IntrinsicType::kMax:
|
||||
case sem::IntrinsicType::kMin:
|
||||
case sem::IntrinsicType::kModf:
|
||||
case sem::IntrinsicType::kNormalize:
|
||||
case sem::IntrinsicType::kPow:
|
||||
case sem::IntrinsicType::kReflect:
|
||||
case sem::IntrinsicType::kRefract:
|
||||
case sem::IntrinsicType::kRound:
|
||||
case sem::IntrinsicType::kSign:
|
||||
case sem::IntrinsicType::kSin:
|
||||
case sem::IntrinsicType::kSinh:
|
||||
case sem::IntrinsicType::kSqrt:
|
||||
case sem::IntrinsicType::kStep:
|
||||
case sem::IntrinsicType::kTan:
|
||||
case sem::IntrinsicType::kTanh:
|
||||
case sem::IntrinsicType::kTranspose:
|
||||
case sem::IntrinsicType::kTrunc:
|
||||
return intrinsic->str();
|
||||
case sem::IntrinsicType::kAtan2:
|
||||
std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kAbs:
|
||||
case sem::BuiltinType::kAcos:
|
||||
case sem::BuiltinType::kAll:
|
||||
case sem::BuiltinType::kAny:
|
||||
case sem::BuiltinType::kAsin:
|
||||
case sem::BuiltinType::kAtan:
|
||||
case sem::BuiltinType::kCeil:
|
||||
case sem::BuiltinType::kClamp:
|
||||
case sem::BuiltinType::kCos:
|
||||
case sem::BuiltinType::kCosh:
|
||||
case sem::BuiltinType::kCross:
|
||||
case sem::BuiltinType::kDeterminant:
|
||||
case sem::BuiltinType::kDistance:
|
||||
case sem::BuiltinType::kDot:
|
||||
case sem::BuiltinType::kExp:
|
||||
case sem::BuiltinType::kExp2:
|
||||
case sem::BuiltinType::kFloor:
|
||||
case sem::BuiltinType::kFrexp:
|
||||
case sem::BuiltinType::kLdexp:
|
||||
case sem::BuiltinType::kLength:
|
||||
case sem::BuiltinType::kLog:
|
||||
case sem::BuiltinType::kLog2:
|
||||
case sem::BuiltinType::kMax:
|
||||
case sem::BuiltinType::kMin:
|
||||
case sem::BuiltinType::kModf:
|
||||
case sem::BuiltinType::kNormalize:
|
||||
case sem::BuiltinType::kPow:
|
||||
case sem::BuiltinType::kReflect:
|
||||
case sem::BuiltinType::kRefract:
|
||||
case sem::BuiltinType::kRound:
|
||||
case sem::BuiltinType::kSign:
|
||||
case sem::BuiltinType::kSin:
|
||||
case sem::BuiltinType::kSinh:
|
||||
case sem::BuiltinType::kSqrt:
|
||||
case sem::BuiltinType::kStep:
|
||||
case sem::BuiltinType::kTan:
|
||||
case sem::BuiltinType::kTanh:
|
||||
case sem::BuiltinType::kTranspose:
|
||||
case sem::BuiltinType::kTrunc:
|
||||
return builtin->str();
|
||||
case sem::BuiltinType::kAtan2:
|
||||
return "atan";
|
||||
case sem::IntrinsicType::kCountOneBits:
|
||||
case sem::BuiltinType::kCountOneBits:
|
||||
return "countbits";
|
||||
case sem::IntrinsicType::kDpdx:
|
||||
case sem::BuiltinType::kDpdx:
|
||||
return "ddx";
|
||||
case sem::IntrinsicType::kDpdxCoarse:
|
||||
case sem::BuiltinType::kDpdxCoarse:
|
||||
return "ddx_coarse";
|
||||
case sem::IntrinsicType::kDpdxFine:
|
||||
case sem::BuiltinType::kDpdxFine:
|
||||
return "ddx_fine";
|
||||
case sem::IntrinsicType::kDpdy:
|
||||
case sem::BuiltinType::kDpdy:
|
||||
return "ddy";
|
||||
case sem::IntrinsicType::kDpdyCoarse:
|
||||
case sem::BuiltinType::kDpdyCoarse:
|
||||
return "ddy_coarse";
|
||||
case sem::IntrinsicType::kDpdyFine:
|
||||
case sem::BuiltinType::kDpdyFine:
|
||||
return "ddy_fine";
|
||||
case sem::IntrinsicType::kFaceForward:
|
||||
case sem::BuiltinType::kFaceForward:
|
||||
return "faceforward";
|
||||
case sem::IntrinsicType::kFract:
|
||||
case sem::BuiltinType::kFract:
|
||||
return "frac";
|
||||
case sem::IntrinsicType::kFma:
|
||||
case sem::BuiltinType::kFma:
|
||||
return "mad";
|
||||
case sem::IntrinsicType::kFwidth:
|
||||
case sem::IntrinsicType::kFwidthCoarse:
|
||||
case sem::IntrinsicType::kFwidthFine:
|
||||
case sem::BuiltinType::kFwidth:
|
||||
case sem::BuiltinType::kFwidthCoarse:
|
||||
case sem::BuiltinType::kFwidthFine:
|
||||
return "fwidth";
|
||||
case sem::IntrinsicType::kInverseSqrt:
|
||||
case sem::BuiltinType::kInverseSqrt:
|
||||
return "rsqrt";
|
||||
case sem::IntrinsicType::kIsFinite:
|
||||
case sem::BuiltinType::kIsFinite:
|
||||
return "isfinite";
|
||||
case sem::IntrinsicType::kIsInf:
|
||||
case sem::BuiltinType::kIsInf:
|
||||
return "isinf";
|
||||
case sem::IntrinsicType::kIsNan:
|
||||
case sem::BuiltinType::kIsNan:
|
||||
return "isnan";
|
||||
case sem::IntrinsicType::kMix:
|
||||
case sem::BuiltinType::kMix:
|
||||
return "mix";
|
||||
case sem::IntrinsicType::kReverseBits:
|
||||
case sem::BuiltinType::kReverseBits:
|
||||
return "reversebits";
|
||||
case sem::IntrinsicType::kSmoothStep:
|
||||
case sem::BuiltinType::kSmoothStep:
|
||||
return "smoothstep";
|
||||
default:
|
||||
diagnostics_.add_error(
|
||||
diag::System::Writer,
|
||||
"Unknown builtin method: " + std::string(intrinsic->str()));
|
||||
"Unknown builtin method: " + std::string(builtin->str()));
|
||||
}
|
||||
|
||||
return "";
|
||||
|
@ -2624,28 +2623,28 @@ bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
|
|||
}
|
||||
|
||||
template <typename F>
|
||||
bool GeneratorImpl::CallIntrinsicHelper(std::ostream& out,
|
||||
const ast::CallExpression* call,
|
||||
const sem::Intrinsic* intrinsic,
|
||||
F&& build) {
|
||||
bool GeneratorImpl::CallBuiltinHelper(std::ostream& out,
|
||||
const ast::CallExpression* call,
|
||||
const sem::Builtin* builtin,
|
||||
F&& build) {
|
||||
// Generate the helper function if it hasn't been created already
|
||||
auto fn = utils::GetOrCreate(intrinsics_, intrinsic, [&]() -> std::string {
|
||||
auto fn = utils::GetOrCreate(builtins_, builtin, [&]() -> std::string {
|
||||
TextBuffer b;
|
||||
TINT_DEFER(helpers_.Append(b));
|
||||
|
||||
auto fn_name =
|
||||
UniqueIdentifier(std::string("tint_") + sem::str(intrinsic->Type()));
|
||||
UniqueIdentifier(std::string("tint_") + sem::str(builtin->Type()));
|
||||
std::vector<std::string> parameter_names;
|
||||
{
|
||||
auto decl = line(&b);
|
||||
if (!EmitTypeAndName(decl, intrinsic->ReturnType(),
|
||||
if (!EmitTypeAndName(decl, builtin->ReturnType(),
|
||||
ast::StorageClass::kNone, ast::Access::kUndefined,
|
||||
fn_name)) {
|
||||
return "";
|
||||
}
|
||||
{
|
||||
ScopedParen sp(decl);
|
||||
for (auto* param : intrinsic->Parameters()) {
|
||||
for (auto* param : builtin->Parameters()) {
|
||||
if (!parameter_names.empty()) {
|
||||
decl << ", ";
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace tint {
|
|||
// Forward declarations
|
||||
namespace sem {
|
||||
class Call;
|
||||
class Intrinsic;
|
||||
class Builtin;
|
||||
class TypeConstructor;
|
||||
class TypeConversion;
|
||||
} // namespace sem
|
||||
|
@ -116,14 +116,14 @@ class GeneratorImpl : public TextGenerator {
|
|||
bool EmitFunctionCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Function* function);
|
||||
/// Handles generating an intrinsic call expression
|
||||
/// Handles generating a builtin call expression
|
||||
/// @param out the output of the expression stream
|
||||
/// @param call the call expression
|
||||
/// @param intrinsic the intrinsic being called
|
||||
/// @param builtin the builtin being called
|
||||
/// @returns true if the expression is emitted
|
||||
bool EmitIntrinsicCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
bool EmitBuiltinCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a type conversion expression
|
||||
/// @param out the output of the expression stream
|
||||
/// @param call the call expression
|
||||
|
@ -140,11 +140,11 @@ class GeneratorImpl : public TextGenerator {
|
|||
bool EmitTypeConstructor(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::TypeConstructor* ctor);
|
||||
/// Handles generating a barrier intrinsic call
|
||||
/// Handles generating a barrier builtin call
|
||||
/// @param out the output of the expression stream
|
||||
/// @param intrinsic the semantic information for the barrier intrinsic
|
||||
/// @param builtin the semantic information for the barrier builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitBarrierCall(std::ostream& out, const sem::Intrinsic* intrinsic);
|
||||
bool EmitBarrierCall(std::ostream& out, const sem::Builtin* builtin);
|
||||
/// Handles generating an atomic intrinsic call for a storage buffer variable
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
|
@ -154,92 +154,92 @@ class GeneratorImpl : public TextGenerator {
|
|||
std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const transform::DecomposeMemoryAccess::Intrinsic* intrinsic);
|
||||
/// Handles generating an atomic intrinsic call for a workgroup variable
|
||||
/// Handles generating an atomic builtin call for a workgroup variable
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the atomic intrinsic
|
||||
/// @param builtin the semantic information for the atomic builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitWorkgroupAtomicCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to a texture function (`textureSample`,
|
||||
/// `textureSampleGrad`, etc)
|
||||
/// @param out the output of the expression stream
|
||||
/// @param call the call expression
|
||||
/// @param intrinsic the semantic information for the texture intrinsic
|
||||
/// @param builtin the semantic information for the texture builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitTextureCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `select()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `select()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitSelectCall(std::ostream& out, const ast::CallExpression* expr);
|
||||
/// Handles generating a call to the `dot()` intrinsic
|
||||
/// Handles generating a call to the `dot()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitDotCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `modf()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `modf()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitModfCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `frexp()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `frexp()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitFrexpCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `isNormal()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `isNormal()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitIsNormalCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `degrees()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `degrees()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitDegreesCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `radians()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `radians()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitRadiansCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to data packing intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to data packing builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the texture intrinsic
|
||||
/// @param builtin the semantic information for the texture builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitDataPackingCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to data unpacking intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to data unpacking builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the texture intrinsic
|
||||
/// @param builtin the semantic information for the texture builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitDataUnpackingCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles a case statement
|
||||
/// @param stmt the statement
|
||||
/// @returns true if the statement was emitted successfully
|
||||
|
@ -407,9 +407,9 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// @returns true if the variable was emitted
|
||||
bool EmitProgramConstVariable(const ast::Variable* var);
|
||||
/// Handles generating a builtin method name
|
||||
/// @param intrinsic the semantic info for the intrinsic
|
||||
/// @param builtin the semantic info for the builtin
|
||||
/// @returns the name or "" if not valid
|
||||
std::string generate_builtin_name(const sem::Intrinsic* intrinsic);
|
||||
std::string generate_builtin_name(const sem::Builtin* builtin);
|
||||
/// Converts a builtin to a gl_ string
|
||||
/// @param builtin the builtin to convert
|
||||
/// @param stage pipeline stage in which this builtin is used
|
||||
|
@ -444,13 +444,13 @@ class GeneratorImpl : public TextGenerator {
|
|||
};
|
||||
};
|
||||
|
||||
/// CallIntrinsicHelper will call the intrinsic helper function, creating it
|
||||
/// if it hasn't been built already. If the intrinsic needs to be built then
|
||||
/// CallIntrinsicHelper will generate the function signature and will call
|
||||
/// CallBuiltinHelper will call the builtin helper function, creating it
|
||||
/// if it hasn't been built already. If the builtin needs to be built then
|
||||
/// CallBuiltinHelper will generate the function signature and will call
|
||||
/// `build` to emit the body of the function.
|
||||
/// @param out the output of the expression stream
|
||||
/// @param call the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @param build a function with the signature:
|
||||
/// `bool(TextBuffer* buffer, const std::vector<std::string>& params)`
|
||||
/// Where:
|
||||
|
@ -458,16 +458,16 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// `params` is the name of all the generated function parameters
|
||||
/// @returns true if the call expression is emitted
|
||||
template <typename F>
|
||||
bool CallIntrinsicHelper(std::ostream& out,
|
||||
const ast::CallExpression* call,
|
||||
const sem::Intrinsic* intrinsic,
|
||||
F&& build);
|
||||
bool CallBuiltinHelper(std::ostream& out,
|
||||
const ast::CallExpression* call,
|
||||
const sem::Builtin* builtin,
|
||||
F&& build);
|
||||
|
||||
TextBuffer helpers_; // Helper functions emitted at the top of the output
|
||||
std::function<bool()> emit_continuing_;
|
||||
std::unordered_map<DMAIntrinsic, std::string, DMAIntrinsic::Hasher>
|
||||
dma_intrinsics_;
|
||||
std::unordered_map<const sem::Intrinsic*, std::string> intrinsics_;
|
||||
std::unordered_map<const sem::Builtin*, std::string> builtins_;
|
||||
std::unordered_map<const sem::Struct*, std::string> structure_builders_;
|
||||
std::unordered_map<const sem::Vector*, std::string> dynamic_vector_write_;
|
||||
std::unordered_map<const sem::Vector*, std::string> int_dot_funcs_;
|
||||
|
|
|
@ -23,11 +23,11 @@ namespace writer {
|
|||
namespace glsl {
|
||||
namespace {
|
||||
|
||||
using IntrinsicType = sem::IntrinsicType;
|
||||
using BuiltinType = sem::BuiltinType;
|
||||
|
||||
using ::testing::HasSubstr;
|
||||
|
||||
using GlslGeneratorImplTest_Intrinsic = TestHelper;
|
||||
using GlslGeneratorImplTest_Builtin = TestHelper;
|
||||
|
||||
enum class ParamType {
|
||||
kF32,
|
||||
|
@ -35,12 +35,12 @@ enum class ParamType {
|
|||
kBool,
|
||||
};
|
||||
|
||||
struct IntrinsicData {
|
||||
IntrinsicType intrinsic;
|
||||
struct BuiltinData {
|
||||
BuiltinType builtin;
|
||||
ParamType type;
|
||||
const char* glsl_name;
|
||||
};
|
||||
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
|
||||
inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
|
||||
out << data.glsl_name;
|
||||
switch (data.type) {
|
||||
case ParamType::kF32:
|
||||
|
@ -57,104 +57,104 @@ inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
|
|||
return out;
|
||||
}
|
||||
|
||||
const ast::CallExpression* GenerateCall(IntrinsicType intrinsic,
|
||||
const ast::CallExpression* GenerateCall(BuiltinType builtin,
|
||||
ParamType type,
|
||||
ProgramBuilder* builder) {
|
||||
std::string name;
|
||||
std::ostringstream str(name);
|
||||
str << intrinsic;
|
||||
switch (intrinsic) {
|
||||
case IntrinsicType::kAcos:
|
||||
case IntrinsicType::kAsin:
|
||||
case IntrinsicType::kAtan:
|
||||
case IntrinsicType::kCeil:
|
||||
case IntrinsicType::kCos:
|
||||
case IntrinsicType::kCosh:
|
||||
case IntrinsicType::kDpdx:
|
||||
case IntrinsicType::kDpdxCoarse:
|
||||
case IntrinsicType::kDpdxFine:
|
||||
case IntrinsicType::kDpdy:
|
||||
case IntrinsicType::kDpdyCoarse:
|
||||
case IntrinsicType::kDpdyFine:
|
||||
case IntrinsicType::kExp:
|
||||
case IntrinsicType::kExp2:
|
||||
case IntrinsicType::kFloor:
|
||||
case IntrinsicType::kFract:
|
||||
case IntrinsicType::kFwidth:
|
||||
case IntrinsicType::kFwidthCoarse:
|
||||
case IntrinsicType::kFwidthFine:
|
||||
case IntrinsicType::kInverseSqrt:
|
||||
case IntrinsicType::kIsFinite:
|
||||
case IntrinsicType::kIsInf:
|
||||
case IntrinsicType::kIsNan:
|
||||
case IntrinsicType::kIsNormal:
|
||||
case IntrinsicType::kLength:
|
||||
case IntrinsicType::kLog:
|
||||
case IntrinsicType::kLog2:
|
||||
case IntrinsicType::kNormalize:
|
||||
case IntrinsicType::kRound:
|
||||
case IntrinsicType::kSin:
|
||||
case IntrinsicType::kSinh:
|
||||
case IntrinsicType::kSqrt:
|
||||
case IntrinsicType::kTan:
|
||||
case IntrinsicType::kTanh:
|
||||
case IntrinsicType::kTrunc:
|
||||
case IntrinsicType::kSign:
|
||||
str << builtin;
|
||||
switch (builtin) {
|
||||
case BuiltinType::kAcos:
|
||||
case BuiltinType::kAsin:
|
||||
case BuiltinType::kAtan:
|
||||
case BuiltinType::kCeil:
|
||||
case BuiltinType::kCos:
|
||||
case BuiltinType::kCosh:
|
||||
case BuiltinType::kDpdx:
|
||||
case BuiltinType::kDpdxCoarse:
|
||||
case BuiltinType::kDpdxFine:
|
||||
case BuiltinType::kDpdy:
|
||||
case BuiltinType::kDpdyCoarse:
|
||||
case BuiltinType::kDpdyFine:
|
||||
case BuiltinType::kExp:
|
||||
case BuiltinType::kExp2:
|
||||
case BuiltinType::kFloor:
|
||||
case BuiltinType::kFract:
|
||||
case BuiltinType::kFwidth:
|
||||
case BuiltinType::kFwidthCoarse:
|
||||
case BuiltinType::kFwidthFine:
|
||||
case BuiltinType::kInverseSqrt:
|
||||
case BuiltinType::kIsFinite:
|
||||
case BuiltinType::kIsInf:
|
||||
case BuiltinType::kIsNan:
|
||||
case BuiltinType::kIsNormal:
|
||||
case BuiltinType::kLength:
|
||||
case BuiltinType::kLog:
|
||||
case BuiltinType::kLog2:
|
||||
case BuiltinType::kNormalize:
|
||||
case BuiltinType::kRound:
|
||||
case BuiltinType::kSin:
|
||||
case BuiltinType::kSinh:
|
||||
case BuiltinType::kSqrt:
|
||||
case BuiltinType::kTan:
|
||||
case BuiltinType::kTanh:
|
||||
case BuiltinType::kTrunc:
|
||||
case BuiltinType::kSign:
|
||||
return builder->Call(str.str(), "f2");
|
||||
case IntrinsicType::kLdexp:
|
||||
case BuiltinType::kLdexp:
|
||||
return builder->Call(str.str(), "f2", "i2");
|
||||
case IntrinsicType::kAtan2:
|
||||
case IntrinsicType::kDot:
|
||||
case IntrinsicType::kDistance:
|
||||
case IntrinsicType::kPow:
|
||||
case IntrinsicType::kReflect:
|
||||
case IntrinsicType::kStep:
|
||||
case BuiltinType::kAtan2:
|
||||
case BuiltinType::kDot:
|
||||
case BuiltinType::kDistance:
|
||||
case BuiltinType::kPow:
|
||||
case BuiltinType::kReflect:
|
||||
case BuiltinType::kStep:
|
||||
return builder->Call(str.str(), "f2", "f2");
|
||||
case IntrinsicType::kCross:
|
||||
case BuiltinType::kCross:
|
||||
return builder->Call(str.str(), "f3", "f3");
|
||||
case IntrinsicType::kFma:
|
||||
case IntrinsicType::kMix:
|
||||
case IntrinsicType::kFaceForward:
|
||||
case IntrinsicType::kSmoothStep:
|
||||
case BuiltinType::kFma:
|
||||
case BuiltinType::kMix:
|
||||
case BuiltinType::kFaceForward:
|
||||
case BuiltinType::kSmoothStep:
|
||||
return builder->Call(str.str(), "f2", "f2", "f2");
|
||||
case IntrinsicType::kAll:
|
||||
case IntrinsicType::kAny:
|
||||
case BuiltinType::kAll:
|
||||
case BuiltinType::kAny:
|
||||
return builder->Call(str.str(), "b2");
|
||||
case IntrinsicType::kAbs:
|
||||
case BuiltinType::kAbs:
|
||||
if (type == ParamType::kF32) {
|
||||
return builder->Call(str.str(), "f2");
|
||||
} else {
|
||||
return builder->Call(str.str(), "u2");
|
||||
}
|
||||
case IntrinsicType::kCountOneBits:
|
||||
case IntrinsicType::kReverseBits:
|
||||
case BuiltinType::kCountOneBits:
|
||||
case BuiltinType::kReverseBits:
|
||||
return builder->Call(str.str(), "u2");
|
||||
case IntrinsicType::kMax:
|
||||
case IntrinsicType::kMin:
|
||||
case BuiltinType::kMax:
|
||||
case BuiltinType::kMin:
|
||||
if (type == ParamType::kF32) {
|
||||
return builder->Call(str.str(), "f2", "f2");
|
||||
} else {
|
||||
return builder->Call(str.str(), "u2", "u2");
|
||||
}
|
||||
case IntrinsicType::kClamp:
|
||||
case BuiltinType::kClamp:
|
||||
if (type == ParamType::kF32) {
|
||||
return builder->Call(str.str(), "f2", "f2", "f2");
|
||||
} else {
|
||||
return builder->Call(str.str(), "u2", "u2", "u2");
|
||||
}
|
||||
case IntrinsicType::kSelect:
|
||||
case BuiltinType::kSelect:
|
||||
return builder->Call(str.str(), "f2", "f2", "b2");
|
||||
case IntrinsicType::kDeterminant:
|
||||
case BuiltinType::kDeterminant:
|
||||
return builder->Call(str.str(), "m2x2");
|
||||
case IntrinsicType::kTranspose:
|
||||
case BuiltinType::kTranspose:
|
||||
return builder->Call(str.str(), "m3x2");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
using GlslIntrinsicTest = TestParamHelper<IntrinsicData>;
|
||||
TEST_P(GlslIntrinsicTest, Emit) {
|
||||
using GlslBuiltinTest = TestParamHelper<BuiltinData>;
|
||||
TEST_P(GlslBuiltinTest, Emit) {
|
||||
auto param = GetParam();
|
||||
|
||||
Global("f2", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
|
@ -165,8 +165,8 @@ TEST_P(GlslIntrinsicTest, Emit) {
|
|||
Global("m2x2", ty.mat2x2<f32>(), ast::StorageClass::kPrivate);
|
||||
Global("m3x2", ty.mat3x2<f32>(), ast::StorageClass::kPrivate);
|
||||
|
||||
auto* call = GenerateCall(param.intrinsic, param.type, this);
|
||||
ASSERT_NE(nullptr, call) << "Unhandled intrinsic";
|
||||
auto* call = GenerateCall(param.builtin, param.type, this);
|
||||
ASSERT_NE(nullptr, call) << "Unhandled builtin";
|
||||
Func("func", {}, ty.void_(), {CallStmt(call)},
|
||||
{create<ast::StageAttribute>(ast::PipelineStage::kFragment)});
|
||||
|
||||
|
@ -176,89 +176,82 @@ TEST_P(GlslIntrinsicTest, Emit) {
|
|||
ASSERT_NE(sem, nullptr);
|
||||
auto* target = sem->Target();
|
||||
ASSERT_NE(target, nullptr);
|
||||
auto* intrinsic = target->As<sem::Intrinsic>();
|
||||
ASSERT_NE(intrinsic, nullptr);
|
||||
auto* builtin = target->As<sem::Builtin>();
|
||||
ASSERT_NE(builtin, nullptr);
|
||||
|
||||
EXPECT_EQ(gen.generate_builtin_name(intrinsic), param.glsl_name);
|
||||
EXPECT_EQ(gen.generate_builtin_name(builtin), param.glsl_name);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
GlslGeneratorImplTest_Intrinsic,
|
||||
GlslIntrinsicTest,
|
||||
GlslGeneratorImplTest_Builtin,
|
||||
GlslBuiltinTest,
|
||||
testing::Values(
|
||||
IntrinsicData{IntrinsicType::kAbs, ParamType::kF32, "abs"},
|
||||
IntrinsicData{IntrinsicType::kAbs, ParamType::kU32, "abs"},
|
||||
IntrinsicData{IntrinsicType::kAcos, ParamType::kF32, "acos"},
|
||||
IntrinsicData{IntrinsicType::kAll, ParamType::kBool, "all"},
|
||||
IntrinsicData{IntrinsicType::kAny, ParamType::kBool, "any"},
|
||||
IntrinsicData{IntrinsicType::kAsin, ParamType::kF32, "asin"},
|
||||
IntrinsicData{IntrinsicType::kAtan, ParamType::kF32, "atan"},
|
||||
IntrinsicData{IntrinsicType::kAtan2, ParamType::kF32, "atan"},
|
||||
IntrinsicData{IntrinsicType::kCeil, ParamType::kF32, "ceil"},
|
||||
IntrinsicData{IntrinsicType::kClamp, ParamType::kF32, "clamp"},
|
||||
IntrinsicData{IntrinsicType::kClamp, ParamType::kU32, "clamp"},
|
||||
IntrinsicData{IntrinsicType::kCos, ParamType::kF32, "cos"},
|
||||
IntrinsicData{IntrinsicType::kCosh, ParamType::kF32, "cosh"},
|
||||
IntrinsicData{IntrinsicType::kCountOneBits, ParamType::kU32,
|
||||
"countbits"},
|
||||
IntrinsicData{IntrinsicType::kCross, ParamType::kF32, "cross"},
|
||||
IntrinsicData{IntrinsicType::kDeterminant, ParamType::kF32,
|
||||
"determinant"},
|
||||
IntrinsicData{IntrinsicType::kDistance, ParamType::kF32, "distance"},
|
||||
IntrinsicData{IntrinsicType::kDot, ParamType::kF32, "dot"},
|
||||
IntrinsicData{IntrinsicType::kDpdx, ParamType::kF32, "ddx"},
|
||||
IntrinsicData{IntrinsicType::kDpdxCoarse, ParamType::kF32,
|
||||
"ddx_coarse"},
|
||||
IntrinsicData{IntrinsicType::kDpdxFine, ParamType::kF32, "ddx_fine"},
|
||||
IntrinsicData{IntrinsicType::kDpdy, ParamType::kF32, "ddy"},
|
||||
IntrinsicData{IntrinsicType::kDpdyCoarse, ParamType::kF32,
|
||||
"ddy_coarse"},
|
||||
IntrinsicData{IntrinsicType::kDpdyFine, ParamType::kF32, "ddy_fine"},
|
||||
IntrinsicData{IntrinsicType::kExp, ParamType::kF32, "exp"},
|
||||
IntrinsicData{IntrinsicType::kExp2, ParamType::kF32, "exp2"},
|
||||
IntrinsicData{IntrinsicType::kFaceForward, ParamType::kF32,
|
||||
"faceforward"},
|
||||
IntrinsicData{IntrinsicType::kFloor, ParamType::kF32, "floor"},
|
||||
IntrinsicData{IntrinsicType::kFma, ParamType::kF32, "mad"},
|
||||
IntrinsicData{IntrinsicType::kFract, ParamType::kF32, "frac"},
|
||||
IntrinsicData{IntrinsicType::kFwidth, ParamType::kF32, "fwidth"},
|
||||
IntrinsicData{IntrinsicType::kFwidthCoarse, ParamType::kF32, "fwidth"},
|
||||
IntrinsicData{IntrinsicType::kFwidthFine, ParamType::kF32, "fwidth"},
|
||||
IntrinsicData{IntrinsicType::kInverseSqrt, ParamType::kF32, "rsqrt"},
|
||||
IntrinsicData{IntrinsicType::kIsFinite, ParamType::kF32, "isfinite"},
|
||||
IntrinsicData{IntrinsicType::kIsInf, ParamType::kF32, "isinf"},
|
||||
IntrinsicData{IntrinsicType::kIsNan, ParamType::kF32, "isnan"},
|
||||
IntrinsicData{IntrinsicType::kLdexp, ParamType::kF32, "ldexp"},
|
||||
IntrinsicData{IntrinsicType::kLength, ParamType::kF32, "length"},
|
||||
IntrinsicData{IntrinsicType::kLog, ParamType::kF32, "log"},
|
||||
IntrinsicData{IntrinsicType::kLog2, ParamType::kF32, "log2"},
|
||||
IntrinsicData{IntrinsicType::kMax, ParamType::kF32, "max"},
|
||||
IntrinsicData{IntrinsicType::kMax, ParamType::kU32, "max"},
|
||||
IntrinsicData{IntrinsicType::kMin, ParamType::kF32, "min"},
|
||||
IntrinsicData{IntrinsicType::kMin, ParamType::kU32, "min"},
|
||||
IntrinsicData{IntrinsicType::kMix, ParamType::kF32, "mix"},
|
||||
IntrinsicData{IntrinsicType::kNormalize, ParamType::kF32, "normalize"},
|
||||
IntrinsicData{IntrinsicType::kPow, ParamType::kF32, "pow"},
|
||||
IntrinsicData{IntrinsicType::kReflect, ParamType::kF32, "reflect"},
|
||||
IntrinsicData{IntrinsicType::kReverseBits, ParamType::kU32,
|
||||
"reversebits"},
|
||||
IntrinsicData{IntrinsicType::kRound, ParamType::kU32, "round"},
|
||||
IntrinsicData{IntrinsicType::kSign, ParamType::kF32, "sign"},
|
||||
IntrinsicData{IntrinsicType::kSin, ParamType::kF32, "sin"},
|
||||
IntrinsicData{IntrinsicType::kSinh, ParamType::kF32, "sinh"},
|
||||
IntrinsicData{IntrinsicType::kSmoothStep, ParamType::kF32,
|
||||
"smoothstep"},
|
||||
IntrinsicData{IntrinsicType::kSqrt, ParamType::kF32, "sqrt"},
|
||||
IntrinsicData{IntrinsicType::kStep, ParamType::kF32, "step"},
|
||||
IntrinsicData{IntrinsicType::kTan, ParamType::kF32, "tan"},
|
||||
IntrinsicData{IntrinsicType::kTanh, ParamType::kF32, "tanh"},
|
||||
IntrinsicData{IntrinsicType::kTranspose, ParamType::kF32, "transpose"},
|
||||
IntrinsicData{IntrinsicType::kTrunc, ParamType::kF32, "trunc"}));
|
||||
BuiltinData{BuiltinType::kAbs, ParamType::kF32, "abs"},
|
||||
BuiltinData{BuiltinType::kAbs, ParamType::kU32, "abs"},
|
||||
BuiltinData{BuiltinType::kAcos, ParamType::kF32, "acos"},
|
||||
BuiltinData{BuiltinType::kAll, ParamType::kBool, "all"},
|
||||
BuiltinData{BuiltinType::kAny, ParamType::kBool, "any"},
|
||||
BuiltinData{BuiltinType::kAsin, ParamType::kF32, "asin"},
|
||||
BuiltinData{BuiltinType::kAtan, ParamType::kF32, "atan"},
|
||||
BuiltinData{BuiltinType::kAtan2, ParamType::kF32, "atan"},
|
||||
BuiltinData{BuiltinType::kCeil, ParamType::kF32, "ceil"},
|
||||
BuiltinData{BuiltinType::kClamp, ParamType::kF32, "clamp"},
|
||||
BuiltinData{BuiltinType::kClamp, ParamType::kU32, "clamp"},
|
||||
BuiltinData{BuiltinType::kCos, ParamType::kF32, "cos"},
|
||||
BuiltinData{BuiltinType::kCosh, ParamType::kF32, "cosh"},
|
||||
BuiltinData{BuiltinType::kCountOneBits, ParamType::kU32, "countbits"},
|
||||
BuiltinData{BuiltinType::kCross, ParamType::kF32, "cross"},
|
||||
BuiltinData{BuiltinType::kDeterminant, ParamType::kF32, "determinant"},
|
||||
BuiltinData{BuiltinType::kDistance, ParamType::kF32, "distance"},
|
||||
BuiltinData{BuiltinType::kDot, ParamType::kF32, "dot"},
|
||||
BuiltinData{BuiltinType::kDpdx, ParamType::kF32, "ddx"},
|
||||
BuiltinData{BuiltinType::kDpdxCoarse, ParamType::kF32, "ddx_coarse"},
|
||||
BuiltinData{BuiltinType::kDpdxFine, ParamType::kF32, "ddx_fine"},
|
||||
BuiltinData{BuiltinType::kDpdy, ParamType::kF32, "ddy"},
|
||||
BuiltinData{BuiltinType::kDpdyCoarse, ParamType::kF32, "ddy_coarse"},
|
||||
BuiltinData{BuiltinType::kDpdyFine, ParamType::kF32, "ddy_fine"},
|
||||
BuiltinData{BuiltinType::kExp, ParamType::kF32, "exp"},
|
||||
BuiltinData{BuiltinType::kExp2, ParamType::kF32, "exp2"},
|
||||
BuiltinData{BuiltinType::kFaceForward, ParamType::kF32, "faceforward"},
|
||||
BuiltinData{BuiltinType::kFloor, ParamType::kF32, "floor"},
|
||||
BuiltinData{BuiltinType::kFma, ParamType::kF32, "mad"},
|
||||
BuiltinData{BuiltinType::kFract, ParamType::kF32, "frac"},
|
||||
BuiltinData{BuiltinType::kFwidth, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kFwidthCoarse, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kFwidthFine, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kInverseSqrt, ParamType::kF32, "rsqrt"},
|
||||
BuiltinData{BuiltinType::kIsFinite, ParamType::kF32, "isfinite"},
|
||||
BuiltinData{BuiltinType::kIsInf, ParamType::kF32, "isinf"},
|
||||
BuiltinData{BuiltinType::kIsNan, ParamType::kF32, "isnan"},
|
||||
BuiltinData{BuiltinType::kLdexp, ParamType::kF32, "ldexp"},
|
||||
BuiltinData{BuiltinType::kLength, ParamType::kF32, "length"},
|
||||
BuiltinData{BuiltinType::kLog, ParamType::kF32, "log"},
|
||||
BuiltinData{BuiltinType::kLog2, ParamType::kF32, "log2"},
|
||||
BuiltinData{BuiltinType::kMax, ParamType::kF32, "max"},
|
||||
BuiltinData{BuiltinType::kMax, ParamType::kU32, "max"},
|
||||
BuiltinData{BuiltinType::kMin, ParamType::kF32, "min"},
|
||||
BuiltinData{BuiltinType::kMin, ParamType::kU32, "min"},
|
||||
BuiltinData{BuiltinType::kMix, ParamType::kF32, "mix"},
|
||||
BuiltinData{BuiltinType::kNormalize, ParamType::kF32, "normalize"},
|
||||
BuiltinData{BuiltinType::kPow, ParamType::kF32, "pow"},
|
||||
BuiltinData{BuiltinType::kReflect, ParamType::kF32, "reflect"},
|
||||
BuiltinData{BuiltinType::kReverseBits, ParamType::kU32, "reversebits"},
|
||||
BuiltinData{BuiltinType::kRound, ParamType::kU32, "round"},
|
||||
BuiltinData{BuiltinType::kSign, ParamType::kF32, "sign"},
|
||||
BuiltinData{BuiltinType::kSin, ParamType::kF32, "sin"},
|
||||
BuiltinData{BuiltinType::kSinh, ParamType::kF32, "sinh"},
|
||||
BuiltinData{BuiltinType::kSmoothStep, ParamType::kF32, "smoothstep"},
|
||||
BuiltinData{BuiltinType::kSqrt, ParamType::kF32, "sqrt"},
|
||||
BuiltinData{BuiltinType::kStep, ParamType::kF32, "step"},
|
||||
BuiltinData{BuiltinType::kTan, ParamType::kF32, "tan"},
|
||||
BuiltinData{BuiltinType::kTanh, ParamType::kF32, "tanh"},
|
||||
BuiltinData{BuiltinType::kTranspose, ParamType::kF32, "transpose"},
|
||||
BuiltinData{BuiltinType::kTrunc, ParamType::kF32, "trunc"}));
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, DISABLED_Intrinsic_IsNormal) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, DISABLED_Builtin_IsNormal) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Intrinsic_Call) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Builtin_Call) {
|
||||
auto* call = Call("dot", "param1", "param2");
|
||||
|
||||
Global("param1", ty.vec3<f32>(), ast::StorageClass::kPrivate);
|
||||
|
@ -274,7 +267,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Intrinsic_Call) {
|
|||
EXPECT_EQ(out.str(), "dot(param1, param2)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Select_Scalar) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Select_Scalar) {
|
||||
auto* call = Call("select", 1.0f, 2.0f, true);
|
||||
WrapInFunction(CallStmt(call));
|
||||
GeneratorImpl& gen = Build();
|
||||
|
@ -285,7 +278,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Select_Scalar) {
|
|||
EXPECT_EQ(out.str(), "(true ? 2.0f : 1.0f)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Select_Vector) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Select_Vector) {
|
||||
auto* call =
|
||||
Call("select", vec2<i32>(1, 2), vec2<i32>(3, 4), vec2<bool>(true, false));
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -298,7 +291,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Select_Vector) {
|
|||
}
|
||||
|
||||
#if 0
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Modf_Scalar) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Modf_Scalar) {
|
||||
auto* res = Var("res", ty.f32());
|
||||
auto* call = Call("modf", 1.0f, AddressOf(res));
|
||||
WrapInFunction(res, call);
|
||||
|
@ -309,7 +302,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Modf_Scalar) {
|
|||
EXPECT_THAT(gen.result(), HasSubstr("modf(1.0f, res)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Modf_Vector) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Modf_Vector) {
|
||||
auto* res = Var("res", ty.vec3<f32>());
|
||||
auto* call = Call("modf", vec3<f32>(), AddressOf(res));
|
||||
WrapInFunction(res, call);
|
||||
|
@ -320,7 +313,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Modf_Vector) {
|
|||
EXPECT_THAT(gen.result(), HasSubstr("modf(vec3(0.0f, 0.0f, 0.0f), res)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Frexp_Scalar_i32) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Frexp_Scalar_i32) {
|
||||
auto* exp = Var("exp", ty.i32());
|
||||
auto* call = Call("frexp", 1.0f, AddressOf(exp));
|
||||
WrapInFunction(exp, call);
|
||||
|
@ -336,7 +329,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Frexp_Scalar_i32) {
|
|||
)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Frexp_Vector_i32) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Frexp_Vector_i32) {
|
||||
auto* res = Var("res", ty.vec3<i32>());
|
||||
auto* call = Call("frexp", vec3<f32>(), AddressOf(res));
|
||||
WrapInFunction(res, call);
|
||||
|
@ -352,7 +345,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Frexp_Vector_i32) {
|
|||
)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, IsNormal_Scalar) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, IsNormal_Scalar) {
|
||||
auto* val = Var("val", ty.f32());
|
||||
auto* call = Call("isNormal", val);
|
||||
WrapInFunction(val, call);
|
||||
|
@ -367,7 +360,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, IsNormal_Scalar) {
|
|||
)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, IsNormal_Vector) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, IsNormal_Vector) {
|
||||
auto* val = Var("val", ty.vec3<f32>());
|
||||
auto* call = Call("isNormal", val);
|
||||
WrapInFunction(val, call);
|
||||
|
@ -383,7 +376,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, IsNormal_Vector) {
|
|||
}
|
||||
#endif
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Degrees_Scalar) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Degrees_Scalar) {
|
||||
auto* val = Var("val", ty.f32());
|
||||
auto* call = Call("degrees", val);
|
||||
WrapInFunction(val, call);
|
||||
|
@ -412,7 +405,7 @@ void main() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Degrees_Vector) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Degrees_Vector) {
|
||||
auto* val = Var("val", ty.vec3<f32>());
|
||||
auto* call = Call("degrees", val);
|
||||
WrapInFunction(val, call);
|
||||
|
@ -441,7 +434,7 @@ void main() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Radians_Scalar) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Radians_Scalar) {
|
||||
auto* val = Var("val", ty.f32());
|
||||
auto* call = Call("radians", val);
|
||||
WrapInFunction(val, call);
|
||||
|
@ -470,7 +463,7 @@ void main() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Radians_Vector) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Radians_Vector) {
|
||||
auto* val = Var("val", ty.vec3<f32>());
|
||||
auto* call = Call("radians", val);
|
||||
WrapInFunction(val, call);
|
||||
|
@ -500,7 +493,7 @@ void main() {
|
|||
}
|
||||
|
||||
#if 0
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Pack4x8Snorm) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Pack4x8Snorm) {
|
||||
auto* call = Call("pack4x8snorm", "p1");
|
||||
Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -515,7 +508,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Pack4x8Snorm) {
|
|||
"tint_tmp.z << 16 | tint_tmp.w << 24)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Pack4x8Unorm) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Pack4x8Unorm) {
|
||||
auto* call = Call("pack4x8unorm", "p1");
|
||||
Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -530,7 +523,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Pack4x8Unorm) {
|
|||
"tint_tmp.z << 16 | tint_tmp.w << 24)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Pack2x16Snorm) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Pack2x16Snorm) {
|
||||
auto* call = Call("pack2x16snorm", "p1");
|
||||
Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -544,7 +537,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Pack2x16Snorm) {
|
|||
EXPECT_THAT(out.str(), HasSubstr("asuint(tint_tmp.x | tint_tmp.y << 16)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Pack2x16Unorm) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Pack2x16Unorm) {
|
||||
auto* call = Call("pack2x16unorm", "p1");
|
||||
Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -558,7 +551,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Pack2x16Unorm) {
|
|||
EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Pack2x16Float) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Pack2x16Float) {
|
||||
auto* call = Call("pack2x16float", "p1");
|
||||
Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -571,7 +564,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Pack2x16Float) {
|
|||
EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack4x8Snorm) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Unpack4x8Snorm) {
|
||||
auto* call = Call("unpack4x8snorm", "p1");
|
||||
Global("p1", ty.u32(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -588,7 +581,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack4x8Snorm) {
|
|||
HasSubstr("clamp(float4(tint_tmp) / 127.0, -1.0, 1.0)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack4x8Unorm) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Unpack4x8Unorm) {
|
||||
auto* call = Call("unpack4x8unorm", "p1");
|
||||
Global("p1", ty.u32(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -605,7 +598,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack4x8Unorm) {
|
|||
EXPECT_THAT(out.str(), HasSubstr("float4(tint_tmp) / 255.0"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack2x16Snorm) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Unpack2x16Snorm) {
|
||||
auto* call = Call("unpack2x16snorm", "p1");
|
||||
Global("p1", ty.u32(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -622,7 +615,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack2x16Snorm) {
|
|||
HasSubstr("clamp(float2(tint_tmp) / 32767.0, -1.0, 1.0)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack2x16Unorm) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Unpack2x16Unorm) {
|
||||
auto* call = Call("unpack2x16unorm", "p1");
|
||||
Global("p1", ty.u32(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -638,7 +631,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack2x16Unorm) {
|
|||
EXPECT_THAT(out.str(), HasSubstr("float2(tint_tmp) / 65535.0"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack2x16Float) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Unpack2x16Float) {
|
||||
auto* call = Call("unpack2x16float", "p1");
|
||||
Global("p1", ty.u32(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -652,7 +645,7 @@ TEST_F(GlslGeneratorImplTest_Intrinsic, Unpack2x16Float) {
|
|||
HasSubstr("f16tof32(uint2(tint_tmp & 0xffff, tint_tmp >> 16))"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, StorageBarrier) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, StorageBarrier) {
|
||||
Func("main", {}, ty.void_(),
|
||||
{CallStmt(Call("storageBarrier"))},
|
||||
{
|
||||
|
@ -671,7 +664,7 @@ void main() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, WorkgroupBarrier) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, WorkgroupBarrier) {
|
||||
Func("main", {}, ty.void_(),
|
||||
{CallStmt(Call("workgroupBarrier"))},
|
||||
{
|
||||
|
@ -692,7 +685,7 @@ void main() {
|
|||
|
||||
#endif
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, DotI32) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, DotI32) {
|
||||
Global("v", ty.vec3<i32>(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(Call("dot", "v", "v")));
|
||||
|
||||
|
@ -719,7 +712,7 @@ void main() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Intrinsic, DotU32) {
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, DotU32) {
|
||||
Global("v", ty.vec3<u32>(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(Call("dot", "v", "v")));
|
||||
|
|
@ -13,8 +13,8 @@
|
|||
// limitations under the License.
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/ast/builtin_texture_helper_test.h"
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/intrinsic_texture_helper_test.h"
|
||||
#include "src/ast/stage_attribute.h"
|
||||
#include "src/writer/glsl/test_helper.h"
|
||||
|
||||
|
@ -33,8 +33,8 @@ struct ExpectedResult {
|
|||
};
|
||||
|
||||
ExpectedResult expected_texture_overload(
|
||||
ast::intrinsic::test::ValidTextureOverload overload) {
|
||||
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
|
||||
ast::builtin::test::ValidTextureOverload overload) {
|
||||
using ValidTextureOverload = ast::builtin::test::ValidTextureOverload;
|
||||
switch (overload) {
|
||||
case ValidTextureOverload::kDimensions1d:
|
||||
case ValidTextureOverload::kDimensions2d:
|
||||
|
@ -267,10 +267,10 @@ ExpectedResult expected_texture_overload(
|
|||
return "<unmatched texture overload>";
|
||||
} // NOLINT - Ignore the length of this function
|
||||
|
||||
class GlslGeneratorIntrinsicTextureTest
|
||||
: public TestParamHelper<ast::intrinsic::test::TextureOverloadCase> {};
|
||||
class GlslGeneratorBuiltinTextureTest
|
||||
: public TestParamHelper<ast::builtin::test::TextureOverloadCase> {};
|
||||
|
||||
TEST_P(GlslGeneratorIntrinsicTextureTest, Call) {
|
||||
TEST_P(GlslGeneratorBuiltinTextureTest, Call) {
|
||||
auto param = GetParam();
|
||||
|
||||
param.BuildTextureVariable(this);
|
||||
|
@ -292,9 +292,9 @@ TEST_P(GlslGeneratorIntrinsicTextureTest, Call) {
|
|||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
GlslGeneratorIntrinsicTextureTest,
|
||||
GlslGeneratorIntrinsicTextureTest,
|
||||
testing::ValuesIn(ast::intrinsic::test::TextureOverloadCase::ValidCases()));
|
||||
GlslGeneratorBuiltinTextureTest,
|
||||
GlslGeneratorBuiltinTextureTest,
|
||||
testing::ValuesIn(ast::builtin::test::TextureOverloadCase::ValidCases()));
|
||||
|
||||
} // namespace
|
||||
} // namespace glsl
|
|
@ -933,8 +933,8 @@ bool GeneratorImpl::EmitCall(std::ostream& out,
|
|||
if (auto* func = target->As<sem::Function>()) {
|
||||
return EmitFunctionCall(out, call, func);
|
||||
}
|
||||
if (auto* intrinsic = target->As<sem::Intrinsic>()) {
|
||||
return EmitIntrinsicCall(out, call, intrinsic);
|
||||
if (auto* builtin = target->As<sem::Builtin>()) {
|
||||
return EmitBuiltinCall(out, call, builtin);
|
||||
}
|
||||
if (auto* conv = target->As<sem::TypeConversion>()) {
|
||||
return EmitTypeConversion(out, call, conv);
|
||||
|
@ -1001,44 +1001,44 @@ bool GeneratorImpl::EmitFunctionCall(std::ostream& out,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
bool GeneratorImpl::EmitBuiltinCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Builtin* builtin) {
|
||||
auto* expr = call->Declaration();
|
||||
if (intrinsic->IsTexture()) {
|
||||
return EmitTextureCall(out, call, intrinsic);
|
||||
if (builtin->IsTexture()) {
|
||||
return EmitTextureCall(out, call, builtin);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kSelect) {
|
||||
if (builtin->Type() == sem::BuiltinType::kSelect) {
|
||||
return EmitSelectCall(out, expr);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kModf) {
|
||||
return EmitModfCall(out, expr, intrinsic);
|
||||
if (builtin->Type() == sem::BuiltinType::kModf) {
|
||||
return EmitModfCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kFrexp) {
|
||||
return EmitFrexpCall(out, expr, intrinsic);
|
||||
if (builtin->Type() == sem::BuiltinType::kFrexp) {
|
||||
return EmitFrexpCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kIsNormal) {
|
||||
return EmitIsNormalCall(out, expr, intrinsic);
|
||||
if (builtin->Type() == sem::BuiltinType::kIsNormal) {
|
||||
return EmitIsNormalCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kDegrees) {
|
||||
return EmitDegreesCall(out, expr, intrinsic);
|
||||
if (builtin->Type() == sem::BuiltinType::kDegrees) {
|
||||
return EmitDegreesCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kRadians) {
|
||||
return EmitRadiansCall(out, expr, intrinsic);
|
||||
if (builtin->Type() == sem::BuiltinType::kRadians) {
|
||||
return EmitRadiansCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->IsDataPacking()) {
|
||||
return EmitDataPackingCall(out, expr, intrinsic);
|
||||
if (builtin->IsDataPacking()) {
|
||||
return EmitDataPackingCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->IsDataUnpacking()) {
|
||||
return EmitDataUnpackingCall(out, expr, intrinsic);
|
||||
if (builtin->IsDataUnpacking()) {
|
||||
return EmitDataUnpackingCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->IsBarrier()) {
|
||||
return EmitBarrierCall(out, intrinsic);
|
||||
if (builtin->IsBarrier()) {
|
||||
return EmitBarrierCall(out, builtin);
|
||||
}
|
||||
if (intrinsic->IsAtomic()) {
|
||||
return EmitWorkgroupAtomicCall(out, expr, intrinsic);
|
||||
if (builtin->IsAtomic()) {
|
||||
return EmitWorkgroupAtomicCall(out, expr, builtin);
|
||||
}
|
||||
auto name = generate_builtin_name(intrinsic);
|
||||
auto name = generate_builtin_name(builtin);
|
||||
if (name.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1637,17 +1637,17 @@ bool GeneratorImpl::EmitStorageAtomicCall(
|
|||
|
||||
bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
const sem::Builtin* builtin) {
|
||||
std::string result = UniqueIdentifier("atomic_result");
|
||||
|
||||
if (!intrinsic->ReturnType()->Is<sem::Void>()) {
|
||||
if (!builtin->ReturnType()->Is<sem::Void>()) {
|
||||
auto pre = line();
|
||||
if (!EmitTypeAndName(pre, intrinsic->ReturnType(), ast::StorageClass::kNone,
|
||||
if (!EmitTypeAndName(pre, builtin->ReturnType(), ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, result)) {
|
||||
return false;
|
||||
}
|
||||
pre << " = ";
|
||||
if (!EmitZeroValue(pre, intrinsic->ReturnType())) {
|
||||
if (!EmitZeroValue(pre, builtin->ReturnType())) {
|
||||
return false;
|
||||
}
|
||||
pre << ";";
|
||||
|
@ -1664,7 +1664,7 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
|||
if (i > 0) {
|
||||
pre << ", ";
|
||||
}
|
||||
if (i == 1 && intrinsic->Type() == sem::IntrinsicType::kAtomicSub) {
|
||||
if (i == 1 && builtin->Type() == sem::BuiltinType::kAtomicSub) {
|
||||
// Sub uses InterlockedAdd with the operand negated.
|
||||
pre << "-";
|
||||
}
|
||||
|
@ -1682,8 +1682,8 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
|||
return true;
|
||||
};
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kAtomicLoad: {
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kAtomicLoad: {
|
||||
// HLSL does not have an InterlockedLoad, so we emulate it with
|
||||
// InterlockedOr using 0 as the OR value
|
||||
auto pre = line();
|
||||
|
@ -1700,12 +1700,12 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
|||
out << result;
|
||||
return true;
|
||||
}
|
||||
case sem::IntrinsicType::kAtomicStore: {
|
||||
case sem::BuiltinType::kAtomicStore: {
|
||||
// HLSL does not have an InterlockedStore, so we emulate it with
|
||||
// InterlockedExchange and discard the returned value
|
||||
{ // T result = 0;
|
||||
auto pre = line();
|
||||
auto* value_ty = intrinsic->Parameters()[1]->Type()->UnwrapRef();
|
||||
auto* value_ty = builtin->Parameters()[1]->Type()->UnwrapRef();
|
||||
if (!EmitTypeAndName(pre, value_ty, ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, result)) {
|
||||
return false;
|
||||
|
@ -1731,7 +1731,7 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
|||
}
|
||||
return true;
|
||||
}
|
||||
case sem::IntrinsicType::kAtomicCompareExchangeWeak: {
|
||||
case sem::BuiltinType::kAtomicCompareExchangeWeak: {
|
||||
auto* dest = expr->args[0];
|
||||
auto* compare_value = expr->args[1];
|
||||
auto* value = expr->args[2];
|
||||
|
@ -1777,26 +1777,26 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
|||
return true;
|
||||
}
|
||||
|
||||
case sem::IntrinsicType::kAtomicAdd:
|
||||
case sem::IntrinsicType::kAtomicSub:
|
||||
case sem::BuiltinType::kAtomicAdd:
|
||||
case sem::BuiltinType::kAtomicSub:
|
||||
return call("InterlockedAdd");
|
||||
|
||||
case sem::IntrinsicType::kAtomicMax:
|
||||
case sem::BuiltinType::kAtomicMax:
|
||||
return call("InterlockedMax");
|
||||
|
||||
case sem::IntrinsicType::kAtomicMin:
|
||||
case sem::BuiltinType::kAtomicMin:
|
||||
return call("InterlockedMin");
|
||||
|
||||
case sem::IntrinsicType::kAtomicAnd:
|
||||
case sem::BuiltinType::kAtomicAnd:
|
||||
return call("InterlockedAnd");
|
||||
|
||||
case sem::IntrinsicType::kAtomicOr:
|
||||
case sem::BuiltinType::kAtomicOr:
|
||||
return call("InterlockedOr");
|
||||
|
||||
case sem::IntrinsicType::kAtomicXor:
|
||||
case sem::BuiltinType::kAtomicXor:
|
||||
return call("InterlockedXor");
|
||||
|
||||
case sem::IntrinsicType::kAtomicExchange:
|
||||
case sem::BuiltinType::kAtomicExchange:
|
||||
return call("InterlockedExchange");
|
||||
|
||||
default:
|
||||
|
@ -1804,7 +1804,7 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
|||
}
|
||||
|
||||
TINT_UNREACHABLE(Writer, diagnostics_)
|
||||
<< "unsupported atomic intrinsic: " << intrinsic->Type();
|
||||
<< "unsupported atomic builtin: " << builtin->Type();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1835,11 +1835,11 @@ bool GeneratorImpl::EmitSelectCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitModfCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
auto* ty = intrinsic->Parameters()[0]->Type();
|
||||
auto* ty = builtin->Parameters()[0]->Type();
|
||||
auto in = params[0];
|
||||
|
||||
std::string width;
|
||||
|
@ -1850,7 +1850,7 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
|
|||
// Emit the builtin return type unique to this overload. This does not
|
||||
// exist in the AST, so it will not be generated in Generate().
|
||||
if (!EmitStructType(&helpers_,
|
||||
intrinsic->ReturnType()->As<sem::Struct>())) {
|
||||
builtin->ReturnType()->As<sem::Struct>())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1858,7 +1858,7 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
|
|||
line(b) << "float" << width << " fract = modf(" << in << ", whole);";
|
||||
{
|
||||
auto l = line(b);
|
||||
if (!EmitType(l, intrinsic->ReturnType(), ast::StorageClass::kNone,
|
||||
if (!EmitType(l, builtin->ReturnType(), ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, "")) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1871,11 +1871,11 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
auto* ty = intrinsic->Parameters()[0]->Type();
|
||||
auto* ty = builtin->Parameters()[0]->Type();
|
||||
auto in = params[0];
|
||||
|
||||
std::string width;
|
||||
|
@ -1886,7 +1886,7 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
|||
// Emit the builtin return type unique to this overload. This does not
|
||||
// exist in the AST, so it will not be generated in Generate().
|
||||
if (!EmitStructType(&helpers_,
|
||||
intrinsic->ReturnType()->As<sem::Struct>())) {
|
||||
builtin->ReturnType()->As<sem::Struct>())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1894,7 +1894,7 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
|||
line(b) << "float" << width << " sig = frexp(" << in << ", exp);";
|
||||
{
|
||||
auto l = line(b);
|
||||
if (!EmitType(l, intrinsic->ReturnType(), ast::StorageClass::kNone,
|
||||
if (!EmitType(l, builtin->ReturnType(), ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, "")) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1907,12 +1907,12 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitIsNormalCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
// HLSL doesn't have a isNormal intrinsic, we need to emulate
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
// HLSL doesn't have a isNormal builtin, we need to emulate
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
auto* input_ty = intrinsic->Parameters()[0]->Type();
|
||||
auto* input_ty = builtin->Parameters()[0]->Type();
|
||||
|
||||
std::string width;
|
||||
if (auto* vec = input_ty->As<sem::Vector>()) {
|
||||
|
@ -1935,9 +1935,9 @@ bool GeneratorImpl::EmitIsNormalCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
line(b) << "return " << params[0] << " * " << std::setprecision(20)
|
||||
<< sem::kRadToDeg << ";";
|
||||
|
@ -1947,9 +1947,9 @@ bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
line(b) << "return " << params[0] << " * " << std::setprecision(20)
|
||||
<< sem::kDegToRad << ";";
|
||||
|
@ -1959,28 +1959,28 @@ bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
uint32_t dims = 2;
|
||||
bool is_signed = false;
|
||||
uint32_t scale = 65535;
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kPack4x8snorm ||
|
||||
intrinsic->Type() == sem::IntrinsicType::kPack4x8unorm) {
|
||||
if (builtin->Type() == sem::BuiltinType::kPack4x8snorm ||
|
||||
builtin->Type() == sem::BuiltinType::kPack4x8unorm) {
|
||||
dims = 4;
|
||||
scale = 255;
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kPack4x8snorm ||
|
||||
intrinsic->Type() == sem::IntrinsicType::kPack2x16snorm) {
|
||||
if (builtin->Type() == sem::BuiltinType::kPack4x8snorm ||
|
||||
builtin->Type() == sem::BuiltinType::kPack2x16snorm) {
|
||||
is_signed = true;
|
||||
scale = (scale - 1) / 2;
|
||||
}
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kPack4x8snorm:
|
||||
case sem::IntrinsicType::kPack4x8unorm:
|
||||
case sem::IntrinsicType::kPack2x16snorm:
|
||||
case sem::IntrinsicType::kPack2x16unorm: {
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kPack4x8snorm:
|
||||
case sem::BuiltinType::kPack4x8unorm:
|
||||
case sem::BuiltinType::kPack2x16snorm:
|
||||
case sem::BuiltinType::kPack2x16unorm: {
|
||||
{
|
||||
auto l = line(b);
|
||||
l << (is_signed ? "" : "u") << "int" << dims
|
||||
|
@ -2007,7 +2007,7 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case sem::IntrinsicType::kPack2x16float: {
|
||||
case sem::BuiltinType::kPack2x16float: {
|
||||
line(b) << "uint2 i = f32tof16(" << params[0] << ");";
|
||||
line(b) << "return i.x | (i.y << 16);";
|
||||
break;
|
||||
|
@ -2015,7 +2015,7 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
|
|||
default:
|
||||
diagnostics_.add_error(
|
||||
diag::System::Writer,
|
||||
"Internal error: unhandled data packing intrinsic");
|
||||
"Internal error: unhandled data packing builtin");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2025,26 +2025,26 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
uint32_t dims = 2;
|
||||
bool is_signed = false;
|
||||
uint32_t scale = 65535;
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kUnpack4x8snorm ||
|
||||
intrinsic->Type() == sem::IntrinsicType::kUnpack4x8unorm) {
|
||||
if (builtin->Type() == sem::BuiltinType::kUnpack4x8snorm ||
|
||||
builtin->Type() == sem::BuiltinType::kUnpack4x8unorm) {
|
||||
dims = 4;
|
||||
scale = 255;
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kUnpack4x8snorm ||
|
||||
intrinsic->Type() == sem::IntrinsicType::kUnpack2x16snorm) {
|
||||
if (builtin->Type() == sem::BuiltinType::kUnpack4x8snorm ||
|
||||
builtin->Type() == sem::BuiltinType::kUnpack2x16snorm) {
|
||||
is_signed = true;
|
||||
scale = (scale - 1) / 2;
|
||||
}
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kUnpack4x8snorm:
|
||||
case sem::IntrinsicType::kUnpack2x16snorm: {
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kUnpack4x8snorm:
|
||||
case sem::BuiltinType::kUnpack2x16snorm: {
|
||||
line(b) << "int j = int(" << params[0] << ");";
|
||||
{ // Perform sign extension on the converted values.
|
||||
auto l = line(b);
|
||||
|
@ -2060,8 +2060,8 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
|
|||
<< ".0, " << (is_signed ? "-1.0" : "0.0") << ", 1.0);";
|
||||
break;
|
||||
}
|
||||
case sem::IntrinsicType::kUnpack4x8unorm:
|
||||
case sem::IntrinsicType::kUnpack2x16unorm: {
|
||||
case sem::BuiltinType::kUnpack4x8unorm:
|
||||
case sem::BuiltinType::kUnpack2x16unorm: {
|
||||
line(b) << "uint j = " << params[0] << ";";
|
||||
{
|
||||
auto l = line(b);
|
||||
|
@ -2078,14 +2078,14 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
|
|||
line(b) << "return float" << dims << "(i) / " << scale << ".0;";
|
||||
break;
|
||||
}
|
||||
case sem::IntrinsicType::kUnpack2x16float:
|
||||
case sem::BuiltinType::kUnpack2x16float:
|
||||
line(b) << "uint i = " << params[0] << ";";
|
||||
line(b) << "return f16tof32(uint2(i & 0xffff, i >> 16));";
|
||||
break;
|
||||
default:
|
||||
diagnostics_.add_error(
|
||||
diag::System::Writer,
|
||||
"Internal error: unhandled data packing intrinsic");
|
||||
"Internal error: unhandled data packing builtin");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2094,16 +2094,16 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
|
|||
}
|
||||
|
||||
bool GeneratorImpl::EmitBarrierCall(std::ostream& out,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
const sem::Builtin* builtin) {
|
||||
// TODO(crbug.com/tint/661): Combine sequential barriers to a single
|
||||
// instruction.
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kWorkgroupBarrier) {
|
||||
if (builtin->Type() == sem::BuiltinType::kWorkgroupBarrier) {
|
||||
out << "GroupMemoryBarrierWithGroupSync()";
|
||||
} else if (intrinsic->Type() == sem::IntrinsicType::kStorageBarrier) {
|
||||
} else if (builtin->Type() == sem::BuiltinType::kStorageBarrier) {
|
||||
out << "DeviceMemoryBarrierWithGroupSync()";
|
||||
} else {
|
||||
TINT_UNREACHABLE(Writer, diagnostics_)
|
||||
<< "unexpected barrier intrinsic type " << sem::str(intrinsic->Type());
|
||||
<< "unexpected barrier builtin type " << sem::str(builtin->Type());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -2111,10 +2111,10 @@ bool GeneratorImpl::EmitBarrierCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
const sem::Builtin* builtin) {
|
||||
using Usage = sem::ParameterUsage;
|
||||
|
||||
auto& signature = intrinsic->Signature();
|
||||
auto& signature = builtin->Signature();
|
||||
auto* expr = call->Declaration();
|
||||
auto arguments = expr->args;
|
||||
|
||||
|
@ -2132,19 +2132,19 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
|
||||
auto* texture_type = TypeOf(texture)->UnwrapRef()->As<sem::Texture>();
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kTextureDimensions:
|
||||
case sem::IntrinsicType::kTextureNumLayers:
|
||||
case sem::IntrinsicType::kTextureNumLevels:
|
||||
case sem::IntrinsicType::kTextureNumSamples: {
|
||||
// All of these intrinsics use the GetDimensions() method on the texture
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kTextureDimensions:
|
||||
case sem::BuiltinType::kTextureNumLayers:
|
||||
case sem::BuiltinType::kTextureNumLevels:
|
||||
case sem::BuiltinType::kTextureNumSamples: {
|
||||
// All of these builtins use the GetDimensions() method on the texture
|
||||
bool is_ms = texture_type->IsAnyOf<sem::MultisampledTexture,
|
||||
sem::DepthMultisampledTexture>();
|
||||
int num_dimensions = 0;
|
||||
std::string swizzle;
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kTextureDimensions:
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kTextureDimensions:
|
||||
switch (texture_type->dim()) {
|
||||
case ast::TextureDimension::kNone:
|
||||
TINT_ICE(Writer, diagnostics_) << "texture dimension is kNone";
|
||||
|
@ -2172,7 +2172,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureNumLayers:
|
||||
case sem::BuiltinType::kTextureNumLayers:
|
||||
switch (texture_type->dim()) {
|
||||
default:
|
||||
TINT_ICE(Writer, diagnostics_)
|
||||
|
@ -2188,7 +2188,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureNumLevels:
|
||||
case sem::BuiltinType::kTextureNumLevels:
|
||||
switch (texture_type->dim()) {
|
||||
default:
|
||||
TINT_ICE(Writer, diagnostics_)
|
||||
|
@ -2211,7 +2211,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureNumSamples:
|
||||
case sem::BuiltinType::kTextureNumSamples:
|
||||
switch (texture_type->dim()) {
|
||||
default:
|
||||
TINT_ICE(Writer, diagnostics_)
|
||||
|
@ -2228,7 +2228,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
}
|
||||
break;
|
||||
default:
|
||||
TINT_ICE(Writer, diagnostics_) << "unexpected intrinsic";
|
||||
TINT_ICE(Writer, diagnostics_) << "unexpected builtin";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2251,7 +2251,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
|
||||
if (num_dimensions > 4) {
|
||||
TINT_ICE(Writer, diagnostics_)
|
||||
<< "Texture query intrinsic temporary vector has " << num_dimensions
|
||||
<< "Texture query builtin temporary vector has " << num_dimensions
|
||||
<< " dimensions";
|
||||
return false;
|
||||
}
|
||||
|
@ -2276,7 +2276,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
return false;
|
||||
}
|
||||
pre << ", ";
|
||||
} else if (intrinsic->Type() == sem::IntrinsicType::kTextureNumLevels) {
|
||||
} else if (builtin->Type() == sem::BuiltinType::kTextureNumLevels) {
|
||||
pre << "0, ";
|
||||
}
|
||||
|
||||
|
@ -2314,44 +2314,44 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
return false;
|
||||
|
||||
// If pack_level_in_coords is true, then the mip level will be appended as the
|
||||
// last value of the coordinates argument. If the WGSL intrinsic overload does
|
||||
// last value of the coordinates argument. If the WGSL builtin overload does
|
||||
// not have a level parameter and pack_level_in_coords is true, then a zero
|
||||
// mip level will be inserted.
|
||||
bool pack_level_in_coords = false;
|
||||
|
||||
uint32_t hlsl_ret_width = 4u;
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kTextureSample:
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kTextureSample:
|
||||
out << ".Sample(";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureSampleBias:
|
||||
case sem::BuiltinType::kTextureSampleBias:
|
||||
out << ".SampleBias(";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureSampleLevel:
|
||||
case sem::BuiltinType::kTextureSampleLevel:
|
||||
out << ".SampleLevel(";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureSampleGrad:
|
||||
case sem::BuiltinType::kTextureSampleGrad:
|
||||
out << ".SampleGrad(";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureSampleCompare:
|
||||
case sem::BuiltinType::kTextureSampleCompare:
|
||||
out << ".SampleCmp(";
|
||||
hlsl_ret_width = 1;
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureSampleCompareLevel:
|
||||
case sem::BuiltinType::kTextureSampleCompareLevel:
|
||||
out << ".SampleCmpLevelZero(";
|
||||
hlsl_ret_width = 1;
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureLoad:
|
||||
case sem::BuiltinType::kTextureLoad:
|
||||
out << ".Load(";
|
||||
// Multisampled textures do not support mip-levels.
|
||||
if (!texture_type->Is<sem::MultisampledTexture>()) {
|
||||
pack_level_in_coords = true;
|
||||
}
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureGather:
|
||||
case sem::BuiltinType::kTextureGather:
|
||||
out << ".Gather";
|
||||
if (intrinsic->Parameters()[0]->Usage() ==
|
||||
if (builtin->Parameters()[0]->Usage() ==
|
||||
sem::ParameterUsage::kComponent) {
|
||||
switch (call->Arguments()[0]->ConstantValue().Elements()[0].i32) {
|
||||
case 0:
|
||||
|
@ -2370,17 +2370,17 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
}
|
||||
out << "(";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureGatherCompare:
|
||||
case sem::BuiltinType::kTextureGatherCompare:
|
||||
out << ".GatherCmp(";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureStore:
|
||||
case sem::BuiltinType::kTextureStore:
|
||||
out << "[";
|
||||
break;
|
||||
default:
|
||||
diagnostics_.add_error(
|
||||
diag::System::Writer,
|
||||
"Internal compiler error: Unhandled texture intrinsic '" +
|
||||
std::string(intrinsic->str()) + "'");
|
||||
"Internal compiler error: Unhandled texture builtin '" +
|
||||
std::string(builtin->str()) + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2451,7 +2451,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
}
|
||||
}
|
||||
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kTextureStore) {
|
||||
if (builtin->Type() == sem::BuiltinType::kTextureStore) {
|
||||
out << "] = ";
|
||||
if (!EmitExpression(out, arg(Usage::kValue))) {
|
||||
return false;
|
||||
|
@ -2459,11 +2459,11 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
} else {
|
||||
out << ")";
|
||||
|
||||
// If the intrinsic return type does not match the number of elements of the
|
||||
// HLSL intrinsic, we need to swizzle the expression to generate the correct
|
||||
// If the builtin return type does not match the number of elements of the
|
||||
// HLSL builtin, we need to swizzle the expression to generate the correct
|
||||
// number of components.
|
||||
uint32_t wgsl_ret_width = 1;
|
||||
if (auto* vec = intrinsic->ReturnType()->As<sem::Vector>()) {
|
||||
if (auto* vec = builtin->ReturnType()->As<sem::Vector>()) {
|
||||
wgsl_ret_width = vec->Width();
|
||||
}
|
||||
if (wgsl_ret_width < hlsl_ret_width) {
|
||||
|
@ -2476,7 +2476,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
TINT_ICE(Writer, diagnostics_)
|
||||
<< "WGSL return width (" << wgsl_ret_width
|
||||
<< ") is wider than HLSL return width (" << hlsl_ret_width << ") for "
|
||||
<< intrinsic->Type();
|
||||
<< builtin->Type();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2484,92 +2484,91 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
return true;
|
||||
}
|
||||
|
||||
std::string GeneratorImpl::generate_builtin_name(
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kAbs:
|
||||
case sem::IntrinsicType::kAcos:
|
||||
case sem::IntrinsicType::kAll:
|
||||
case sem::IntrinsicType::kAny:
|
||||
case sem::IntrinsicType::kAsin:
|
||||
case sem::IntrinsicType::kAtan:
|
||||
case sem::IntrinsicType::kAtan2:
|
||||
case sem::IntrinsicType::kCeil:
|
||||
case sem::IntrinsicType::kClamp:
|
||||
case sem::IntrinsicType::kCos:
|
||||
case sem::IntrinsicType::kCosh:
|
||||
case sem::IntrinsicType::kCross:
|
||||
case sem::IntrinsicType::kDeterminant:
|
||||
case sem::IntrinsicType::kDistance:
|
||||
case sem::IntrinsicType::kDot:
|
||||
case sem::IntrinsicType::kExp:
|
||||
case sem::IntrinsicType::kExp2:
|
||||
case sem::IntrinsicType::kFloor:
|
||||
case sem::IntrinsicType::kFrexp:
|
||||
case sem::IntrinsicType::kLdexp:
|
||||
case sem::IntrinsicType::kLength:
|
||||
case sem::IntrinsicType::kLog:
|
||||
case sem::IntrinsicType::kLog2:
|
||||
case sem::IntrinsicType::kMax:
|
||||
case sem::IntrinsicType::kMin:
|
||||
case sem::IntrinsicType::kModf:
|
||||
case sem::IntrinsicType::kNormalize:
|
||||
case sem::IntrinsicType::kPow:
|
||||
case sem::IntrinsicType::kReflect:
|
||||
case sem::IntrinsicType::kRefract:
|
||||
case sem::IntrinsicType::kRound:
|
||||
case sem::IntrinsicType::kSign:
|
||||
case sem::IntrinsicType::kSin:
|
||||
case sem::IntrinsicType::kSinh:
|
||||
case sem::IntrinsicType::kSqrt:
|
||||
case sem::IntrinsicType::kStep:
|
||||
case sem::IntrinsicType::kTan:
|
||||
case sem::IntrinsicType::kTanh:
|
||||
case sem::IntrinsicType::kTranspose:
|
||||
case sem::IntrinsicType::kTrunc:
|
||||
return intrinsic->str();
|
||||
case sem::IntrinsicType::kCountOneBits:
|
||||
std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kAbs:
|
||||
case sem::BuiltinType::kAcos:
|
||||
case sem::BuiltinType::kAll:
|
||||
case sem::BuiltinType::kAny:
|
||||
case sem::BuiltinType::kAsin:
|
||||
case sem::BuiltinType::kAtan:
|
||||
case sem::BuiltinType::kAtan2:
|
||||
case sem::BuiltinType::kCeil:
|
||||
case sem::BuiltinType::kClamp:
|
||||
case sem::BuiltinType::kCos:
|
||||
case sem::BuiltinType::kCosh:
|
||||
case sem::BuiltinType::kCross:
|
||||
case sem::BuiltinType::kDeterminant:
|
||||
case sem::BuiltinType::kDistance:
|
||||
case sem::BuiltinType::kDot:
|
||||
case sem::BuiltinType::kExp:
|
||||
case sem::BuiltinType::kExp2:
|
||||
case sem::BuiltinType::kFloor:
|
||||
case sem::BuiltinType::kFrexp:
|
||||
case sem::BuiltinType::kLdexp:
|
||||
case sem::BuiltinType::kLength:
|
||||
case sem::BuiltinType::kLog:
|
||||
case sem::BuiltinType::kLog2:
|
||||
case sem::BuiltinType::kMax:
|
||||
case sem::BuiltinType::kMin:
|
||||
case sem::BuiltinType::kModf:
|
||||
case sem::BuiltinType::kNormalize:
|
||||
case sem::BuiltinType::kPow:
|
||||
case sem::BuiltinType::kReflect:
|
||||
case sem::BuiltinType::kRefract:
|
||||
case sem::BuiltinType::kRound:
|
||||
case sem::BuiltinType::kSign:
|
||||
case sem::BuiltinType::kSin:
|
||||
case sem::BuiltinType::kSinh:
|
||||
case sem::BuiltinType::kSqrt:
|
||||
case sem::BuiltinType::kStep:
|
||||
case sem::BuiltinType::kTan:
|
||||
case sem::BuiltinType::kTanh:
|
||||
case sem::BuiltinType::kTranspose:
|
||||
case sem::BuiltinType::kTrunc:
|
||||
return builtin->str();
|
||||
case sem::BuiltinType::kCountOneBits:
|
||||
return "countbits";
|
||||
case sem::IntrinsicType::kDpdx:
|
||||
case sem::BuiltinType::kDpdx:
|
||||
return "ddx";
|
||||
case sem::IntrinsicType::kDpdxCoarse:
|
||||
case sem::BuiltinType::kDpdxCoarse:
|
||||
return "ddx_coarse";
|
||||
case sem::IntrinsicType::kDpdxFine:
|
||||
case sem::BuiltinType::kDpdxFine:
|
||||
return "ddx_fine";
|
||||
case sem::IntrinsicType::kDpdy:
|
||||
case sem::BuiltinType::kDpdy:
|
||||
return "ddy";
|
||||
case sem::IntrinsicType::kDpdyCoarse:
|
||||
case sem::BuiltinType::kDpdyCoarse:
|
||||
return "ddy_coarse";
|
||||
case sem::IntrinsicType::kDpdyFine:
|
||||
case sem::BuiltinType::kDpdyFine:
|
||||
return "ddy_fine";
|
||||
case sem::IntrinsicType::kFaceForward:
|
||||
case sem::BuiltinType::kFaceForward:
|
||||
return "faceforward";
|
||||
case sem::IntrinsicType::kFract:
|
||||
case sem::BuiltinType::kFract:
|
||||
return "frac";
|
||||
case sem::IntrinsicType::kFma:
|
||||
case sem::BuiltinType::kFma:
|
||||
return "mad";
|
||||
case sem::IntrinsicType::kFwidth:
|
||||
case sem::IntrinsicType::kFwidthCoarse:
|
||||
case sem::IntrinsicType::kFwidthFine:
|
||||
case sem::BuiltinType::kFwidth:
|
||||
case sem::BuiltinType::kFwidthCoarse:
|
||||
case sem::BuiltinType::kFwidthFine:
|
||||
return "fwidth";
|
||||
case sem::IntrinsicType::kInverseSqrt:
|
||||
case sem::BuiltinType::kInverseSqrt:
|
||||
return "rsqrt";
|
||||
case sem::IntrinsicType::kIsFinite:
|
||||
case sem::BuiltinType::kIsFinite:
|
||||
return "isfinite";
|
||||
case sem::IntrinsicType::kIsInf:
|
||||
case sem::BuiltinType::kIsInf:
|
||||
return "isinf";
|
||||
case sem::IntrinsicType::kIsNan:
|
||||
case sem::BuiltinType::kIsNan:
|
||||
return "isnan";
|
||||
case sem::IntrinsicType::kMix:
|
||||
case sem::BuiltinType::kMix:
|
||||
return "lerp";
|
||||
case sem::IntrinsicType::kReverseBits:
|
||||
case sem::BuiltinType::kReverseBits:
|
||||
return "reversebits";
|
||||
case sem::IntrinsicType::kSmoothStep:
|
||||
case sem::BuiltinType::kSmoothStep:
|
||||
return "smoothstep";
|
||||
default:
|
||||
diagnostics_.add_error(
|
||||
diag::System::Writer,
|
||||
"Unknown builtin method: " + std::string(intrinsic->str()));
|
||||
"Unknown builtin method: " + std::string(builtin->str()));
|
||||
}
|
||||
|
||||
return "";
|
||||
|
@ -3892,28 +3891,28 @@ bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
|
|||
}
|
||||
|
||||
template <typename F>
|
||||
bool GeneratorImpl::CallIntrinsicHelper(std::ostream& out,
|
||||
const ast::CallExpression* call,
|
||||
const sem::Intrinsic* intrinsic,
|
||||
F&& build) {
|
||||
bool GeneratorImpl::CallBuiltinHelper(std::ostream& out,
|
||||
const ast::CallExpression* call,
|
||||
const sem::Builtin* builtin,
|
||||
F&& build) {
|
||||
// Generate the helper function if it hasn't been created already
|
||||
auto fn = utils::GetOrCreate(intrinsics_, intrinsic, [&]() -> std::string {
|
||||
auto fn = utils::GetOrCreate(builtins_, builtin, [&]() -> std::string {
|
||||
TextBuffer b;
|
||||
TINT_DEFER(helpers_.Append(b));
|
||||
|
||||
auto fn_name =
|
||||
UniqueIdentifier(std::string("tint_") + sem::str(intrinsic->Type()));
|
||||
UniqueIdentifier(std::string("tint_") + sem::str(builtin->Type()));
|
||||
std::vector<std::string> parameter_names;
|
||||
{
|
||||
auto decl = line(&b);
|
||||
if (!EmitTypeAndName(decl, intrinsic->ReturnType(),
|
||||
if (!EmitTypeAndName(decl, builtin->ReturnType(),
|
||||
ast::StorageClass::kNone, ast::Access::kUndefined,
|
||||
fn_name)) {
|
||||
return "";
|
||||
}
|
||||
{
|
||||
ScopedParen sp(decl);
|
||||
for (auto* param : intrinsic->Parameters()) {
|
||||
for (auto* param : builtin->Parameters()) {
|
||||
if (!parameter_names.empty()) {
|
||||
decl << ", ";
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace tint {
|
|||
// Forward declarations
|
||||
namespace sem {
|
||||
class Call;
|
||||
class Intrinsic;
|
||||
class Builtin;
|
||||
class TypeConstructor;
|
||||
class TypeConversion;
|
||||
} // namespace sem
|
||||
|
@ -145,14 +145,14 @@ class GeneratorImpl : public TextGenerator {
|
|||
bool EmitFunctionCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Function* function);
|
||||
/// Handles generating an intrinsic call expression
|
||||
/// Handles generating a builtin call expression
|
||||
/// @param out the output of the expression stream
|
||||
/// @param call the call expression
|
||||
/// @param intrinsic the intrinsic being called
|
||||
/// @param builtin the builtin being called
|
||||
/// @returns true if the expression is emitted
|
||||
bool EmitIntrinsicCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
bool EmitBuiltinCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a type conversion expression
|
||||
/// @param out the output of the expression stream
|
||||
/// @param call the call expression
|
||||
|
@ -191,9 +191,9 @@ class GeneratorImpl : public TextGenerator {
|
|||
const transform::DecomposeMemoryAccess::Intrinsic* intrinsic);
|
||||
/// Handles generating a barrier intrinsic call
|
||||
/// @param out the output of the expression stream
|
||||
/// @param intrinsic the semantic information for the barrier intrinsic
|
||||
/// @param builtin the semantic information for the barrier builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitBarrierCall(std::ostream& out, const sem::Intrinsic* intrinsic);
|
||||
bool EmitBarrierCall(std::ostream& out, const sem::Builtin* builtin);
|
||||
/// Handles generating an atomic intrinsic call for a storage buffer variable
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
|
@ -206,81 +206,81 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// Handles generating an atomic intrinsic call for a workgroup variable
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the atomic intrinsic
|
||||
/// @param builtin the semantic information for the atomic builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitWorkgroupAtomicCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to a texture function (`textureSample`,
|
||||
/// `textureSampleGrad`, etc)
|
||||
/// @param out the output of the expression stream
|
||||
/// @param call the call expression
|
||||
/// @param intrinsic the semantic information for the texture intrinsic
|
||||
/// @param builtin the semantic information for the texture builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitTextureCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `select()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `select()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitSelectCall(std::ostream& out, const ast::CallExpression* expr);
|
||||
/// Handles generating a call to the `modf()` intrinsic
|
||||
/// Handles generating a call to the `modf()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitModfCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `frexp()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `frexp()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitFrexpCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `isNormal()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `isNormal()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitIsNormalCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `degrees()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `degrees()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitDegreesCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `radians()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `radians()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitRadiansCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to data packing intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to data packing builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the texture intrinsic
|
||||
/// @param builtin the semantic information for the texture builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitDataPackingCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to data unpacking intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to data unpacking builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the texture intrinsic
|
||||
/// @param builtin the semantic information for the texture builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitDataUnpackingCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles a case statement
|
||||
/// @param s the switch statement
|
||||
/// @param case_idx the index of the switch case in the switch statement
|
||||
|
@ -473,9 +473,9 @@ class GeneratorImpl : public TextGenerator {
|
|||
const sem::Matrix* mat);
|
||||
|
||||
/// Handles generating a builtin method name
|
||||
/// @param intrinsic the semantic info for the intrinsic
|
||||
/// @param builtin the semantic info for the builtin
|
||||
/// @returns the name or "" if not valid
|
||||
std::string generate_builtin_name(const sem::Intrinsic* intrinsic);
|
||||
std::string generate_builtin_name(const sem::Builtin* builtin);
|
||||
/// Converts a builtin to an attribute name
|
||||
/// @param builtin the builtin to convert
|
||||
/// @returns the string name of the builtin or blank on error
|
||||
|
@ -513,13 +513,13 @@ class GeneratorImpl : public TextGenerator {
|
|||
};
|
||||
};
|
||||
|
||||
/// CallIntrinsicHelper will call the intrinsic helper function, creating it
|
||||
/// if it hasn't been built already. If the intrinsic needs to be built then
|
||||
/// CallIntrinsicHelper will generate the function signature and will call
|
||||
/// CallBuiltinHelper will call the builtin helper function, creating it
|
||||
/// if it hasn't been built already. If the builtin needs to be built then
|
||||
/// CallBuiltinHelper will generate the function signature and will call
|
||||
/// `build` to emit the body of the function.
|
||||
/// @param out the output of the expression stream
|
||||
/// @param call the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @param build a function with the signature:
|
||||
/// `bool(TextBuffer* buffer, const std::vector<std::string>& params)`
|
||||
/// Where:
|
||||
|
@ -527,16 +527,16 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// `params` is the name of all the generated function parameters
|
||||
/// @returns true if the call expression is emitted
|
||||
template <typename F>
|
||||
bool CallIntrinsicHelper(std::ostream& out,
|
||||
const ast::CallExpression* call,
|
||||
const sem::Intrinsic* intrinsic,
|
||||
F&& build);
|
||||
bool CallBuiltinHelper(std::ostream& out,
|
||||
const ast::CallExpression* call,
|
||||
const sem::Builtin* builtin,
|
||||
F&& build);
|
||||
|
||||
TextBuffer helpers_; // Helper functions emitted at the top of the output
|
||||
std::function<bool()> emit_continuing_;
|
||||
std::unordered_map<DMAIntrinsic, std::string, DMAIntrinsic::Hasher>
|
||||
dma_intrinsics_;
|
||||
std::unordered_map<const sem::Intrinsic*, std::string> intrinsics_;
|
||||
std::unordered_map<const sem::Builtin*, std::string> builtins_;
|
||||
std::unordered_map<const sem::Struct*, std::string> structure_builders_;
|
||||
std::unordered_map<const sem::Vector*, std::string> dynamic_vector_write_;
|
||||
std::unordered_map<const sem::Matrix*, std::string>
|
||||
|
|
|
@ -23,11 +23,11 @@ namespace writer {
|
|||
namespace hlsl {
|
||||
namespace {
|
||||
|
||||
using IntrinsicType = sem::IntrinsicType;
|
||||
using BuiltinType = sem::BuiltinType;
|
||||
|
||||
using ::testing::HasSubstr;
|
||||
|
||||
using HlslGeneratorImplTest_Intrinsic = TestHelper;
|
||||
using HlslGeneratorImplTest_Builtin = TestHelper;
|
||||
|
||||
enum class ParamType {
|
||||
kF32,
|
||||
|
@ -35,12 +35,12 @@ enum class ParamType {
|
|||
kBool,
|
||||
};
|
||||
|
||||
struct IntrinsicData {
|
||||
IntrinsicType intrinsic;
|
||||
struct BuiltinData {
|
||||
BuiltinType builtin;
|
||||
ParamType type;
|
||||
const char* hlsl_name;
|
||||
};
|
||||
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
|
||||
inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
|
||||
out << data.hlsl_name;
|
||||
switch (data.type) {
|
||||
case ParamType::kF32:
|
||||
|
@ -57,104 +57,104 @@ inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
|
|||
return out;
|
||||
}
|
||||
|
||||
const ast::CallExpression* GenerateCall(IntrinsicType intrinsic,
|
||||
const ast::CallExpression* GenerateCall(BuiltinType builtin,
|
||||
ParamType type,
|
||||
ProgramBuilder* builder) {
|
||||
std::string name;
|
||||
std::ostringstream str(name);
|
||||
str << intrinsic;
|
||||
switch (intrinsic) {
|
||||
case IntrinsicType::kAcos:
|
||||
case IntrinsicType::kAsin:
|
||||
case IntrinsicType::kAtan:
|
||||
case IntrinsicType::kCeil:
|
||||
case IntrinsicType::kCos:
|
||||
case IntrinsicType::kCosh:
|
||||
case IntrinsicType::kDpdx:
|
||||
case IntrinsicType::kDpdxCoarse:
|
||||
case IntrinsicType::kDpdxFine:
|
||||
case IntrinsicType::kDpdy:
|
||||
case IntrinsicType::kDpdyCoarse:
|
||||
case IntrinsicType::kDpdyFine:
|
||||
case IntrinsicType::kExp:
|
||||
case IntrinsicType::kExp2:
|
||||
case IntrinsicType::kFloor:
|
||||
case IntrinsicType::kFract:
|
||||
case IntrinsicType::kFwidth:
|
||||
case IntrinsicType::kFwidthCoarse:
|
||||
case IntrinsicType::kFwidthFine:
|
||||
case IntrinsicType::kInverseSqrt:
|
||||
case IntrinsicType::kIsFinite:
|
||||
case IntrinsicType::kIsInf:
|
||||
case IntrinsicType::kIsNan:
|
||||
case IntrinsicType::kIsNormal:
|
||||
case IntrinsicType::kLength:
|
||||
case IntrinsicType::kLog:
|
||||
case IntrinsicType::kLog2:
|
||||
case IntrinsicType::kNormalize:
|
||||
case IntrinsicType::kRound:
|
||||
case IntrinsicType::kSin:
|
||||
case IntrinsicType::kSinh:
|
||||
case IntrinsicType::kSqrt:
|
||||
case IntrinsicType::kTan:
|
||||
case IntrinsicType::kTanh:
|
||||
case IntrinsicType::kTrunc:
|
||||
case IntrinsicType::kSign:
|
||||
str << builtin;
|
||||
switch (builtin) {
|
||||
case BuiltinType::kAcos:
|
||||
case BuiltinType::kAsin:
|
||||
case BuiltinType::kAtan:
|
||||
case BuiltinType::kCeil:
|
||||
case BuiltinType::kCos:
|
||||
case BuiltinType::kCosh:
|
||||
case BuiltinType::kDpdx:
|
||||
case BuiltinType::kDpdxCoarse:
|
||||
case BuiltinType::kDpdxFine:
|
||||
case BuiltinType::kDpdy:
|
||||
case BuiltinType::kDpdyCoarse:
|
||||
case BuiltinType::kDpdyFine:
|
||||
case BuiltinType::kExp:
|
||||
case BuiltinType::kExp2:
|
||||
case BuiltinType::kFloor:
|
||||
case BuiltinType::kFract:
|
||||
case BuiltinType::kFwidth:
|
||||
case BuiltinType::kFwidthCoarse:
|
||||
case BuiltinType::kFwidthFine:
|
||||
case BuiltinType::kInverseSqrt:
|
||||
case BuiltinType::kIsFinite:
|
||||
case BuiltinType::kIsInf:
|
||||
case BuiltinType::kIsNan:
|
||||
case BuiltinType::kIsNormal:
|
||||
case BuiltinType::kLength:
|
||||
case BuiltinType::kLog:
|
||||
case BuiltinType::kLog2:
|
||||
case BuiltinType::kNormalize:
|
||||
case BuiltinType::kRound:
|
||||
case BuiltinType::kSin:
|
||||
case BuiltinType::kSinh:
|
||||
case BuiltinType::kSqrt:
|
||||
case BuiltinType::kTan:
|
||||
case BuiltinType::kTanh:
|
||||
case BuiltinType::kTrunc:
|
||||
case BuiltinType::kSign:
|
||||
return builder->Call(str.str(), "f2");
|
||||
case IntrinsicType::kLdexp:
|
||||
case BuiltinType::kLdexp:
|
||||
return builder->Call(str.str(), "f2", "i2");
|
||||
case IntrinsicType::kAtan2:
|
||||
case IntrinsicType::kDot:
|
||||
case IntrinsicType::kDistance:
|
||||
case IntrinsicType::kPow:
|
||||
case IntrinsicType::kReflect:
|
||||
case IntrinsicType::kStep:
|
||||
case BuiltinType::kAtan2:
|
||||
case BuiltinType::kDot:
|
||||
case BuiltinType::kDistance:
|
||||
case BuiltinType::kPow:
|
||||
case BuiltinType::kReflect:
|
||||
case BuiltinType::kStep:
|
||||
return builder->Call(str.str(), "f2", "f2");
|
||||
case IntrinsicType::kCross:
|
||||
case BuiltinType::kCross:
|
||||
return builder->Call(str.str(), "f3", "f3");
|
||||
case IntrinsicType::kFma:
|
||||
case IntrinsicType::kMix:
|
||||
case IntrinsicType::kFaceForward:
|
||||
case IntrinsicType::kSmoothStep:
|
||||
case BuiltinType::kFma:
|
||||
case BuiltinType::kMix:
|
||||
case BuiltinType::kFaceForward:
|
||||
case BuiltinType::kSmoothStep:
|
||||
return builder->Call(str.str(), "f2", "f2", "f2");
|
||||
case IntrinsicType::kAll:
|
||||
case IntrinsicType::kAny:
|
||||
case BuiltinType::kAll:
|
||||
case BuiltinType::kAny:
|
||||
return builder->Call(str.str(), "b2");
|
||||
case IntrinsicType::kAbs:
|
||||
case BuiltinType::kAbs:
|
||||
if (type == ParamType::kF32) {
|
||||
return builder->Call(str.str(), "f2");
|
||||
} else {
|
||||
return builder->Call(str.str(), "u2");
|
||||
}
|
||||
case IntrinsicType::kCountOneBits:
|
||||
case IntrinsicType::kReverseBits:
|
||||
case BuiltinType::kCountOneBits:
|
||||
case BuiltinType::kReverseBits:
|
||||
return builder->Call(str.str(), "u2");
|
||||
case IntrinsicType::kMax:
|
||||
case IntrinsicType::kMin:
|
||||
case BuiltinType::kMax:
|
||||
case BuiltinType::kMin:
|
||||
if (type == ParamType::kF32) {
|
||||
return builder->Call(str.str(), "f2", "f2");
|
||||
} else {
|
||||
return builder->Call(str.str(), "u2", "u2");
|
||||
}
|
||||
case IntrinsicType::kClamp:
|
||||
case BuiltinType::kClamp:
|
||||
if (type == ParamType::kF32) {
|
||||
return builder->Call(str.str(), "f2", "f2", "f2");
|
||||
} else {
|
||||
return builder->Call(str.str(), "u2", "u2", "u2");
|
||||
}
|
||||
case IntrinsicType::kSelect:
|
||||
case BuiltinType::kSelect:
|
||||
return builder->Call(str.str(), "f2", "f2", "b2");
|
||||
case IntrinsicType::kDeterminant:
|
||||
case BuiltinType::kDeterminant:
|
||||
return builder->Call(str.str(), "m2x2");
|
||||
case IntrinsicType::kTranspose:
|
||||
case BuiltinType::kTranspose:
|
||||
return builder->Call(str.str(), "m3x2");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
using HlslIntrinsicTest = TestParamHelper<IntrinsicData>;
|
||||
TEST_P(HlslIntrinsicTest, Emit) {
|
||||
using HlslBuiltinTest = TestParamHelper<BuiltinData>;
|
||||
TEST_P(HlslBuiltinTest, Emit) {
|
||||
auto param = GetParam();
|
||||
|
||||
Global("f2", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
|
@ -165,8 +165,8 @@ TEST_P(HlslIntrinsicTest, Emit) {
|
|||
Global("m2x2", ty.mat2x2<f32>(), ast::StorageClass::kPrivate);
|
||||
Global("m3x2", ty.mat3x2<f32>(), ast::StorageClass::kPrivate);
|
||||
|
||||
auto* call = GenerateCall(param.intrinsic, param.type, this);
|
||||
ASSERT_NE(nullptr, call) << "Unhandled intrinsic";
|
||||
auto* call = GenerateCall(param.builtin, param.type, this);
|
||||
ASSERT_NE(nullptr, call) << "Unhandled builtin";
|
||||
Func("func", {}, ty.void_(), {CallStmt(call)},
|
||||
{create<ast::StageAttribute>(ast::PipelineStage::kFragment)});
|
||||
|
||||
|
@ -176,89 +176,82 @@ TEST_P(HlslIntrinsicTest, Emit) {
|
|||
ASSERT_NE(sem, nullptr);
|
||||
auto* target = sem->Target();
|
||||
ASSERT_NE(target, nullptr);
|
||||
auto* intrinsic = target->As<sem::Intrinsic>();
|
||||
ASSERT_NE(intrinsic, nullptr);
|
||||
auto* builtin = target->As<sem::Builtin>();
|
||||
ASSERT_NE(builtin, nullptr);
|
||||
|
||||
EXPECT_EQ(gen.generate_builtin_name(intrinsic), param.hlsl_name);
|
||||
EXPECT_EQ(gen.generate_builtin_name(builtin), param.hlsl_name);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
HlslGeneratorImplTest_Intrinsic,
|
||||
HlslIntrinsicTest,
|
||||
HlslGeneratorImplTest_Builtin,
|
||||
HlslBuiltinTest,
|
||||
testing::Values(
|
||||
IntrinsicData{IntrinsicType::kAbs, ParamType::kF32, "abs"},
|
||||
IntrinsicData{IntrinsicType::kAbs, ParamType::kU32, "abs"},
|
||||
IntrinsicData{IntrinsicType::kAcos, ParamType::kF32, "acos"},
|
||||
IntrinsicData{IntrinsicType::kAll, ParamType::kBool, "all"},
|
||||
IntrinsicData{IntrinsicType::kAny, ParamType::kBool, "any"},
|
||||
IntrinsicData{IntrinsicType::kAsin, ParamType::kF32, "asin"},
|
||||
IntrinsicData{IntrinsicType::kAtan, ParamType::kF32, "atan"},
|
||||
IntrinsicData{IntrinsicType::kAtan2, ParamType::kF32, "atan2"},
|
||||
IntrinsicData{IntrinsicType::kCeil, ParamType::kF32, "ceil"},
|
||||
IntrinsicData{IntrinsicType::kClamp, ParamType::kF32, "clamp"},
|
||||
IntrinsicData{IntrinsicType::kClamp, ParamType::kU32, "clamp"},
|
||||
IntrinsicData{IntrinsicType::kCos, ParamType::kF32, "cos"},
|
||||
IntrinsicData{IntrinsicType::kCosh, ParamType::kF32, "cosh"},
|
||||
IntrinsicData{IntrinsicType::kCountOneBits, ParamType::kU32,
|
||||
"countbits"},
|
||||
IntrinsicData{IntrinsicType::kCross, ParamType::kF32, "cross"},
|
||||
IntrinsicData{IntrinsicType::kDeterminant, ParamType::kF32,
|
||||
"determinant"},
|
||||
IntrinsicData{IntrinsicType::kDistance, ParamType::kF32, "distance"},
|
||||
IntrinsicData{IntrinsicType::kDot, ParamType::kF32, "dot"},
|
||||
IntrinsicData{IntrinsicType::kDpdx, ParamType::kF32, "ddx"},
|
||||
IntrinsicData{IntrinsicType::kDpdxCoarse, ParamType::kF32,
|
||||
"ddx_coarse"},
|
||||
IntrinsicData{IntrinsicType::kDpdxFine, ParamType::kF32, "ddx_fine"},
|
||||
IntrinsicData{IntrinsicType::kDpdy, ParamType::kF32, "ddy"},
|
||||
IntrinsicData{IntrinsicType::kDpdyCoarse, ParamType::kF32,
|
||||
"ddy_coarse"},
|
||||
IntrinsicData{IntrinsicType::kDpdyFine, ParamType::kF32, "ddy_fine"},
|
||||
IntrinsicData{IntrinsicType::kExp, ParamType::kF32, "exp"},
|
||||
IntrinsicData{IntrinsicType::kExp2, ParamType::kF32, "exp2"},
|
||||
IntrinsicData{IntrinsicType::kFaceForward, ParamType::kF32,
|
||||
"faceforward"},
|
||||
IntrinsicData{IntrinsicType::kFloor, ParamType::kF32, "floor"},
|
||||
IntrinsicData{IntrinsicType::kFma, ParamType::kF32, "mad"},
|
||||
IntrinsicData{IntrinsicType::kFract, ParamType::kF32, "frac"},
|
||||
IntrinsicData{IntrinsicType::kFwidth, ParamType::kF32, "fwidth"},
|
||||
IntrinsicData{IntrinsicType::kFwidthCoarse, ParamType::kF32, "fwidth"},
|
||||
IntrinsicData{IntrinsicType::kFwidthFine, ParamType::kF32, "fwidth"},
|
||||
IntrinsicData{IntrinsicType::kInverseSqrt, ParamType::kF32, "rsqrt"},
|
||||
IntrinsicData{IntrinsicType::kIsFinite, ParamType::kF32, "isfinite"},
|
||||
IntrinsicData{IntrinsicType::kIsInf, ParamType::kF32, "isinf"},
|
||||
IntrinsicData{IntrinsicType::kIsNan, ParamType::kF32, "isnan"},
|
||||
IntrinsicData{IntrinsicType::kLdexp, ParamType::kF32, "ldexp"},
|
||||
IntrinsicData{IntrinsicType::kLength, ParamType::kF32, "length"},
|
||||
IntrinsicData{IntrinsicType::kLog, ParamType::kF32, "log"},
|
||||
IntrinsicData{IntrinsicType::kLog2, ParamType::kF32, "log2"},
|
||||
IntrinsicData{IntrinsicType::kMax, ParamType::kF32, "max"},
|
||||
IntrinsicData{IntrinsicType::kMax, ParamType::kU32, "max"},
|
||||
IntrinsicData{IntrinsicType::kMin, ParamType::kF32, "min"},
|
||||
IntrinsicData{IntrinsicType::kMin, ParamType::kU32, "min"},
|
||||
IntrinsicData{IntrinsicType::kMix, ParamType::kF32, "lerp"},
|
||||
IntrinsicData{IntrinsicType::kNormalize, ParamType::kF32, "normalize"},
|
||||
IntrinsicData{IntrinsicType::kPow, ParamType::kF32, "pow"},
|
||||
IntrinsicData{IntrinsicType::kReflect, ParamType::kF32, "reflect"},
|
||||
IntrinsicData{IntrinsicType::kReverseBits, ParamType::kU32,
|
||||
"reversebits"},
|
||||
IntrinsicData{IntrinsicType::kRound, ParamType::kU32, "round"},
|
||||
IntrinsicData{IntrinsicType::kSign, ParamType::kF32, "sign"},
|
||||
IntrinsicData{IntrinsicType::kSin, ParamType::kF32, "sin"},
|
||||
IntrinsicData{IntrinsicType::kSinh, ParamType::kF32, "sinh"},
|
||||
IntrinsicData{IntrinsicType::kSmoothStep, ParamType::kF32,
|
||||
"smoothstep"},
|
||||
IntrinsicData{IntrinsicType::kSqrt, ParamType::kF32, "sqrt"},
|
||||
IntrinsicData{IntrinsicType::kStep, ParamType::kF32, "step"},
|
||||
IntrinsicData{IntrinsicType::kTan, ParamType::kF32, "tan"},
|
||||
IntrinsicData{IntrinsicType::kTanh, ParamType::kF32, "tanh"},
|
||||
IntrinsicData{IntrinsicType::kTranspose, ParamType::kF32, "transpose"},
|
||||
IntrinsicData{IntrinsicType::kTrunc, ParamType::kF32, "trunc"}));
|
||||
BuiltinData{BuiltinType::kAbs, ParamType::kF32, "abs"},
|
||||
BuiltinData{BuiltinType::kAbs, ParamType::kU32, "abs"},
|
||||
BuiltinData{BuiltinType::kAcos, ParamType::kF32, "acos"},
|
||||
BuiltinData{BuiltinType::kAll, ParamType::kBool, "all"},
|
||||
BuiltinData{BuiltinType::kAny, ParamType::kBool, "any"},
|
||||
BuiltinData{BuiltinType::kAsin, ParamType::kF32, "asin"},
|
||||
BuiltinData{BuiltinType::kAtan, ParamType::kF32, "atan"},
|
||||
BuiltinData{BuiltinType::kAtan2, ParamType::kF32, "atan2"},
|
||||
BuiltinData{BuiltinType::kCeil, ParamType::kF32, "ceil"},
|
||||
BuiltinData{BuiltinType::kClamp, ParamType::kF32, "clamp"},
|
||||
BuiltinData{BuiltinType::kClamp, ParamType::kU32, "clamp"},
|
||||
BuiltinData{BuiltinType::kCos, ParamType::kF32, "cos"},
|
||||
BuiltinData{BuiltinType::kCosh, ParamType::kF32, "cosh"},
|
||||
BuiltinData{BuiltinType::kCountOneBits, ParamType::kU32, "countbits"},
|
||||
BuiltinData{BuiltinType::kCross, ParamType::kF32, "cross"},
|
||||
BuiltinData{BuiltinType::kDeterminant, ParamType::kF32, "determinant"},
|
||||
BuiltinData{BuiltinType::kDistance, ParamType::kF32, "distance"},
|
||||
BuiltinData{BuiltinType::kDot, ParamType::kF32, "dot"},
|
||||
BuiltinData{BuiltinType::kDpdx, ParamType::kF32, "ddx"},
|
||||
BuiltinData{BuiltinType::kDpdxCoarse, ParamType::kF32, "ddx_coarse"},
|
||||
BuiltinData{BuiltinType::kDpdxFine, ParamType::kF32, "ddx_fine"},
|
||||
BuiltinData{BuiltinType::kDpdy, ParamType::kF32, "ddy"},
|
||||
BuiltinData{BuiltinType::kDpdyCoarse, ParamType::kF32, "ddy_coarse"},
|
||||
BuiltinData{BuiltinType::kDpdyFine, ParamType::kF32, "ddy_fine"},
|
||||
BuiltinData{BuiltinType::kExp, ParamType::kF32, "exp"},
|
||||
BuiltinData{BuiltinType::kExp2, ParamType::kF32, "exp2"},
|
||||
BuiltinData{BuiltinType::kFaceForward, ParamType::kF32, "faceforward"},
|
||||
BuiltinData{BuiltinType::kFloor, ParamType::kF32, "floor"},
|
||||
BuiltinData{BuiltinType::kFma, ParamType::kF32, "mad"},
|
||||
BuiltinData{BuiltinType::kFract, ParamType::kF32, "frac"},
|
||||
BuiltinData{BuiltinType::kFwidth, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kFwidthCoarse, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kFwidthFine, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kInverseSqrt, ParamType::kF32, "rsqrt"},
|
||||
BuiltinData{BuiltinType::kIsFinite, ParamType::kF32, "isfinite"},
|
||||
BuiltinData{BuiltinType::kIsInf, ParamType::kF32, "isinf"},
|
||||
BuiltinData{BuiltinType::kIsNan, ParamType::kF32, "isnan"},
|
||||
BuiltinData{BuiltinType::kLdexp, ParamType::kF32, "ldexp"},
|
||||
BuiltinData{BuiltinType::kLength, ParamType::kF32, "length"},
|
||||
BuiltinData{BuiltinType::kLog, ParamType::kF32, "log"},
|
||||
BuiltinData{BuiltinType::kLog2, ParamType::kF32, "log2"},
|
||||
BuiltinData{BuiltinType::kMax, ParamType::kF32, "max"},
|
||||
BuiltinData{BuiltinType::kMax, ParamType::kU32, "max"},
|
||||
BuiltinData{BuiltinType::kMin, ParamType::kF32, "min"},
|
||||
BuiltinData{BuiltinType::kMin, ParamType::kU32, "min"},
|
||||
BuiltinData{BuiltinType::kMix, ParamType::kF32, "lerp"},
|
||||
BuiltinData{BuiltinType::kNormalize, ParamType::kF32, "normalize"},
|
||||
BuiltinData{BuiltinType::kPow, ParamType::kF32, "pow"},
|
||||
BuiltinData{BuiltinType::kReflect, ParamType::kF32, "reflect"},
|
||||
BuiltinData{BuiltinType::kReverseBits, ParamType::kU32, "reversebits"},
|
||||
BuiltinData{BuiltinType::kRound, ParamType::kU32, "round"},
|
||||
BuiltinData{BuiltinType::kSign, ParamType::kF32, "sign"},
|
||||
BuiltinData{BuiltinType::kSin, ParamType::kF32, "sin"},
|
||||
BuiltinData{BuiltinType::kSinh, ParamType::kF32, "sinh"},
|
||||
BuiltinData{BuiltinType::kSmoothStep, ParamType::kF32, "smoothstep"},
|
||||
BuiltinData{BuiltinType::kSqrt, ParamType::kF32, "sqrt"},
|
||||
BuiltinData{BuiltinType::kStep, ParamType::kF32, "step"},
|
||||
BuiltinData{BuiltinType::kTan, ParamType::kF32, "tan"},
|
||||
BuiltinData{BuiltinType::kTanh, ParamType::kF32, "tanh"},
|
||||
BuiltinData{BuiltinType::kTranspose, ParamType::kF32, "transpose"},
|
||||
BuiltinData{BuiltinType::kTrunc, ParamType::kF32, "trunc"}));
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, DISABLED_Intrinsic_IsNormal) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, DISABLED_Builtin_IsNormal) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Intrinsic_Call) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Builtin_Call) {
|
||||
auto* call = Call("dot", "param1", "param2");
|
||||
|
||||
Global("param1", ty.vec3<f32>(), ast::StorageClass::kPrivate);
|
||||
|
@ -274,7 +267,7 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Intrinsic_Call) {
|
|||
EXPECT_EQ(out.str(), "dot(param1, param2)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Scalar) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Select_Scalar) {
|
||||
auto* call = Call("select", 1.0f, 2.0f, true);
|
||||
WrapInFunction(CallStmt(call));
|
||||
GeneratorImpl& gen = Build();
|
||||
|
@ -285,7 +278,7 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Scalar) {
|
|||
EXPECT_EQ(out.str(), "(true ? 2.0f : 1.0f)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Vector) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Select_Vector) {
|
||||
auto* call =
|
||||
Call("select", vec2<i32>(1, 2), vec2<i32>(3, 4), vec2<bool>(true, false));
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -297,7 +290,7 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Vector) {
|
|||
EXPECT_EQ(out.str(), "(bool2(true, false) ? int2(3, 4) : int2(1, 2))");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Modf_Scalar) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Modf_Scalar) {
|
||||
auto* call = Call("modf", 1.0f);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
||||
|
@ -323,7 +316,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Modf_Vector) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Modf_Vector) {
|
||||
auto* call = Call("modf", vec3<f32>());
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
||||
|
@ -349,7 +342,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Scalar_i32) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Frexp_Scalar_i32) {
|
||||
auto* call = Call("frexp", 1.0f);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
||||
|
@ -375,7 +368,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Vector_i32) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Frexp_Vector_i32) {
|
||||
auto* call = Call("frexp", vec3<f32>());
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
||||
|
@ -401,7 +394,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, IsNormal_Scalar) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, IsNormal_Scalar) {
|
||||
auto* val = Var("val", ty.f32());
|
||||
auto* call = Call("isNormal", val);
|
||||
WrapInFunction(val, call);
|
||||
|
@ -424,7 +417,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, IsNormal_Vector) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, IsNormal_Vector) {
|
||||
auto* val = Var("val", ty.vec3<f32>());
|
||||
auto* call = Call("isNormal", val);
|
||||
WrapInFunction(val, call);
|
||||
|
@ -447,7 +440,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Degrees_Scalar) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Degrees_Scalar) {
|
||||
auto* val = Var("val", ty.f32());
|
||||
auto* call = Call("degrees", val);
|
||||
WrapInFunction(val, call);
|
||||
|
@ -468,7 +461,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Degrees_Vector) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Degrees_Vector) {
|
||||
auto* val = Var("val", ty.vec3<f32>());
|
||||
auto* call = Call("degrees", val);
|
||||
WrapInFunction(val, call);
|
||||
|
@ -489,7 +482,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Radians_Scalar) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Radians_Scalar) {
|
||||
auto* val = Var("val", ty.f32());
|
||||
auto* call = Call("radians", val);
|
||||
WrapInFunction(val, call);
|
||||
|
@ -510,7 +503,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Radians_Vector) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Radians_Vector) {
|
||||
auto* val = Var("val", ty.vec3<f32>());
|
||||
auto* call = Call("radians", val);
|
||||
WrapInFunction(val, call);
|
||||
|
@ -531,7 +524,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Pack4x8Snorm) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Pack4x8Snorm) {
|
||||
auto* call = Call("pack4x8snorm", "p1");
|
||||
Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -553,7 +546,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Pack4x8Unorm) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Pack4x8Unorm) {
|
||||
auto* call = Call("pack4x8unorm", "p1");
|
||||
Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -575,7 +568,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Snorm) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Pack2x16Snorm) {
|
||||
auto* call = Call("pack2x16snorm", "p1");
|
||||
Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -597,7 +590,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Unorm) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Pack2x16Unorm) {
|
||||
auto* call = Call("pack2x16unorm", "p1");
|
||||
Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -619,7 +612,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Float) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Pack2x16Float) {
|
||||
auto* call = Call("pack2x16float", "p1");
|
||||
Global("p1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -641,7 +634,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack4x8Snorm) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Unpack4x8Snorm) {
|
||||
auto* call = Call("unpack4x8snorm", "p1");
|
||||
Global("p1", ty.u32(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -664,7 +657,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack4x8Unorm) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Unpack4x8Unorm) {
|
||||
auto* call = Call("unpack4x8unorm", "p1");
|
||||
Global("p1", ty.u32(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -687,7 +680,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Snorm) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Unpack2x16Snorm) {
|
||||
auto* call = Call("unpack2x16snorm", "p1");
|
||||
Global("p1", ty.u32(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -710,7 +703,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Unorm) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Unpack2x16Unorm) {
|
||||
auto* call = Call("unpack2x16unorm", "p1");
|
||||
Global("p1", ty.u32(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -733,7 +726,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Float) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Unpack2x16Float) {
|
||||
auto* call = Call("unpack2x16float", "p1");
|
||||
Global("p1", ty.u32(), ast::StorageClass::kPrivate);
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
@ -755,7 +748,7 @@ void test_function() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, StorageBarrier) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, StorageBarrier) {
|
||||
Func("main", {}, ty.void_(), {CallStmt(Call("storageBarrier"))},
|
||||
{
|
||||
Stage(ast::PipelineStage::kCompute),
|
||||
|
@ -773,7 +766,7 @@ void main() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, WorkgroupBarrier) {
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, WorkgroupBarrier) {
|
||||
Func("main", {}, ty.void_(), {CallStmt(Call("workgroupBarrier"))},
|
||||
{
|
||||
Stage(ast::PipelineStage::kCompute),
|
|
@ -13,8 +13,8 @@
|
|||
// limitations under the License.
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/ast/builtin_texture_helper_test.h"
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/intrinsic_texture_helper_test.h"
|
||||
#include "src/ast/stage_attribute.h"
|
||||
#include "src/writer/hlsl/test_helper.h"
|
||||
|
||||
|
@ -34,8 +34,8 @@ struct ExpectedResult {
|
|||
};
|
||||
|
||||
ExpectedResult expected_texture_overload(
|
||||
ast::intrinsic::test::ValidTextureOverload overload) {
|
||||
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
|
||||
ast::builtin::test::ValidTextureOverload overload) {
|
||||
using ValidTextureOverload = ast::builtin::test::ValidTextureOverload;
|
||||
switch (overload) {
|
||||
case ValidTextureOverload::kDimensions1d:
|
||||
case ValidTextureOverload::kDimensionsStorageWO1d:
|
||||
|
@ -361,10 +361,10 @@ ExpectedResult expected_texture_overload(
|
|||
return "<unmatched texture overload>";
|
||||
} // NOLINT - Ignore the length of this function
|
||||
|
||||
class HlslGeneratorIntrinsicTextureTest
|
||||
: public TestParamHelper<ast::intrinsic::test::TextureOverloadCase> {};
|
||||
class HlslGeneratorBuiltinTextureTest
|
||||
: public TestParamHelper<ast::builtin::test::TextureOverloadCase> {};
|
||||
|
||||
TEST_P(HlslGeneratorIntrinsicTextureTest, Call) {
|
||||
TEST_P(HlslGeneratorBuiltinTextureTest, Call) {
|
||||
auto param = GetParam();
|
||||
|
||||
param.BuildTextureVariable(this);
|
||||
|
@ -386,9 +386,9 @@ TEST_P(HlslGeneratorIntrinsicTextureTest, Call) {
|
|||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
HlslGeneratorIntrinsicTextureTest,
|
||||
HlslGeneratorIntrinsicTextureTest,
|
||||
testing::ValuesIn(ast::intrinsic::test::TextureOverloadCase::ValidCases()));
|
||||
HlslGeneratorBuiltinTextureTest,
|
||||
HlslGeneratorBuiltinTextureTest,
|
||||
testing::ValuesIn(ast::builtin::test::TextureOverloadCase::ValidCases()));
|
||||
|
||||
} // namespace
|
||||
} // namespace hlsl
|
|
@ -542,8 +542,8 @@ bool GeneratorImpl::EmitCall(std::ostream& out,
|
|||
if (auto* func = target->As<sem::Function>()) {
|
||||
return EmitFunctionCall(out, call, func);
|
||||
}
|
||||
if (auto* intrinsic = target->As<sem::Intrinsic>()) {
|
||||
return EmitIntrinsicCall(out, call, intrinsic);
|
||||
if (auto* builtin = target->As<sem::Builtin>()) {
|
||||
return EmitBuiltinCall(out, call, builtin);
|
||||
}
|
||||
if (auto* conv = target->As<sem::TypeConversion>()) {
|
||||
return EmitTypeConversion(out, call, conv);
|
||||
|
@ -579,34 +579,34 @@ bool GeneratorImpl::EmitFunctionCall(std::ostream& out,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
bool GeneratorImpl::EmitBuiltinCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Builtin* builtin) {
|
||||
auto* expr = call->Declaration();
|
||||
if (intrinsic->IsAtomic()) {
|
||||
return EmitAtomicCall(out, expr, intrinsic);
|
||||
if (builtin->IsAtomic()) {
|
||||
return EmitAtomicCall(out, expr, builtin);
|
||||
}
|
||||
if (intrinsic->IsTexture()) {
|
||||
return EmitTextureCall(out, call, intrinsic);
|
||||
if (builtin->IsTexture()) {
|
||||
return EmitTextureCall(out, call, builtin);
|
||||
}
|
||||
|
||||
auto name = generate_builtin_name(intrinsic);
|
||||
auto name = generate_builtin_name(builtin);
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kDot:
|
||||
return EmitDotCall(out, expr, intrinsic);
|
||||
case sem::IntrinsicType::kModf:
|
||||
return EmitModfCall(out, expr, intrinsic);
|
||||
case sem::IntrinsicType::kFrexp:
|
||||
return EmitFrexpCall(out, expr, intrinsic);
|
||||
case sem::IntrinsicType::kDegrees:
|
||||
return EmitDegreesCall(out, expr, intrinsic);
|
||||
case sem::IntrinsicType::kRadians:
|
||||
return EmitRadiansCall(out, expr, intrinsic);
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kDot:
|
||||
return EmitDotCall(out, expr, builtin);
|
||||
case sem::BuiltinType::kModf:
|
||||
return EmitModfCall(out, expr, builtin);
|
||||
case sem::BuiltinType::kFrexp:
|
||||
return EmitFrexpCall(out, expr, builtin);
|
||||
case sem::BuiltinType::kDegrees:
|
||||
return EmitDegreesCall(out, expr, builtin);
|
||||
case sem::BuiltinType::kRadians:
|
||||
return EmitRadiansCall(out, expr, builtin);
|
||||
|
||||
case sem::IntrinsicType::kPack2x16float:
|
||||
case sem::IntrinsicType::kUnpack2x16float: {
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kPack2x16float) {
|
||||
case sem::BuiltinType::kPack2x16float:
|
||||
case sem::BuiltinType::kUnpack2x16float: {
|
||||
if (builtin->Type() == sem::BuiltinType::kPack2x16float) {
|
||||
out << "as_type<uint>(half2(";
|
||||
} else {
|
||||
out << "float2(as_type<half2>(";
|
||||
|
@ -619,16 +619,16 @@ bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out,
|
|||
}
|
||||
// TODO(crbug.com/tint/661): Combine sequential barriers to a single
|
||||
// instruction.
|
||||
case sem::IntrinsicType::kStorageBarrier: {
|
||||
case sem::BuiltinType::kStorageBarrier: {
|
||||
out << "threadgroup_barrier(mem_flags::mem_device)";
|
||||
return true;
|
||||
}
|
||||
case sem::IntrinsicType::kWorkgroupBarrier: {
|
||||
case sem::BuiltinType::kWorkgroupBarrier: {
|
||||
out << "threadgroup_barrier(mem_flags::mem_threadgroup)";
|
||||
return true;
|
||||
}
|
||||
|
||||
case sem::IntrinsicType::kLength: {
|
||||
case sem::BuiltinType::kLength: {
|
||||
auto* sem = builder_.Sem().Get(expr->args[0]);
|
||||
if (sem->Type()->UnwrapRef()->is_scalar()) {
|
||||
// Emulate scalar overload using fabs(x).
|
||||
|
@ -637,7 +637,7 @@ bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out,
|
|||
break;
|
||||
}
|
||||
|
||||
case sem::IntrinsicType::kDistance: {
|
||||
case sem::BuiltinType::kDistance: {
|
||||
auto* sem = builder_.Sem().Get(expr->args[0]);
|
||||
if (sem->Type()->UnwrapRef()->is_scalar()) {
|
||||
// Emulate scalar overload using fabs(x - y);
|
||||
|
@ -741,7 +741,7 @@ bool GeneratorImpl::EmitTypeConstructor(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitAtomicCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
const sem::Builtin* builtin) {
|
||||
auto call = [&](const std::string& name, bool append_memory_order_relaxed) {
|
||||
out << name;
|
||||
{
|
||||
|
@ -762,38 +762,38 @@ bool GeneratorImpl::EmitAtomicCall(std::ostream& out,
|
|||
return true;
|
||||
};
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kAtomicLoad:
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kAtomicLoad:
|
||||
return call("atomic_load_explicit", true);
|
||||
|
||||
case sem::IntrinsicType::kAtomicStore:
|
||||
case sem::BuiltinType::kAtomicStore:
|
||||
return call("atomic_store_explicit", true);
|
||||
|
||||
case sem::IntrinsicType::kAtomicAdd:
|
||||
case sem::BuiltinType::kAtomicAdd:
|
||||
return call("atomic_fetch_add_explicit", true);
|
||||
|
||||
case sem::IntrinsicType::kAtomicSub:
|
||||
case sem::BuiltinType::kAtomicSub:
|
||||
return call("atomic_fetch_sub_explicit", true);
|
||||
|
||||
case sem::IntrinsicType::kAtomicMax:
|
||||
case sem::BuiltinType::kAtomicMax:
|
||||
return call("atomic_fetch_max_explicit", true);
|
||||
|
||||
case sem::IntrinsicType::kAtomicMin:
|
||||
case sem::BuiltinType::kAtomicMin:
|
||||
return call("atomic_fetch_min_explicit", true);
|
||||
|
||||
case sem::IntrinsicType::kAtomicAnd:
|
||||
case sem::BuiltinType::kAtomicAnd:
|
||||
return call("atomic_fetch_and_explicit", true);
|
||||
|
||||
case sem::IntrinsicType::kAtomicOr:
|
||||
case sem::BuiltinType::kAtomicOr:
|
||||
return call("atomic_fetch_or_explicit", true);
|
||||
|
||||
case sem::IntrinsicType::kAtomicXor:
|
||||
case sem::BuiltinType::kAtomicXor:
|
||||
return call("atomic_fetch_xor_explicit", true);
|
||||
|
||||
case sem::IntrinsicType::kAtomicExchange:
|
||||
case sem::BuiltinType::kAtomicExchange:
|
||||
return call("atomic_exchange_explicit", true);
|
||||
|
||||
case sem::IntrinsicType::kAtomicCompareExchangeWeak: {
|
||||
case sem::BuiltinType::kAtomicCompareExchangeWeak: {
|
||||
auto* ptr_ty = TypeOf(expr->args[0])->UnwrapRef()->As<sem::Pointer>();
|
||||
auto sc = ptr_ty->StorageClass();
|
||||
|
||||
|
@ -836,16 +836,16 @@ bool GeneratorImpl::EmitAtomicCall(std::ostream& out,
|
|||
}
|
||||
|
||||
TINT_UNREACHABLE(Writer, diagnostics_)
|
||||
<< "unsupported atomic intrinsic: " << intrinsic->Type();
|
||||
<< "unsupported atomic builtin: " << builtin->Type();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
const sem::Builtin* builtin) {
|
||||
using Usage = sem::ParameterUsage;
|
||||
|
||||
auto& signature = intrinsic->Signature();
|
||||
auto& signature = builtin->Signature();
|
||||
auto* expr = call->Declaration();
|
||||
auto& arguments = call->Arguments();
|
||||
|
||||
|
@ -883,8 +883,8 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
return true;
|
||||
};
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kTextureDimensions: {
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kTextureDimensions: {
|
||||
std::vector<const char*> dims;
|
||||
switch (texture_type->dim()) {
|
||||
case ast::TextureDimension::kNone:
|
||||
|
@ -936,7 +936,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
}
|
||||
return true;
|
||||
}
|
||||
case sem::IntrinsicType::kTextureNumLayers: {
|
||||
case sem::BuiltinType::kTextureNumLayers: {
|
||||
out << "int(";
|
||||
if (!texture_expr()) {
|
||||
return false;
|
||||
|
@ -944,7 +944,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
out << ".get_array_size())";
|
||||
return true;
|
||||
}
|
||||
case sem::IntrinsicType::kTextureNumLevels: {
|
||||
case sem::BuiltinType::kTextureNumLevels: {
|
||||
out << "int(";
|
||||
if (!texture_expr()) {
|
||||
return false;
|
||||
|
@ -952,7 +952,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
out << ".get_num_mip_levels())";
|
||||
return true;
|
||||
}
|
||||
case sem::IntrinsicType::kTextureNumSamples: {
|
||||
case sem::BuiltinType::kTextureNumSamples: {
|
||||
out << "int(";
|
||||
if (!texture_expr()) {
|
||||
return false;
|
||||
|
@ -970,33 +970,33 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
|
||||
bool lod_param_is_named = true;
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kTextureSample:
|
||||
case sem::IntrinsicType::kTextureSampleBias:
|
||||
case sem::IntrinsicType::kTextureSampleLevel:
|
||||
case sem::IntrinsicType::kTextureSampleGrad:
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kTextureSample:
|
||||
case sem::BuiltinType::kTextureSampleBias:
|
||||
case sem::BuiltinType::kTextureSampleLevel:
|
||||
case sem::BuiltinType::kTextureSampleGrad:
|
||||
out << ".sample(";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureSampleCompare:
|
||||
case sem::IntrinsicType::kTextureSampleCompareLevel:
|
||||
case sem::BuiltinType::kTextureSampleCompare:
|
||||
case sem::BuiltinType::kTextureSampleCompareLevel:
|
||||
out << ".sample_compare(";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureGather:
|
||||
case sem::BuiltinType::kTextureGather:
|
||||
out << ".gather(";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureGatherCompare:
|
||||
case sem::BuiltinType::kTextureGatherCompare:
|
||||
out << ".gather_compare(";
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureLoad:
|
||||
case sem::BuiltinType::kTextureLoad:
|
||||
out << ".read(";
|
||||
lod_param_is_named = false;
|
||||
break;
|
||||
case sem::IntrinsicType::kTextureStore:
|
||||
case sem::BuiltinType::kTextureStore:
|
||||
out << ".write(";
|
||||
break;
|
||||
default:
|
||||
TINT_UNREACHABLE(Writer, diagnostics_)
|
||||
<< "Unhandled texture intrinsic '" << intrinsic->str() << "'";
|
||||
<< "Unhandled texture builtin '" << builtin->str() << "'";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1066,7 +1066,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
out << ")";
|
||||
}
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kTextureSampleCompareLevel) {
|
||||
if (builtin->Type() == sem::BuiltinType::kTextureSampleCompareLevel) {
|
||||
maybe_write_comma();
|
||||
out << "level(0)";
|
||||
}
|
||||
|
@ -1154,8 +1154,8 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitDotCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
auto* vec_ty = intrinsic->Parameters()[0]->Type()->As<sem::Vector>();
|
||||
const sem::Builtin* builtin) {
|
||||
auto* vec_ty = builtin->Parameters()[0]->Type()->As<sem::Vector>();
|
||||
std::string fn = "dot";
|
||||
if (vec_ty->type()->is_integer_scalar()) {
|
||||
// MSL does not have a builtin for dot() with integer vector types.
|
||||
|
@ -1201,11 +1201,11 @@ bool GeneratorImpl::EmitDotCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitModfCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
auto* ty = intrinsic->Parameters()[0]->Type();
|
||||
auto* ty = builtin->Parameters()[0]->Type();
|
||||
auto in = params[0];
|
||||
|
||||
std::string width;
|
||||
|
@ -1216,7 +1216,7 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
|
|||
// Emit the builtin return type unique to this overload. This does not
|
||||
// exist in the AST, so it will not be generated in Generate().
|
||||
if (!EmitStructType(&helpers_,
|
||||
intrinsic->ReturnType()->As<sem::Struct>())) {
|
||||
builtin->ReturnType()->As<sem::Struct>())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1229,11 +1229,11 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
auto* ty = intrinsic->Parameters()[0]->Type();
|
||||
auto* ty = builtin->Parameters()[0]->Type();
|
||||
auto in = params[0];
|
||||
|
||||
std::string width;
|
||||
|
@ -1244,7 +1244,7 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
|||
// Emit the builtin return type unique to this overload. This does not
|
||||
// exist in the AST, so it will not be generated in Generate().
|
||||
if (!EmitStructType(&helpers_,
|
||||
intrinsic->ReturnType()->As<sem::Struct>())) {
|
||||
builtin->ReturnType()->As<sem::Struct>())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1257,9 +1257,9 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
line(b) << "return " << params[0] << " * " << std::setprecision(20)
|
||||
<< sem::kRadToDeg << ";";
|
||||
|
@ -1269,9 +1269,9 @@ bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
|
|||
|
||||
bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
return CallIntrinsicHelper(
|
||||
out, expr, intrinsic,
|
||||
const sem::Builtin* builtin) {
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
line(b) << "return " << params[0] << " * " << std::setprecision(20)
|
||||
<< sem::kDegToRad << ";";
|
||||
|
@ -1279,153 +1279,152 @@ bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
|
|||
});
|
||||
}
|
||||
|
||||
std::string GeneratorImpl::generate_builtin_name(
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
|
||||
std::string out = "";
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kAcos:
|
||||
case sem::IntrinsicType::kAll:
|
||||
case sem::IntrinsicType::kAny:
|
||||
case sem::IntrinsicType::kAsin:
|
||||
case sem::IntrinsicType::kAtan:
|
||||
case sem::IntrinsicType::kAtan2:
|
||||
case sem::IntrinsicType::kCeil:
|
||||
case sem::IntrinsicType::kCos:
|
||||
case sem::IntrinsicType::kCosh:
|
||||
case sem::IntrinsicType::kCross:
|
||||
case sem::IntrinsicType::kDeterminant:
|
||||
case sem::IntrinsicType::kDistance:
|
||||
case sem::IntrinsicType::kDot:
|
||||
case sem::IntrinsicType::kExp:
|
||||
case sem::IntrinsicType::kExp2:
|
||||
case sem::IntrinsicType::kFloor:
|
||||
case sem::IntrinsicType::kFma:
|
||||
case sem::IntrinsicType::kFract:
|
||||
case sem::IntrinsicType::kFrexp:
|
||||
case sem::IntrinsicType::kLength:
|
||||
case sem::IntrinsicType::kLdexp:
|
||||
case sem::IntrinsicType::kLog:
|
||||
case sem::IntrinsicType::kLog2:
|
||||
case sem::IntrinsicType::kMix:
|
||||
case sem::IntrinsicType::kModf:
|
||||
case sem::IntrinsicType::kNormalize:
|
||||
case sem::IntrinsicType::kPow:
|
||||
case sem::IntrinsicType::kReflect:
|
||||
case sem::IntrinsicType::kRefract:
|
||||
case sem::IntrinsicType::kSelect:
|
||||
case sem::IntrinsicType::kSin:
|
||||
case sem::IntrinsicType::kSinh:
|
||||
case sem::IntrinsicType::kSqrt:
|
||||
case sem::IntrinsicType::kStep:
|
||||
case sem::IntrinsicType::kTan:
|
||||
case sem::IntrinsicType::kTanh:
|
||||
case sem::IntrinsicType::kTranspose:
|
||||
case sem::IntrinsicType::kTrunc:
|
||||
case sem::IntrinsicType::kSign:
|
||||
case sem::IntrinsicType::kClamp:
|
||||
out += intrinsic->str();
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kAcos:
|
||||
case sem::BuiltinType::kAll:
|
||||
case sem::BuiltinType::kAny:
|
||||
case sem::BuiltinType::kAsin:
|
||||
case sem::BuiltinType::kAtan:
|
||||
case sem::BuiltinType::kAtan2:
|
||||
case sem::BuiltinType::kCeil:
|
||||
case sem::BuiltinType::kCos:
|
||||
case sem::BuiltinType::kCosh:
|
||||
case sem::BuiltinType::kCross:
|
||||
case sem::BuiltinType::kDeterminant:
|
||||
case sem::BuiltinType::kDistance:
|
||||
case sem::BuiltinType::kDot:
|
||||
case sem::BuiltinType::kExp:
|
||||
case sem::BuiltinType::kExp2:
|
||||
case sem::BuiltinType::kFloor:
|
||||
case sem::BuiltinType::kFma:
|
||||
case sem::BuiltinType::kFract:
|
||||
case sem::BuiltinType::kFrexp:
|
||||
case sem::BuiltinType::kLength:
|
||||
case sem::BuiltinType::kLdexp:
|
||||
case sem::BuiltinType::kLog:
|
||||
case sem::BuiltinType::kLog2:
|
||||
case sem::BuiltinType::kMix:
|
||||
case sem::BuiltinType::kModf:
|
||||
case sem::BuiltinType::kNormalize:
|
||||
case sem::BuiltinType::kPow:
|
||||
case sem::BuiltinType::kReflect:
|
||||
case sem::BuiltinType::kRefract:
|
||||
case sem::BuiltinType::kSelect:
|
||||
case sem::BuiltinType::kSin:
|
||||
case sem::BuiltinType::kSinh:
|
||||
case sem::BuiltinType::kSqrt:
|
||||
case sem::BuiltinType::kStep:
|
||||
case sem::BuiltinType::kTan:
|
||||
case sem::BuiltinType::kTanh:
|
||||
case sem::BuiltinType::kTranspose:
|
||||
case sem::BuiltinType::kTrunc:
|
||||
case sem::BuiltinType::kSign:
|
||||
case sem::BuiltinType::kClamp:
|
||||
out += builtin->str();
|
||||
break;
|
||||
case sem::IntrinsicType::kAbs:
|
||||
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) {
|
||||
case sem::BuiltinType::kAbs:
|
||||
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
|
||||
out += "fabs";
|
||||
} else {
|
||||
out += "abs";
|
||||
}
|
||||
break;
|
||||
case sem::IntrinsicType::kCountOneBits:
|
||||
case sem::BuiltinType::kCountOneBits:
|
||||
out += "popcount";
|
||||
break;
|
||||
case sem::IntrinsicType::kDpdx:
|
||||
case sem::IntrinsicType::kDpdxCoarse:
|
||||
case sem::IntrinsicType::kDpdxFine:
|
||||
case sem::BuiltinType::kDpdx:
|
||||
case sem::BuiltinType::kDpdxCoarse:
|
||||
case sem::BuiltinType::kDpdxFine:
|
||||
out += "dfdx";
|
||||
break;
|
||||
case sem::IntrinsicType::kDpdy:
|
||||
case sem::IntrinsicType::kDpdyCoarse:
|
||||
case sem::IntrinsicType::kDpdyFine:
|
||||
case sem::BuiltinType::kDpdy:
|
||||
case sem::BuiltinType::kDpdyCoarse:
|
||||
case sem::BuiltinType::kDpdyFine:
|
||||
out += "dfdy";
|
||||
break;
|
||||
case sem::IntrinsicType::kFwidth:
|
||||
case sem::IntrinsicType::kFwidthCoarse:
|
||||
case sem::IntrinsicType::kFwidthFine:
|
||||
case sem::BuiltinType::kFwidth:
|
||||
case sem::BuiltinType::kFwidthCoarse:
|
||||
case sem::BuiltinType::kFwidthFine:
|
||||
out += "fwidth";
|
||||
break;
|
||||
case sem::IntrinsicType::kIsFinite:
|
||||
case sem::BuiltinType::kIsFinite:
|
||||
out += "isfinite";
|
||||
break;
|
||||
case sem::IntrinsicType::kIsInf:
|
||||
case sem::BuiltinType::kIsInf:
|
||||
out += "isinf";
|
||||
break;
|
||||
case sem::IntrinsicType::kIsNan:
|
||||
case sem::BuiltinType::kIsNan:
|
||||
out += "isnan";
|
||||
break;
|
||||
case sem::IntrinsicType::kIsNormal:
|
||||
case sem::BuiltinType::kIsNormal:
|
||||
out += "isnormal";
|
||||
break;
|
||||
case sem::IntrinsicType::kMax:
|
||||
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) {
|
||||
case sem::BuiltinType::kMax:
|
||||
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
|
||||
out += "fmax";
|
||||
} else {
|
||||
out += "max";
|
||||
}
|
||||
break;
|
||||
case sem::IntrinsicType::kMin:
|
||||
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) {
|
||||
case sem::BuiltinType::kMin:
|
||||
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
|
||||
out += "fmin";
|
||||
} else {
|
||||
out += "min";
|
||||
}
|
||||
break;
|
||||
case sem::IntrinsicType::kFaceForward:
|
||||
case sem::BuiltinType::kFaceForward:
|
||||
out += "faceforward";
|
||||
break;
|
||||
case sem::IntrinsicType::kPack4x8snorm:
|
||||
case sem::BuiltinType::kPack4x8snorm:
|
||||
out += "pack_float_to_snorm4x8";
|
||||
break;
|
||||
case sem::IntrinsicType::kPack4x8unorm:
|
||||
case sem::BuiltinType::kPack4x8unorm:
|
||||
out += "pack_float_to_unorm4x8";
|
||||
break;
|
||||
case sem::IntrinsicType::kPack2x16snorm:
|
||||
case sem::BuiltinType::kPack2x16snorm:
|
||||
out += "pack_float_to_snorm2x16";
|
||||
break;
|
||||
case sem::IntrinsicType::kPack2x16unorm:
|
||||
case sem::BuiltinType::kPack2x16unorm:
|
||||
out += "pack_float_to_unorm2x16";
|
||||
break;
|
||||
case sem::IntrinsicType::kReverseBits:
|
||||
case sem::BuiltinType::kReverseBits:
|
||||
out += "reverse_bits";
|
||||
break;
|
||||
case sem::IntrinsicType::kRound:
|
||||
case sem::BuiltinType::kRound:
|
||||
out += "rint";
|
||||
break;
|
||||
case sem::IntrinsicType::kSmoothStep:
|
||||
case sem::BuiltinType::kSmoothStep:
|
||||
out += "smoothstep";
|
||||
break;
|
||||
case sem::IntrinsicType::kInverseSqrt:
|
||||
case sem::BuiltinType::kInverseSqrt:
|
||||
out += "rsqrt";
|
||||
break;
|
||||
case sem::IntrinsicType::kUnpack4x8snorm:
|
||||
case sem::BuiltinType::kUnpack4x8snorm:
|
||||
out += "unpack_snorm4x8_to_float";
|
||||
break;
|
||||
case sem::IntrinsicType::kUnpack4x8unorm:
|
||||
case sem::BuiltinType::kUnpack4x8unorm:
|
||||
out += "unpack_unorm4x8_to_float";
|
||||
break;
|
||||
case sem::IntrinsicType::kUnpack2x16snorm:
|
||||
case sem::BuiltinType::kUnpack2x16snorm:
|
||||
out += "unpack_snorm2x16_to_float";
|
||||
break;
|
||||
case sem::IntrinsicType::kUnpack2x16unorm:
|
||||
case sem::BuiltinType::kUnpack2x16unorm:
|
||||
out += "unpack_unorm2x16_to_float";
|
||||
break;
|
||||
case sem::IntrinsicType::kArrayLength:
|
||||
case sem::BuiltinType::kArrayLength:
|
||||
diagnostics_.add_error(
|
||||
diag::System::Writer,
|
||||
"Unable to translate builtin: " + std::string(intrinsic->str()) +
|
||||
"Unable to translate builtin: " + std::string(builtin->str()) +
|
||||
"\nDid you forget to pass array_length_from_uniform generator "
|
||||
"options?");
|
||||
return "";
|
||||
default:
|
||||
diagnostics_.add_error(
|
||||
diag::System::Writer,
|
||||
"Unknown import method: " + std::string(intrinsic->str()));
|
||||
"Unknown import method: " + std::string(builtin->str()));
|
||||
return "";
|
||||
}
|
||||
return out;
|
||||
|
@ -2871,26 +2870,26 @@ GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign(
|
|||
}
|
||||
|
||||
template <typename F>
|
||||
bool GeneratorImpl::CallIntrinsicHelper(std::ostream& out,
|
||||
const ast::CallExpression* call,
|
||||
const sem::Intrinsic* intrinsic,
|
||||
F&& build) {
|
||||
bool GeneratorImpl::CallBuiltinHelper(std::ostream& out,
|
||||
const ast::CallExpression* call,
|
||||
const sem::Builtin* builtin,
|
||||
F&& build) {
|
||||
// Generate the helper function if it hasn't been created already
|
||||
auto fn = utils::GetOrCreate(intrinsics_, intrinsic, [&]() -> std::string {
|
||||
auto fn = utils::GetOrCreate(builtins_, builtin, [&]() -> std::string {
|
||||
TextBuffer b;
|
||||
TINT_DEFER(helpers_.Append(b));
|
||||
|
||||
auto fn_name =
|
||||
UniqueIdentifier(std::string("tint_") + sem::str(intrinsic->Type()));
|
||||
UniqueIdentifier(std::string("tint_") + sem::str(builtin->Type()));
|
||||
std::vector<std::string> parameter_names;
|
||||
{
|
||||
auto decl = line(&b);
|
||||
if (!EmitTypeAndName(decl, intrinsic->ReturnType(), fn_name)) {
|
||||
if (!EmitTypeAndName(decl, builtin->ReturnType(), fn_name)) {
|
||||
return "";
|
||||
}
|
||||
{
|
||||
ScopedParen sp(decl);
|
||||
for (auto* param : intrinsic->Parameters()) {
|
||||
for (auto* param : builtin->Parameters()) {
|
||||
if (!parameter_names.empty()) {
|
||||
decl << ", ";
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace tint {
|
|||
// Forward declarations
|
||||
namespace sem {
|
||||
class Call;
|
||||
class Intrinsic;
|
||||
class Builtin;
|
||||
class TypeConstructor;
|
||||
class TypeConversion;
|
||||
} // namespace sem
|
||||
|
@ -143,14 +143,14 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// @param expr the call expression
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitCall(std::ostream& out, const ast::CallExpression* expr);
|
||||
/// Handles generating an intrinsic call expression
|
||||
/// Handles generating a builtin call expression
|
||||
/// @param out the output of the expression stream
|
||||
/// @param call the call expression
|
||||
/// @param intrinsic the intrinsic being called
|
||||
/// @param builtin the builtin being called
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitIntrinsicCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
bool EmitBuiltinCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a type conversion expression
|
||||
/// @param out the output of the expression stream
|
||||
/// @param call the call expression
|
||||
|
@ -179,60 +179,60 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// `atomicMax`, etc)
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the atomic intrinsic
|
||||
/// @param builtin the semantic information for the atomic builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitAtomicCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to a texture function (`textureSample`,
|
||||
/// `textureSampleGrad`, etc)
|
||||
/// @param out the output of the expression stream
|
||||
/// @param call the call expression
|
||||
/// @param intrinsic the semantic information for the texture intrinsic
|
||||
/// @param builtin the semantic information for the texture builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitTextureCall(std::ostream& out,
|
||||
const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `dot()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `dot()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitDotCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `modf()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `modf()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitModfCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `frexp()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `frexp()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitFrexpCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `degrees()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `degrees()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitDegreesCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to the `radians()` intrinsic
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `radians()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitRadiansCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles a case statement
|
||||
/// @param stmt the statement
|
||||
/// @returns true if the statement was emitted successfully
|
||||
|
@ -368,9 +368,9 @@ class GeneratorImpl : public TextGenerator {
|
|||
bool EmitZeroValue(std::ostream& out, const sem::Type* type);
|
||||
|
||||
/// Handles generating a builtin name
|
||||
/// @param intrinsic the semantic info for the intrinsic
|
||||
/// @param builtin the semantic info for the builtin
|
||||
/// @returns the name or "" if not valid
|
||||
std::string generate_builtin_name(const sem::Intrinsic* intrinsic);
|
||||
std::string generate_builtin_name(const sem::Builtin* builtin);
|
||||
|
||||
/// Converts a builtin to an attribute name
|
||||
/// @param builtin the builtin to convert
|
||||
|
@ -392,13 +392,13 @@ class GeneratorImpl : public TextGenerator {
|
|||
uint32_t align;
|
||||
};
|
||||
|
||||
/// CallIntrinsicHelper will call the intrinsic helper function, creating it
|
||||
/// if it hasn't been built already. If the intrinsic needs to be built then
|
||||
/// CallIntrinsicHelper will generate the function signature and will call
|
||||
/// CallBuiltinHelper will call the builtin helper function, creating it
|
||||
/// if it hasn't been built already. If the builtin needs to be built then
|
||||
/// CallBuiltinHelper will generate the function signature and will call
|
||||
/// `build` to emit the body of the function.
|
||||
/// @param out the output of the expression stream
|
||||
/// @param call the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @param build a function with the signature:
|
||||
/// `bool(TextBuffer* buffer, const std::vector<std::string>& params)`
|
||||
/// Where:
|
||||
|
@ -406,10 +406,10 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// `params` is the name of all the generated function parameters
|
||||
/// @returns true if the call expression is emitted
|
||||
template <typename F>
|
||||
bool CallIntrinsicHelper(std::ostream& out,
|
||||
const ast::CallExpression* call,
|
||||
const sem::Intrinsic* intrinsic,
|
||||
F&& build);
|
||||
bool CallBuiltinHelper(std::ostream& out,
|
||||
const ast::CallExpression* call,
|
||||
const sem::Builtin* builtin,
|
||||
F&& build);
|
||||
|
||||
TextBuffer helpers_; // Helper functions emitted at the top of the output
|
||||
|
||||
|
@ -438,7 +438,7 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// should be created for that index.
|
||||
std::unordered_map<std::string, std::vector<uint32_t>> workgroup_allocations_;
|
||||
|
||||
std::unordered_map<const sem::Intrinsic*, std::string> intrinsics_;
|
||||
std::unordered_map<const sem::Builtin*, std::string> builtins_;
|
||||
std::unordered_map<const sem::Type*, std::string> unary_minus_funcs_;
|
||||
std::unordered_map<uint32_t, std::string> int_dot_funcs_;
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace writer {
|
|||
namespace msl {
|
||||
namespace {
|
||||
|
||||
using IntrinsicType = sem::IntrinsicType;
|
||||
using BuiltinType = sem::BuiltinType;
|
||||
|
||||
using MslGeneratorImplTest = TestHelper;
|
||||
|
||||
|
@ -31,12 +31,12 @@ enum class ParamType {
|
|||
kBool,
|
||||
};
|
||||
|
||||
struct IntrinsicData {
|
||||
IntrinsicType intrinsic;
|
||||
struct BuiltinData {
|
||||
BuiltinType builtin;
|
||||
ParamType type;
|
||||
const char* msl_name;
|
||||
};
|
||||
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
|
||||
inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
|
||||
out << data.msl_name << "<";
|
||||
switch (data.type) {
|
||||
case ParamType::kF32:
|
||||
|
@ -53,111 +53,111 @@ inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
|
|||
return out;
|
||||
}
|
||||
|
||||
const ast::CallExpression* GenerateCall(IntrinsicType intrinsic,
|
||||
const ast::CallExpression* GenerateCall(BuiltinType builtin,
|
||||
ParamType type,
|
||||
ProgramBuilder* builder) {
|
||||
std::string name;
|
||||
std::ostringstream str(name);
|
||||
str << intrinsic;
|
||||
switch (intrinsic) {
|
||||
case IntrinsicType::kAcos:
|
||||
case IntrinsicType::kAsin:
|
||||
case IntrinsicType::kAtan:
|
||||
case IntrinsicType::kCeil:
|
||||
case IntrinsicType::kCos:
|
||||
case IntrinsicType::kCosh:
|
||||
case IntrinsicType::kDpdx:
|
||||
case IntrinsicType::kDpdxCoarse:
|
||||
case IntrinsicType::kDpdxFine:
|
||||
case IntrinsicType::kDpdy:
|
||||
case IntrinsicType::kDpdyCoarse:
|
||||
case IntrinsicType::kDpdyFine:
|
||||
case IntrinsicType::kExp:
|
||||
case IntrinsicType::kExp2:
|
||||
case IntrinsicType::kFloor:
|
||||
case IntrinsicType::kFract:
|
||||
case IntrinsicType::kFwidth:
|
||||
case IntrinsicType::kFwidthCoarse:
|
||||
case IntrinsicType::kFwidthFine:
|
||||
case IntrinsicType::kInverseSqrt:
|
||||
case IntrinsicType::kIsFinite:
|
||||
case IntrinsicType::kIsInf:
|
||||
case IntrinsicType::kIsNan:
|
||||
case IntrinsicType::kIsNormal:
|
||||
case IntrinsicType::kLength:
|
||||
case IntrinsicType::kLog:
|
||||
case IntrinsicType::kLog2:
|
||||
case IntrinsicType::kNormalize:
|
||||
case IntrinsicType::kRound:
|
||||
case IntrinsicType::kSin:
|
||||
case IntrinsicType::kSinh:
|
||||
case IntrinsicType::kSqrt:
|
||||
case IntrinsicType::kTan:
|
||||
case IntrinsicType::kTanh:
|
||||
case IntrinsicType::kTrunc:
|
||||
case IntrinsicType::kSign:
|
||||
str << builtin;
|
||||
switch (builtin) {
|
||||
case BuiltinType::kAcos:
|
||||
case BuiltinType::kAsin:
|
||||
case BuiltinType::kAtan:
|
||||
case BuiltinType::kCeil:
|
||||
case BuiltinType::kCos:
|
||||
case BuiltinType::kCosh:
|
||||
case BuiltinType::kDpdx:
|
||||
case BuiltinType::kDpdxCoarse:
|
||||
case BuiltinType::kDpdxFine:
|
||||
case BuiltinType::kDpdy:
|
||||
case BuiltinType::kDpdyCoarse:
|
||||
case BuiltinType::kDpdyFine:
|
||||
case BuiltinType::kExp:
|
||||
case BuiltinType::kExp2:
|
||||
case BuiltinType::kFloor:
|
||||
case BuiltinType::kFract:
|
||||
case BuiltinType::kFwidth:
|
||||
case BuiltinType::kFwidthCoarse:
|
||||
case BuiltinType::kFwidthFine:
|
||||
case BuiltinType::kInverseSqrt:
|
||||
case BuiltinType::kIsFinite:
|
||||
case BuiltinType::kIsInf:
|
||||
case BuiltinType::kIsNan:
|
||||
case BuiltinType::kIsNormal:
|
||||
case BuiltinType::kLength:
|
||||
case BuiltinType::kLog:
|
||||
case BuiltinType::kLog2:
|
||||
case BuiltinType::kNormalize:
|
||||
case BuiltinType::kRound:
|
||||
case BuiltinType::kSin:
|
||||
case BuiltinType::kSinh:
|
||||
case BuiltinType::kSqrt:
|
||||
case BuiltinType::kTan:
|
||||
case BuiltinType::kTanh:
|
||||
case BuiltinType::kTrunc:
|
||||
case BuiltinType::kSign:
|
||||
return builder->Call(str.str(), "f2");
|
||||
case IntrinsicType::kLdexp:
|
||||
case BuiltinType::kLdexp:
|
||||
return builder->Call(str.str(), "f2", "i2");
|
||||
case IntrinsicType::kAtan2:
|
||||
case IntrinsicType::kDot:
|
||||
case IntrinsicType::kDistance:
|
||||
case IntrinsicType::kPow:
|
||||
case IntrinsicType::kReflect:
|
||||
case IntrinsicType::kStep:
|
||||
case BuiltinType::kAtan2:
|
||||
case BuiltinType::kDot:
|
||||
case BuiltinType::kDistance:
|
||||
case BuiltinType::kPow:
|
||||
case BuiltinType::kReflect:
|
||||
case BuiltinType::kStep:
|
||||
return builder->Call(str.str(), "f2", "f2");
|
||||
case IntrinsicType::kStorageBarrier:
|
||||
case BuiltinType::kStorageBarrier:
|
||||
return builder->Call(str.str());
|
||||
case IntrinsicType::kCross:
|
||||
case BuiltinType::kCross:
|
||||
return builder->Call(str.str(), "f3", "f3");
|
||||
case IntrinsicType::kFma:
|
||||
case IntrinsicType::kMix:
|
||||
case IntrinsicType::kFaceForward:
|
||||
case IntrinsicType::kSmoothStep:
|
||||
case BuiltinType::kFma:
|
||||
case BuiltinType::kMix:
|
||||
case BuiltinType::kFaceForward:
|
||||
case BuiltinType::kSmoothStep:
|
||||
return builder->Call(str.str(), "f2", "f2", "f2");
|
||||
case IntrinsicType::kAll:
|
||||
case IntrinsicType::kAny:
|
||||
case BuiltinType::kAll:
|
||||
case BuiltinType::kAny:
|
||||
return builder->Call(str.str(), "b2");
|
||||
case IntrinsicType::kAbs:
|
||||
case BuiltinType::kAbs:
|
||||
if (type == ParamType::kF32) {
|
||||
return builder->Call(str.str(), "f2");
|
||||
} else {
|
||||
return builder->Call(str.str(), "u2");
|
||||
}
|
||||
case IntrinsicType::kCountOneBits:
|
||||
case IntrinsicType::kReverseBits:
|
||||
case BuiltinType::kCountOneBits:
|
||||
case BuiltinType::kReverseBits:
|
||||
return builder->Call(str.str(), "u2");
|
||||
case IntrinsicType::kMax:
|
||||
case IntrinsicType::kMin:
|
||||
case BuiltinType::kMax:
|
||||
case BuiltinType::kMin:
|
||||
if (type == ParamType::kF32) {
|
||||
return builder->Call(str.str(), "f2", "f2");
|
||||
} else {
|
||||
return builder->Call(str.str(), "u2", "u2");
|
||||
}
|
||||
case IntrinsicType::kClamp:
|
||||
case BuiltinType::kClamp:
|
||||
if (type == ParamType::kF32) {
|
||||
return builder->Call(str.str(), "f2", "f2", "f2");
|
||||
} else {
|
||||
return builder->Call(str.str(), "u2", "u2", "u2");
|
||||
}
|
||||
case IntrinsicType::kSelect:
|
||||
case BuiltinType::kSelect:
|
||||
return builder->Call(str.str(), "f2", "f2", "b2");
|
||||
case IntrinsicType::kDeterminant:
|
||||
case BuiltinType::kDeterminant:
|
||||
return builder->Call(str.str(), "m2x2");
|
||||
case IntrinsicType::kPack2x16snorm:
|
||||
case IntrinsicType::kPack2x16unorm:
|
||||
case BuiltinType::kPack2x16snorm:
|
||||
case BuiltinType::kPack2x16unorm:
|
||||
return builder->Call(str.str(), "f2");
|
||||
case IntrinsicType::kPack4x8snorm:
|
||||
case IntrinsicType::kPack4x8unorm:
|
||||
case BuiltinType::kPack4x8snorm:
|
||||
case BuiltinType::kPack4x8unorm:
|
||||
return builder->Call(str.str(), "f4");
|
||||
case IntrinsicType::kUnpack4x8snorm:
|
||||
case IntrinsicType::kUnpack4x8unorm:
|
||||
case IntrinsicType::kUnpack2x16snorm:
|
||||
case IntrinsicType::kUnpack2x16unorm:
|
||||
case BuiltinType::kUnpack4x8snorm:
|
||||
case BuiltinType::kUnpack4x8unorm:
|
||||
case BuiltinType::kUnpack2x16snorm:
|
||||
case BuiltinType::kUnpack2x16unorm:
|
||||
return builder->Call(str.str(), "u1");
|
||||
case IntrinsicType::kWorkgroupBarrier:
|
||||
case BuiltinType::kWorkgroupBarrier:
|
||||
return builder->Call(str.str());
|
||||
case IntrinsicType::kTranspose:
|
||||
case BuiltinType::kTranspose:
|
||||
return builder->Call(str.str(), "m3x2");
|
||||
default:
|
||||
break;
|
||||
|
@ -165,8 +165,8 @@ const ast::CallExpression* GenerateCall(IntrinsicType intrinsic,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
using MslIntrinsicTest = TestParamHelper<IntrinsicData>;
|
||||
TEST_P(MslIntrinsicTest, Emit) {
|
||||
using MslBuiltinTest = TestParamHelper<BuiltinData>;
|
||||
TEST_P(MslBuiltinTest, Emit) {
|
||||
auto param = GetParam();
|
||||
|
||||
Global("f2", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
|
@ -179,8 +179,8 @@ TEST_P(MslIntrinsicTest, Emit) {
|
|||
Global("m2x2", ty.mat2x2<f32>(), ast::StorageClass::kPrivate);
|
||||
Global("m3x2", ty.mat3x2<f32>(), ast::StorageClass::kPrivate);
|
||||
|
||||
auto* call = GenerateCall(param.intrinsic, param.type, this);
|
||||
ASSERT_NE(nullptr, call) << "Unhandled intrinsic";
|
||||
auto* call = GenerateCall(param.builtin, param.type, this);
|
||||
ASSERT_NE(nullptr, call) << "Unhandled builtin";
|
||||
Func("func", {}, ty.void_(), {Ignore(call)},
|
||||
{create<ast::StageAttribute>(ast::PipelineStage::kFragment)});
|
||||
|
||||
|
@ -190,100 +190,95 @@ TEST_P(MslIntrinsicTest, Emit) {
|
|||
ASSERT_NE(sem, nullptr);
|
||||
auto* target = sem->Target();
|
||||
ASSERT_NE(target, nullptr);
|
||||
auto* intrinsic = target->As<sem::Intrinsic>();
|
||||
ASSERT_NE(intrinsic, nullptr);
|
||||
auto* builtin = target->As<sem::Builtin>();
|
||||
ASSERT_NE(builtin, nullptr);
|
||||
|
||||
EXPECT_EQ(gen.generate_builtin_name(intrinsic), param.msl_name);
|
||||
EXPECT_EQ(gen.generate_builtin_name(builtin), param.msl_name);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
MslGeneratorImplTest,
|
||||
MslIntrinsicTest,
|
||||
MslBuiltinTest,
|
||||
testing::Values(
|
||||
IntrinsicData{IntrinsicType::kAbs, ParamType::kF32, "fabs"},
|
||||
IntrinsicData{IntrinsicType::kAbs, ParamType::kU32, "abs"},
|
||||
IntrinsicData{IntrinsicType::kAcos, ParamType::kF32, "acos"},
|
||||
IntrinsicData{IntrinsicType::kAll, ParamType::kBool, "all"},
|
||||
IntrinsicData{IntrinsicType::kAny, ParamType::kBool, "any"},
|
||||
IntrinsicData{IntrinsicType::kAsin, ParamType::kF32, "asin"},
|
||||
IntrinsicData{IntrinsicType::kAtan, ParamType::kF32, "atan"},
|
||||
IntrinsicData{IntrinsicType::kAtan2, ParamType::kF32, "atan2"},
|
||||
IntrinsicData{IntrinsicType::kCeil, ParamType::kF32, "ceil"},
|
||||
IntrinsicData{IntrinsicType::kClamp, ParamType::kF32, "clamp"},
|
||||
IntrinsicData{IntrinsicType::kClamp, ParamType::kU32, "clamp"},
|
||||
IntrinsicData{IntrinsicType::kCos, ParamType::kF32, "cos"},
|
||||
IntrinsicData{IntrinsicType::kCosh, ParamType::kF32, "cosh"},
|
||||
IntrinsicData{IntrinsicType::kCountOneBits, ParamType::kU32,
|
||||
"popcount"},
|
||||
IntrinsicData{IntrinsicType::kCross, ParamType::kF32, "cross"},
|
||||
IntrinsicData{IntrinsicType::kDeterminant, ParamType::kF32,
|
||||
"determinant"},
|
||||
IntrinsicData{IntrinsicType::kDistance, ParamType::kF32, "distance"},
|
||||
IntrinsicData{IntrinsicType::kDot, ParamType::kF32, "dot"},
|
||||
IntrinsicData{IntrinsicType::kDpdx, ParamType::kF32, "dfdx"},
|
||||
IntrinsicData{IntrinsicType::kDpdxCoarse, ParamType::kF32, "dfdx"},
|
||||
IntrinsicData{IntrinsicType::kDpdxFine, ParamType::kF32, "dfdx"},
|
||||
IntrinsicData{IntrinsicType::kDpdy, ParamType::kF32, "dfdy"},
|
||||
IntrinsicData{IntrinsicType::kDpdyCoarse, ParamType::kF32, "dfdy"},
|
||||
IntrinsicData{IntrinsicType::kDpdyFine, ParamType::kF32, "dfdy"},
|
||||
IntrinsicData{IntrinsicType::kExp, ParamType::kF32, "exp"},
|
||||
IntrinsicData{IntrinsicType::kExp2, ParamType::kF32, "exp2"},
|
||||
IntrinsicData{IntrinsicType::kFaceForward, ParamType::kF32,
|
||||
"faceforward"},
|
||||
IntrinsicData{IntrinsicType::kFloor, ParamType::kF32, "floor"},
|
||||
IntrinsicData{IntrinsicType::kFma, ParamType::kF32, "fma"},
|
||||
IntrinsicData{IntrinsicType::kFract, ParamType::kF32, "fract"},
|
||||
IntrinsicData{IntrinsicType::kFwidth, ParamType::kF32, "fwidth"},
|
||||
IntrinsicData{IntrinsicType::kFwidthCoarse, ParamType::kF32, "fwidth"},
|
||||
IntrinsicData{IntrinsicType::kFwidthFine, ParamType::kF32, "fwidth"},
|
||||
IntrinsicData{IntrinsicType::kInverseSqrt, ParamType::kF32, "rsqrt"},
|
||||
IntrinsicData{IntrinsicType::kIsFinite, ParamType::kF32, "isfinite"},
|
||||
IntrinsicData{IntrinsicType::kIsInf, ParamType::kF32, "isinf"},
|
||||
IntrinsicData{IntrinsicType::kIsNan, ParamType::kF32, "isnan"},
|
||||
IntrinsicData{IntrinsicType::kIsNormal, ParamType::kF32, "isnormal"},
|
||||
IntrinsicData{IntrinsicType::kLdexp, ParamType::kF32, "ldexp"},
|
||||
IntrinsicData{IntrinsicType::kLength, ParamType::kF32, "length"},
|
||||
IntrinsicData{IntrinsicType::kLog, ParamType::kF32, "log"},
|
||||
IntrinsicData{IntrinsicType::kLog2, ParamType::kF32, "log2"},
|
||||
IntrinsicData{IntrinsicType::kMax, ParamType::kF32, "fmax"},
|
||||
IntrinsicData{IntrinsicType::kMax, ParamType::kU32, "max"},
|
||||
IntrinsicData{IntrinsicType::kMin, ParamType::kF32, "fmin"},
|
||||
IntrinsicData{IntrinsicType::kMin, ParamType::kU32, "min"},
|
||||
IntrinsicData{IntrinsicType::kNormalize, ParamType::kF32, "normalize"},
|
||||
IntrinsicData{IntrinsicType::kPack4x8snorm, ParamType::kF32,
|
||||
"pack_float_to_snorm4x8"},
|
||||
IntrinsicData{IntrinsicType::kPack4x8unorm, ParamType::kF32,
|
||||
"pack_float_to_unorm4x8"},
|
||||
IntrinsicData{IntrinsicType::kPack2x16snorm, ParamType::kF32,
|
||||
"pack_float_to_snorm2x16"},
|
||||
IntrinsicData{IntrinsicType::kPack2x16unorm, ParamType::kF32,
|
||||
"pack_float_to_unorm2x16"},
|
||||
IntrinsicData{IntrinsicType::kPow, ParamType::kF32, "pow"},
|
||||
IntrinsicData{IntrinsicType::kReflect, ParamType::kF32, "reflect"},
|
||||
IntrinsicData{IntrinsicType::kReverseBits, ParamType::kU32,
|
||||
"reverse_bits"},
|
||||
IntrinsicData{IntrinsicType::kRound, ParamType::kU32, "rint"},
|
||||
IntrinsicData{IntrinsicType::kSelect, ParamType::kF32, "select"},
|
||||
IntrinsicData{IntrinsicType::kSign, ParamType::kF32, "sign"},
|
||||
IntrinsicData{IntrinsicType::kSin, ParamType::kF32, "sin"},
|
||||
IntrinsicData{IntrinsicType::kSinh, ParamType::kF32, "sinh"},
|
||||
IntrinsicData{IntrinsicType::kSmoothStep, ParamType::kF32,
|
||||
"smoothstep"},
|
||||
IntrinsicData{IntrinsicType::kSqrt, ParamType::kF32, "sqrt"},
|
||||
IntrinsicData{IntrinsicType::kStep, ParamType::kF32, "step"},
|
||||
IntrinsicData{IntrinsicType::kTan, ParamType::kF32, "tan"},
|
||||
IntrinsicData{IntrinsicType::kTanh, ParamType::kF32, "tanh"},
|
||||
IntrinsicData{IntrinsicType::kTranspose, ParamType::kF32, "transpose"},
|
||||
IntrinsicData{IntrinsicType::kTrunc, ParamType::kF32, "trunc"},
|
||||
IntrinsicData{IntrinsicType::kUnpack4x8snorm, ParamType::kU32,
|
||||
"unpack_snorm4x8_to_float"},
|
||||
IntrinsicData{IntrinsicType::kUnpack4x8unorm, ParamType::kU32,
|
||||
"unpack_unorm4x8_to_float"},
|
||||
IntrinsicData{IntrinsicType::kUnpack2x16snorm, ParamType::kU32,
|
||||
"unpack_snorm2x16_to_float"},
|
||||
IntrinsicData{IntrinsicType::kUnpack2x16unorm, ParamType::kU32,
|
||||
"unpack_unorm2x16_to_float"}));
|
||||
BuiltinData{BuiltinType::kAbs, ParamType::kF32, "fabs"},
|
||||
BuiltinData{BuiltinType::kAbs, ParamType::kU32, "abs"},
|
||||
BuiltinData{BuiltinType::kAcos, ParamType::kF32, "acos"},
|
||||
BuiltinData{BuiltinType::kAll, ParamType::kBool, "all"},
|
||||
BuiltinData{BuiltinType::kAny, ParamType::kBool, "any"},
|
||||
BuiltinData{BuiltinType::kAsin, ParamType::kF32, "asin"},
|
||||
BuiltinData{BuiltinType::kAtan, ParamType::kF32, "atan"},
|
||||
BuiltinData{BuiltinType::kAtan2, ParamType::kF32, "atan2"},
|
||||
BuiltinData{BuiltinType::kCeil, ParamType::kF32, "ceil"},
|
||||
BuiltinData{BuiltinType::kClamp, ParamType::kF32, "clamp"},
|
||||
BuiltinData{BuiltinType::kClamp, ParamType::kU32, "clamp"},
|
||||
BuiltinData{BuiltinType::kCos, ParamType::kF32, "cos"},
|
||||
BuiltinData{BuiltinType::kCosh, ParamType::kF32, "cosh"},
|
||||
BuiltinData{BuiltinType::kCountOneBits, ParamType::kU32, "popcount"},
|
||||
BuiltinData{BuiltinType::kCross, ParamType::kF32, "cross"},
|
||||
BuiltinData{BuiltinType::kDeterminant, ParamType::kF32, "determinant"},
|
||||
BuiltinData{BuiltinType::kDistance, ParamType::kF32, "distance"},
|
||||
BuiltinData{BuiltinType::kDot, ParamType::kF32, "dot"},
|
||||
BuiltinData{BuiltinType::kDpdx, ParamType::kF32, "dfdx"},
|
||||
BuiltinData{BuiltinType::kDpdxCoarse, ParamType::kF32, "dfdx"},
|
||||
BuiltinData{BuiltinType::kDpdxFine, ParamType::kF32, "dfdx"},
|
||||
BuiltinData{BuiltinType::kDpdy, ParamType::kF32, "dfdy"},
|
||||
BuiltinData{BuiltinType::kDpdyCoarse, ParamType::kF32, "dfdy"},
|
||||
BuiltinData{BuiltinType::kDpdyFine, ParamType::kF32, "dfdy"},
|
||||
BuiltinData{BuiltinType::kExp, ParamType::kF32, "exp"},
|
||||
BuiltinData{BuiltinType::kExp2, ParamType::kF32, "exp2"},
|
||||
BuiltinData{BuiltinType::kFaceForward, ParamType::kF32, "faceforward"},
|
||||
BuiltinData{BuiltinType::kFloor, ParamType::kF32, "floor"},
|
||||
BuiltinData{BuiltinType::kFma, ParamType::kF32, "fma"},
|
||||
BuiltinData{BuiltinType::kFract, ParamType::kF32, "fract"},
|
||||
BuiltinData{BuiltinType::kFwidth, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kFwidthCoarse, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kFwidthFine, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kInverseSqrt, ParamType::kF32, "rsqrt"},
|
||||
BuiltinData{BuiltinType::kIsFinite, ParamType::kF32, "isfinite"},
|
||||
BuiltinData{BuiltinType::kIsInf, ParamType::kF32, "isinf"},
|
||||
BuiltinData{BuiltinType::kIsNan, ParamType::kF32, "isnan"},
|
||||
BuiltinData{BuiltinType::kIsNormal, ParamType::kF32, "isnormal"},
|
||||
BuiltinData{BuiltinType::kLdexp, ParamType::kF32, "ldexp"},
|
||||
BuiltinData{BuiltinType::kLength, ParamType::kF32, "length"},
|
||||
BuiltinData{BuiltinType::kLog, ParamType::kF32, "log"},
|
||||
BuiltinData{BuiltinType::kLog2, ParamType::kF32, "log2"},
|
||||
BuiltinData{BuiltinType::kMax, ParamType::kF32, "fmax"},
|
||||
BuiltinData{BuiltinType::kMax, ParamType::kU32, "max"},
|
||||
BuiltinData{BuiltinType::kMin, ParamType::kF32, "fmin"},
|
||||
BuiltinData{BuiltinType::kMin, ParamType::kU32, "min"},
|
||||
BuiltinData{BuiltinType::kNormalize, ParamType::kF32, "normalize"},
|
||||
BuiltinData{BuiltinType::kPack4x8snorm, ParamType::kF32,
|
||||
"pack_float_to_snorm4x8"},
|
||||
BuiltinData{BuiltinType::kPack4x8unorm, ParamType::kF32,
|
||||
"pack_float_to_unorm4x8"},
|
||||
BuiltinData{BuiltinType::kPack2x16snorm, ParamType::kF32,
|
||||
"pack_float_to_snorm2x16"},
|
||||
BuiltinData{BuiltinType::kPack2x16unorm, ParamType::kF32,
|
||||
"pack_float_to_unorm2x16"},
|
||||
BuiltinData{BuiltinType::kPow, ParamType::kF32, "pow"},
|
||||
BuiltinData{BuiltinType::kReflect, ParamType::kF32, "reflect"},
|
||||
BuiltinData{BuiltinType::kReverseBits, ParamType::kU32, "reverse_bits"},
|
||||
BuiltinData{BuiltinType::kRound, ParamType::kU32, "rint"},
|
||||
BuiltinData{BuiltinType::kSelect, ParamType::kF32, "select"},
|
||||
BuiltinData{BuiltinType::kSign, ParamType::kF32, "sign"},
|
||||
BuiltinData{BuiltinType::kSin, ParamType::kF32, "sin"},
|
||||
BuiltinData{BuiltinType::kSinh, ParamType::kF32, "sinh"},
|
||||
BuiltinData{BuiltinType::kSmoothStep, ParamType::kF32, "smoothstep"},
|
||||
BuiltinData{BuiltinType::kSqrt, ParamType::kF32, "sqrt"},
|
||||
BuiltinData{BuiltinType::kStep, ParamType::kF32, "step"},
|
||||
BuiltinData{BuiltinType::kTan, ParamType::kF32, "tan"},
|
||||
BuiltinData{BuiltinType::kTanh, ParamType::kF32, "tanh"},
|
||||
BuiltinData{BuiltinType::kTranspose, ParamType::kF32, "transpose"},
|
||||
BuiltinData{BuiltinType::kTrunc, ParamType::kF32, "trunc"},
|
||||
BuiltinData{BuiltinType::kUnpack4x8snorm, ParamType::kU32,
|
||||
"unpack_snorm4x8_to_float"},
|
||||
BuiltinData{BuiltinType::kUnpack4x8unorm, ParamType::kU32,
|
||||
"unpack_unorm4x8_to_float"},
|
||||
BuiltinData{BuiltinType::kUnpack2x16snorm, ParamType::kU32,
|
||||
"unpack_snorm2x16_to_float"},
|
||||
BuiltinData{BuiltinType::kUnpack2x16unorm, ParamType::kU32,
|
||||
"unpack_unorm2x16_to_float"}));
|
||||
|
||||
TEST_F(MslGeneratorImplTest, Intrinsic_Call) {
|
||||
TEST_F(MslGeneratorImplTest, Builtin_Call) {
|
||||
Global("param1", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
Global("param2", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
|
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/builtin_texture_helper_test.h"
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/intrinsic_texture_helper_test.h"
|
||||
#include "src/writer/msl/test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -22,8 +22,8 @@ namespace msl {
|
|||
namespace {
|
||||
|
||||
std::string expected_texture_overload(
|
||||
ast::intrinsic::test::ValidTextureOverload overload) {
|
||||
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
|
||||
ast::builtin::test::ValidTextureOverload overload) {
|
||||
using ValidTextureOverload = ast::builtin::test::ValidTextureOverload;
|
||||
switch (overload) {
|
||||
case ValidTextureOverload::kDimensions1d:
|
||||
case ValidTextureOverload::kDimensionsStorageWO1d:
|
||||
|
@ -271,10 +271,10 @@ std::string expected_texture_overload(
|
|||
return "<unmatched texture overload>";
|
||||
} // NOLINT - Ignore the length of this function
|
||||
|
||||
class MslGeneratorIntrinsicTextureTest
|
||||
: public TestParamHelper<ast::intrinsic::test::TextureOverloadCase> {};
|
||||
class MslGeneratorBuiltinTextureTest
|
||||
: public TestParamHelper<ast::builtin::test::TextureOverloadCase> {};
|
||||
|
||||
TEST_P(MslGeneratorIntrinsicTextureTest, Call) {
|
||||
TEST_P(MslGeneratorBuiltinTextureTest, Call) {
|
||||
auto param = GetParam();
|
||||
|
||||
param.BuildTextureVariable(this);
|
||||
|
@ -295,9 +295,9 @@ TEST_P(MslGeneratorIntrinsicTextureTest, Call) {
|
|||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
MslGeneratorIntrinsicTextureTest,
|
||||
MslGeneratorIntrinsicTextureTest,
|
||||
testing::ValuesIn(ast::intrinsic::test::TextureOverloadCase::ValidCases()));
|
||||
MslGeneratorBuiltinTextureTest,
|
||||
MslGeneratorBuiltinTextureTest,
|
||||
testing::ValuesIn(ast::builtin::test::TextureOverloadCase::ValidCases()));
|
||||
|
||||
} // namespace
|
||||
} // namespace msl
|
|
@ -35,7 +35,7 @@ TEST_P(MslImportData_SingleParamTest, FloatScalar) {
|
|||
auto param = GetParam();
|
||||
auto* call = Call(param.name, 1.f);
|
||||
|
||||
// The resolver will set the intrinsic data for the ident
|
||||
// The resolver will set the builtin data for the ident
|
||||
WrapInFunction(call);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
@ -44,10 +44,10 @@ TEST_P(MslImportData_SingleParamTest, FloatScalar) {
|
|||
ASSERT_NE(sem, nullptr);
|
||||
auto* target = sem->Target();
|
||||
ASSERT_NE(target, nullptr);
|
||||
auto* intrinsic = target->As<sem::Intrinsic>();
|
||||
ASSERT_NE(intrinsic, nullptr);
|
||||
auto* builtin = target->As<sem::Builtin>();
|
||||
ASSERT_NE(builtin, nullptr);
|
||||
|
||||
ASSERT_EQ(gen.generate_builtin_name(intrinsic), param.msl_name);
|
||||
ASSERT_EQ(gen.generate_builtin_name(builtin), param.msl_name);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(MslGeneratorImplTest,
|
||||
MslImportData_SingleParamTest,
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
#include "src/ast/traverse_expressions.h"
|
||||
#include "src/sem/array.h"
|
||||
#include "src/sem/atomic_type.h"
|
||||
#include "src/sem/builtin.h"
|
||||
#include "src/sem/call.h"
|
||||
#include "src/sem/depth_multisampled_texture_type.h"
|
||||
#include "src/sem/depth_texture_type.h"
|
||||
#include "src/sem/function.h"
|
||||
#include "src/sem/intrinsic.h"
|
||||
#include "src/sem/member_accessor_expression.h"
|
||||
#include "src/sem/multisampled_texture_type.h"
|
||||
#include "src/sem/reference_type.h"
|
||||
|
@ -62,7 +62,7 @@ namespace writer {
|
|||
namespace spirv {
|
||||
namespace {
|
||||
|
||||
using IntrinsicType = sem::IntrinsicType;
|
||||
using BuiltinType = sem::BuiltinType;
|
||||
|
||||
const char kGLSLstd450[] = "GLSL.std.450";
|
||||
|
||||
|
@ -109,131 +109,131 @@ const sem::Matrix* GetNestedMatrixType(const sem::Type* type) {
|
|||
return type->As<sem::Matrix>();
|
||||
}
|
||||
|
||||
uint32_t intrinsic_to_glsl_method(const sem::Intrinsic* intrinsic) {
|
||||
switch (intrinsic->Type()) {
|
||||
case IntrinsicType::kAcos:
|
||||
uint32_t builtin_to_glsl_method(const sem::Builtin* builtin) {
|
||||
switch (builtin->Type()) {
|
||||
case BuiltinType::kAcos:
|
||||
return GLSLstd450Acos;
|
||||
case IntrinsicType::kAsin:
|
||||
case BuiltinType::kAsin:
|
||||
return GLSLstd450Asin;
|
||||
case IntrinsicType::kAtan:
|
||||
case BuiltinType::kAtan:
|
||||
return GLSLstd450Atan;
|
||||
case IntrinsicType::kAtan2:
|
||||
case BuiltinType::kAtan2:
|
||||
return GLSLstd450Atan2;
|
||||
case IntrinsicType::kCeil:
|
||||
case BuiltinType::kCeil:
|
||||
return GLSLstd450Ceil;
|
||||
case IntrinsicType::kClamp:
|
||||
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) {
|
||||
case BuiltinType::kClamp:
|
||||
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
|
||||
return GLSLstd450NClamp;
|
||||
} else if (intrinsic->ReturnType()->is_unsigned_scalar_or_vector()) {
|
||||
} else if (builtin->ReturnType()->is_unsigned_scalar_or_vector()) {
|
||||
return GLSLstd450UClamp;
|
||||
} else {
|
||||
return GLSLstd450SClamp;
|
||||
}
|
||||
case IntrinsicType::kCos:
|
||||
case BuiltinType::kCos:
|
||||
return GLSLstd450Cos;
|
||||
case IntrinsicType::kCosh:
|
||||
case BuiltinType::kCosh:
|
||||
return GLSLstd450Cosh;
|
||||
case IntrinsicType::kCross:
|
||||
case BuiltinType::kCross:
|
||||
return GLSLstd450Cross;
|
||||
case IntrinsicType::kDegrees:
|
||||
case BuiltinType::kDegrees:
|
||||
return GLSLstd450Degrees;
|
||||
case IntrinsicType::kDeterminant:
|
||||
case BuiltinType::kDeterminant:
|
||||
return GLSLstd450Determinant;
|
||||
case IntrinsicType::kDistance:
|
||||
case BuiltinType::kDistance:
|
||||
return GLSLstd450Distance;
|
||||
case IntrinsicType::kExp:
|
||||
case BuiltinType::kExp:
|
||||
return GLSLstd450Exp;
|
||||
case IntrinsicType::kExp2:
|
||||
case BuiltinType::kExp2:
|
||||
return GLSLstd450Exp2;
|
||||
case IntrinsicType::kFaceForward:
|
||||
case BuiltinType::kFaceForward:
|
||||
return GLSLstd450FaceForward;
|
||||
case IntrinsicType::kFloor:
|
||||
case BuiltinType::kFloor:
|
||||
return GLSLstd450Floor;
|
||||
case IntrinsicType::kFma:
|
||||
case BuiltinType::kFma:
|
||||
return GLSLstd450Fma;
|
||||
case IntrinsicType::kFract:
|
||||
case BuiltinType::kFract:
|
||||
return GLSLstd450Fract;
|
||||
case IntrinsicType::kFrexp:
|
||||
case BuiltinType::kFrexp:
|
||||
return GLSLstd450FrexpStruct;
|
||||
case IntrinsicType::kInverseSqrt:
|
||||
case BuiltinType::kInverseSqrt:
|
||||
return GLSLstd450InverseSqrt;
|
||||
case IntrinsicType::kLdexp:
|
||||
case BuiltinType::kLdexp:
|
||||
return GLSLstd450Ldexp;
|
||||
case IntrinsicType::kLength:
|
||||
case BuiltinType::kLength:
|
||||
return GLSLstd450Length;
|
||||
case IntrinsicType::kLog:
|
||||
case BuiltinType::kLog:
|
||||
return GLSLstd450Log;
|
||||
case IntrinsicType::kLog2:
|
||||
case BuiltinType::kLog2:
|
||||
return GLSLstd450Log2;
|
||||
case IntrinsicType::kMax:
|
||||
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) {
|
||||
case BuiltinType::kMax:
|
||||
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
|
||||
return GLSLstd450NMax;
|
||||
} else if (intrinsic->ReturnType()->is_unsigned_scalar_or_vector()) {
|
||||
} else if (builtin->ReturnType()->is_unsigned_scalar_or_vector()) {
|
||||
return GLSLstd450UMax;
|
||||
} else {
|
||||
return GLSLstd450SMax;
|
||||
}
|
||||
case IntrinsicType::kMin:
|
||||
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) {
|
||||
case BuiltinType::kMin:
|
||||
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
|
||||
return GLSLstd450NMin;
|
||||
} else if (intrinsic->ReturnType()->is_unsigned_scalar_or_vector()) {
|
||||
} else if (builtin->ReturnType()->is_unsigned_scalar_or_vector()) {
|
||||
return GLSLstd450UMin;
|
||||
} else {
|
||||
return GLSLstd450SMin;
|
||||
}
|
||||
case IntrinsicType::kMix:
|
||||
case BuiltinType::kMix:
|
||||
return GLSLstd450FMix;
|
||||
case IntrinsicType::kModf:
|
||||
case BuiltinType::kModf:
|
||||
return GLSLstd450ModfStruct;
|
||||
case IntrinsicType::kNormalize:
|
||||
case BuiltinType::kNormalize:
|
||||
return GLSLstd450Normalize;
|
||||
case IntrinsicType::kPack4x8snorm:
|
||||
case BuiltinType::kPack4x8snorm:
|
||||
return GLSLstd450PackSnorm4x8;
|
||||
case IntrinsicType::kPack4x8unorm:
|
||||
case BuiltinType::kPack4x8unorm:
|
||||
return GLSLstd450PackUnorm4x8;
|
||||
case IntrinsicType::kPack2x16snorm:
|
||||
case BuiltinType::kPack2x16snorm:
|
||||
return GLSLstd450PackSnorm2x16;
|
||||
case IntrinsicType::kPack2x16unorm:
|
||||
case BuiltinType::kPack2x16unorm:
|
||||
return GLSLstd450PackUnorm2x16;
|
||||
case IntrinsicType::kPack2x16float:
|
||||
case BuiltinType::kPack2x16float:
|
||||
return GLSLstd450PackHalf2x16;
|
||||
case IntrinsicType::kPow:
|
||||
case BuiltinType::kPow:
|
||||
return GLSLstd450Pow;
|
||||
case IntrinsicType::kRadians:
|
||||
case BuiltinType::kRadians:
|
||||
return GLSLstd450Radians;
|
||||
case IntrinsicType::kReflect:
|
||||
case BuiltinType::kReflect:
|
||||
return GLSLstd450Reflect;
|
||||
case IntrinsicType::kRefract:
|
||||
case BuiltinType::kRefract:
|
||||
return GLSLstd450Refract;
|
||||
case IntrinsicType::kRound:
|
||||
case BuiltinType::kRound:
|
||||
return GLSLstd450RoundEven;
|
||||
case IntrinsicType::kSign:
|
||||
case BuiltinType::kSign:
|
||||
return GLSLstd450FSign;
|
||||
case IntrinsicType::kSin:
|
||||
case BuiltinType::kSin:
|
||||
return GLSLstd450Sin;
|
||||
case IntrinsicType::kSinh:
|
||||
case BuiltinType::kSinh:
|
||||
return GLSLstd450Sinh;
|
||||
case IntrinsicType::kSmoothStep:
|
||||
case BuiltinType::kSmoothStep:
|
||||
return GLSLstd450SmoothStep;
|
||||
case IntrinsicType::kSqrt:
|
||||
case BuiltinType::kSqrt:
|
||||
return GLSLstd450Sqrt;
|
||||
case IntrinsicType::kStep:
|
||||
case BuiltinType::kStep:
|
||||
return GLSLstd450Step;
|
||||
case IntrinsicType::kTan:
|
||||
case BuiltinType::kTan:
|
||||
return GLSLstd450Tan;
|
||||
case IntrinsicType::kTanh:
|
||||
case BuiltinType::kTanh:
|
||||
return GLSLstd450Tanh;
|
||||
case IntrinsicType::kTrunc:
|
||||
case BuiltinType::kTrunc:
|
||||
return GLSLstd450Trunc;
|
||||
case IntrinsicType::kUnpack4x8snorm:
|
||||
case BuiltinType::kUnpack4x8snorm:
|
||||
return GLSLstd450UnpackSnorm4x8;
|
||||
case IntrinsicType::kUnpack4x8unorm:
|
||||
case BuiltinType::kUnpack4x8unorm:
|
||||
return GLSLstd450UnpackUnorm4x8;
|
||||
case IntrinsicType::kUnpack2x16snorm:
|
||||
case BuiltinType::kUnpack2x16snorm:
|
||||
return GLSLstd450UnpackSnorm2x16;
|
||||
case IntrinsicType::kUnpack2x16unorm:
|
||||
case BuiltinType::kUnpack2x16unorm:
|
||||
return GLSLstd450UnpackUnorm2x16;
|
||||
case IntrinsicType::kUnpack2x16float:
|
||||
case BuiltinType::kUnpack2x16float:
|
||||
return GLSLstd450UnpackHalf2x16;
|
||||
default:
|
||||
break;
|
||||
|
@ -2213,8 +2213,8 @@ uint32_t Builder::GenerateCallExpression(const ast::CallExpression* expr) {
|
|||
if (auto* func = target->As<sem::Function>()) {
|
||||
return GenerateFunctionCall(call, func);
|
||||
}
|
||||
if (auto* intrinsic = target->As<sem::Intrinsic>()) {
|
||||
return GenerateIntrinsicCall(call, intrinsic);
|
||||
if (auto* builtin = target->As<sem::Builtin>()) {
|
||||
return GenerateBuiltinCall(call, builtin);
|
||||
}
|
||||
if (target->IsAnyOf<sem::TypeConversion, sem::TypeConstructor>()) {
|
||||
return GenerateTypeConstructorOrConversion(call, nullptr);
|
||||
|
@ -2264,42 +2264,42 @@ uint32_t Builder::GenerateFunctionCall(const sem::Call* call,
|
|||
return result_id;
|
||||
}
|
||||
|
||||
uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
uint32_t Builder::GenerateBuiltinCall(const sem::Call* call,
|
||||
const sem::Builtin* builtin) {
|
||||
auto result = result_op();
|
||||
auto result_id = result.to_i();
|
||||
|
||||
auto result_type_id = GenerateTypeIfNeeded(intrinsic->ReturnType());
|
||||
auto result_type_id = GenerateTypeIfNeeded(builtin->ReturnType());
|
||||
if (result_type_id == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (intrinsic->IsFineDerivative() || intrinsic->IsCoarseDerivative()) {
|
||||
if (builtin->IsFineDerivative() || builtin->IsCoarseDerivative()) {
|
||||
push_capability(SpvCapabilityDerivativeControl);
|
||||
}
|
||||
|
||||
if (intrinsic->IsImageQuery()) {
|
||||
if (builtin->IsImageQuery()) {
|
||||
push_capability(SpvCapabilityImageQuery);
|
||||
}
|
||||
|
||||
if (intrinsic->IsTexture()) {
|
||||
if (!GenerateTextureIntrinsic(call, intrinsic, Operand::Int(result_type_id),
|
||||
result)) {
|
||||
if (builtin->IsTexture()) {
|
||||
if (!GenerateTextureBuiltin(call, builtin, Operand::Int(result_type_id),
|
||||
result)) {
|
||||
return 0;
|
||||
}
|
||||
return result_id;
|
||||
}
|
||||
|
||||
if (intrinsic->IsBarrier()) {
|
||||
if (!GenerateControlBarrierIntrinsic(intrinsic)) {
|
||||
if (builtin->IsBarrier()) {
|
||||
if (!GenerateControlBarrierBuiltin(builtin)) {
|
||||
return 0;
|
||||
}
|
||||
return result_id;
|
||||
}
|
||||
|
||||
if (intrinsic->IsAtomic()) {
|
||||
if (!GenerateAtomicIntrinsic(call, intrinsic, Operand::Int(result_type_id),
|
||||
result)) {
|
||||
if (builtin->IsAtomic()) {
|
||||
if (!GenerateAtomicBuiltin(call, builtin, Operand::Int(result_type_id),
|
||||
result)) {
|
||||
return 0;
|
||||
}
|
||||
return result_id;
|
||||
|
@ -2310,7 +2310,7 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
auto get_arg_as_value_id = [&](size_t i,
|
||||
bool generate_load = true) -> uint32_t {
|
||||
auto* arg = call->Arguments()[i];
|
||||
auto* param = intrinsic->Parameters()[i];
|
||||
auto* param = builtin->Parameters()[i];
|
||||
auto val_id = GenerateExpression(arg->Declaration());
|
||||
if (val_id == 0) {
|
||||
return 0;
|
||||
|
@ -2334,22 +2334,22 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
op = spv::Op::OpExtInst;
|
||||
};
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case IntrinsicType::kAny:
|
||||
if (intrinsic->Parameters()[0]->Type()->Is<sem::Bool>()) {
|
||||
switch (builtin->Type()) {
|
||||
case BuiltinType::kAny:
|
||||
if (builtin->Parameters()[0]->Type()->Is<sem::Bool>()) {
|
||||
// any(v: bool) just resolves to v.
|
||||
return get_arg_as_value_id(0);
|
||||
}
|
||||
op = spv::Op::OpAny;
|
||||
break;
|
||||
case IntrinsicType::kAll:
|
||||
if (intrinsic->Parameters()[0]->Type()->Is<sem::Bool>()) {
|
||||
case BuiltinType::kAll:
|
||||
if (builtin->Parameters()[0]->Type()->Is<sem::Bool>()) {
|
||||
// all(v: bool) just resolves to v.
|
||||
return get_arg_as_value_id(0);
|
||||
}
|
||||
op = spv::Op::OpAll;
|
||||
break;
|
||||
case IntrinsicType::kArrayLength: {
|
||||
case BuiltinType::kArrayLength: {
|
||||
auto* address_of =
|
||||
call->Arguments()[0]->Declaration()->As<ast::UnaryOpExpression>();
|
||||
if (!address_of || address_of->op != ast::UnaryOp::kAddressOf) {
|
||||
|
@ -2388,12 +2388,12 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
}
|
||||
return result_id;
|
||||
}
|
||||
case IntrinsicType::kCountOneBits:
|
||||
case BuiltinType::kCountOneBits:
|
||||
op = spv::Op::OpBitCount;
|
||||
break;
|
||||
case IntrinsicType::kDot: {
|
||||
case BuiltinType::kDot: {
|
||||
op = spv::Op::OpDot;
|
||||
auto* vec_ty = intrinsic->Parameters()[0]->Type()->As<sem::Vector>();
|
||||
auto* vec_ty = builtin->Parameters()[0]->Type()->As<sem::Vector>();
|
||||
if (vec_ty->type()->is_integer_scalar()) {
|
||||
// TODO(crbug.com/tint/1267): OpDot requires floating-point types, but
|
||||
// WGSL also supports integer types. SPV_KHR_integer_dot_product adds
|
||||
|
@ -2433,40 +2433,40 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kDpdx:
|
||||
case BuiltinType::kDpdx:
|
||||
op = spv::Op::OpDPdx;
|
||||
break;
|
||||
case IntrinsicType::kDpdxCoarse:
|
||||
case BuiltinType::kDpdxCoarse:
|
||||
op = spv::Op::OpDPdxCoarse;
|
||||
break;
|
||||
case IntrinsicType::kDpdxFine:
|
||||
case BuiltinType::kDpdxFine:
|
||||
op = spv::Op::OpDPdxFine;
|
||||
break;
|
||||
case IntrinsicType::kDpdy:
|
||||
case BuiltinType::kDpdy:
|
||||
op = spv::Op::OpDPdy;
|
||||
break;
|
||||
case IntrinsicType::kDpdyCoarse:
|
||||
case BuiltinType::kDpdyCoarse:
|
||||
op = spv::Op::OpDPdyCoarse;
|
||||
break;
|
||||
case IntrinsicType::kDpdyFine:
|
||||
case BuiltinType::kDpdyFine:
|
||||
op = spv::Op::OpDPdyFine;
|
||||
break;
|
||||
case IntrinsicType::kFwidth:
|
||||
case BuiltinType::kFwidth:
|
||||
op = spv::Op::OpFwidth;
|
||||
break;
|
||||
case IntrinsicType::kFwidthCoarse:
|
||||
case BuiltinType::kFwidthCoarse:
|
||||
op = spv::Op::OpFwidthCoarse;
|
||||
break;
|
||||
case IntrinsicType::kFwidthFine:
|
||||
case BuiltinType::kFwidthFine:
|
||||
op = spv::Op::OpFwidthFine;
|
||||
break;
|
||||
case IntrinsicType::kIsInf:
|
||||
case BuiltinType::kIsInf:
|
||||
op = spv::Op::OpIsInf;
|
||||
break;
|
||||
case IntrinsicType::kIsNan:
|
||||
case BuiltinType::kIsNan:
|
||||
op = spv::Op::OpIsNan;
|
||||
break;
|
||||
case IntrinsicType::kIsFinite: {
|
||||
case BuiltinType::kIsFinite: {
|
||||
// Implemented as: not(IsInf or IsNan)
|
||||
auto val_id = get_arg_as_value_id(0);
|
||||
if (!val_id) {
|
||||
|
@ -2492,7 +2492,7 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
case IntrinsicType::kIsNormal: {
|
||||
case BuiltinType::kIsNormal: {
|
||||
// A normal number is finite, non-zero, and not subnormal.
|
||||
// Its exponent is neither of the extreme possible values.
|
||||
// Implemented as:
|
||||
|
@ -2520,7 +2520,7 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
GenerateConstantIfNeeded(ScalarConstant::U32(kMinNormalExponent));
|
||||
auto max_exponent_id =
|
||||
GenerateConstantIfNeeded(ScalarConstant::U32(kMaxNormalExponent));
|
||||
if (auto* fvec_ty = intrinsic->ReturnType()->As<sem::Vector>()) {
|
||||
if (auto* fvec_ty = builtin->ReturnType()->As<sem::Vector>()) {
|
||||
// In the vector case, update the unsigned type to a vector type of the
|
||||
// same size, and create vector constants by replicating the scalars.
|
||||
// I expect backend compilers to fold these into unique constants, so
|
||||
|
@ -2570,7 +2570,7 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
case IntrinsicType::kMix: {
|
||||
case BuiltinType::kMix: {
|
||||
auto std450 = Operand::Int(GetGLSLstd450Import());
|
||||
|
||||
auto a_id = get_arg_as_value_id(0);
|
||||
|
@ -2582,10 +2582,9 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
|
||||
// If the interpolant is scalar but the objects are vectors, we need to
|
||||
// splat the interpolant into a vector of the same size.
|
||||
auto* result_vector_type = intrinsic->ReturnType()->As<sem::Vector>();
|
||||
if (result_vector_type &&
|
||||
intrinsic->Parameters()[2]->Type()->is_scalar()) {
|
||||
f_id = GenerateSplat(f_id, intrinsic->Parameters()[0]->Type());
|
||||
auto* result_vector_type = builtin->ReturnType()->As<sem::Vector>();
|
||||
if (result_vector_type && builtin->Parameters()[2]->Type()->is_scalar()) {
|
||||
f_id = GenerateSplat(f_id, builtin->Parameters()[0]->Type());
|
||||
if (f_id == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -2599,10 +2598,10 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
}
|
||||
return result_id;
|
||||
}
|
||||
case IntrinsicType::kReverseBits:
|
||||
case BuiltinType::kReverseBits:
|
||||
op = spv::Op::OpBitReverse;
|
||||
break;
|
||||
case IntrinsicType::kSelect: {
|
||||
case BuiltinType::kSelect: {
|
||||
// Note: Argument order is different in WGSL and SPIR-V
|
||||
auto cond_id = get_arg_as_value_id(2);
|
||||
auto true_id = get_arg_as_value_id(1);
|
||||
|
@ -2614,9 +2613,8 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
// If the condition is scalar but the objects are vectors, we need to
|
||||
// splat the condition into a vector of the same size.
|
||||
// TODO(jrprice): If we're targeting SPIR-V 1.4, we don't need to do this.
|
||||
auto* result_vector_type = intrinsic->ReturnType()->As<sem::Vector>();
|
||||
if (result_vector_type &&
|
||||
intrinsic->Parameters()[2]->Type()->is_scalar()) {
|
||||
auto* result_vector_type = builtin->ReturnType()->As<sem::Vector>();
|
||||
if (result_vector_type && builtin->Parameters()[2]->Type()->is_scalar()) {
|
||||
auto* bool_vec_ty = builder_.create<sem::Vector>(
|
||||
builder_.create<sem::Bool>(), result_vector_type->Width());
|
||||
if (!GenerateTypeIfNeeded(bool_vec_ty)) {
|
||||
|
@ -2636,25 +2634,25 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
}
|
||||
return result_id;
|
||||
}
|
||||
case IntrinsicType::kTranspose:
|
||||
case BuiltinType::kTranspose:
|
||||
op = spv::Op::OpTranspose;
|
||||
break;
|
||||
case IntrinsicType::kAbs:
|
||||
if (intrinsic->ReturnType()->is_unsigned_scalar_or_vector()) {
|
||||
case BuiltinType::kAbs:
|
||||
if (builtin->ReturnType()->is_unsigned_scalar_or_vector()) {
|
||||
// abs() only operates on *signed* integers.
|
||||
// This is a no-op for unsigned integers.
|
||||
return get_arg_as_value_id(0);
|
||||
}
|
||||
if (intrinsic->ReturnType()->is_float_scalar_or_vector()) {
|
||||
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
|
||||
glsl_std450(GLSLstd450FAbs);
|
||||
} else {
|
||||
glsl_std450(GLSLstd450SAbs);
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
auto inst_id = intrinsic_to_glsl_method(intrinsic);
|
||||
auto inst_id = builtin_to_glsl_method(builtin);
|
||||
if (inst_id == 0) {
|
||||
error_ = "unknown method " + std::string(intrinsic->str());
|
||||
error_ = "unknown method " + std::string(builtin->str());
|
||||
return 0;
|
||||
}
|
||||
glsl_std450(inst_id);
|
||||
|
@ -2663,8 +2661,7 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
}
|
||||
|
||||
if (op == spv::Op::OpNop) {
|
||||
error_ =
|
||||
"unable to determine operator for: " + std::string(intrinsic->str());
|
||||
error_ = "unable to determine operator for: " + std::string(builtin->str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2683,13 +2680,13 @@ uint32_t Builder::GenerateIntrinsicCall(const sem::Call* call,
|
|||
return result_id;
|
||||
}
|
||||
|
||||
bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic,
|
||||
Operand result_type,
|
||||
Operand result_id) {
|
||||
bool Builder::GenerateTextureBuiltin(const sem::Call* call,
|
||||
const sem::Builtin* builtin,
|
||||
Operand result_type,
|
||||
Operand result_id) {
|
||||
using Usage = sem::ParameterUsage;
|
||||
|
||||
auto& signature = intrinsic->Signature();
|
||||
auto& signature = builtin->Signature();
|
||||
auto& arguments = call->Arguments();
|
||||
|
||||
// Generates the given expression, returning the operand ID
|
||||
|
@ -2723,7 +2720,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
|
||||
auto op = spv::Op::OpNop;
|
||||
|
||||
// Custom function to call after the texture-intrinsic op has been generated.
|
||||
// Custom function to call after the texture-builtin op has been generated.
|
||||
std::function<bool()> post_emission = [] { return true; };
|
||||
|
||||
// Populate the spirv_params with common parameters
|
||||
|
@ -2848,8 +2845,8 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
return append_coords_to_spirv_params();
|
||||
};
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case IntrinsicType::kTextureDimensions: {
|
||||
switch (builtin->Type()) {
|
||||
case BuiltinType::kTextureDimensions: {
|
||||
// Number of returned elements from OpImageQuerySize[Lod] may not match
|
||||
// those of textureDimensions().
|
||||
// This might be due to an extra vector scalar describing the number of
|
||||
|
@ -2896,7 +2893,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureNumLayers: {
|
||||
case BuiltinType::kTextureNumLayers: {
|
||||
uint32_t spirv_dims = 0;
|
||||
switch (texture_type->dim()) {
|
||||
default:
|
||||
|
@ -2928,19 +2925,19 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureNumLevels: {
|
||||
case BuiltinType::kTextureNumLevels: {
|
||||
op = spv::Op::OpImageQueryLevels;
|
||||
append_result_type_and_id_to_spirv_params();
|
||||
spirv_params.emplace_back(gen_arg(Usage::kTexture));
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureNumSamples: {
|
||||
case BuiltinType::kTextureNumSamples: {
|
||||
op = spv::Op::OpImageQuerySamples;
|
||||
append_result_type_and_id_to_spirv_params();
|
||||
spirv_params.emplace_back(gen_arg(Usage::kTexture));
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureLoad: {
|
||||
case BuiltinType::kTextureLoad: {
|
||||
op = texture_type->Is<sem::StorageTexture>() ? spv::Op::OpImageRead
|
||||
: spv::Op::OpImageFetch;
|
||||
append_result_type_and_id_to_spirv_params_for_read();
|
||||
|
@ -2961,7 +2958,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureStore: {
|
||||
case BuiltinType::kTextureStore: {
|
||||
op = spv::Op::OpImageWrite;
|
||||
spirv_params.emplace_back(gen_arg(Usage::kTexture));
|
||||
if (!append_coords_to_spirv_params()) {
|
||||
|
@ -2970,7 +2967,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
spirv_params.emplace_back(gen_arg(Usage::kValue));
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureGather: {
|
||||
case BuiltinType::kTextureGather: {
|
||||
op = spv::Op::OpImageGather;
|
||||
append_result_type_and_id_to_spirv_params();
|
||||
if (!append_image_and_coords_to_spirv_params()) {
|
||||
|
@ -2984,7 +2981,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureGatherCompare: {
|
||||
case BuiltinType::kTextureGatherCompare: {
|
||||
op = spv::Op::OpImageDrefGather;
|
||||
append_result_type_and_id_to_spirv_params();
|
||||
if (!append_image_and_coords_to_spirv_params()) {
|
||||
|
@ -2993,7 +2990,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
spirv_params.emplace_back(gen_arg(Usage::kDepthRef));
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureSample: {
|
||||
case BuiltinType::kTextureSample: {
|
||||
op = spv::Op::OpImageSampleImplicitLod;
|
||||
append_result_type_and_id_to_spirv_params_for_read();
|
||||
if (!append_image_and_coords_to_spirv_params()) {
|
||||
|
@ -3001,7 +2998,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureSampleBias: {
|
||||
case BuiltinType::kTextureSampleBias: {
|
||||
op = spv::Op::OpImageSampleImplicitLod;
|
||||
append_result_type_and_id_to_spirv_params_for_read();
|
||||
if (!append_image_and_coords_to_spirv_params()) {
|
||||
|
@ -3011,7 +3008,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
ImageOperand{SpvImageOperandsBiasMask, gen_arg(Usage::kBias)});
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureSampleLevel: {
|
||||
case BuiltinType::kTextureSampleLevel: {
|
||||
op = spv::Op::OpImageSampleExplicitLod;
|
||||
append_result_type_and_id_to_spirv_params_for_read();
|
||||
if (!append_image_and_coords_to_spirv_params()) {
|
||||
|
@ -3037,7 +3034,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
image_operands.emplace_back(ImageOperand{SpvImageOperandsLodMask, level});
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureSampleGrad: {
|
||||
case BuiltinType::kTextureSampleGrad: {
|
||||
op = spv::Op::OpImageSampleExplicitLod;
|
||||
append_result_type_and_id_to_spirv_params_for_read();
|
||||
if (!append_image_and_coords_to_spirv_params()) {
|
||||
|
@ -3049,7 +3046,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
ImageOperand{SpvImageOperandsGradMask, gen_arg(Usage::kDdy)});
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureSampleCompare: {
|
||||
case BuiltinType::kTextureSampleCompare: {
|
||||
op = spv::Op::OpImageSampleDrefImplicitLod;
|
||||
append_result_type_and_id_to_spirv_params();
|
||||
if (!append_image_and_coords_to_spirv_params()) {
|
||||
|
@ -3058,7 +3055,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
spirv_params.emplace_back(gen_arg(Usage::kDepthRef));
|
||||
break;
|
||||
}
|
||||
case IntrinsicType::kTextureSampleCompareLevel: {
|
||||
case BuiltinType::kTextureSampleCompareLevel: {
|
||||
op = spv::Op::OpImageSampleDrefExplicitLod;
|
||||
append_result_type_and_id_to_spirv_params();
|
||||
if (!append_image_and_coords_to_spirv_params()) {
|
||||
|
@ -3096,8 +3093,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
}
|
||||
|
||||
if (op == spv::Op::OpNop) {
|
||||
error_ =
|
||||
"unable to determine operator for: " + std::string(intrinsic->str());
|
||||
error_ = "unable to determine operator for: " + std::string(builtin->str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3108,7 +3104,7 @@ bool Builder::GenerateTextureIntrinsic(const sem::Call* call,
|
|||
return post_emission();
|
||||
}
|
||||
|
||||
bool Builder::GenerateControlBarrierIntrinsic(const sem::Intrinsic* intrinsic) {
|
||||
bool Builder::GenerateControlBarrierBuiltin(const sem::Builtin* builtin) {
|
||||
auto const op = spv::Op::OpControlBarrier;
|
||||
uint32_t execution = 0;
|
||||
uint32_t memory = 0;
|
||||
|
@ -3116,21 +3112,21 @@ bool Builder::GenerateControlBarrierIntrinsic(const sem::Intrinsic* intrinsic) {
|
|||
|
||||
// TODO(crbug.com/tint/661): Combine sequential barriers to a single
|
||||
// instruction.
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kWorkgroupBarrier) {
|
||||
if (builtin->Type() == sem::BuiltinType::kWorkgroupBarrier) {
|
||||
execution = static_cast<uint32_t>(spv::Scope::Workgroup);
|
||||
memory = static_cast<uint32_t>(spv::Scope::Workgroup);
|
||||
semantics =
|
||||
static_cast<uint32_t>(spv::MemorySemanticsMask::AcquireRelease) |
|
||||
static_cast<uint32_t>(spv::MemorySemanticsMask::WorkgroupMemory);
|
||||
} else if (intrinsic->Type() == sem::IntrinsicType::kStorageBarrier) {
|
||||
} else if (builtin->Type() == sem::BuiltinType::kStorageBarrier) {
|
||||
execution = static_cast<uint32_t>(spv::Scope::Workgroup);
|
||||
memory = static_cast<uint32_t>(spv::Scope::Workgroup);
|
||||
semantics =
|
||||
static_cast<uint32_t>(spv::MemorySemanticsMask::AcquireRelease) |
|
||||
static_cast<uint32_t>(spv::MemorySemanticsMask::UniformMemory);
|
||||
} else {
|
||||
error_ = "unexpected barrier intrinsic type ";
|
||||
error_ += sem::str(intrinsic->Type());
|
||||
error_ = "unexpected barrier builtin type ";
|
||||
error_ += sem::str(builtin->Type());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3148,20 +3144,20 @@ bool Builder::GenerateControlBarrierIntrinsic(const sem::Intrinsic* intrinsic) {
|
|||
});
|
||||
}
|
||||
|
||||
bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic,
|
||||
Operand result_type,
|
||||
Operand result_id) {
|
||||
bool Builder::GenerateAtomicBuiltin(const sem::Call* call,
|
||||
const sem::Builtin* builtin,
|
||||
Operand result_type,
|
||||
Operand result_id) {
|
||||
auto is_value_signed = [&] {
|
||||
return intrinsic->Parameters()[1]->Type()->Is<sem::I32>();
|
||||
return builtin->Parameters()[1]->Type()->Is<sem::I32>();
|
||||
};
|
||||
|
||||
auto storage_class =
|
||||
intrinsic->Parameters()[0]->Type()->As<sem::Pointer>()->StorageClass();
|
||||
builtin->Parameters()[0]->Type()->As<sem::Pointer>()->StorageClass();
|
||||
|
||||
uint32_t memory_id = 0;
|
||||
switch (
|
||||
intrinsic->Parameters()[0]->Type()->As<sem::Pointer>()->StorageClass()) {
|
||||
builtin->Parameters()[0]->Type()->As<sem::Pointer>()->StorageClass()) {
|
||||
case ast::StorageClass::kWorkgroup:
|
||||
memory_id = GenerateConstantIfNeeded(
|
||||
ScalarConstant::U32(static_cast<uint32_t>(spv::Scope::Workgroup)));
|
||||
|
@ -3203,8 +3199,8 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
|
|||
Operand memory = Operand::Int(memory_id);
|
||||
Operand semantics = Operand::Int(semantics_id);
|
||||
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kAtomicLoad:
|
||||
switch (builtin->Type()) {
|
||||
case sem::BuiltinType::kAtomicLoad:
|
||||
return push_function_inst(spv::Op::OpAtomicLoad, {
|
||||
result_type,
|
||||
result_id,
|
||||
|
@ -3212,14 +3208,14 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
|
|||
memory,
|
||||
semantics,
|
||||
});
|
||||
case sem::IntrinsicType::kAtomicStore:
|
||||
case sem::BuiltinType::kAtomicStore:
|
||||
return push_function_inst(spv::Op::OpAtomicStore, {
|
||||
pointer,
|
||||
memory,
|
||||
semantics,
|
||||
value,
|
||||
});
|
||||
case sem::IntrinsicType::kAtomicAdd:
|
||||
case sem::BuiltinType::kAtomicAdd:
|
||||
return push_function_inst(spv::Op::OpAtomicIAdd, {
|
||||
result_type,
|
||||
result_id,
|
||||
|
@ -3228,7 +3224,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
|
|||
semantics,
|
||||
value,
|
||||
});
|
||||
case sem::IntrinsicType::kAtomicSub:
|
||||
case sem::BuiltinType::kAtomicSub:
|
||||
return push_function_inst(spv::Op::OpAtomicISub, {
|
||||
result_type,
|
||||
result_id,
|
||||
|
@ -3237,7 +3233,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
|
|||
semantics,
|
||||
value,
|
||||
});
|
||||
case sem::IntrinsicType::kAtomicMax:
|
||||
case sem::BuiltinType::kAtomicMax:
|
||||
return push_function_inst(
|
||||
is_value_signed() ? spv::Op::OpAtomicSMax : spv::Op::OpAtomicUMax,
|
||||
{
|
||||
|
@ -3248,7 +3244,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
|
|||
semantics,
|
||||
value,
|
||||
});
|
||||
case sem::IntrinsicType::kAtomicMin:
|
||||
case sem::BuiltinType::kAtomicMin:
|
||||
return push_function_inst(
|
||||
is_value_signed() ? spv::Op::OpAtomicSMin : spv::Op::OpAtomicUMin,
|
||||
{
|
||||
|
@ -3259,7 +3255,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
|
|||
semantics,
|
||||
value,
|
||||
});
|
||||
case sem::IntrinsicType::kAtomicAnd:
|
||||
case sem::BuiltinType::kAtomicAnd:
|
||||
return push_function_inst(spv::Op::OpAtomicAnd, {
|
||||
result_type,
|
||||
result_id,
|
||||
|
@ -3268,7 +3264,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
|
|||
semantics,
|
||||
value,
|
||||
});
|
||||
case sem::IntrinsicType::kAtomicOr:
|
||||
case sem::BuiltinType::kAtomicOr:
|
||||
return push_function_inst(spv::Op::OpAtomicOr, {
|
||||
result_type,
|
||||
result_id,
|
||||
|
@ -3277,7 +3273,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
|
|||
semantics,
|
||||
value,
|
||||
});
|
||||
case sem::IntrinsicType::kAtomicXor:
|
||||
case sem::BuiltinType::kAtomicXor:
|
||||
return push_function_inst(spv::Op::OpAtomicXor, {
|
||||
result_type,
|
||||
result_id,
|
||||
|
@ -3286,7 +3282,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
|
|||
semantics,
|
||||
value,
|
||||
});
|
||||
case sem::IntrinsicType::kAtomicExchange:
|
||||
case sem::BuiltinType::kAtomicExchange:
|
||||
return push_function_inst(spv::Op::OpAtomicExchange, {
|
||||
result_type,
|
||||
result_id,
|
||||
|
@ -3295,7 +3291,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
|
|||
semantics,
|
||||
value,
|
||||
});
|
||||
case sem::IntrinsicType::kAtomicCompareExchangeWeak: {
|
||||
case sem::BuiltinType::kAtomicCompareExchangeWeak: {
|
||||
auto comparator = GenerateExpression(call->Arguments()[1]->Declaration());
|
||||
if (comparator == 0) {
|
||||
return false;
|
||||
|
@ -3383,7 +3379,7 @@ bool Builder::GenerateAtomicIntrinsic(const sem::Call* call,
|
|||
}
|
||||
default:
|
||||
TINT_UNREACHABLE(Writer, builder_.Diagnostics())
|
||||
<< "unhandled atomic intrinsic " << intrinsic->Type();
|
||||
<< "unhandled atomic builtin " << builtin->Type();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "src/ast/variable_decl_statement.h"
|
||||
#include "src/program_builder.h"
|
||||
#include "src/scope_stack.h"
|
||||
#include "src/sem/intrinsic.h"
|
||||
#include "src/sem/builtin.h"
|
||||
#include "src/sem/storage_texture_type.h"
|
||||
#include "src/writer/spirv/function.h"
|
||||
#include "src/writer/spirv/scalar_constant.h"
|
||||
|
@ -376,44 +376,44 @@ class Builder {
|
|||
/// @returns the expression ID on success or 0 otherwise
|
||||
uint32_t GenerateFunctionCall(const sem::Call* call,
|
||||
const sem::Function* function);
|
||||
/// Handles generating an intrinsic call expression
|
||||
/// Handles generating a builtin call expression
|
||||
/// @param call the call expression
|
||||
/// @param intrinsic the intrinsic being called
|
||||
/// @param builtin the builtin being called
|
||||
/// @returns the expression ID on success or 0 otherwise
|
||||
uint32_t GenerateIntrinsicCall(const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
uint32_t GenerateBuiltinCall(const sem::Call* call,
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a type constructor or type conversion expression
|
||||
/// @param call the call expression
|
||||
/// @param var the variable that is being initialized. May be null.
|
||||
/// @returns the expression ID on success or 0 otherwise
|
||||
uint32_t GenerateTypeConstructorOrConversion(const sem::Call* call,
|
||||
const ast::Variable* var);
|
||||
/// Generates a texture intrinsic call. Emits an error and returns false if
|
||||
/// Generates a texture builtin call. Emits an error and returns false if
|
||||
/// we're currently outside a function.
|
||||
/// @param call the call expression
|
||||
/// @param intrinsic the semantic information for the texture intrinsic
|
||||
/// @param builtin the semantic information for the texture builtin
|
||||
/// @param result_type result type operand of the texture instruction
|
||||
/// @param result_id result identifier operand of the texture instruction
|
||||
/// parameters
|
||||
/// @returns true on success
|
||||
bool GenerateTextureIntrinsic(const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic,
|
||||
spirv::Operand result_type,
|
||||
spirv::Operand result_id);
|
||||
bool GenerateTextureBuiltin(const sem::Call* call,
|
||||
const sem::Builtin* builtin,
|
||||
spirv::Operand result_type,
|
||||
spirv::Operand result_id);
|
||||
/// Generates a control barrier statement.
|
||||
/// @param intrinsic the semantic information for the barrier intrinsic call
|
||||
/// @param builtin the semantic information for the barrier builtin call
|
||||
/// @returns true on success
|
||||
bool GenerateControlBarrierIntrinsic(const sem::Intrinsic* intrinsic);
|
||||
/// Generates an atomic intrinsic call.
|
||||
bool GenerateControlBarrierBuiltin(const sem::Builtin* builtin);
|
||||
/// Generates an atomic builtin call.
|
||||
/// @param call the call expression
|
||||
/// @param intrinsic the semantic information for the atomic intrinsic call
|
||||
/// @param builtin the semantic information for the atomic builtin call
|
||||
/// @param result_type result type operand of the texture instruction
|
||||
/// @param result_id result identifier operand of the texture instruction
|
||||
/// @returns true on success
|
||||
bool GenerateAtomicIntrinsic(const sem::Call* call,
|
||||
const sem::Intrinsic* intrinsic,
|
||||
Operand result_type,
|
||||
Operand result_id);
|
||||
bool GenerateAtomicBuiltin(const sem::Call* call,
|
||||
const sem::Builtin* builtin,
|
||||
Operand result_type,
|
||||
Operand result_id);
|
||||
/// Generates a sampled image
|
||||
/// @param texture_type the texture type
|
||||
/// @param texture_operand the texture operand
|
||||
|
|
|
@ -25,22 +25,22 @@ namespace writer {
|
|||
namespace spirv {
|
||||
namespace {
|
||||
|
||||
using IntrinsicBuilderTest = TestHelper;
|
||||
using BuiltinBuilderTest = TestHelper;
|
||||
|
||||
template <typename T>
|
||||
using IntrinsicBuilderTestWithParam = TestParamHelper<T>;
|
||||
using BuiltinBuilderTestWithParam = TestParamHelper<T>;
|
||||
|
||||
struct IntrinsicData {
|
||||
struct BuiltinData {
|
||||
std::string name;
|
||||
std::string op;
|
||||
};
|
||||
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
|
||||
inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
|
||||
out << data.name;
|
||||
return out;
|
||||
}
|
||||
|
||||
using IntrinsicBoolTest = IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(IntrinsicBoolTest, Call_Bool_Scalar) {
|
||||
using BuiltinBoolTest = BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(BuiltinBoolTest, Call_Bool_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* var = Global("v", ty.bool_(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call(param.name, "v");
|
||||
|
@ -67,7 +67,7 @@ TEST_P(IntrinsicBoolTest, Call_Bool_Scalar) {
|
|||
"%10 = OpLoad %3 %1\nOpReturn\n");
|
||||
}
|
||||
|
||||
TEST_P(IntrinsicBoolTest, Call_Bool_Vector) {
|
||||
TEST_P(BuiltinBoolTest, Call_Bool_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* var = Global("v", ty.vec3<bool>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call(param.name, "v");
|
||||
|
@ -97,13 +97,13 @@ OpReturn
|
|||
"${op}", param.op);
|
||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
|
||||
IntrinsicBoolTest,
|
||||
testing::Values(IntrinsicData{"any", "OpAny"},
|
||||
IntrinsicData{"all", "OpAll"}));
|
||||
INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
|
||||
BuiltinBoolTest,
|
||||
testing::Values(BuiltinData{"any", "OpAny"},
|
||||
BuiltinData{"all", "OpAll"}));
|
||||
|
||||
using IntrinsicFloatTest = IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(IntrinsicFloatTest, Call_Float_Scalar) {
|
||||
using BuiltinFloatTest = BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(BuiltinFloatTest, Call_Float_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call(param.name, "v");
|
||||
|
@ -134,7 +134,7 @@ OpReturn
|
|||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
|
||||
}
|
||||
|
||||
TEST_P(IntrinsicFloatTest, Call_Float_Vector) {
|
||||
TEST_P(BuiltinFloatTest, Call_Float_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call(param.name, "v");
|
||||
|
@ -166,12 +166,12 @@ OpReturn
|
|||
"${op}", param.op);
|
||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
|
||||
IntrinsicFloatTest,
|
||||
testing::Values(IntrinsicData{"isNan", "OpIsNan"},
|
||||
IntrinsicData{"isInf", "OpIsInf"}));
|
||||
INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
|
||||
BuiltinFloatTest,
|
||||
testing::Values(BuiltinData{"isNan", "OpIsNan"},
|
||||
BuiltinData{"isInf", "OpIsInf"}));
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, IsFinite_Scalar) {
|
||||
TEST_F(BuiltinBuilderTest, IsFinite_Scalar) {
|
||||
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("isFinite", "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -202,7 +202,7 @@ OpReturn
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, IsFinite_Vector) {
|
||||
TEST_F(BuiltinBuilderTest, IsFinite_Vector) {
|
||||
auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("isFinite", "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -235,7 +235,7 @@ OpReturn
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, IsNormal_Scalar) {
|
||||
TEST_F(BuiltinBuilderTest, IsNormal_Scalar) {
|
||||
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("isNormal", "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -275,7 +275,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, IsNormal_Vector) {
|
||||
TEST_F(BuiltinBuilderTest, IsNormal_Vector) {
|
||||
auto* var = Global("v", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("isNormal", "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -321,8 +321,8 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
using IntrinsicIntTest = IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(IntrinsicIntTest, Call_SInt_Scalar) {
|
||||
using BuiltinIntTest = BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(BuiltinIntTest, Call_SInt_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* var = Global("v", ty.i32(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call(param.name, "v");
|
||||
|
@ -352,7 +352,7 @@ OpReturn
|
|||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
|
||||
}
|
||||
|
||||
TEST_P(IntrinsicIntTest, Call_SInt_Vector) {
|
||||
TEST_P(BuiltinIntTest, Call_SInt_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* var = Global("v", ty.vec3<i32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call(param.name, "v");
|
||||
|
@ -383,7 +383,7 @@ OpReturn
|
|||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
|
||||
}
|
||||
|
||||
TEST_P(IntrinsicIntTest, Call_UInt_Scalar) {
|
||||
TEST_P(BuiltinIntTest, Call_UInt_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* var = Global("v", ty.u32(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call(param.name, "v");
|
||||
|
@ -413,7 +413,7 @@ OpReturn
|
|||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
|
||||
}
|
||||
|
||||
TEST_P(IntrinsicIntTest, Call_UInt_Vector) {
|
||||
TEST_P(BuiltinIntTest, Call_UInt_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* var = Global("v", ty.vec3<u32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call(param.name, "v");
|
||||
|
@ -444,12 +444,12 @@ OpReturn
|
|||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IntrinsicBuilderTest,
|
||||
IntrinsicIntTest,
|
||||
testing::Values(IntrinsicData{"countOneBits", "OpBitCount"},
|
||||
IntrinsicData{"reverseBits", "OpBitReverse"}));
|
||||
BuiltinBuilderTest,
|
||||
BuiltinIntTest,
|
||||
testing::Values(BuiltinData{"countOneBits", "OpBitCount"},
|
||||
BuiltinData{"reverseBits", "OpBitReverse"}));
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Dot_F32) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Dot_F32) {
|
||||
auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("dot", "v", "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -478,7 +478,7 @@ OpReturn
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Dot_U32) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Dot_U32) {
|
||||
auto* var = Global("v", ty.vec3<u32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("dot", "v", "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -517,7 +517,7 @@ OpReturn
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Dot_I32) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Dot_I32) {
|
||||
auto* var = Global("v", ty.vec3<i32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("dot", "v", "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -556,8 +556,8 @@ OpReturn
|
|||
)");
|
||||
}
|
||||
|
||||
using IntrinsicDeriveTest = IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(IntrinsicDeriveTest, Call_Derivative_Scalar) {
|
||||
using BuiltinDeriveTest = BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(BuiltinDeriveTest, Call_Derivative_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call(param.name, "v");
|
||||
|
@ -585,7 +585,7 @@ OpReturn
|
|||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
|
||||
}
|
||||
|
||||
TEST_P(IntrinsicDeriveTest, Call_Derivative_Vector) {
|
||||
TEST_P(BuiltinDeriveTest, Call_Derivative_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call(param.name, "v");
|
||||
|
@ -620,19 +620,19 @@ OpReturn
|
|||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IntrinsicBuilderTest,
|
||||
IntrinsicDeriveTest,
|
||||
testing::Values(IntrinsicData{"dpdx", "OpDPdx"},
|
||||
IntrinsicData{"dpdxFine", "OpDPdxFine"},
|
||||
IntrinsicData{"dpdxCoarse", "OpDPdxCoarse"},
|
||||
IntrinsicData{"dpdy", "OpDPdy"},
|
||||
IntrinsicData{"dpdyFine", "OpDPdyFine"},
|
||||
IntrinsicData{"dpdyCoarse", "OpDPdyCoarse"},
|
||||
IntrinsicData{"fwidth", "OpFwidth"},
|
||||
IntrinsicData{"fwidthFine", "OpFwidthFine"},
|
||||
IntrinsicData{"fwidthCoarse", "OpFwidthCoarse"}));
|
||||
BuiltinBuilderTest,
|
||||
BuiltinDeriveTest,
|
||||
testing::Values(BuiltinData{"dpdx", "OpDPdx"},
|
||||
BuiltinData{"dpdxFine", "OpDPdxFine"},
|
||||
BuiltinData{"dpdxCoarse", "OpDPdxCoarse"},
|
||||
BuiltinData{"dpdy", "OpDPdy"},
|
||||
BuiltinData{"dpdyFine", "OpDPdyFine"},
|
||||
BuiltinData{"dpdyCoarse", "OpDPdyCoarse"},
|
||||
BuiltinData{"fwidth", "OpFwidth"},
|
||||
BuiltinData{"fwidthFine", "OpFwidthFine"},
|
||||
BuiltinData{"fwidthCoarse", "OpFwidthCoarse"}));
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Select) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Select) {
|
||||
auto* v3 = Global("v3", ty.vec3<f32>(), ast::StorageClass::kPrivate);
|
||||
|
||||
auto* bool_v3 =
|
||||
|
@ -672,7 +672,7 @@ OpReturn
|
|||
}
|
||||
|
||||
// This tests that we do not push OpTypeSampledImage and float_0 type twice.
|
||||
TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) {
|
||||
TEST_F(BuiltinBuilderTest, Call_TextureSampleCompare_Twice) {
|
||||
auto* s = ty.sampler(ast::SamplerKind::kComparisonSampler);
|
||||
auto* t = ty.depth_texture(ast::TextureDimension::k2d);
|
||||
|
||||
|
@ -732,7 +732,7 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_GLSLMethod_WithLoad) {
|
||||
TEST_F(BuiltinBuilderTest, Call_GLSLMethod_WithLoad) {
|
||||
auto* var = Global("ident", ty.f32(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("round", "ident");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -763,9 +763,9 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
using Intrinsic_Builtin_SingleParam_Float_Test =
|
||||
IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(Intrinsic_Builtin_SingleParam_Float_Test, Call_Scalar) {
|
||||
using Builtin_Builtin_SingleParam_Float_Test =
|
||||
BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(Builtin_Builtin_SingleParam_Float_Test, Call_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, 1.0f);
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -792,7 +792,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_P(Intrinsic_Builtin_SingleParam_Float_Test, Call_Vector) {
|
||||
TEST_P(Builtin_Builtin_SingleParam_Float_Test, Call_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, vec2<f32>(1.0f, 1.0f));
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -820,35 +820,35 @@ OpReturn
|
|||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
|
||||
Intrinsic_Builtin_SingleParam_Float_Test,
|
||||
testing::Values(IntrinsicData{"abs", "FAbs"},
|
||||
IntrinsicData{"acos", "Acos"},
|
||||
IntrinsicData{"asin", "Asin"},
|
||||
IntrinsicData{"atan", "Atan"},
|
||||
IntrinsicData{"ceil", "Ceil"},
|
||||
IntrinsicData{"cos", "Cos"},
|
||||
IntrinsicData{"cosh", "Cosh"},
|
||||
IntrinsicData{"degrees", "Degrees"},
|
||||
IntrinsicData{"exp", "Exp"},
|
||||
IntrinsicData{"exp2", "Exp2"},
|
||||
IntrinsicData{"floor", "Floor"},
|
||||
IntrinsicData{"fract", "Fract"},
|
||||
IntrinsicData{"inverseSqrt",
|
||||
"InverseSqrt"},
|
||||
IntrinsicData{"log", "Log"},
|
||||
IntrinsicData{"log2", "Log2"},
|
||||
IntrinsicData{"radians", "Radians"},
|
||||
IntrinsicData{"round", "RoundEven"},
|
||||
IntrinsicData{"sign", "FSign"},
|
||||
IntrinsicData{"sin", "Sin"},
|
||||
IntrinsicData{"sinh", "Sinh"},
|
||||
IntrinsicData{"sqrt", "Sqrt"},
|
||||
IntrinsicData{"tan", "Tan"},
|
||||
IntrinsicData{"tanh", "Tanh"},
|
||||
IntrinsicData{"trunc", "Trunc"}));
|
||||
INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
|
||||
Builtin_Builtin_SingleParam_Float_Test,
|
||||
testing::Values(BuiltinData{"abs", "FAbs"},
|
||||
BuiltinData{"acos", "Acos"},
|
||||
BuiltinData{"asin", "Asin"},
|
||||
BuiltinData{"atan", "Atan"},
|
||||
BuiltinData{"ceil", "Ceil"},
|
||||
BuiltinData{"cos", "Cos"},
|
||||
BuiltinData{"cosh", "Cosh"},
|
||||
BuiltinData{"degrees", "Degrees"},
|
||||
BuiltinData{"exp", "Exp"},
|
||||
BuiltinData{"exp2", "Exp2"},
|
||||
BuiltinData{"floor", "Floor"},
|
||||
BuiltinData{"fract", "Fract"},
|
||||
BuiltinData{"inverseSqrt",
|
||||
"InverseSqrt"},
|
||||
BuiltinData{"log", "Log"},
|
||||
BuiltinData{"log2", "Log2"},
|
||||
BuiltinData{"radians", "Radians"},
|
||||
BuiltinData{"round", "RoundEven"},
|
||||
BuiltinData{"sign", "FSign"},
|
||||
BuiltinData{"sin", "Sin"},
|
||||
BuiltinData{"sinh", "Sinh"},
|
||||
BuiltinData{"sqrt", "Sqrt"},
|
||||
BuiltinData{"tan", "Tan"},
|
||||
BuiltinData{"tanh", "Tanh"},
|
||||
BuiltinData{"trunc", "Trunc"}));
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Length_Scalar) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Length_Scalar) {
|
||||
auto* expr = Call("length", 1.0f);
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
|
@ -873,7 +873,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Length_Vector) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Length_Vector) {
|
||||
auto* expr = Call("length", vec2<f32>(1.0f, 1.0f));
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
|
@ -900,7 +900,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Normalize) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Normalize) {
|
||||
auto* expr = Call("normalize", vec2<f32>(1.0f, 1.0f));
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
|
@ -927,9 +927,9 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
using Intrinsic_Builtin_DualParam_Float_Test =
|
||||
IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(Intrinsic_Builtin_DualParam_Float_Test, Call_Scalar) {
|
||||
using Builtin_Builtin_DualParam_Float_Test =
|
||||
BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(Builtin_Builtin_DualParam_Float_Test, Call_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, 1.0f, 1.0f);
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -956,7 +956,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_P(Intrinsic_Builtin_DualParam_Float_Test, Call_Vector) {
|
||||
TEST_P(Builtin_Builtin_DualParam_Float_Test, Call_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f));
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -984,15 +984,15 @@ OpReturn
|
|||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
|
||||
Intrinsic_Builtin_DualParam_Float_Test,
|
||||
testing::Values(IntrinsicData{"atan2", "Atan2"},
|
||||
IntrinsicData{"max", "NMax"},
|
||||
IntrinsicData{"min", "NMin"},
|
||||
IntrinsicData{"pow", "Pow"},
|
||||
IntrinsicData{"step", "Step"}));
|
||||
INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
|
||||
Builtin_Builtin_DualParam_Float_Test,
|
||||
testing::Values(BuiltinData{"atan2", "Atan2"},
|
||||
BuiltinData{"max", "NMax"},
|
||||
BuiltinData{"min", "NMin"},
|
||||
BuiltinData{"pow", "Pow"},
|
||||
BuiltinData{"step", "Step"}));
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Reflect_Vector) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Reflect_Vector) {
|
||||
auto* expr = Call("reflect", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f));
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
|
@ -1019,7 +1019,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Distance_Scalar) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Distance_Scalar) {
|
||||
auto* expr = Call("distance", 1.0f, 1.0f);
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
|
@ -1044,7 +1044,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Distance_Vector) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Distance_Vector) {
|
||||
auto* expr = Call("distance", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f));
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
|
@ -1071,7 +1071,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Cross) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Cross) {
|
||||
auto* expr =
|
||||
Call("cross", vec3<f32>(1.0f, 1.0f, 1.0f), vec3<f32>(1.0f, 1.0f, 1.0f));
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1099,9 +1099,9 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
using Intrinsic_Builtin_ThreeParam_Float_Test =
|
||||
IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(Intrinsic_Builtin_ThreeParam_Float_Test, Call_Scalar) {
|
||||
using Builtin_Builtin_ThreeParam_Float_Test =
|
||||
BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(Builtin_Builtin_ThreeParam_Float_Test, Call_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, 1.0f, 1.0f, 1.0f);
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1128,7 +1128,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_P(Intrinsic_Builtin_ThreeParam_Float_Test, Call_Vector) {
|
||||
TEST_P(Builtin_Builtin_ThreeParam_Float_Test, Call_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f),
|
||||
vec2<f32>(1.0f, 1.0f));
|
||||
|
@ -1157,16 +1157,16 @@ OpReturn
|
|||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
|
||||
Intrinsic_Builtin_ThreeParam_Float_Test,
|
||||
testing::Values(IntrinsicData{"clamp", "NClamp"},
|
||||
IntrinsicData{"fma", "Fma"},
|
||||
IntrinsicData{"mix", "FMix"},
|
||||
INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
|
||||
Builtin_Builtin_ThreeParam_Float_Test,
|
||||
testing::Values(BuiltinData{"clamp", "NClamp"},
|
||||
BuiltinData{"fma", "Fma"},
|
||||
BuiltinData{"mix", "FMix"},
|
||||
|
||||
IntrinsicData{"smoothStep",
|
||||
"SmoothStep"}));
|
||||
BuiltinData{"smoothStep",
|
||||
"SmoothStep"}));
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_FaceForward_Vector) {
|
||||
TEST_F(BuiltinBuilderTest, Call_FaceForward_Vector) {
|
||||
auto* expr = Call("faceForward", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f),
|
||||
vec2<f32>(1.0f, 1.0f));
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1194,9 +1194,9 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
using Intrinsic_Builtin_SingleParam_Sint_Test =
|
||||
IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(Intrinsic_Builtin_SingleParam_Sint_Test, Call_Scalar) {
|
||||
using Builtin_Builtin_SingleParam_Sint_Test =
|
||||
BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(Builtin_Builtin_SingleParam_Sint_Test, Call_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, 1);
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1223,7 +1223,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_P(Intrinsic_Builtin_SingleParam_Sint_Test, Call_Vector) {
|
||||
TEST_P(Builtin_Builtin_SingleParam_Sint_Test, Call_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, vec2<i32>(1, 1));
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1251,13 +1251,13 @@ OpReturn
|
|||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
|
||||
Intrinsic_Builtin_SingleParam_Sint_Test,
|
||||
testing::Values(IntrinsicData{"abs", "SAbs"}));
|
||||
INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
|
||||
Builtin_Builtin_SingleParam_Sint_Test,
|
||||
testing::Values(BuiltinData{"abs", "SAbs"}));
|
||||
|
||||
// Calling abs() on an unsigned integer scalar / vector is a no-op.
|
||||
using Intrinsic_Builtin_Abs_Uint_Test = IntrinsicBuilderTest;
|
||||
TEST_F(Intrinsic_Builtin_Abs_Uint_Test, Call_Scalar) {
|
||||
using Builtin_Builtin_Abs_Uint_Test = BuiltinBuilderTest;
|
||||
TEST_F(Builtin_Builtin_Abs_Uint_Test, Call_Scalar) {
|
||||
auto* expr = Call("abs", 1u);
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
|
@ -1280,7 +1280,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(Intrinsic_Builtin_Abs_Uint_Test, Call_Vector) {
|
||||
TEST_F(Builtin_Builtin_Abs_Uint_Test, Call_Vector) {
|
||||
auto* expr = Call("abs", vec2<u32>(1u, 1u));
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
|
@ -1305,9 +1305,9 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
using Intrinsic_Builtin_DualParam_SInt_Test =
|
||||
IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(Intrinsic_Builtin_DualParam_SInt_Test, Call_Scalar) {
|
||||
using Builtin_Builtin_DualParam_SInt_Test =
|
||||
BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(Builtin_Builtin_DualParam_SInt_Test, Call_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, 1, 1);
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1334,7 +1334,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_P(Intrinsic_Builtin_DualParam_SInt_Test, Call_Vector) {
|
||||
TEST_P(Builtin_Builtin_DualParam_SInt_Test, Call_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, vec2<i32>(1, 1), vec2<i32>(1, 1));
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1362,14 +1362,14 @@ OpReturn
|
|||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
|
||||
Intrinsic_Builtin_DualParam_SInt_Test,
|
||||
testing::Values(IntrinsicData{"max", "SMax"},
|
||||
IntrinsicData{"min", "SMin"}));
|
||||
INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
|
||||
Builtin_Builtin_DualParam_SInt_Test,
|
||||
testing::Values(BuiltinData{"max", "SMax"},
|
||||
BuiltinData{"min", "SMin"}));
|
||||
|
||||
using Intrinsic_Builtin_DualParam_UInt_Test =
|
||||
IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(Intrinsic_Builtin_DualParam_UInt_Test, Call_Scalar) {
|
||||
using Builtin_Builtin_DualParam_UInt_Test =
|
||||
BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(Builtin_Builtin_DualParam_UInt_Test, Call_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, 1u, 1u);
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1396,7 +1396,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_P(Intrinsic_Builtin_DualParam_UInt_Test, Call_Vector) {
|
||||
TEST_P(Builtin_Builtin_DualParam_UInt_Test, Call_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, vec2<u32>(1u, 1u), vec2<u32>(1u, 1u));
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1424,14 +1424,14 @@ OpReturn
|
|||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
|
||||
Intrinsic_Builtin_DualParam_UInt_Test,
|
||||
testing::Values(IntrinsicData{"max", "UMax"},
|
||||
IntrinsicData{"min", "UMin"}));
|
||||
INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
|
||||
Builtin_Builtin_DualParam_UInt_Test,
|
||||
testing::Values(BuiltinData{"max", "UMax"},
|
||||
BuiltinData{"min", "UMin"}));
|
||||
|
||||
using Intrinsic_Builtin_ThreeParam_Sint_Test =
|
||||
IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(Intrinsic_Builtin_ThreeParam_Sint_Test, Call_Scalar) {
|
||||
using Builtin_Builtin_ThreeParam_Sint_Test =
|
||||
BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(Builtin_Builtin_ThreeParam_Sint_Test, Call_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, 1, 1, 1);
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1458,7 +1458,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_P(Intrinsic_Builtin_ThreeParam_Sint_Test, Call_Vector) {
|
||||
TEST_P(Builtin_Builtin_ThreeParam_Sint_Test, Call_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* expr =
|
||||
Call(param.name, vec2<i32>(1, 1), vec2<i32>(1, 1), vec2<i32>(1, 1));
|
||||
|
@ -1487,13 +1487,13 @@ OpReturn
|
|||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
|
||||
Intrinsic_Builtin_ThreeParam_Sint_Test,
|
||||
testing::Values(IntrinsicData{"clamp", "SClamp"}));
|
||||
INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
|
||||
Builtin_Builtin_ThreeParam_Sint_Test,
|
||||
testing::Values(BuiltinData{"clamp", "SClamp"}));
|
||||
|
||||
using Intrinsic_Builtin_ThreeParam_Uint_Test =
|
||||
IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(Intrinsic_Builtin_ThreeParam_Uint_Test, Call_Scalar) {
|
||||
using Builtin_Builtin_ThreeParam_Uint_Test =
|
||||
BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(Builtin_Builtin_ThreeParam_Uint_Test, Call_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* expr = Call(param.name, 1u, 1u, 1u);
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1520,7 +1520,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_P(Intrinsic_Builtin_ThreeParam_Uint_Test, Call_Vector) {
|
||||
TEST_P(Builtin_Builtin_ThreeParam_Uint_Test, Call_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* expr =
|
||||
Call(param.name, vec2<u32>(1u, 1u), vec2<u32>(1u, 1u), vec2<u32>(1u, 1u));
|
||||
|
@ -1549,11 +1549,11 @@ OpReturn
|
|||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(IntrinsicBuilderTest,
|
||||
Intrinsic_Builtin_ThreeParam_Uint_Test,
|
||||
testing::Values(IntrinsicData{"clamp", "UClamp"}));
|
||||
INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
|
||||
Builtin_Builtin_ThreeParam_Uint_Test,
|
||||
testing::Values(BuiltinData{"clamp", "UClamp"}));
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Modf) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Modf) {
|
||||
auto* expr = Call("modf", vec2<f32>(1.0f, 2.0f));
|
||||
Func("a_func", {}, ty.void_(), {CallStmt(expr)},
|
||||
{Stage(ast::PipelineStage::kFragment)});
|
||||
|
@ -1592,7 +1592,7 @@ OpFunctionEnd
|
|||
Validate(b);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Frexp) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Frexp) {
|
||||
auto* expr = Call("frexp", vec2<f32>(1.0f, 2.0f));
|
||||
Func("a_func", {}, ty.void_(), {CallStmt(expr)},
|
||||
{Stage(ast::PipelineStage::kFragment)});
|
||||
|
@ -1633,7 +1633,7 @@ OpFunctionEnd
|
|||
Validate(b);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Determinant) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Determinant) {
|
||||
auto* var = Global("var", ty.mat3x3<f32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("determinant", "var");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1666,7 +1666,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_Transpose) {
|
||||
TEST_F(BuiltinBuilderTest, Call_Transpose) {
|
||||
auto* var = Global("var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("transpose", "var");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
|
@ -1700,7 +1700,7 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_ArrayLength) {
|
||||
TEST_F(BuiltinBuilderTest, Call_ArrayLength) {
|
||||
auto* s = Structure("my_struct", {Member("a", ty.array<f32>(4))},
|
||||
{create<ast::StructBlockAttribute>()});
|
||||
Global("b", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
|
||||
|
@ -1745,7 +1745,7 @@ OpReturn
|
|||
Validate(b);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_ArrayLength_OtherMembersInStruct) {
|
||||
TEST_F(BuiltinBuilderTest, Call_ArrayLength_OtherMembersInStruct) {
|
||||
auto* s = Structure("my_struct",
|
||||
{
|
||||
Member("z", ty.f32()),
|
||||
|
@ -1794,7 +1794,7 @@ OpReturn
|
|||
Validate(b);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_ArrayLength_ViaLets) {
|
||||
TEST_F(BuiltinBuilderTest, Call_ArrayLength_ViaLets) {
|
||||
auto* s = Structure("my_struct", {Member("a", ty.array<f32>(4))},
|
||||
{create<ast::StructBlockAttribute>()});
|
||||
Global("b", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
|
||||
|
@ -1844,7 +1844,7 @@ OpReturn
|
|||
Validate(b);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_ArrayLength_ViaLets_WithPtrNoise) {
|
||||
TEST_F(BuiltinBuilderTest, Call_ArrayLength_ViaLets_WithPtrNoise) {
|
||||
// [[block]] struct my_struct {
|
||||
// a : @stride(4) array<f32>;
|
||||
// };
|
||||
|
@ -1907,7 +1907,7 @@ OpReturn
|
|||
Validate(b);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_AtomicLoad) {
|
||||
TEST_F(BuiltinBuilderTest, Call_AtomicLoad) {
|
||||
// [[block]] struct S {
|
||||
// u : atomic<u32>;
|
||||
// i : atomic<i32>;
|
||||
|
@ -1973,7 +1973,7 @@ OpReturn
|
|||
Validate(b);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_AtomicStore) {
|
||||
TEST_F(BuiltinBuilderTest, Call_AtomicStore) {
|
||||
// [[block]] struct S {
|
||||
// u : atomic<u32>;
|
||||
// i : atomic<i32>;
|
||||
|
@ -2052,9 +2052,8 @@ OpReturn
|
|||
Validate(b);
|
||||
}
|
||||
|
||||
using Intrinsic_Builtin_AtomicRMW_i32 =
|
||||
IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(Intrinsic_Builtin_AtomicRMW_i32, Test) {
|
||||
using Builtin_Builtin_AtomicRMW_i32 = BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(Builtin_Builtin_AtomicRMW_i32, Test) {
|
||||
// [[block]] struct S {
|
||||
// v : atomic<i32>;
|
||||
// }
|
||||
|
@ -2121,18 +2120,17 @@ TEST_P(Intrinsic_Builtin_AtomicRMW_i32, Test) {
|
|||
Validate(b);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IntrinsicBuilderTest,
|
||||
Intrinsic_Builtin_AtomicRMW_i32,
|
||||
testing::Values(IntrinsicData{"atomicAdd", "OpAtomicIAdd"},
|
||||
IntrinsicData{"atomicMax", "OpAtomicSMax"},
|
||||
IntrinsicData{"atomicMin", "OpAtomicSMin"},
|
||||
IntrinsicData{"atomicAnd", "OpAtomicAnd"},
|
||||
IntrinsicData{"atomicOr", "OpAtomicOr"},
|
||||
IntrinsicData{"atomicXor", "OpAtomicXor"}));
|
||||
BuiltinBuilderTest,
|
||||
Builtin_Builtin_AtomicRMW_i32,
|
||||
testing::Values(BuiltinData{"atomicAdd", "OpAtomicIAdd"},
|
||||
BuiltinData{"atomicMax", "OpAtomicSMax"},
|
||||
BuiltinData{"atomicMin", "OpAtomicSMin"},
|
||||
BuiltinData{"atomicAnd", "OpAtomicAnd"},
|
||||
BuiltinData{"atomicOr", "OpAtomicOr"},
|
||||
BuiltinData{"atomicXor", "OpAtomicXor"}));
|
||||
|
||||
using Intrinsic_Builtin_AtomicRMW_u32 =
|
||||
IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(Intrinsic_Builtin_AtomicRMW_u32, Test) {
|
||||
using Builtin_Builtin_AtomicRMW_u32 = BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(Builtin_Builtin_AtomicRMW_u32, Test) {
|
||||
// [[block]] struct S {
|
||||
// v : atomic<u32>;
|
||||
// }
|
||||
|
@ -2198,16 +2196,16 @@ TEST_P(Intrinsic_Builtin_AtomicRMW_u32, Test) {
|
|||
Validate(b);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IntrinsicBuilderTest,
|
||||
Intrinsic_Builtin_AtomicRMW_u32,
|
||||
testing::Values(IntrinsicData{"atomicAdd", "OpAtomicIAdd"},
|
||||
IntrinsicData{"atomicMax", "OpAtomicUMax"},
|
||||
IntrinsicData{"atomicMin", "OpAtomicUMin"},
|
||||
IntrinsicData{"atomicAnd", "OpAtomicAnd"},
|
||||
IntrinsicData{"atomicOr", "OpAtomicOr"},
|
||||
IntrinsicData{"atomicXor", "OpAtomicXor"}));
|
||||
BuiltinBuilderTest,
|
||||
Builtin_Builtin_AtomicRMW_u32,
|
||||
testing::Values(BuiltinData{"atomicAdd", "OpAtomicIAdd"},
|
||||
BuiltinData{"atomicMax", "OpAtomicUMax"},
|
||||
BuiltinData{"atomicMin", "OpAtomicUMin"},
|
||||
BuiltinData{"atomicAnd", "OpAtomicAnd"},
|
||||
BuiltinData{"atomicOr", "OpAtomicOr"},
|
||||
BuiltinData{"atomicXor", "OpAtomicXor"}));
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_AtomicExchange) {
|
||||
TEST_F(BuiltinBuilderTest, Call_AtomicExchange) {
|
||||
// [[block]] struct S {
|
||||
// u : atomic<u32>;
|
||||
// i : atomic<i32>;
|
||||
|
@ -2289,7 +2287,7 @@ OpReturn
|
|||
Validate(b);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_AtomicCompareExchangeWeak) {
|
||||
TEST_F(BuiltinBuilderTest, Call_AtomicCompareExchangeWeak) {
|
||||
// [[block]] struct S {
|
||||
// u : atomic<u32>;
|
||||
// i : atomic<i32>;
|
||||
|
@ -2372,9 +2370,9 @@ OpReturn
|
|||
Validate(b);
|
||||
}
|
||||
|
||||
using Intrinsic_Builtin_DataPacking_Test =
|
||||
IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(Intrinsic_Builtin_DataPacking_Test, Binary) {
|
||||
using Builtin_Builtin_DataPacking_Test =
|
||||
BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(Builtin_Builtin_DataPacking_Test, Binary) {
|
||||
auto param = GetParam();
|
||||
|
||||
bool pack4 = param.name == "pack4x8snorm" || param.name == "pack4x8unorm";
|
||||
|
@ -2424,17 +2422,17 @@ OpFunctionEnd
|
|||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IntrinsicBuilderTest,
|
||||
Intrinsic_Builtin_DataPacking_Test,
|
||||
testing::Values(IntrinsicData{"pack4x8snorm", "PackSnorm4x8"},
|
||||
IntrinsicData{"pack4x8unorm", "PackUnorm4x8"},
|
||||
IntrinsicData{"pack2x16snorm", "PackSnorm2x16"},
|
||||
IntrinsicData{"pack2x16unorm", "PackUnorm2x16"},
|
||||
IntrinsicData{"pack2x16float", "PackHalf2x16"}));
|
||||
BuiltinBuilderTest,
|
||||
Builtin_Builtin_DataPacking_Test,
|
||||
testing::Values(BuiltinData{"pack4x8snorm", "PackSnorm4x8"},
|
||||
BuiltinData{"pack4x8unorm", "PackUnorm4x8"},
|
||||
BuiltinData{"pack2x16snorm", "PackSnorm2x16"},
|
||||
BuiltinData{"pack2x16unorm", "PackUnorm2x16"},
|
||||
BuiltinData{"pack2x16float", "PackHalf2x16"}));
|
||||
|
||||
using Intrinsic_Builtin_DataUnpacking_Test =
|
||||
IntrinsicBuilderTestWithParam<IntrinsicData>;
|
||||
TEST_P(Intrinsic_Builtin_DataUnpacking_Test, Binary) {
|
||||
using Builtin_Builtin_DataUnpacking_Test =
|
||||
BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(Builtin_Builtin_DataUnpacking_Test, Binary) {
|
||||
auto param = GetParam();
|
||||
|
||||
bool pack4 = param.name == "unpack4x8snorm" || param.name == "unpack4x8unorm";
|
||||
|
@ -2480,15 +2478,15 @@ OpFunctionEnd
|
|||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IntrinsicBuilderTest,
|
||||
Intrinsic_Builtin_DataUnpacking_Test,
|
||||
testing::Values(IntrinsicData{"unpack4x8snorm", "UnpackSnorm4x8"},
|
||||
IntrinsicData{"unpack4x8unorm", "UnpackUnorm4x8"},
|
||||
IntrinsicData{"unpack2x16snorm", "UnpackSnorm2x16"},
|
||||
IntrinsicData{"unpack2x16unorm", "UnpackUnorm2x16"},
|
||||
IntrinsicData{"unpack2x16float", "UnpackHalf2x16"}));
|
||||
BuiltinBuilderTest,
|
||||
Builtin_Builtin_DataUnpacking_Test,
|
||||
testing::Values(BuiltinData{"unpack4x8snorm", "UnpackSnorm4x8"},
|
||||
BuiltinData{"unpack4x8unorm", "UnpackUnorm4x8"},
|
||||
BuiltinData{"unpack2x16snorm", "UnpackSnorm2x16"},
|
||||
BuiltinData{"unpack2x16unorm", "UnpackUnorm2x16"},
|
||||
BuiltinData{"unpack2x16float", "UnpackHalf2x16"}));
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_WorkgroupBarrier) {
|
||||
TEST_F(BuiltinBuilderTest, Call_WorkgroupBarrier) {
|
||||
Func("f", {}, ty.void_(),
|
||||
ast::StatementList{
|
||||
CallStmt(Call("workgroupBarrier")),
|
||||
|
@ -2522,7 +2520,7 @@ OpReturn
|
|||
Validate(b);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_StorageBarrier) {
|
||||
TEST_F(BuiltinBuilderTest, Call_StorageBarrier) {
|
||||
Func("f", {}, ty.void_(),
|
||||
ast::StatementList{
|
||||
CallStmt(Call("storageBarrier")),
|
|
@ -13,8 +13,8 @@
|
|||
// limitations under the License.
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/ast/builtin_texture_helper_test.h"
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/intrinsic_texture_helper_test.h"
|
||||
#include "src/ast/stage_attribute.h"
|
||||
#include "src/writer/spirv/spv_dump.h"
|
||||
#include "src/writer/spirv/test_helper.h"
|
||||
|
@ -31,8 +31,8 @@ struct expected_texture_overload_spirv {
|
|||
};
|
||||
|
||||
expected_texture_overload_spirv expected_texture_overload(
|
||||
ast::intrinsic::test::ValidTextureOverload overload) {
|
||||
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
|
||||
ast::builtin::test::ValidTextureOverload overload) {
|
||||
using ValidTextureOverload = ast::builtin::test::ValidTextureOverload;
|
||||
switch (overload) {
|
||||
case ValidTextureOverload::kDimensions1d:
|
||||
return {
|
||||
|
@ -3672,15 +3672,15 @@ OpImageWrite %10 %16 %22
|
|||
"<unmatched texture overload>"};
|
||||
} // NOLINT - Ignore the length of this function
|
||||
|
||||
using IntrinsicTextureTest =
|
||||
TestParamHelper<ast::intrinsic::test::TextureOverloadCase>;
|
||||
using BuiltinTextureTest =
|
||||
TestParamHelper<ast::builtin::test::TextureOverloadCase>;
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IntrinsicTextureTest,
|
||||
IntrinsicTextureTest,
|
||||
testing::ValuesIn(ast::intrinsic::test::TextureOverloadCase::ValidCases()));
|
||||
BuiltinTextureTest,
|
||||
BuiltinTextureTest,
|
||||
testing::ValuesIn(ast::builtin::test::TextureOverloadCase::ValidCases()));
|
||||
|
||||
TEST_P(IntrinsicTextureTest, Call) {
|
||||
TEST_P(BuiltinTextureTest, Call) {
|
||||
auto param = GetParam();
|
||||
|
||||
auto* texture = param.BuildTextureVariable(this);
|
||||
|
@ -3706,7 +3706,7 @@ TEST_P(IntrinsicTextureTest, Call) {
|
|||
}
|
||||
|
||||
// Check the SPIRV generated passes validation
|
||||
TEST_P(IntrinsicTextureTest, ValidateSPIRV) {
|
||||
TEST_P(BuiltinTextureTest, ValidateSPIRV) {
|
||||
auto param = GetParam();
|
||||
|
||||
param.BuildTextureVariable(this);
|
||||
|
@ -3724,11 +3724,11 @@ TEST_P(IntrinsicTextureTest, ValidateSPIRV) {
|
|||
Validate(b);
|
||||
}
|
||||
|
||||
TEST_P(IntrinsicTextureTest, OutsideFunction_IsError) {
|
||||
TEST_P(BuiltinTextureTest, OutsideFunction_IsError) {
|
||||
auto param = GetParam();
|
||||
|
||||
// The point of this test is to try to generate the texture
|
||||
// intrinsic call outside a function.
|
||||
// builtin call outside a function.
|
||||
|
||||
auto* texture = param.BuildTextureVariable(this);
|
||||
auto* sampler = param.BuildSamplerVariable(this);
|
|
@ -153,6 +153,8 @@ tint_unittests_source_set("tint_unittests_ast_src") {
|
|||
"../src/ast/bool_test.cc",
|
||||
"../src/ast/break_statement_test.cc",
|
||||
"../src/ast/builtin_attribute_test.cc",
|
||||
"../src/ast/builtin_texture_helper_test.cc",
|
||||
"../src/ast/builtin_texture_helper_test.h",
|
||||
"../src/ast/call_expression_test.cc",
|
||||
"../src/ast/call_statement_test.cc",
|
||||
"../src/ast/case_statement_test.cc",
|
||||
|
@ -174,8 +176,6 @@ tint_unittests_source_set("tint_unittests_ast_src") {
|
|||
"../src/ast/index_accessor_expression_test.cc",
|
||||
"../src/ast/int_literal_expression_test.cc",
|
||||
"../src/ast/interpolate_attribute_test.cc",
|
||||
"../src/ast/intrinsic_texture_helper_test.cc",
|
||||
"../src/ast/intrinsic_texture_helper_test.h",
|
||||
"../src/ast/invariant_attribute_test.cc",
|
||||
"../src/ast/location_attribute_test.cc",
|
||||
"../src/ast/loop_statement_test.cc",
|
||||
|
@ -239,6 +239,8 @@ tint_unittests_source_set("tint_unittests_resolver_src") {
|
|||
"../src/resolver/atomics_validation_test.cc",
|
||||
"../src/resolver/bitcast_validation_test.cc",
|
||||
"../src/resolver/builtins_validation_test.cc",
|
||||
"../src/resolver/builtin_test.cc",
|
||||
"../src/resolver/builtin_validation_test.cc",
|
||||
"../src/resolver/call_test.cc",
|
||||
"../src/resolver/call_validation_test.cc",
|
||||
"../src/resolver/compound_statement_test.cc",
|
||||
|
@ -248,8 +250,6 @@ tint_unittests_source_set("tint_unittests_resolver_src") {
|
|||
"../src/resolver/entry_point_validation_test.cc",
|
||||
"../src/resolver/function_validation_test.cc",
|
||||
"../src/resolver/host_shareable_validation_test.cc",
|
||||
"../src/resolver/intrinsic_test.cc",
|
||||
"../src/resolver/intrinsic_validation_test.cc",
|
||||
"../src/resolver/is_host_shareable_test.cc",
|
||||
"../src/resolver/is_storeable_test.cc",
|
||||
"../src/resolver/pipeline_overridable_constant_test.cc",
|
||||
|
@ -278,12 +278,12 @@ tint_unittests_source_set("tint_unittests_sem_src") {
|
|||
sources = [
|
||||
"../src/sem/atomic_type_test.cc",
|
||||
"../src/sem/bool_type_test.cc",
|
||||
"../src/sem/builtin_test.cc",
|
||||
"../src/sem/depth_multisampled_texture_type_test.cc",
|
||||
"../src/sem/depth_texture_type_test.cc",
|
||||
"../src/sem/external_texture_type_test.cc",
|
||||
"../src/sem/f32_type_test.cc",
|
||||
"../src/sem/i32_type_test.cc",
|
||||
"../src/sem/intrinsic_test.cc",
|
||||
"../src/sem/matrix_type_test.cc",
|
||||
"../src/sem/multisampled_texture_type_test.cc",
|
||||
"../src/sem/pointer_type_test.cc",
|
||||
|
@ -413,6 +413,8 @@ tint_unittests_source_set("tint_unittests_spv_writer_src") {
|
|||
"../src/writer/spirv/builder_binary_expression_test.cc",
|
||||
"../src/writer/spirv/builder_bitcast_expression_test.cc",
|
||||
"../src/writer/spirv/builder_block_test.cc",
|
||||
"../src/writer/spirv/builder_builtin_test.cc",
|
||||
"../src/writer/spirv/builder_builtin_texture_test.cc",
|
||||
"../src/writer/spirv/builder_call_test.cc",
|
||||
"../src/writer/spirv/builder_constructor_expression_test.cc",
|
||||
"../src/writer/spirv/builder_discard_test.cc",
|
||||
|
@ -424,8 +426,6 @@ tint_unittests_source_set("tint_unittests_spv_writer_src") {
|
|||
"../src/writer/spirv/builder_global_variable_test.cc",
|
||||
"../src/writer/spirv/builder_ident_expression_test.cc",
|
||||
"../src/writer/spirv/builder_if_test.cc",
|
||||
"../src/writer/spirv/builder_intrinsic_test.cc",
|
||||
"../src/writer/spirv/builder_intrinsic_texture_test.cc",
|
||||
"../src/writer/spirv/builder_literal_test.cc",
|
||||
"../src/writer/spirv/builder_loop_test.cc",
|
||||
"../src/writer/spirv/builder_return_test.cc",
|
||||
|
@ -576,6 +576,8 @@ tint_unittests_source_set("tint_unittests_msl_writer_src") {
|
|||
"../src/writer/msl/generator_impl_bitcast_test.cc",
|
||||
"../src/writer/msl/generator_impl_block_test.cc",
|
||||
"../src/writer/msl/generator_impl_break_test.cc",
|
||||
"../src/writer/msl/generator_impl_builtin_test.cc",
|
||||
"../src/writer/msl/generator_impl_builtin_texture_test.cc",
|
||||
"../src/writer/msl/generator_impl_call_test.cc",
|
||||
"../src/writer/msl/generator_impl_case_test.cc",
|
||||
"../src/writer/msl/generator_impl_cast_test.cc",
|
||||
|
@ -586,8 +588,6 @@ tint_unittests_source_set("tint_unittests_msl_writer_src") {
|
|||
"../src/writer/msl/generator_impl_identifier_test.cc",
|
||||
"../src/writer/msl/generator_impl_if_test.cc",
|
||||
"../src/writer/msl/generator_impl_import_test.cc",
|
||||
"../src/writer/msl/generator_impl_intrinsic_test.cc",
|
||||
"../src/writer/msl/generator_impl_intrinsic_texture_test.cc",
|
||||
"../src/writer/msl/generator_impl_loop_test.cc",
|
||||
"../src/writer/msl/generator_impl_member_accessor_test.cc",
|
||||
"../src/writer/msl/generator_impl_module_constant_test.cc",
|
||||
|
@ -615,6 +615,8 @@ tint_unittests_source_set("tint_unittests_hlsl_writer_src") {
|
|||
"../src/writer/hlsl/generator_impl_bitcast_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_block_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_break_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_builtin_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_builtin_texture_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_call_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_case_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_cast_test.cc",
|
||||
|
@ -625,8 +627,6 @@ tint_unittests_source_set("tint_unittests_hlsl_writer_src") {
|
|||
"../src/writer/hlsl/generator_impl_identifier_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_if_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_import_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_intrinsic_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_intrinsic_texture_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_loop_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_member_accessor_test.cc",
|
||||
"../src/writer/hlsl/generator_impl_module_constant_test.cc",
|
||||
|
@ -656,6 +656,8 @@ tint_unittests_source_set("tint_unittests_glsl_writer_src") {
|
|||
"../src/writer/glsl/generator_impl_bitcast_test.cc",
|
||||
"../src/writer/glsl/generator_impl_block_test.cc",
|
||||
"../src/writer/glsl/generator_impl_break_test.cc",
|
||||
"../src/writer/glsl/generator_impl_builtin_test.cc",
|
||||
"../src/writer/glsl/generator_impl_builtin_texture_test.cc",
|
||||
"../src/writer/glsl/generator_impl_call_test.cc",
|
||||
"../src/writer/glsl/generator_impl_case_test.cc",
|
||||
"../src/writer/glsl/generator_impl_cast_test.cc",
|
||||
|
@ -666,8 +668,6 @@ tint_unittests_source_set("tint_unittests_glsl_writer_src") {
|
|||
"../src/writer/glsl/generator_impl_identifier_test.cc",
|
||||
"../src/writer/glsl/generator_impl_if_test.cc",
|
||||
"../src/writer/glsl/generator_impl_import_test.cc",
|
||||
"../src/writer/glsl/generator_impl_intrinsic_test.cc",
|
||||
"../src/writer/glsl/generator_impl_intrinsic_texture_test.cc",
|
||||
"../src/writer/glsl/generator_impl_loop_test.cc",
|
||||
"../src/writer/glsl/generator_impl_member_accessor_test.cc",
|
||||
"../src/writer/glsl/generator_impl_module_constant_test.cc",
|
||||
|
@ -692,11 +692,11 @@ tint_unittests_source_set("tint_unittests_glsl_writer_src") {
|
|||
tint_unittests_source_set("tint_unittests_core_src") {
|
||||
sources = [
|
||||
"../src/block_allocator_test.cc",
|
||||
"../src/builtin_table_test.cc",
|
||||
"../src/castable_test.cc",
|
||||
"../src/clone_context_test.cc",
|
||||
"../src/debug_test.cc",
|
||||
"../src/demangler_test.cc",
|
||||
"../src/intrinsic_table_test.cc",
|
||||
"../src/program_builder_test.cc",
|
||||
"../src/program_test.cc",
|
||||
"../src/scope_stack_test.cc",
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated builtin
|
||||
_ = isNormal(4.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated builtin
|
||||
isNormal(vec4<f32>());
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated builtin
|
||||
isNormal(0.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated builtin
|
||||
_ = isNormal(4.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated builtin
|
||||
_ = isNormal(2.);
|
||||
^^^^^^^^
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated builtin
|
||||
_ = isNormal(4.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated builtin
|
||||
isNormal(vec4<f32>());
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated builtin
|
||||
isNormal(0.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated builtin
|
||||
_ = isNormal(4.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated builtin
|
||||
_ = isNormal(2.);
|
||||
^^^^^^^^
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated builtin
|
||||
_ = isNormal(4.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated builtin
|
||||
isNormal(vec4<f32>());
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated builtin
|
||||
isNormal(0.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated builtin
|
||||
_ = isNormal(4.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated builtin
|
||||
_ = isNormal(2.);
|
||||
^^^^^^^^
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated builtin
|
||||
_ = isNormal(4.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated builtin
|
||||
isNormal(vec4<f32>());
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated builtin
|
||||
isNormal(0.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated builtin
|
||||
_ = isNormal(4.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated builtin
|
||||
_ = isNormal(2.);
|
||||
^^^^^^^^
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:4:7 warning: use of deprecated builtin
|
||||
_ = isNormal(4.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:7:3 warning: use of deprecated builtin
|
||||
isNormal(vec4<f32>());
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:10:6 warning: use of deprecated builtin
|
||||
isNormal(0.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:11:9 warning: use of deprecated builtin
|
||||
_ = isNormal(4.);
|
||||
^^^^^^^^
|
||||
|
||||
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated intrinsic
|
||||
bug/chromium/1273230.wgsl:12:9 warning: use of deprecated builtin
|
||||
_ = isNormal(2.);
|
||||
^^^^^^^^
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue