Implement textureLoad()
Bug: tint:140 Bug: tint:143 Bug: tint:144 Bug: tint:145 Bug: tint:146 Bug: tint:147 Change-Id: I8f41abac2e355c121e8868aa708ae51d0db87665 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/34960 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
7a0daa233d
commit
7f04e5c1e2
4
BUILD.gn
4
BUILD.gn
|
@ -431,10 +431,10 @@ source_set("libtint_core_src") {
|
||||||
"src/validator/validator_impl.h",
|
"src/validator/validator_impl.h",
|
||||||
"src/validator/validator_test_helper.cc",
|
"src/validator/validator_test_helper.cc",
|
||||||
"src/validator/validator_test_helper.h",
|
"src/validator/validator_test_helper.h",
|
||||||
|
"src/writer/append_vector.cc",
|
||||||
|
"src/writer/append_vector.h",
|
||||||
"src/writer/float_to_string.cc",
|
"src/writer/float_to_string.cc",
|
||||||
"src/writer/float_to_string.h",
|
"src/writer/float_to_string.h",
|
||||||
"src/writer/pack_coord_arrayidx.cc",
|
|
||||||
"src/writer/pack_coord_arrayidx.h",
|
|
||||||
"src/writer/text.cc",
|
"src/writer/text.cc",
|
||||||
"src/writer/text.h",
|
"src/writer/text.h",
|
||||||
"src/writer/text_generator.cc",
|
"src/writer/text_generator.cc",
|
||||||
|
|
|
@ -252,10 +252,10 @@ set(TINT_LIB_SRCS
|
||||||
validator/validator_impl.h
|
validator/validator_impl.h
|
||||||
validator/validator_test_helper.cc
|
validator/validator_test_helper.cc
|
||||||
validator/validator_test_helper.h
|
validator/validator_test_helper.h
|
||||||
|
writer/append_vector.cc
|
||||||
|
writer/append_vector.h
|
||||||
writer/float_to_string.cc
|
writer/float_to_string.cc
|
||||||
writer/float_to_string.h
|
writer/float_to_string.h
|
||||||
writer/pack_coord_arrayidx.cc
|
|
||||||
writer/pack_coord_arrayidx.h
|
|
||||||
writer/text.cc
|
writer/text.cc
|
||||||
writer/text.h
|
writer/text.h
|
||||||
writer/text_generator.cc
|
writer/text_generator.cc
|
||||||
|
|
|
@ -139,6 +139,8 @@ struct TextureSignature : public Signature {
|
||||||
size_t offset = kNotUsed;
|
size_t offset = kNotUsed;
|
||||||
/// `sampler` parameter index.
|
/// `sampler` parameter index.
|
||||||
size_t sampler = kNotUsed;
|
size_t sampler = kNotUsed;
|
||||||
|
/// `sample_index` parameter index.
|
||||||
|
size_t sample_index = kNotUsed;
|
||||||
/// `texture` parameter index.
|
/// `texture` parameter index.
|
||||||
size_t texture = kNotUsed;
|
size_t texture = kNotUsed;
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "src/ast/builder.h"
|
#include "src/ast/builder.h"
|
||||||
#include "src/ast/type/sampler_type.h"
|
#include "src/ast/type/sampler_type.h"
|
||||||
|
#include "src/ast/type/storage_texture_type.h"
|
||||||
#include "src/ast/type/texture_type.h"
|
#include "src/ast/type/texture_type.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
@ -27,37 +28,13 @@ namespace ast {
|
||||||
namespace intrinsic {
|
namespace intrinsic {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
enum class TextureKind { kRegular, kDepth };
|
enum class TextureKind { kRegular, kDepth, kMultisampled, kStorage };
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& out, const TextureKind& kind) {
|
|
||||||
switch (kind) {
|
|
||||||
case TextureKind::kRegular:
|
|
||||||
out << "regular";
|
|
||||||
break;
|
|
||||||
case TextureKind::kDepth:
|
|
||||||
out << "depth";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class TextureDataType { kF32, kU32, kI32 };
|
enum class TextureDataType { kF32, kU32, kI32 };
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& out, const TextureDataType& ty) {
|
std::ostream& operator<<(std::ostream& out, const TextureKind& kind);
|
||||||
switch (ty) {
|
std::ostream& operator<<(std::ostream& out, const TextureDataType& ty);
|
||||||
case TextureDataType::kF32:
|
|
||||||
out << "f32";
|
|
||||||
break;
|
|
||||||
case TextureDataType::kU32:
|
|
||||||
out << "u32";
|
|
||||||
break;
|
|
||||||
case TextureDataType::kI32:
|
|
||||||
out << "i32";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// Non-exhaustive list of valid texture overloads
|
||||||
enum class ValidTextureOverload {
|
enum class ValidTextureOverload {
|
||||||
kSample1dF32,
|
kSample1dF32,
|
||||||
kSample1dArrayF32,
|
kSample1dArrayF32,
|
||||||
|
@ -111,13 +88,65 @@ enum class ValidTextureOverload {
|
||||||
kSampleGradDepth2dArrayOffsetF32,
|
kSampleGradDepth2dArrayOffsetF32,
|
||||||
kSampleGradDepthCubeF32,
|
kSampleGradDepthCubeF32,
|
||||||
kSampleGradDepthCubeArrayF32,
|
kSampleGradDepthCubeArrayF32,
|
||||||
|
kLoad1dF32,
|
||||||
|
kLoad1dU32,
|
||||||
|
kLoad1dI32,
|
||||||
|
kLoad1dArrayF32,
|
||||||
|
kLoad1dArrayU32,
|
||||||
|
kLoad1dArrayI32,
|
||||||
|
kLoad2dF32,
|
||||||
|
kLoad2dU32,
|
||||||
|
kLoad2dI32,
|
||||||
|
kLoad2dLevelF32,
|
||||||
|
kLoad2dLevelU32,
|
||||||
|
kLoad2dLevelI32,
|
||||||
|
kLoad2dArrayF32,
|
||||||
|
kLoad2dArrayU32,
|
||||||
|
kLoad2dArrayI32,
|
||||||
|
kLoad2dArrayLevelF32,
|
||||||
|
kLoad2dArrayLevelU32,
|
||||||
|
kLoad2dArrayLevelI32,
|
||||||
|
kLoad3dF32,
|
||||||
|
kLoad3dU32,
|
||||||
|
kLoad3dI32,
|
||||||
|
kLoad3dLevelF32,
|
||||||
|
kLoad3dLevelU32,
|
||||||
|
kLoad3dLevelI32,
|
||||||
|
kLoadMultisampled2dF32,
|
||||||
|
kLoadMultisampled2dU32,
|
||||||
|
kLoadMultisampled2dI32,
|
||||||
|
kLoadMultisampled2dArrayF32,
|
||||||
|
kLoadMultisampled2dArrayU32,
|
||||||
|
kLoadMultisampled2dArrayI32,
|
||||||
|
kLoadDepth2dF32,
|
||||||
|
kLoadDepth2dLevelF32,
|
||||||
|
kLoadDepth2dArrayF32,
|
||||||
|
kLoadDepth2dArrayLevelF32,
|
||||||
|
kLoadStorageRO1dRgba32float, // Not permutated for all texel formats
|
||||||
|
kLoadStorageRO1dArrayRgba32float, // Not permutated for all texel formats
|
||||||
|
kLoadStorageRO2dRgba8unorm,
|
||||||
|
kLoadStorageRO2dRgba8snorm,
|
||||||
|
kLoadStorageRO2dRgba8uint,
|
||||||
|
kLoadStorageRO2dRgba8sint,
|
||||||
|
kLoadStorageRO2dRgba16uint,
|
||||||
|
kLoadStorageRO2dRgba16sint,
|
||||||
|
kLoadStorageRO2dRgba16float,
|
||||||
|
kLoadStorageRO2dR32uint,
|
||||||
|
kLoadStorageRO2dR32sint,
|
||||||
|
kLoadStorageRO2dR32float,
|
||||||
|
kLoadStorageRO2dRg32uint,
|
||||||
|
kLoadStorageRO2dRg32sint,
|
||||||
|
kLoadStorageRO2dRg32float,
|
||||||
|
kLoadStorageRO2dRgba32uint,
|
||||||
|
kLoadStorageRO2dRgba32sint,
|
||||||
|
kLoadStorageRO2dRgba32float,
|
||||||
|
kLoadStorageRO2dArrayRgba32float, // Not permutated for all texel formats
|
||||||
|
kLoadStorageRO3dRgba32float, // Not permutated for all texel formats
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Describes a texture intrinsic overload
|
/// Describes a texture intrinsic overload
|
||||||
struct TextureOverloadCase {
|
struct TextureOverloadCase {
|
||||||
/// Constructor
|
/// Constructor for textureSample...() functions
|
||||||
TextureOverloadCase();
|
|
||||||
/// Constructor
|
|
||||||
TextureOverloadCase(ValidTextureOverload,
|
TextureOverloadCase(ValidTextureOverload,
|
||||||
const char*,
|
const char*,
|
||||||
TextureKind,
|
TextureKind,
|
||||||
|
@ -126,42 +155,68 @@ struct TextureOverloadCase {
|
||||||
TextureDataType,
|
TextureDataType,
|
||||||
const char*,
|
const char*,
|
||||||
std::function<ExpressionList(Builder*)>);
|
std::function<ExpressionList(Builder*)>);
|
||||||
|
/// Constructor for textureLoad() functions with non-storage textures
|
||||||
|
TextureOverloadCase(ValidTextureOverload,
|
||||||
|
const char*,
|
||||||
|
TextureKind,
|
||||||
|
type::TextureDimension,
|
||||||
|
TextureDataType,
|
||||||
|
const char*,
|
||||||
|
std::function<ExpressionList(Builder*)>);
|
||||||
|
/// Constructor for textureLoad() with storage textures
|
||||||
|
TextureOverloadCase(ValidTextureOverload,
|
||||||
|
const char*,
|
||||||
|
AccessControl,
|
||||||
|
type::ImageFormat,
|
||||||
|
type::TextureDimension,
|
||||||
|
TextureDataType,
|
||||||
|
const char*,
|
||||||
|
std::function<ExpressionList(Builder*)>);
|
||||||
/// Copy constructor
|
/// Copy constructor
|
||||||
TextureOverloadCase(const TextureOverloadCase&);
|
TextureOverloadCase(const TextureOverloadCase&);
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~TextureOverloadCase();
|
~TextureOverloadCase();
|
||||||
|
|
||||||
/// @return a vector containing a large number of valid texture overloads
|
/// @return a vector containing a large number (non-exhaustive) of valid
|
||||||
|
/// texture overloads.
|
||||||
static std::vector<TextureOverloadCase> ValidCases();
|
static std::vector<TextureOverloadCase> ValidCases();
|
||||||
|
|
||||||
|
/// @param builder the AST builder used for the test
|
||||||
|
/// @returns the vector component type of the texture function return value
|
||||||
|
ast::type::Type* resultVectorComponentType(ast::Builder* builder) const;
|
||||||
|
/// @param builder the AST builder used for the test
|
||||||
|
/// @returns a Variable holding the test texture
|
||||||
|
ast::Variable* buildTextureVariable(ast::Builder* builder) const;
|
||||||
|
/// @param builder the AST builder used for the test
|
||||||
|
/// @returns a Variable holding the test sampler
|
||||||
|
ast::Variable* buildSamplerVariable(ast::Builder* builder) const;
|
||||||
|
|
||||||
/// The enumerator for this overload
|
/// The enumerator for this overload
|
||||||
ValidTextureOverload overload;
|
ValidTextureOverload const overload;
|
||||||
/// A human readable description of the overload
|
/// A human readable description of the overload
|
||||||
const char* description;
|
const char* const description;
|
||||||
/// The texture kind for the texture parameter
|
/// The texture kind for the texture parameter
|
||||||
TextureKind texture_kind;
|
TextureKind const texture_kind;
|
||||||
/// The sampler kind for the sampler parameter
|
/// The sampler kind for the sampler parameter
|
||||||
type::SamplerKind sampler_kind;
|
/// Used only when texture_kind is not kStorage
|
||||||
|
type::SamplerKind const sampler_kind = type::SamplerKind::kSampler;
|
||||||
|
/// The access control for the storage texture
|
||||||
|
/// Used only when texture_kind is kStorage
|
||||||
|
AccessControl const access_control = AccessControl::kReadWrite;
|
||||||
|
/// The image format for the storage texture
|
||||||
|
/// Used only when texture_kind is kStorage
|
||||||
|
type::ImageFormat const image_format = type::ImageFormat::kNone;
|
||||||
/// The dimensions of the texture parameter
|
/// The dimensions of the texture parameter
|
||||||
type::TextureDimension texture_dimension;
|
type::TextureDimension const texture_dimension;
|
||||||
/// The data type of the texture parameter
|
/// The data type of the texture parameter
|
||||||
TextureDataType texture_data_type;
|
TextureDataType const texture_data_type;
|
||||||
/// Name of the function. e.g. `textureSample`, `textureSampleGrad`, etc
|
/// Name of the function. e.g. `textureSample`, `textureSampleGrad`, etc
|
||||||
const char* function;
|
const char* const function;
|
||||||
/// A function that builds the AST arguments for the overload
|
/// A function that builds the AST arguments for the overload
|
||||||
std::function<ExpressionList(Builder*)> args;
|
std::function<ExpressionList(Builder*)> const args;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& out,
|
std::ostream& operator<<(std::ostream& out, const TextureOverloadCase& data);
|
||||||
const TextureOverloadCase& data) {
|
|
||||||
out << "TextureOverloadCase" << static_cast<int>(data.overload) << "\n";
|
|
||||||
out << data.description << "\n";
|
|
||||||
out << "texture_kind: " << data.texture_kind << "\n";
|
|
||||||
out << "sampler_kind: " << data.sampler_kind << "\n";
|
|
||||||
out << "texture_dimension: " << data.texture_dimension << "\n";
|
|
||||||
out << "texture_data_type: " << data.texture_data_type << "\n";
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
} // namespace intrinsic
|
} // namespace intrinsic
|
||||||
|
|
|
@ -408,7 +408,7 @@ std::string GetGlslStd450FuncName(uint32_t ext_opcode) {
|
||||||
return "trunc";
|
return "trunc";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// TODO(dneto). The following are not implemented.
|
// TODO(dneto) - The following are not implemented.
|
||||||
// They are grouped semantically, as in GLSL.std.450.h.
|
// They are grouped semantically, as in GLSL.std.450.h.
|
||||||
case GLSLstd450RoundEven:
|
case GLSLstd450RoundEven:
|
||||||
case GLSLstd450SAbs:
|
case GLSLstd450SAbs:
|
||||||
|
|
|
@ -235,10 +235,10 @@ class ParserImpl : Reader {
|
||||||
/// @returns true if parser is still successful.
|
/// @returns true if parser is still successful.
|
||||||
bool RegisterExtendedInstructionImports();
|
bool RegisterExtendedInstructionImports();
|
||||||
|
|
||||||
// Returns true when the given instruction is an extended instruction
|
/// Returns true when the given instruction is an extended instruction
|
||||||
// for GLSL.std.450.
|
/// for GLSL.std.450.
|
||||||
// @param inst a SPIR-V instruction
|
/// @param inst a SPIR-V instruction
|
||||||
// @returns true if its an SpvOpExtInst for GLSL.std.450
|
/// @returns true if its an SpvOpExtInst for GLSL.std.450
|
||||||
bool IsGlslExtendedInstruction(const spvtools::opt::Instruction& inst) const;
|
bool IsGlslExtendedInstruction(const spvtools::opt::Instruction& inst) const;
|
||||||
|
|
||||||
/// Registers user names for SPIR-V objects, from OpName, and OpMemberName.
|
/// Registers user names for SPIR-V objects, from OpName, and OpMemberName.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2020 The Tint Authors.
|
// Copyright 2020 The Tint Authors.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -555,6 +555,7 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
|
||||||
->As<ast::type::Texture>();
|
->As<ast::type::Texture>();
|
||||||
|
|
||||||
bool is_array = false;
|
bool is_array = false;
|
||||||
|
bool is_multisampled = texture->Is<ast::type::MultisampledTexture>();
|
||||||
switch (texture->dim()) {
|
switch (texture->dim()) {
|
||||||
case ast::type::TextureDimension::k1dArray:
|
case ast::type::TextureDimension::k1dArray:
|
||||||
case ast::type::TextureDimension::k2dArray:
|
case ast::type::TextureDimension::k2dArray:
|
||||||
|
@ -571,13 +572,13 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
|
||||||
if (is_array) {
|
if (is_array) {
|
||||||
param.idx.array_index = param.count++;
|
param.idx.array_index = param.count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(dsinclair): Remove the LOD param from textureLoad on storage
|
|
||||||
// textures when https://github.com/gpuweb/gpuweb/pull/1032 gets merged.
|
|
||||||
if (expr->params().size() > param.count) {
|
if (expr->params().size() > param.count) {
|
||||||
param.idx.level = param.count++;
|
if (is_multisampled) {
|
||||||
|
param.idx.sample_index = param.count++;
|
||||||
|
} else {
|
||||||
|
param.idx.level = param.count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ast::Intrinsic::kTextureSample:
|
case ast::Intrinsic::kTextureSample:
|
||||||
param.idx.texture = param.count++;
|
param.idx.texture = param.count++;
|
||||||
|
@ -659,21 +660,21 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
|
||||||
|
|
||||||
if (texture->Is<ast::type::DepthTexture>()) {
|
if (texture->Is<ast::type::DepthTexture>()) {
|
||||||
expr->func()->set_result_type(mod_->create<ast::type::F32>());
|
expr->func()->set_result_type(mod_->create<ast::type::F32>());
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ast::type::Type* type = nullptr;
|
|
||||||
if (auto* storage = texture->As<ast::type::StorageTexture>()) {
|
|
||||||
type = storage->type();
|
|
||||||
} else if (auto* sampled = texture->As<ast::type::SampledTexture>()) {
|
|
||||||
type = sampled->type();
|
|
||||||
} else if (auto* msampled = texture->As<ast::type::MultisampledTexture>()) {
|
|
||||||
type = msampled->type();
|
|
||||||
} else {
|
} else {
|
||||||
set_error(expr->source(), "unknown texture type for texture sampling");
|
ast::type::Type* type = nullptr;
|
||||||
return false;
|
if (auto* storage = texture->As<ast::type::StorageTexture>()) {
|
||||||
|
type = storage->type();
|
||||||
|
} else if (auto* sampled = texture->As<ast::type::SampledTexture>()) {
|
||||||
|
type = sampled->type();
|
||||||
|
} else if (auto* msampled =
|
||||||
|
texture->As<ast::type::MultisampledTexture>()) {
|
||||||
|
type = msampled->type();
|
||||||
|
} else {
|
||||||
|
set_error(expr->source(), "unknown texture type for texture sampling");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
expr->func()->set_result_type(mod_->create<ast::type::Vector>(type, 4));
|
||||||
}
|
}
|
||||||
expr->func()->set_result_type(mod_->create<ast::type::Vector>(type, 4));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ident->intrinsic() == ast::Intrinsic::kDot) {
|
if (ident->intrinsic() == ast::Intrinsic::kDot) {
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#include "src/ast/type/f32_type.h"
|
#include "src/ast/type/f32_type.h"
|
||||||
#include "src/ast/type/i32_type.h"
|
#include "src/ast/type/i32_type.h"
|
||||||
#include "src/ast/type/matrix_type.h"
|
#include "src/ast/type/matrix_type.h"
|
||||||
|
#include "src/ast/type/multisampled_texture_type.h"
|
||||||
#include "src/ast/type/pointer_type.h"
|
#include "src/ast/type/pointer_type.h"
|
||||||
#include "src/ast/type/sampled_texture_type.h"
|
#include "src/ast/type/sampled_texture_type.h"
|
||||||
#include "src/ast/type/sampler_type.h"
|
#include "src/ast/type/sampler_type.h"
|
||||||
|
@ -4510,6 +4511,7 @@ std::string to_str(const std::string& function,
|
||||||
maybe_add_param(sig->params.idx.level, "level");
|
maybe_add_param(sig->params.idx.level, "level");
|
||||||
maybe_add_param(sig->params.idx.offset, "offset");
|
maybe_add_param(sig->params.idx.offset, "offset");
|
||||||
maybe_add_param(sig->params.idx.sampler, "sampler");
|
maybe_add_param(sig->params.idx.sampler, "sampler");
|
||||||
|
maybe_add_param(sig->params.idx.sample_index, "sample_index");
|
||||||
maybe_add_param(sig->params.idx.texture, "texture");
|
maybe_add_param(sig->params.idx.texture, "texture");
|
||||||
std::sort(
|
std::sort(
|
||||||
params.begin(), params.end(),
|
params.begin(), params.end(),
|
||||||
|
@ -4534,126 +4536,202 @@ const char* expected_texture_overload(
|
||||||
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
|
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
|
||||||
switch (overload) {
|
switch (overload) {
|
||||||
case ValidTextureOverload::kSample1dF32:
|
case ValidTextureOverload::kSample1dF32:
|
||||||
return "textureSample(texture, sampler, coords)";
|
return R"(textureSample(texture, sampler, coords))";
|
||||||
case ValidTextureOverload::kSample1dArrayF32:
|
case ValidTextureOverload::kSample1dArrayF32:
|
||||||
return "textureSample(texture, sampler, coords, array_index)";
|
return R"(textureSample(texture, sampler, coords, array_index))";
|
||||||
case ValidTextureOverload::kSample2dF32:
|
case ValidTextureOverload::kSample2dF32:
|
||||||
return "textureSample(texture, sampler, coords)";
|
return R"(textureSample(texture, sampler, coords))";
|
||||||
case ValidTextureOverload::kSample2dOffsetF32:
|
case ValidTextureOverload::kSample2dOffsetF32:
|
||||||
return "textureSample(texture, sampler, coords, offset)";
|
return R"(textureSample(texture, sampler, coords, offset))";
|
||||||
case ValidTextureOverload::kSample2dArrayF32:
|
case ValidTextureOverload::kSample2dArrayF32:
|
||||||
return "textureSample(texture, sampler, coords, array_index)";
|
return R"(textureSample(texture, sampler, coords, array_index))";
|
||||||
case ValidTextureOverload::kSample2dArrayOffsetF32:
|
case ValidTextureOverload::kSample2dArrayOffsetF32:
|
||||||
return "textureSample(texture, sampler, coords, array_index, offset)";
|
return R"(textureSample(texture, sampler, coords, array_index, offset))";
|
||||||
case ValidTextureOverload::kSample3dF32:
|
case ValidTextureOverload::kSample3dF32:
|
||||||
return "textureSample(texture, sampler, coords)";
|
return R"(textureSample(texture, sampler, coords))";
|
||||||
case ValidTextureOverload::kSample3dOffsetF32:
|
case ValidTextureOverload::kSample3dOffsetF32:
|
||||||
return "textureSample(texture, sampler, coords, offset)";
|
return R"(textureSample(texture, sampler, coords, offset))";
|
||||||
case ValidTextureOverload::kSampleCubeF32:
|
case ValidTextureOverload::kSampleCubeF32:
|
||||||
return "textureSample(texture, sampler, coords)";
|
return R"(textureSample(texture, sampler, coords))";
|
||||||
case ValidTextureOverload::kSampleCubeArrayF32:
|
case ValidTextureOverload::kSampleCubeArrayF32:
|
||||||
return "textureSample(texture, sampler, coords, array_index)";
|
return R"(textureSample(texture, sampler, coords, array_index))";
|
||||||
case ValidTextureOverload::kSampleDepth2dF32:
|
case ValidTextureOverload::kSampleDepth2dF32:
|
||||||
return "textureSample(texture, sampler, coords)";
|
return R"(textureSample(texture, sampler, coords))";
|
||||||
case ValidTextureOverload::kSampleDepth2dOffsetF32:
|
case ValidTextureOverload::kSampleDepth2dOffsetF32:
|
||||||
return "textureSample(texture, sampler, coords, offset)";
|
return R"(textureSample(texture, sampler, coords, offset))";
|
||||||
case ValidTextureOverload::kSampleDepth2dArrayF32:
|
case ValidTextureOverload::kSampleDepth2dArrayF32:
|
||||||
return "textureSample(texture, sampler, coords, array_index)";
|
return R"(textureSample(texture, sampler, coords, array_index))";
|
||||||
case ValidTextureOverload::kSampleDepth2dArrayOffsetF32:
|
case ValidTextureOverload::kSampleDepth2dArrayOffsetF32:
|
||||||
return "textureSample(texture, sampler, coords, array_index, offset)";
|
return R"(textureSample(texture, sampler, coords, array_index, offset))";
|
||||||
case ValidTextureOverload::kSampleDepthCubeF32:
|
case ValidTextureOverload::kSampleDepthCubeF32:
|
||||||
return "textureSample(texture, sampler, coords)";
|
return R"(textureSample(texture, sampler, coords))";
|
||||||
case ValidTextureOverload::kSampleDepthCubeArrayF32:
|
case ValidTextureOverload::kSampleDepthCubeArrayF32:
|
||||||
return "textureSample(texture, sampler, coords, array_index)";
|
return R"(textureSample(texture, sampler, coords, array_index))";
|
||||||
case ValidTextureOverload::kSampleBias2dF32:
|
case ValidTextureOverload::kSampleBias2dF32:
|
||||||
return "textureSampleBias(texture, sampler, coords, bias)";
|
return R"(textureSampleBias(texture, sampler, coords, bias))";
|
||||||
case ValidTextureOverload::kSampleBias2dOffsetF32:
|
case ValidTextureOverload::kSampleBias2dOffsetF32:
|
||||||
return "textureSampleBias(texture, sampler, coords, bias, offset)";
|
return R"(textureSampleBias(texture, sampler, coords, bias, offset))";
|
||||||
case ValidTextureOverload::kSampleBias2dArrayF32:
|
case ValidTextureOverload::kSampleBias2dArrayF32:
|
||||||
return "textureSampleBias(texture, sampler, coords, array_index, "
|
return R"(textureSampleBias(texture, sampler, coords, array_index, bias))";
|
||||||
"bias)";
|
|
||||||
case ValidTextureOverload::kSampleBias2dArrayOffsetF32:
|
case ValidTextureOverload::kSampleBias2dArrayOffsetF32:
|
||||||
return "textureSampleBias(texture, sampler, coords, array_index, "
|
return R"(textureSampleBias(texture, sampler, coords, array_index, bias, offset))";
|
||||||
"bias, offset)";
|
|
||||||
case ValidTextureOverload::kSampleBias3dF32:
|
case ValidTextureOverload::kSampleBias3dF32:
|
||||||
return "textureSampleBias(texture, sampler, coords, bias)";
|
return R"(textureSampleBias(texture, sampler, coords, bias))";
|
||||||
case ValidTextureOverload::kSampleBias3dOffsetF32:
|
case ValidTextureOverload::kSampleBias3dOffsetF32:
|
||||||
return "textureSampleBias(texture, sampler, coords, bias, offset)";
|
return R"(textureSampleBias(texture, sampler, coords, bias, offset))";
|
||||||
case ValidTextureOverload::kSampleBiasCubeF32:
|
case ValidTextureOverload::kSampleBiasCubeF32:
|
||||||
return "textureSampleBias(texture, sampler, coords, bias)";
|
return R"(textureSampleBias(texture, sampler, coords, bias))";
|
||||||
case ValidTextureOverload::kSampleBiasCubeArrayF32:
|
case ValidTextureOverload::kSampleBiasCubeArrayF32:
|
||||||
return "textureSampleBias(texture, sampler, coords, array_index, "
|
return R"(textureSampleBias(texture, sampler, coords, array_index, bias))";
|
||||||
"bias)";
|
|
||||||
case ValidTextureOverload::kSampleLevel2dF32:
|
case ValidTextureOverload::kSampleLevel2dF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, level)";
|
return R"(textureSampleLevel(texture, sampler, coords, level))";
|
||||||
case ValidTextureOverload::kSampleLevel2dOffsetF32:
|
case ValidTextureOverload::kSampleLevel2dOffsetF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, level, offset)";
|
return R"(textureSampleLevel(texture, sampler, coords, level, offset))";
|
||||||
case ValidTextureOverload::kSampleLevel2dArrayF32:
|
case ValidTextureOverload::kSampleLevel2dArrayF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, array_index, "
|
return R"(textureSampleLevel(texture, sampler, coords, array_index, level))";
|
||||||
"level)";
|
|
||||||
case ValidTextureOverload::kSampleLevel2dArrayOffsetF32:
|
case ValidTextureOverload::kSampleLevel2dArrayOffsetF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, array_index, "
|
return R"(textureSampleLevel(texture, sampler, coords, array_index, level, offset))";
|
||||||
"level, offset)";
|
|
||||||
case ValidTextureOverload::kSampleLevel3dF32:
|
case ValidTextureOverload::kSampleLevel3dF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, level)";
|
return R"(textureSampleLevel(texture, sampler, coords, level))";
|
||||||
case ValidTextureOverload::kSampleLevel3dOffsetF32:
|
case ValidTextureOverload::kSampleLevel3dOffsetF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, level, offset)";
|
return R"(textureSampleLevel(texture, sampler, coords, level, offset))";
|
||||||
case ValidTextureOverload::kSampleLevelCubeF32:
|
case ValidTextureOverload::kSampleLevelCubeF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, level)";
|
return R"(textureSampleLevel(texture, sampler, coords, level))";
|
||||||
case ValidTextureOverload::kSampleLevelCubeArrayF32:
|
case ValidTextureOverload::kSampleLevelCubeArrayF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, array_index, "
|
return R"(textureSampleLevel(texture, sampler, coords, array_index, level))";
|
||||||
"level)";
|
|
||||||
case ValidTextureOverload::kSampleLevelDepth2dF32:
|
case ValidTextureOverload::kSampleLevelDepth2dF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, level)";
|
return R"(textureSampleLevel(texture, sampler, coords, level))";
|
||||||
case ValidTextureOverload::kSampleLevelDepth2dOffsetF32:
|
case ValidTextureOverload::kSampleLevelDepth2dOffsetF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, level, offset)";
|
return R"(textureSampleLevel(texture, sampler, coords, level, offset))";
|
||||||
case ValidTextureOverload::kSampleLevelDepth2dArrayF32:
|
case ValidTextureOverload::kSampleLevelDepth2dArrayF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, array_index, level)";
|
return R"(textureSampleLevel(texture, sampler, coords, array_index, level))";
|
||||||
case ValidTextureOverload::kSampleLevelDepth2dArrayOffsetF32:
|
case ValidTextureOverload::kSampleLevelDepth2dArrayOffsetF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, array_index, level, "
|
return R"(textureSampleLevel(texture, sampler, coords, array_index, level, offset))";
|
||||||
"offset)";
|
|
||||||
case ValidTextureOverload::kSampleLevelDepthCubeF32:
|
case ValidTextureOverload::kSampleLevelDepthCubeF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, level)";
|
return R"(textureSampleLevel(texture, sampler, coords, level))";
|
||||||
case ValidTextureOverload::kSampleLevelDepthCubeArrayF32:
|
case ValidTextureOverload::kSampleLevelDepthCubeArrayF32:
|
||||||
return "textureSampleLevel(texture, sampler, coords, array_index, "
|
return R"(textureSampleLevel(texture, sampler, coords, array_index, level))";
|
||||||
"level)";
|
|
||||||
case ValidTextureOverload::kSampleGrad2dF32:
|
case ValidTextureOverload::kSampleGrad2dF32:
|
||||||
return "textureSampleGrad(texture, sampler, coords, ddx, ddy)";
|
return R"(textureSampleGrad(texture, sampler, coords, ddx, ddy))";
|
||||||
case ValidTextureOverload::kSampleGrad2dOffsetF32:
|
case ValidTextureOverload::kSampleGrad2dOffsetF32:
|
||||||
return "textureSampleGrad(texture, sampler, coords, ddx, ddy, "
|
return R"(textureSampleGrad(texture, sampler, coords, ddx, ddy, offset))";
|
||||||
"offset)";
|
|
||||||
case ValidTextureOverload::kSampleGrad2dArrayF32:
|
case ValidTextureOverload::kSampleGrad2dArrayF32:
|
||||||
return "textureSampleGrad(texture, sampler, coords, array_index, ddx, "
|
return R"(textureSampleGrad(texture, sampler, coords, array_index, ddx, ddy))";
|
||||||
"ddy)";
|
|
||||||
case ValidTextureOverload::kSampleGrad2dArrayOffsetF32:
|
case ValidTextureOverload::kSampleGrad2dArrayOffsetF32:
|
||||||
return "textureSampleGrad(texture, sampler, coords, array_index, ddx, "
|
return R"(textureSampleGrad(texture, sampler, coords, array_index, ddx, ddy, offset))";
|
||||||
"ddy, offset)";
|
|
||||||
case ValidTextureOverload::kSampleGrad3dF32:
|
case ValidTextureOverload::kSampleGrad3dF32:
|
||||||
return "textureSampleGrad(texture, sampler, coords, ddx, ddy)";
|
return R"(textureSampleGrad(texture, sampler, coords, ddx, ddy))";
|
||||||
case ValidTextureOverload::kSampleGrad3dOffsetF32:
|
case ValidTextureOverload::kSampleGrad3dOffsetF32:
|
||||||
return "textureSampleGrad(texture, sampler, coords, ddx, ddy, "
|
return R"(textureSampleGrad(texture, sampler, coords, ddx, ddy, offset))";
|
||||||
"offset)";
|
|
||||||
case ValidTextureOverload::kSampleGradCubeF32:
|
case ValidTextureOverload::kSampleGradCubeF32:
|
||||||
return "textureSampleGrad(texture, sampler, coords, ddx, ddy)";
|
return R"(textureSampleGrad(texture, sampler, coords, ddx, ddy))";
|
||||||
case ValidTextureOverload::kSampleGradCubeArrayF32:
|
case ValidTextureOverload::kSampleGradCubeArrayF32:
|
||||||
return "textureSampleGrad(texture, sampler, coords, array_index, ddx, "
|
return R"(textureSampleGrad(texture, sampler, coords, array_index, ddx, ddy))";
|
||||||
"ddy)";
|
|
||||||
case ValidTextureOverload::kSampleGradDepth2dF32:
|
case ValidTextureOverload::kSampleGradDepth2dF32:
|
||||||
return "textureSampleCompare(texture, sampler, coords, depth_ref)";
|
return R"(textureSampleCompare(texture, sampler, coords, depth_ref))";
|
||||||
case ValidTextureOverload::kSampleGradDepth2dOffsetF32:
|
case ValidTextureOverload::kSampleGradDepth2dOffsetF32:
|
||||||
return "textureSampleCompare(texture, sampler, coords, depth_ref, "
|
return R"(textureSampleCompare(texture, sampler, coords, depth_ref, offset))";
|
||||||
"offset)";
|
|
||||||
case ValidTextureOverload::kSampleGradDepth2dArrayF32:
|
case ValidTextureOverload::kSampleGradDepth2dArrayF32:
|
||||||
return "textureSampleCompare(texture, sampler, coords, array_index, "
|
return R"(textureSampleCompare(texture, sampler, coords, array_index, depth_ref))";
|
||||||
"depth_ref)";
|
|
||||||
case ValidTextureOverload::kSampleGradDepth2dArrayOffsetF32:
|
case ValidTextureOverload::kSampleGradDepth2dArrayOffsetF32:
|
||||||
return "textureSampleCompare(texture, sampler, coords, array_index, "
|
return R"(textureSampleCompare(texture, sampler, coords, array_index, depth_ref, offset))";
|
||||||
"depth_ref, offset)";
|
|
||||||
case ValidTextureOverload::kSampleGradDepthCubeF32:
|
case ValidTextureOverload::kSampleGradDepthCubeF32:
|
||||||
return "textureSampleCompare(texture, sampler, coords, depth_ref)";
|
return R"(textureSampleCompare(texture, sampler, coords, depth_ref))";
|
||||||
case ValidTextureOverload::kSampleGradDepthCubeArrayF32:
|
case ValidTextureOverload::kSampleGradDepthCubeArrayF32:
|
||||||
return "textureSampleCompare(texture, sampler, coords, array_index, "
|
return R"(textureSampleCompare(texture, sampler, coords, array_index, depth_ref))";
|
||||||
"depth_ref)";
|
case ValidTextureOverload::kLoad1dF32:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kLoad1dU32:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kLoad1dI32:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kLoad1dArrayF32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index))";
|
||||||
|
case ValidTextureOverload::kLoad1dArrayU32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index))";
|
||||||
|
case ValidTextureOverload::kLoad1dArrayI32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index))";
|
||||||
|
case ValidTextureOverload::kLoad2dF32:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kLoad2dU32:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kLoad2dI32:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kLoad2dLevelF32:
|
||||||
|
return R"(textureLoad(texture, coords, level))";
|
||||||
|
case ValidTextureOverload::kLoad2dLevelU32:
|
||||||
|
return R"(textureLoad(texture, coords, level))";
|
||||||
|
case ValidTextureOverload::kLoad2dLevelI32:
|
||||||
|
return R"(textureLoad(texture, coords, level))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayF32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayU32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayI32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayLevelF32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index, level))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayLevelU32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index, level))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayLevelI32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index, level))";
|
||||||
|
case ValidTextureOverload::kLoad3dF32:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kLoad3dU32:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kLoad3dI32:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kLoad3dLevelF32:
|
||||||
|
return R"(textureLoad(texture, coords, level))";
|
||||||
|
case ValidTextureOverload::kLoad3dLevelU32:
|
||||||
|
return R"(textureLoad(texture, coords, level))";
|
||||||
|
case ValidTextureOverload::kLoad3dLevelI32:
|
||||||
|
return R"(textureLoad(texture, coords, level))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dF32:
|
||||||
|
return R"(textureLoad(texture, coords, sample_index))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dU32:
|
||||||
|
return R"(textureLoad(texture, coords, sample_index))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dI32:
|
||||||
|
return R"(textureLoad(texture, coords, sample_index))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dArrayF32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index, sample_index))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dArrayU32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index, sample_index))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dArrayI32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index, sample_index))";
|
||||||
|
case ValidTextureOverload::kLoadDepth2dF32:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kLoadDepth2dLevelF32:
|
||||||
|
return R"(textureLoad(texture, coords, level))";
|
||||||
|
case ValidTextureOverload::kLoadDepth2dArrayF32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index))";
|
||||||
|
case ValidTextureOverload::kLoadDepth2dArrayLevelF32:
|
||||||
|
return R"(textureLoad(texture, coords, array_index, level))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO1dRgba32float:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO1dArrayRgba32float:
|
||||||
|
return R"(textureLoad(texture, coords, array_index))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba8unorm:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba8snorm:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba8uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba8sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba16uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba16sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba16float:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dR32uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dR32sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dR32float:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRg32uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRg32sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRg32float:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba32uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba32sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba32float:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dArrayRgba32float:
|
||||||
|
return R"(textureLoad(texture, coords, array_index))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO3dRgba32float:
|
||||||
|
return R"(textureLoad(texture, coords))";
|
||||||
}
|
}
|
||||||
return "<unmatched texture overload>";
|
return "<unmatched texture overload>";
|
||||||
}
|
}
|
||||||
|
@ -4661,56 +4739,37 @@ const char* expected_texture_overload(
|
||||||
TEST_P(TypeDeterminerTextureIntrinsicTest, Call) {
|
TEST_P(TypeDeterminerTextureIntrinsicTest, Call) {
|
||||||
auto param = GetParam();
|
auto param = GetParam();
|
||||||
|
|
||||||
ast::type::Type* datatype = nullptr;
|
param.buildTextureVariable(this);
|
||||||
switch (param.texture_data_type) {
|
param.buildSamplerVariable(this);
|
||||||
case ast::intrinsic::test::TextureDataType::kF32:
|
|
||||||
datatype = ty.f32;
|
|
||||||
break;
|
|
||||||
case ast::intrinsic::test::TextureDataType::kU32:
|
|
||||||
datatype = ty.u32;
|
|
||||||
break;
|
|
||||||
case ast::intrinsic::test::TextureDataType::kI32:
|
|
||||||
datatype = ty.i32;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ast::type::Sampler sampler_type{param.sampler_kind};
|
|
||||||
switch (param.texture_kind) {
|
|
||||||
case ast::intrinsic::test::TextureKind::kRegular:
|
|
||||||
Var("texture", ast::StorageClass::kNone,
|
|
||||||
mod->create<ast::type::SampledTexture>(param.texture_dimension,
|
|
||||||
datatype));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ast::intrinsic::test::TextureKind::kDepth:
|
|
||||||
Var("texture", ast::StorageClass::kNone,
|
|
||||||
mod->create<ast::type::DepthTexture>(param.texture_dimension));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Var("sampler", ast::StorageClass::kNone, &sampler_type);
|
|
||||||
|
|
||||||
auto* ident = Expr(param.function);
|
auto* ident = Expr(param.function);
|
||||||
ast::CallExpression call{ident, param.args(this)};
|
ast::CallExpression call{ident, param.args(this)};
|
||||||
|
|
||||||
EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
|
ASSERT_TRUE(td()->Determine()) << td()->error();
|
||||||
|
ASSERT_TRUE(td()->DetermineResultType(&call)) << td()->error();
|
||||||
|
|
||||||
switch (param.texture_kind) {
|
switch (param.texture_kind) {
|
||||||
case ast::intrinsic::test::TextureKind::kRegular:
|
case ast::intrinsic::test::TextureKind::kRegular:
|
||||||
|
case ast::intrinsic::test::TextureKind::kMultisampled:
|
||||||
|
case ast::intrinsic::test::TextureKind::kStorage: {
|
||||||
|
auto* datatype = param.resultVectorComponentType(this);
|
||||||
ASSERT_TRUE(call.result_type()->Is<ast::type::Vector>());
|
ASSERT_TRUE(call.result_type()->Is<ast::type::Vector>());
|
||||||
EXPECT_EQ(call.result_type()->As<ast::type::Vector>()->type(), datatype);
|
EXPECT_EQ(call.result_type()->As<ast::type::Vector>()->type(), datatype);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case ast::intrinsic::test::TextureKind::kDepth:
|
case ast::intrinsic::test::TextureKind::kDepth: {
|
||||||
EXPECT_EQ(call.result_type(), ty.f32);
|
EXPECT_EQ(call.result_type(), ty.f32);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* sig = static_cast<const ast::intrinsic::TextureSignature*>(
|
auto* sig = static_cast<const ast::intrinsic::TextureSignature*>(
|
||||||
ident->intrinsic_signature());
|
ident->intrinsic_signature());
|
||||||
|
ASSERT_NE(sig, nullptr);
|
||||||
|
|
||||||
|
auto got = to_str(param.function, sig);
|
||||||
auto* expected = expected_texture_overload(param.overload);
|
auto* expected = expected_texture_overload(param.overload);
|
||||||
EXPECT_EQ(to_str(param.function, sig), expected);
|
EXPECT_EQ(got, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "src/writer/pack_coord_arrayidx.h"
|
#include "src/writer/append_vector.h"
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
@ -36,41 +36,46 @@ ast::TypeConstructorExpression* AsVectorConstructor(ast::Expression* expr) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool PackCoordAndArrayIndex(
|
bool AppendVector(
|
||||||
ast::Expression* coords,
|
ast::Expression* vector,
|
||||||
ast::Expression* array_idx,
|
ast::Expression* scalar,
|
||||||
std::function<bool(ast::TypeConstructorExpression*)> callback) {
|
std::function<bool(ast::TypeConstructorExpression*)> callback) {
|
||||||
uint32_t packed_size;
|
uint32_t packed_size;
|
||||||
ast::type::Type* packed_el_ty; // Currently must be f32.
|
ast::type::Type* packed_el_ty; // Currently must be f32.
|
||||||
if (auto* vec = coords->result_type()->As<ast::type::Vector>()) {
|
if (auto* vec = vector->result_type()->As<ast::type::Vector>()) {
|
||||||
packed_size = vec->size() + 1;
|
packed_size = vec->size() + 1;
|
||||||
packed_el_ty = vec->type();
|
packed_el_ty = vec->type();
|
||||||
} else {
|
} else {
|
||||||
packed_size = 2;
|
packed_size = 2;
|
||||||
packed_el_ty = coords->result_type();
|
packed_el_ty = vector->result_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!packed_el_ty) {
|
if (!packed_el_ty) {
|
||||||
return false; // missing type info
|
return false; // missing type info
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cast array_idx to the vector element type
|
// Cast scalar to the vector element type
|
||||||
ast::TypeConstructorExpression array_index_cast(packed_el_ty, {array_idx});
|
ast::TypeConstructorExpression scalar_cast(packed_el_ty, {scalar});
|
||||||
array_index_cast.set_result_type(packed_el_ty);
|
scalar_cast.set_result_type(packed_el_ty);
|
||||||
|
|
||||||
ast::type::Vector packed_ty(packed_el_ty, packed_size);
|
ast::type::Vector packed_ty(packed_el_ty, packed_size);
|
||||||
|
|
||||||
// If the coordinates are already passed in a vector constructor, extract
|
// If the coordinates are already passed in a vector constructor, extract
|
||||||
// the elements into the new vector instead of nesting a vector-in-vector.
|
// the elements into the new vector instead of nesting a vector-in-vector.
|
||||||
ast::ExpressionList packed;
|
ast::ExpressionList packed;
|
||||||
if (auto* vc = AsVectorConstructor(coords)) {
|
if (auto* vc = AsVectorConstructor(vector)) {
|
||||||
packed = vc->values();
|
packed = vc->values();
|
||||||
} else {
|
} else {
|
||||||
packed.emplace_back(coords);
|
packed.emplace_back(vector);
|
||||||
|
}
|
||||||
|
if (packed_el_ty != scalar->result_type()) {
|
||||||
|
packed.emplace_back(&scalar_cast);
|
||||||
|
} else {
|
||||||
|
packed.emplace_back(scalar);
|
||||||
}
|
}
|
||||||
packed.emplace_back(&array_index_cast);
|
|
||||||
|
|
||||||
ast::TypeConstructorExpression constructor{&packed_ty, std::move(packed)};
|
ast::TypeConstructorExpression constructor{&packed_ty, std::move(packed)};
|
||||||
|
constructor.set_result_type(&packed_ty);
|
||||||
|
|
||||||
return callback(&constructor);
|
return callback(&constructor);
|
||||||
}
|
}
|
|
@ -12,8 +12,8 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#ifndef SRC_WRITER_PACK_COORD_ARRAYIDX_H_
|
#ifndef SRC_WRITER_APPEND_VECTOR_H_
|
||||||
#define SRC_WRITER_PACK_COORD_ARRAYIDX_H_
|
#define SRC_WRITER_APPEND_VECTOR_H_
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
@ -28,25 +28,26 @@ class TypeConstructorExpression;
|
||||||
|
|
||||||
namespace writer {
|
namespace writer {
|
||||||
|
|
||||||
/// A helper function use to generate texture intrinsic function calls for
|
/// A helper function used to append a vector with an additional scalar.
|
||||||
/// backends that expect the texture coordinate and array index to be packed
|
/// AppendVector is used to generate texture intrinsic function calls for
|
||||||
/// together into a single 'coordinate' parameter.
|
/// backends that expect the texture coordinates to be packed with an additional
|
||||||
/// PackCoordAndArrayIndex() calls the `callback` function with a vector
|
/// mip-level or array-index parameter.
|
||||||
/// expression containing the elements of `coords` followed by the single
|
/// AppendVector() calls the `callback` function with a vector
|
||||||
/// element of `array_idx` cast to the `coords` element type.
|
/// expression containing the elements of `vector` followed by the single
|
||||||
|
/// element of `scalar` cast to the `vector` element type.
|
||||||
/// All types must have been assigned to the expressions and their child nodes
|
/// All types must have been assigned to the expressions and their child nodes
|
||||||
/// before calling.
|
/// before calling.
|
||||||
/// @param coords the texture coordinates. May be a scalar, `vec2` or `vec3`.
|
/// @param vector the vector to be appended. May be a scalar, `vec2` or `vec3`.
|
||||||
/// @param array_idx the texture array index. Must be a scalar.
|
/// @param scalar the scalar to append to the vector. Must be a scalar.
|
||||||
/// @param callback the function called with the packed result. Note that the
|
/// @param callback the function called with the packed result. Note that the
|
||||||
/// pointer argument is only valid for the duration of the call.
|
/// pointer argument is only valid for the duration of the call.
|
||||||
/// @returns the value returned by `callback` to indicate success
|
/// @returns the value returned by `callback` to indicate success
|
||||||
bool PackCoordAndArrayIndex(
|
bool AppendVector(
|
||||||
ast::Expression* coords,
|
ast::Expression* vector,
|
||||||
ast::Expression* array_idx,
|
ast::Expression* scalar,
|
||||||
std::function<bool(ast::TypeConstructorExpression*)> callback);
|
std::function<bool(ast::TypeConstructorExpression*)> callback);
|
||||||
|
|
||||||
} // namespace writer
|
} // namespace writer
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
||||||
#endif // SRC_WRITER_PACK_COORD_ARRAYIDX_H_
|
#endif // SRC_WRITER_APPEND_VECTOR_H_
|
|
@ -57,8 +57,8 @@
|
||||||
#include "src/ast/uint_literal.h"
|
#include "src/ast/uint_literal.h"
|
||||||
#include "src/ast/unary_op_expression.h"
|
#include "src/ast/unary_op_expression.h"
|
||||||
#include "src/ast/variable_decl_statement.h"
|
#include "src/ast/variable_decl_statement.h"
|
||||||
|
#include "src/writer/append_vector.h"
|
||||||
#include "src/writer/float_to_string.h"
|
#include "src/writer/float_to_string.h"
|
||||||
#include "src/writer/pack_coord_arrayidx.h"
|
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace writer {
|
namespace writer {
|
||||||
|
@ -729,9 +729,14 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
|
||||||
auto& pidx = signature->params.idx;
|
auto& pidx = signature->params.idx;
|
||||||
auto const kNotUsed = ast::intrinsic::TextureSignature::Parameters::kNotUsed;
|
auto const kNotUsed = ast::intrinsic::TextureSignature::Parameters::kNotUsed;
|
||||||
|
|
||||||
if (!EmitExpression(pre, out, params[pidx.texture]))
|
auto* texture = params[pidx.texture];
|
||||||
|
auto* texture_type = texture->result_type()->UnwrapPtrIfNeeded();
|
||||||
|
|
||||||
|
if (!EmitExpression(pre, out, texture))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
bool pack_mip_in_coords = false;
|
||||||
|
|
||||||
switch (ident->intrinsic()) {
|
switch (ident->intrinsic()) {
|
||||||
case ast::Intrinsic::kTextureSample:
|
case ast::Intrinsic::kTextureSample:
|
||||||
out << ".Sample(";
|
out << ".Sample(";
|
||||||
|
@ -748,35 +753,61 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
|
||||||
case ast::Intrinsic::kTextureSampleCompare:
|
case ast::Intrinsic::kTextureSampleCompare:
|
||||||
out << ".SampleCmp(";
|
out << ".SampleCmp(";
|
||||||
break;
|
break;
|
||||||
|
case ast::Intrinsic::kTextureLoad:
|
||||||
|
out << ".Load(";
|
||||||
|
if (!texture_type->Is<ast::type::StorageTexture>()) {
|
||||||
|
pack_mip_in_coords = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error_ = "Internal compiler error: Unhandled texture intrinsic '" +
|
error_ = "Internal compiler error: Unhandled texture intrinsic '" +
|
||||||
ident->name() + "'";
|
ident->name() + "'";
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EmitExpression(pre, out, params[pidx.sampler]))
|
if (pidx.sampler != kNotUsed) {
|
||||||
return false;
|
if (!EmitExpression(pre, out, params[pidx.sampler]))
|
||||||
|
return false;
|
||||||
|
out << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
out << ", ";
|
auto* param_coords = params[pidx.coords];
|
||||||
|
|
||||||
|
auto emit_vector_appended_with_i32_zero = [&](tint::ast::Expression* vector) {
|
||||||
|
auto* i32 = module_->create<ast::type::I32>();
|
||||||
|
ast::SintLiteral zero_lit(i32, 0);
|
||||||
|
ast::ScalarConstructorExpression zero(&zero_lit);
|
||||||
|
zero.set_result_type(i32);
|
||||||
|
return AppendVector(vector, &zero,
|
||||||
|
[&](ast::TypeConstructorExpression* packed) {
|
||||||
|
return EmitExpression(pre, out, packed);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
if (pidx.array_index != kNotUsed) {
|
if (pidx.array_index != kNotUsed) {
|
||||||
// Array index needs to be appended to the coordinates.
|
// Array index needs to be appended to the coordinates.
|
||||||
auto* param_coords = params[pidx.coords];
|
|
||||||
auto* param_array_index = params[pidx.array_index];
|
auto* param_array_index = params[pidx.array_index];
|
||||||
if (!PackCoordAndArrayIndex(param_coords, param_array_index,
|
if (!AppendVector(param_coords, param_array_index,
|
||||||
[&](ast::TypeConstructorExpression* packed) {
|
[&](ast::TypeConstructorExpression* packed) {
|
||||||
return EmitExpression(pre, out, packed);
|
if (pack_mip_in_coords) {
|
||||||
})) {
|
return emit_vector_appended_with_i32_zero(packed);
|
||||||
|
} else {
|
||||||
|
return EmitExpression(pre, out, packed);
|
||||||
|
}
|
||||||
|
})) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (pack_mip_in_coords) {
|
||||||
|
// Mip level needs to be appended to the coordinates, but is always zero.
|
||||||
|
if (!emit_vector_appended_with_i32_zero(param_coords))
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if (!EmitExpression(pre, out, params[pidx.coords]))
|
if (!EmitExpression(pre, out, param_coords))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto idx : {pidx.depth_ref, pidx.bias, pidx.level, pidx.ddx, pidx.ddy,
|
for (auto idx : {pidx.depth_ref, pidx.bias, pidx.level, pidx.ddx, pidx.ddy,
|
||||||
pidx.offset}) {
|
pidx.sample_index, pidx.offset}) {
|
||||||
if (idx != kNotUsed) {
|
if (idx != kNotUsed) {
|
||||||
out << ", ";
|
out << ", ";
|
||||||
if (!EmitExpression(pre, out, params[idx]))
|
if (!EmitExpression(pre, out, params[idx]))
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "src/ast/builder.h"
|
#include "src/ast/builder.h"
|
||||||
#include "src/ast/intrinsic_texture_helper_test.h"
|
#include "src/ast/intrinsic_texture_helper_test.h"
|
||||||
#include "src/ast/type/depth_texture_type.h"
|
#include "src/ast/type/depth_texture_type.h"
|
||||||
|
#include "src/ast/type/multisampled_texture_type.h"
|
||||||
#include "src/ast/type/sampled_texture_type.h"
|
#include "src/ast/type/sampled_texture_type.h"
|
||||||
#include "src/type_determiner.h"
|
#include "src/type_determiner.h"
|
||||||
#include "src/writer/hlsl/generator_impl.h"
|
#include "src/writer/hlsl/generator_impl.h"
|
||||||
|
@ -135,9 +136,102 @@ std::string expected_texture_overload(
|
||||||
return R"(texture_tint_0.SampleCmp(sampler_tint_0, float3(1.0f, 2.0f, 3.0f), 4.0f))";
|
return R"(texture_tint_0.SampleCmp(sampler_tint_0, float3(1.0f, 2.0f, 3.0f), 4.0f))";
|
||||||
case ValidTextureOverload::kSampleGradDepthCubeArrayF32:
|
case ValidTextureOverload::kSampleGradDepthCubeArrayF32:
|
||||||
return R"(texture_tint_0.SampleCmp(sampler_tint_0, float4(1.0f, 2.0f, 3.0f, float(4)), 5.0f))";
|
return R"(texture_tint_0.SampleCmp(sampler_tint_0, float4(1.0f, 2.0f, 3.0f, float(4)), 5.0f))";
|
||||||
|
case ValidTextureOverload::kLoad1dF32:
|
||||||
|
return R"(texture_tint_0.Load(int2(1, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad1dU32:
|
||||||
|
return R"(texture_tint_0.Load(int2(1, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad1dI32:
|
||||||
|
return R"(texture_tint_0.Load(int2(1, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad1dArrayF32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad1dArrayU32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad1dArrayI32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad2dF32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad2dU32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad2dI32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad2dLevelF32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0), 3))";
|
||||||
|
case ValidTextureOverload::kLoad2dLevelU32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0), 3))";
|
||||||
|
case ValidTextureOverload::kLoad2dLevelI32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0), 3))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayF32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayU32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayI32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayLevelF32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0), 4))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayLevelU32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0), 4))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayLevelI32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0), 4))";
|
||||||
|
case ValidTextureOverload::kLoad3dF32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad3dU32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad3dI32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0)))";
|
||||||
|
case ValidTextureOverload::kLoad3dLevelF32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0), 4))";
|
||||||
|
case ValidTextureOverload::kLoad3dLevelU32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0), 4))";
|
||||||
|
case ValidTextureOverload::kLoad3dLevelI32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0), 4))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dF32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0), 3))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dU32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0), 3))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dI32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0), 3))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dArrayF32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0), 4))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dArrayU32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0), 4))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dArrayI32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0), 4))";
|
||||||
|
case ValidTextureOverload::kLoadDepth2dF32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0)))";
|
||||||
|
case ValidTextureOverload::kLoadDepth2dLevelF32:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 0), 3))";
|
||||||
|
case ValidTextureOverload::kLoadDepth2dArrayF32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0)))";
|
||||||
|
case ValidTextureOverload::kLoadDepth2dArrayLevelF32:
|
||||||
|
return R"(texture_tint_0.Load(int4(1, 2, 3, 0), 4))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO1dRgba32float:
|
||||||
|
return R"(texture_tint_0.Load(1))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO1dArrayRgba32float:
|
||||||
|
return R"(texture_tint_0.Load(int2(1, 2)))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba8unorm:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba8snorm:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba8uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba8sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba16uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba16sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba16float:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dR32uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dR32sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dR32float:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRg32uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRg32sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRg32float:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba32uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba32sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba32float:
|
||||||
|
return R"(texture_tint_0.Load(int2(1, 2)))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dArrayRgba32float:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 3)))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO3dRgba32float:
|
||||||
|
return R"(texture_tint_0.Load(int3(1, 2, 3)))";
|
||||||
}
|
}
|
||||||
return "<unmatched texture overload>";
|
return "<unmatched texture overload>";
|
||||||
} // LINT - Ignore the length of this function
|
} // NOLINT - Ignore the length of this function
|
||||||
|
|
||||||
class HlslGeneratorIntrinsicTextureTest
|
class HlslGeneratorIntrinsicTextureTest
|
||||||
: public ast::BuilderWithModule,
|
: public ast::BuilderWithModule,
|
||||||
|
@ -165,38 +259,13 @@ class HlslGeneratorIntrinsicTextureTest
|
||||||
TEST_P(HlslGeneratorIntrinsicTextureTest, Call) {
|
TEST_P(HlslGeneratorIntrinsicTextureTest, Call) {
|
||||||
auto param = GetParam();
|
auto param = GetParam();
|
||||||
|
|
||||||
ast::type::Type* datatype = nullptr;
|
param.buildTextureVariable(this);
|
||||||
switch (param.texture_data_type) {
|
param.buildSamplerVariable(this);
|
||||||
case ast::intrinsic::test::TextureDataType::kF32:
|
|
||||||
datatype = ty.f32;
|
|
||||||
break;
|
|
||||||
case ast::intrinsic::test::TextureDataType::kU32:
|
|
||||||
datatype = ty.u32;
|
|
||||||
break;
|
|
||||||
case ast::intrinsic::test::TextureDataType::kI32:
|
|
||||||
datatype = ty.i32;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ast::type::Sampler sampler_type{param.sampler_kind};
|
|
||||||
switch (param.texture_kind) {
|
|
||||||
case ast::intrinsic::test::TextureKind::kRegular:
|
|
||||||
Var("texture", ast::StorageClass::kNone,
|
|
||||||
mod->create<ast::type::SampledTexture>(param.texture_dimension,
|
|
||||||
datatype));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ast::intrinsic::test::TextureKind::kDepth:
|
|
||||||
Var("texture", ast::StorageClass::kNone,
|
|
||||||
mod->create<ast::type::DepthTexture>(param.texture_dimension));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Var("sampler", ast::StorageClass::kNone, &sampler_type);
|
|
||||||
|
|
||||||
ast::CallExpression call{Expr(param.function), param.args(this)};
|
ast::CallExpression call{Expr(param.function), param.args(this)};
|
||||||
|
|
||||||
EXPECT_TRUE(td.DetermineResultType(&call)) << td.error();
|
ASSERT_TRUE(td.Determine()) << td.error();
|
||||||
|
ASSERT_TRUE(td.DetermineResultType(&call)) << td.error();
|
||||||
|
|
||||||
ASSERT_TRUE(gen.EmitExpression(pre, out, &call)) << gen.error();
|
ASSERT_TRUE(gen.EmitExpression(pre, out, &call)) << gen.error();
|
||||||
|
|
||||||
|
|
|
@ -663,6 +663,8 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
|
||||||
if (!EmitExpression(params[pidx.texture]))
|
if (!EmitExpression(params[pidx.texture]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
bool lod_param_is_named = true;
|
||||||
|
|
||||||
switch (ident->intrinsic()) {
|
switch (ident->intrinsic()) {
|
||||||
case ast::Intrinsic::kTextureSample:
|
case ast::Intrinsic::kTextureSample:
|
||||||
case ast::Intrinsic::kTextureSampleBias:
|
case ast::Intrinsic::kTextureSampleBias:
|
||||||
|
@ -673,37 +675,59 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
|
||||||
case ast::Intrinsic::kTextureSampleCompare:
|
case ast::Intrinsic::kTextureSampleCompare:
|
||||||
out_ << ".sample_compare(";
|
out_ << ".sample_compare(";
|
||||||
break;
|
break;
|
||||||
|
case ast::Intrinsic::kTextureLoad:
|
||||||
|
out_ << ".read(";
|
||||||
|
lod_param_is_named = false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error_ = "Internal compiler error: Unhandled texture intrinsic '" +
|
error_ = "Internal compiler error: Unhandled texture intrinsic '" +
|
||||||
ident->name() + "'";
|
ident->name() + "'";
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EmitExpression(params[pidx.sampler])) {
|
bool first_arg = true;
|
||||||
return false;
|
auto maybe_write_comma = [&] {
|
||||||
}
|
if (!first_arg) {
|
||||||
|
|
||||||
for (auto idx : {pidx.coords, pidx.array_index, pidx.depth_ref}) {
|
|
||||||
if (idx != kNotUsed) {
|
|
||||||
out_ << ", ";
|
out_ << ", ";
|
||||||
|
}
|
||||||
|
first_arg = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pidx.sampler != kNotUsed) {
|
||||||
|
if (!EmitExpression(params[pidx.sampler])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
first_arg = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto idx :
|
||||||
|
{pidx.coords, pidx.array_index, pidx.depth_ref, pidx.sample_index}) {
|
||||||
|
if (idx != kNotUsed) {
|
||||||
|
maybe_write_comma();
|
||||||
if (!EmitExpression(params[idx]))
|
if (!EmitExpression(params[idx]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pidx.bias != kNotUsed) {
|
if (pidx.bias != kNotUsed) {
|
||||||
out_ << ", bias(";
|
maybe_write_comma();
|
||||||
|
out_ << "bias(";
|
||||||
if (!EmitExpression(params[pidx.bias])) {
|
if (!EmitExpression(params[pidx.bias])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out_ << ")";
|
out_ << ")";
|
||||||
}
|
}
|
||||||
if (pidx.level != kNotUsed) {
|
if (pidx.level != kNotUsed) {
|
||||||
out_ << ", level(";
|
maybe_write_comma();
|
||||||
|
if (lod_param_is_named) {
|
||||||
|
out_ << "level(";
|
||||||
|
}
|
||||||
if (!EmitExpression(params[pidx.level])) {
|
if (!EmitExpression(params[pidx.level])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out_ << ")";
|
if (lod_param_is_named) {
|
||||||
|
out_ << ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pidx.ddx != kNotUsed) {
|
if (pidx.ddx != kNotUsed) {
|
||||||
auto dim = params[pidx.texture]
|
auto dim = params[pidx.texture]
|
||||||
|
@ -714,14 +738,17 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
|
||||||
switch (dim) {
|
switch (dim) {
|
||||||
case ast::type::TextureDimension::k2d:
|
case ast::type::TextureDimension::k2d:
|
||||||
case ast::type::TextureDimension::k2dArray:
|
case ast::type::TextureDimension::k2dArray:
|
||||||
out_ << ", gradient2d(";
|
maybe_write_comma();
|
||||||
|
out_ << "gradient2d(";
|
||||||
break;
|
break;
|
||||||
case ast::type::TextureDimension::k3d:
|
case ast::type::TextureDimension::k3d:
|
||||||
out_ << ", gradient3d(";
|
maybe_write_comma();
|
||||||
|
out_ << "gradient3d(";
|
||||||
break;
|
break;
|
||||||
case ast::type::TextureDimension::kCube:
|
case ast::type::TextureDimension::kCube:
|
||||||
case ast::type::TextureDimension::kCubeArray:
|
case ast::type::TextureDimension::kCubeArray:
|
||||||
out_ << ", gradientcube(";
|
maybe_write_comma();
|
||||||
|
out_ << "gradientcube(";
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
std::stringstream err;
|
std::stringstream err;
|
||||||
|
@ -741,7 +768,7 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pidx.offset != kNotUsed) {
|
if (pidx.offset != kNotUsed) {
|
||||||
out_ << ", ";
|
maybe_write_comma();
|
||||||
if (!EmitExpression(params[pidx.offset])) {
|
if (!EmitExpression(params[pidx.offset])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "src/ast/builder.h"
|
#include "src/ast/builder.h"
|
||||||
#include "src/ast/intrinsic_texture_helper_test.h"
|
#include "src/ast/intrinsic_texture_helper_test.h"
|
||||||
#include "src/ast/type/depth_texture_type.h"
|
#include "src/ast/type/depth_texture_type.h"
|
||||||
|
#include "src/ast/type/multisampled_texture_type.h"
|
||||||
#include "src/ast/type/sampled_texture_type.h"
|
#include "src/ast/type/sampled_texture_type.h"
|
||||||
#include "src/type_determiner.h"
|
#include "src/type_determiner.h"
|
||||||
#include "src/writer/msl/generator_impl.h"
|
#include "src/writer/msl/generator_impl.h"
|
||||||
|
@ -135,9 +136,102 @@ std::string expected_texture_overload(
|
||||||
return R"(texture_tint_0.sample_compare(sampler_tint_0, float3(1.0f, 2.0f, 3.0f), 4.0f))";
|
return R"(texture_tint_0.sample_compare(sampler_tint_0, float3(1.0f, 2.0f, 3.0f), 4.0f))";
|
||||||
case ValidTextureOverload::kSampleGradDepthCubeArrayF32:
|
case ValidTextureOverload::kSampleGradDepthCubeArrayF32:
|
||||||
return R"(texture_tint_0.sample_compare(sampler_tint_0, float3(1.0f, 2.0f, 3.0f), 4, 5.0f))";
|
return R"(texture_tint_0.sample_compare(sampler_tint_0, float3(1.0f, 2.0f, 3.0f), 4, 5.0f))";
|
||||||
|
case ValidTextureOverload::kLoad1dF32:
|
||||||
|
return R"(texture_tint_0.read(1))";
|
||||||
|
case ValidTextureOverload::kLoad1dU32:
|
||||||
|
return R"(texture_tint_0.read(1))";
|
||||||
|
case ValidTextureOverload::kLoad1dI32:
|
||||||
|
return R"(texture_tint_0.read(1))";
|
||||||
|
case ValidTextureOverload::kLoad1dArrayF32:
|
||||||
|
return R"(texture_tint_0.read(1, 2))";
|
||||||
|
case ValidTextureOverload::kLoad1dArrayU32:
|
||||||
|
return R"(texture_tint_0.read(1, 2))";
|
||||||
|
case ValidTextureOverload::kLoad1dArrayI32:
|
||||||
|
return R"(texture_tint_0.read(1, 2))";
|
||||||
|
case ValidTextureOverload::kLoad2dF32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2)))";
|
||||||
|
case ValidTextureOverload::kLoad2dU32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2)))";
|
||||||
|
case ValidTextureOverload::kLoad2dI32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2)))";
|
||||||
|
case ValidTextureOverload::kLoad2dLevelF32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kLoad2dLevelU32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kLoad2dLevelI32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayF32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayU32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayI32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayLevelF32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3, 4))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayLevelU32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3, 4))";
|
||||||
|
case ValidTextureOverload::kLoad2dArrayLevelI32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3, 4))";
|
||||||
|
case ValidTextureOverload::kLoad3dF32:
|
||||||
|
return R"(texture_tint_0.read(int3(1, 2, 3)))";
|
||||||
|
case ValidTextureOverload::kLoad3dU32:
|
||||||
|
return R"(texture_tint_0.read(int3(1, 2, 3)))";
|
||||||
|
case ValidTextureOverload::kLoad3dI32:
|
||||||
|
return R"(texture_tint_0.read(int3(1, 2, 3)))";
|
||||||
|
case ValidTextureOverload::kLoad3dLevelF32:
|
||||||
|
return R"(texture_tint_0.read(int3(1, 2, 3), 4))";
|
||||||
|
case ValidTextureOverload::kLoad3dLevelU32:
|
||||||
|
return R"(texture_tint_0.read(int3(1, 2, 3), 4))";
|
||||||
|
case ValidTextureOverload::kLoad3dLevelI32:
|
||||||
|
return R"(texture_tint_0.read(int3(1, 2, 3), 4))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dF32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dU32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dI32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dArrayF32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3, 4))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dArrayU32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3, 4))";
|
||||||
|
case ValidTextureOverload::kLoadMultisampled2dArrayI32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3, 4))";
|
||||||
|
case ValidTextureOverload::kLoadDepth2dF32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2)))";
|
||||||
|
case ValidTextureOverload::kLoadDepth2dLevelF32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kLoadDepth2dArrayF32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kLoadDepth2dArrayLevelF32:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3, 4))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO1dRgba32float:
|
||||||
|
return R"(texture_tint_0.read(1))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO1dArrayRgba32float:
|
||||||
|
return R"(texture_tint_0.read(1, 2))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba8unorm:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba8snorm:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba8uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba8sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba16uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba16sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba16float:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dR32uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dR32sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dR32float:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRg32uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRg32sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRg32float:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba32uint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba32sint:
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dRgba32float:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2)))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO2dArrayRgba32float:
|
||||||
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kLoadStorageRO3dRgba32float:
|
||||||
|
return R"(texture_tint_0.read(int3(1, 2, 3)))";
|
||||||
}
|
}
|
||||||
return "<unmatched texture overload>";
|
return "<unmatched texture overload>";
|
||||||
} // LINT - Ignore the length of this function
|
} // NOLINT - Ignore the length of this function
|
||||||
|
|
||||||
class MslGeneratorIntrinsicTextureTest
|
class MslGeneratorIntrinsicTextureTest
|
||||||
: public ast::BuilderWithModule,
|
: public ast::BuilderWithModule,
|
||||||
|
@ -156,38 +250,13 @@ class MslGeneratorIntrinsicTextureTest
|
||||||
TEST_P(MslGeneratorIntrinsicTextureTest, Call) {
|
TEST_P(MslGeneratorIntrinsicTextureTest, Call) {
|
||||||
auto param = GetParam();
|
auto param = GetParam();
|
||||||
|
|
||||||
ast::type::Type* datatype = nullptr;
|
param.buildTextureVariable(this);
|
||||||
switch (param.texture_data_type) {
|
param.buildSamplerVariable(this);
|
||||||
case ast::intrinsic::test::TextureDataType::kF32:
|
|
||||||
datatype = ty.f32;
|
|
||||||
break;
|
|
||||||
case ast::intrinsic::test::TextureDataType::kU32:
|
|
||||||
datatype = ty.u32;
|
|
||||||
break;
|
|
||||||
case ast::intrinsic::test::TextureDataType::kI32:
|
|
||||||
datatype = ty.i32;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ast::type::Sampler sampler_type{param.sampler_kind};
|
|
||||||
switch (param.texture_kind) {
|
|
||||||
case ast::intrinsic::test::TextureKind::kRegular:
|
|
||||||
Var("texture", ast::StorageClass::kNone,
|
|
||||||
mod->create<ast::type::SampledTexture>(param.texture_dimension,
|
|
||||||
datatype));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ast::intrinsic::test::TextureKind::kDepth:
|
|
||||||
Var("texture", ast::StorageClass::kNone,
|
|
||||||
mod->create<ast::type::DepthTexture>(param.texture_dimension));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Var("sampler", ast::StorageClass::kNone, &sampler_type);
|
|
||||||
|
|
||||||
ast::CallExpression call{Expr(param.function), param.args(this)};
|
ast::CallExpression call{Expr(param.function), param.args(this)};
|
||||||
|
|
||||||
EXPECT_TRUE(td.DetermineResultType(&call)) << td.error();
|
ASSERT_TRUE(td.Determine()) << td.error();
|
||||||
|
ASSERT_TRUE(td.DetermineResultType(&call)) << td.error();
|
||||||
|
|
||||||
ASSERT_TRUE(gen.EmitExpression(&call)) << gen.error();
|
ASSERT_TRUE(gen.EmitExpression(&call)) << gen.error();
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "src/writer/spirv/builder.h"
|
#include "src/writer/spirv/builder.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -72,7 +73,7 @@
|
||||||
#include "src/ast/uint_literal.h"
|
#include "src/ast/uint_literal.h"
|
||||||
#include "src/ast/unary_op_expression.h"
|
#include "src/ast/unary_op_expression.h"
|
||||||
#include "src/ast/variable_decl_statement.h"
|
#include "src/ast/variable_decl_statement.h"
|
||||||
#include "src/writer/pack_coord_arrayidx.h"
|
#include "src/writer/append_vector.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace writer {
|
namespace writer {
|
||||||
|
@ -1946,25 +1947,50 @@ void Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
||||||
spirv_params.emplace_back(std::move(result_id)); // result id
|
spirv_params.emplace_back(std::move(result_id)); // result id
|
||||||
|
|
||||||
// Extra image operands, appended to spirv_params.
|
// Extra image operands, appended to spirv_params.
|
||||||
uint32_t spirv_operand_mask = 0;
|
struct ImageOperand {
|
||||||
OperandList spirv_operands;
|
SpvImageOperandsMask mask;
|
||||||
spirv_operands.reserve(4); // Enough to fit most parameter lists
|
tint::writer::spirv::Operand operand;
|
||||||
|
};
|
||||||
|
std::vector<ImageOperand> image_operands;
|
||||||
|
image_operands.reserve(4); // Enough to fit most parameter lists
|
||||||
|
|
||||||
|
auto append_coords_to_spirv_params = [&] {
|
||||||
|
if (pidx.array_index != kNotUsed) {
|
||||||
|
// Array index needs to be appended to the coordinates.
|
||||||
|
auto* param_coords = call->params()[pidx.coords];
|
||||||
|
auto* param_array_index = call->params()[pidx.array_index];
|
||||||
|
|
||||||
|
if (!AppendVector(param_coords, param_array_index,
|
||||||
|
[&](ast::TypeConstructorExpression* packed) {
|
||||||
|
auto param =
|
||||||
|
GenerateTypeConstructorExpression(packed, false);
|
||||||
|
if (param == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
spirv_params.emplace_back(Operand::Int(param));
|
||||||
|
return true;
|
||||||
|
})) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spirv_params.emplace_back(gen_param(pidx.coords)); // coordinates
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (ident->intrinsic() == ast::Intrinsic::kTextureLoad) {
|
if (ident->intrinsic() == ast::Intrinsic::kTextureLoad) {
|
||||||
op = texture_type->Is<ast::type::StorageTexture>() ? spv::Op::OpImageRead
|
op = texture_type->Is<ast::type::StorageTexture>() ? spv::Op::OpImageRead
|
||||||
: spv::Op::OpImageFetch;
|
: spv::Op::OpImageFetch;
|
||||||
spirv_params.emplace_back(gen_param(pidx.texture));
|
spirv_params.emplace_back(gen_param(pidx.texture));
|
||||||
spirv_params.emplace_back(gen_param(pidx.coords));
|
append_coords_to_spirv_params();
|
||||||
|
|
||||||
// TODO(dsinclair): Remove the LOD param from textureLoad on storage
|
|
||||||
// textures when https://github.com/gpuweb/gpuweb/pull/1032 gets merged.
|
|
||||||
if (pidx.level != kNotUsed) {
|
if (pidx.level != kNotUsed) {
|
||||||
if (texture_type->Is<ast::type::MultisampledTexture>()) {
|
image_operands.emplace_back(
|
||||||
spirv_operand_mask |= SpvImageOperandsSampleMask;
|
ImageOperand{SpvImageOperandsLodMask, gen_param(pidx.level)});
|
||||||
} else {
|
}
|
||||||
spirv_operand_mask |= SpvImageOperandsLodMask;
|
|
||||||
}
|
if (pidx.sample_index != kNotUsed) {
|
||||||
spirv_operands.emplace_back(gen_param(pidx.level));
|
image_operands.emplace_back(ImageOperand{SpvImageOperandsSampleMask,
|
||||||
|
gen_param(pidx.sample_index)});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(pidx.sampler != kNotUsed);
|
assert(pidx.sampler != kNotUsed);
|
||||||
|
@ -1976,27 +2002,7 @@ void Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
||||||
|
|
||||||
// Populate the spirv_params with the common parameters
|
// Populate the spirv_params with the common parameters
|
||||||
spirv_params.emplace_back(Operand::Int(sampled_image)); // sampled image
|
spirv_params.emplace_back(Operand::Int(sampled_image)); // sampled image
|
||||||
|
append_coords_to_spirv_params();
|
||||||
if (pidx.array_index != kNotUsed) {
|
|
||||||
// Array index needs to be appended to the coordinates.
|
|
||||||
auto* param_coords = call->params()[pidx.coords];
|
|
||||||
auto* param_array_index = call->params()[pidx.array_index];
|
|
||||||
|
|
||||||
if (!PackCoordAndArrayIndex(
|
|
||||||
param_coords, param_array_index,
|
|
||||||
[&](ast::TypeConstructorExpression* packed) {
|
|
||||||
auto param = GenerateTypeConstructorExpression(packed, false);
|
|
||||||
if (param == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
spirv_params.emplace_back(Operand::Int(param));
|
|
||||||
return true;
|
|
||||||
})) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
spirv_params.emplace_back(gen_param(pidx.coords)); // coordinates
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ident->intrinsic()) {
|
switch (ident->intrinsic()) {
|
||||||
case ast::Intrinsic::kTextureSample: {
|
case ast::Intrinsic::kTextureSample: {
|
||||||
|
@ -2006,24 +2012,25 @@ void Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
||||||
case ast::Intrinsic::kTextureSampleBias: {
|
case ast::Intrinsic::kTextureSampleBias: {
|
||||||
op = spv::Op::OpImageSampleImplicitLod;
|
op = spv::Op::OpImageSampleImplicitLod;
|
||||||
assert(pidx.bias != kNotUsed);
|
assert(pidx.bias != kNotUsed);
|
||||||
spirv_operand_mask |= SpvImageOperandsBiasMask;
|
image_operands.emplace_back(
|
||||||
spirv_operands.emplace_back(gen_param(pidx.bias));
|
ImageOperand{SpvImageOperandsBiasMask, gen_param(pidx.bias)});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ast::Intrinsic::kTextureSampleLevel: {
|
case ast::Intrinsic::kTextureSampleLevel: {
|
||||||
op = spv::Op::OpImageSampleExplicitLod;
|
op = spv::Op::OpImageSampleExplicitLod;
|
||||||
assert(pidx.level != kNotUsed);
|
assert(pidx.level != kNotUsed);
|
||||||
spirv_operand_mask |= SpvImageOperandsLodMask;
|
image_operands.emplace_back(
|
||||||
spirv_operands.emplace_back(gen_param(pidx.level));
|
ImageOperand{SpvImageOperandsLodMask, gen_param(pidx.level)});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ast::Intrinsic::kTextureSampleGrad: {
|
case ast::Intrinsic::kTextureSampleGrad: {
|
||||||
op = spv::Op::OpImageSampleExplicitLod;
|
op = spv::Op::OpImageSampleExplicitLod;
|
||||||
assert(pidx.ddx != kNotUsed);
|
assert(pidx.ddx != kNotUsed);
|
||||||
assert(pidx.ddy != kNotUsed);
|
assert(pidx.ddy != kNotUsed);
|
||||||
spirv_operand_mask |= SpvImageOperandsGradMask;
|
image_operands.emplace_back(
|
||||||
spirv_operands.emplace_back(gen_param(pidx.ddx));
|
ImageOperand{SpvImageOperandsGradMask, gen_param(pidx.ddx)});
|
||||||
spirv_operands.emplace_back(gen_param(pidx.ddy));
|
image_operands.emplace_back(
|
||||||
|
ImageOperand{SpvImageOperandsGradMask, gen_param(pidx.ddy)});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ast::Intrinsic::kTextureSampleCompare: {
|
case ast::Intrinsic::kTextureSampleCompare: {
|
||||||
|
@ -2031,11 +2038,11 @@ void Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
||||||
assert(pidx.depth_ref != kNotUsed);
|
assert(pidx.depth_ref != kNotUsed);
|
||||||
spirv_params.emplace_back(gen_param(pidx.depth_ref));
|
spirv_params.emplace_back(gen_param(pidx.depth_ref));
|
||||||
|
|
||||||
spirv_operand_mask |= SpvImageOperandsLodMask;
|
|
||||||
ast::type::F32 f32;
|
ast::type::F32 f32;
|
||||||
ast::FloatLiteral float_0(&f32, 0.0);
|
ast::FloatLiteral float_0(&f32, 0.0);
|
||||||
spirv_operands.emplace_back(
|
image_operands.emplace_back(ImageOperand{
|
||||||
Operand::Int(GenerateLiteralIfNeeded(nullptr, &float_0)));
|
SpvImageOperandsLodMask,
|
||||||
|
Operand::Int(GenerateLiteralIfNeeded(nullptr, &float_0))});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -2044,16 +2051,21 @@ void Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pidx.offset != kNotUsed) {
|
if (pidx.offset != kNotUsed) {
|
||||||
spirv_operand_mask |= SpvImageOperandsOffsetMask;
|
image_operands.emplace_back(
|
||||||
spirv_operands.emplace_back(gen_param(pidx.offset));
|
ImageOperand{SpvImageOperandsOffsetMask, gen_param(pidx.offset)});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spirv_operand_mask != 0) {
|
if (!image_operands.empty()) {
|
||||||
// Note: Order of operands is based on SpvImageXXXOperands value -
|
std::sort(image_operands.begin(), image_operands.end(),
|
||||||
// smaller-numbered SpvImageXXXOperands bits appear first.
|
[](auto& a, auto& b) { return a.mask < b.mask; });
|
||||||
spirv_params.emplace_back(Operand::Int(spirv_operand_mask));
|
uint32_t mask = 0;
|
||||||
spirv_params.insert(std::end(spirv_params), std::begin(spirv_operands),
|
for (auto& image_operand : image_operands) {
|
||||||
std::end(spirv_operands));
|
mask |= image_operand.mask;
|
||||||
|
}
|
||||||
|
spirv_params.emplace_back(Operand::Int(mask));
|
||||||
|
for (auto& image_operand : image_operands) {
|
||||||
|
spirv_params.emplace_back(image_operand.operand);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op == spv::Op::OpNop) {
|
if (op == spv::Op::OpNop) {
|
||||||
|
@ -2143,8 +2155,8 @@ bool Builder::GenerateConditionalBlock(
|
||||||
auto true_block = result_op();
|
auto true_block = result_op();
|
||||||
auto true_block_id = true_block.to_i();
|
auto true_block_id = true_block.to_i();
|
||||||
|
|
||||||
// if there are no more else statements we branch on false to the merge block
|
// if there are no more else statements we branch on false to the merge
|
||||||
// otherwise we branch to the false block
|
// block otherwise we branch to the false block
|
||||||
auto false_block_id =
|
auto false_block_id =
|
||||||
cur_else_idx < else_stmts.size() ? next_id() : merge_block_id;
|
cur_else_idx < else_stmts.size() ? next_id() : merge_block_id;
|
||||||
|
|
||||||
|
@ -2644,12 +2656,12 @@ bool Builder::GenerateStructType(ast::type::Struct* struct_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're attaching the access control to the members of the struct instead
|
// We're attaching the access control to the members of the struct instead
|
||||||
// of to the variable. The reason we do this is that WGSL models the access
|
// of to the variable. The reason we do this is that WGSL models the
|
||||||
// as part of the type. If we attach to the variable, it's no longer part
|
// access as part of the type. If we attach to the variable, it's no
|
||||||
// of the type in the SPIR-V backend, but part of the variable. This differs
|
// longer part of the type in the SPIR-V backend, but part of the
|
||||||
// from the modeling and other backends. Attaching to the struct members
|
// variable. This differs from the modeling and other backends. Attaching
|
||||||
// means the access control stays part of the type where it logically makes
|
// to the struct members means the access control stays part of the type
|
||||||
// the most sense.
|
// where it logically makes the most sense.
|
||||||
if (access_control == ast::AccessControl::kReadOnly) {
|
if (access_control == ast::AccessControl::kReadOnly) {
|
||||||
push_annot(spv::Op::OpMemberDecorate,
|
push_annot(spv::Op::OpMemberDecorate,
|
||||||
{Operand::Int(struct_id), Operand::Int(i),
|
{Operand::Int(struct_id), Operand::Int(i),
|
||||||
|
|
|
@ -413,173 +413,6 @@ TEST_F(IntrinsicBuilderTest, Call_Select) {
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Storage_RO_1d) {
|
|
||||||
ast::type::StorageTexture s(ast::type::TextureDimension::k1d,
|
|
||||||
ast::AccessControl::kReadOnly,
|
|
||||||
ast::type::ImageFormat::kR16Float);
|
|
||||||
|
|
||||||
ASSERT_TRUE(td.DetermineStorageTextureSubtype(&s)) << td.error();
|
|
||||||
|
|
||||||
b.push_function(Function{});
|
|
||||||
|
|
||||||
auto* tex = Var("texture", ast::StorageClass::kNone, &s);
|
|
||||||
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
|
|
||||||
|
|
||||||
auto expr = Call("textureLoad", "texture", 1.0f, 2);
|
|
||||||
|
|
||||||
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
|
|
||||||
EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error();
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()),
|
|
||||||
R"(%4 = OpTypeFloat 32
|
|
||||||
%3 = OpTypeImage %4 1D 0 0 0 2 R16f
|
|
||||||
%2 = OpTypePointer Private %3
|
|
||||||
%1 = OpVariable %2 Private
|
|
||||||
%6 = OpTypeVector %4 4
|
|
||||||
%8 = OpConstant %4 1
|
|
||||||
%9 = OpTypeInt 32 1
|
|
||||||
%10 = OpConstant %9 2
|
|
||||||
)");
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%7 = OpLoad %3 %1
|
|
||||||
%5 = OpImageRead %6 %7 %8 Lod %10
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Storage_RO_2d) {
|
|
||||||
ast::type::StorageTexture s(ast::type::TextureDimension::k2d,
|
|
||||||
ast::AccessControl::kReadOnly,
|
|
||||||
ast::type::ImageFormat::kR16Float);
|
|
||||||
|
|
||||||
ASSERT_TRUE(td.DetermineStorageTextureSubtype(&s)) << td.error();
|
|
||||||
|
|
||||||
b.push_function(Function{});
|
|
||||||
|
|
||||||
auto* tex = Var("texture", ast::StorageClass::kNone, &s);
|
|
||||||
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
|
|
||||||
|
|
||||||
auto expr = Call("textureLoad", "texture", vec2<f32>(1.0f, 2.0f), 2);
|
|
||||||
|
|
||||||
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
|
|
||||||
EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error();
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()),
|
|
||||||
R"(%4 = OpTypeFloat 32
|
|
||||||
%3 = OpTypeImage %4 2D 0 0 0 2 R16f
|
|
||||||
%2 = OpTypePointer Private %3
|
|
||||||
%1 = OpVariable %2 Private
|
|
||||||
%6 = OpTypeVector %4 4
|
|
||||||
%8 = OpTypeVector %4 2
|
|
||||||
%9 = OpConstant %4 1
|
|
||||||
%10 = OpConstant %4 2
|
|
||||||
%11 = OpConstantComposite %8 %9 %10
|
|
||||||
%12 = OpTypeInt 32 1
|
|
||||||
%13 = OpConstant %12 2
|
|
||||||
)");
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%7 = OpLoad %3 %1
|
|
||||||
%5 = OpImageRead %6 %7 %11 Lod %13
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Sampled_1d) {
|
|
||||||
ast::type::SampledTexture s(ast::type::TextureDimension::k1d, ty.f32);
|
|
||||||
|
|
||||||
b.push_function(Function{});
|
|
||||||
|
|
||||||
auto* tex = Var("texture", ast::StorageClass::kNone, &s);
|
|
||||||
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
|
|
||||||
|
|
||||||
auto expr = Call("textureLoad", "texture", 1.0f, 2);
|
|
||||||
|
|
||||||
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
|
|
||||||
EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error();
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()),
|
|
||||||
R"(%4 = OpTypeFloat 32
|
|
||||||
%3 = OpTypeImage %4 1D 0 0 0 1 Unknown
|
|
||||||
%2 = OpTypePointer Private %3
|
|
||||||
%1 = OpVariable %2 Private
|
|
||||||
%6 = OpTypeVector %4 4
|
|
||||||
%8 = OpConstant %4 1
|
|
||||||
%9 = OpTypeInt 32 1
|
|
||||||
%10 = OpConstant %9 2
|
|
||||||
)");
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%7 = OpLoad %3 %1
|
|
||||||
%5 = OpImageFetch %6 %7 %8 Lod %10
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Sampled_2d) {
|
|
||||||
ast::type::SampledTexture s(ast::type::TextureDimension::k2d, ty.f32);
|
|
||||||
|
|
||||||
b.push_function(Function{});
|
|
||||||
|
|
||||||
auto* tex = Var("texture", ast::StorageClass::kNone, &s);
|
|
||||||
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
|
|
||||||
|
|
||||||
auto expr = Call("textureLoad", "texture", vec2<f32>(1.0f, 2.0f), 2);
|
|
||||||
|
|
||||||
EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
|
|
||||||
EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error();
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()),
|
|
||||||
R"(%4 = OpTypeFloat 32
|
|
||||||
%3 = OpTypeImage %4 2D 0 0 0 1 Unknown
|
|
||||||
%2 = OpTypePointer Private %3
|
|
||||||
%1 = OpVariable %2 Private
|
|
||||||
%6 = OpTypeVector %4 4
|
|
||||||
%8 = OpTypeVector %4 2
|
|
||||||
%9 = OpConstant %4 1
|
|
||||||
%10 = OpConstant %4 2
|
|
||||||
%11 = OpConstantComposite %8 %9 %10
|
|
||||||
%12 = OpTypeInt 32 1
|
|
||||||
%13 = OpConstant %12 2
|
|
||||||
)");
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%7 = OpLoad %3 %1
|
|
||||||
%5 = OpImageFetch %6 %7 %11 Lod %13
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(IntrinsicBuilderTest, Call_TextureLoad_Multisampled_2d) {
|
|
||||||
ast::type::MultisampledTexture s(ast::type::TextureDimension::k2d, ty.f32);
|
|
||||||
|
|
||||||
b.push_function(Function{});
|
|
||||||
|
|
||||||
auto* tex = Var("texture", ast::StorageClass::kNone, &s);
|
|
||||||
ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
|
|
||||||
|
|
||||||
auto expr = Call("textureLoad", "texture", vec2<f32>(1.0f, 2.0f), 2);
|
|
||||||
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
|
|
||||||
EXPECT_EQ(b.GenerateExpression(&expr), 5u) << b.error();
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()),
|
|
||||||
R"(%4 = OpTypeFloat 32
|
|
||||||
%3 = OpTypeImage %4 2D 0 0 1 1 Unknown
|
|
||||||
%2 = OpTypePointer Private %3
|
|
||||||
%1 = OpVariable %2 Private
|
|
||||||
%6 = OpTypeVector %4 4
|
|
||||||
%8 = OpTypeVector %4 2
|
|
||||||
%9 = OpConstant %4 1
|
|
||||||
%10 = OpConstant %4 2
|
|
||||||
%11 = OpConstantComposite %8 %9 %10
|
|
||||||
%12 = OpTypeInt 32 1
|
|
||||||
%13 = OpConstant %12 2
|
|
||||||
)");
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%7 = OpLoad %3 %1
|
|
||||||
%5 = OpImageFetch %6 %7 %11 Sample %13
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
// This tests that we do not push OpTypeSampledImage and float_0 type twice.
|
// This tests that we do not push OpTypeSampledImage and float_0 type twice.
|
||||||
TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) {
|
TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) {
|
||||||
ast::type::Sampler s(ast::type::SamplerKind::kComparisonSampler);
|
ast::type::Sampler s(ast::type::SamplerKind::kComparisonSampler);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue