Implement textureSample builtins
Handle wsgl parsing and spirv writing of: textureSample(), textureSampleBias(), textureSampleLevel(), textureSampleGrad(), textureSampleCompare() Handle the different signature for array texture types. Includes offset overloads. Change-Id: I6802d97cd9a7083f12439b32725b9a4b666b8c63 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32985 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: David Neto <dneto@google.com> Reviewed-by: Ryan Harrison <rharrison@chromium.org> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
2f4096b0d7
commit
3ea3c997b5
2
BUILD.gn
2
BUILD.gn
|
@ -755,6 +755,8 @@ source_set("tint_unittests_core_src") {
|
|||
"src/ast/function_test.cc",
|
||||
"src/ast/identifier_expression_test.cc",
|
||||
"src/ast/if_statement_test.cc",
|
||||
"src/ast/intrinsic_texture_helper_test.cc",
|
||||
"src/ast/intrinsic_texture_helper_test.h",
|
||||
"src/ast/int_literal_test.cc",
|
||||
"src/ast/location_decoration_test.cc",
|
||||
"src/ast/loop_statement_test.cc",
|
||||
|
|
|
@ -364,6 +364,8 @@ set(TINT_TEST_SRCS
|
|||
ast/function_test.cc
|
||||
ast/identifier_expression_test.cc
|
||||
ast/if_statement_test.cc
|
||||
ast/intrinsic_texture_helper_test.cc
|
||||
ast/intrinsic_texture_helper_test.h
|
||||
ast/int_literal_test.cc
|
||||
ast/location_decoration_test.cc
|
||||
ast/loop_statement_test.cc
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
#ifndef SRC_AST_IDENTIFIER_EXPRESSION_H_
|
||||
#define SRC_AST_IDENTIFIER_EXPRESSION_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "src/ast/expression.h"
|
||||
#include "src/ast/intrinsic.h"
|
||||
|
@ -45,6 +47,17 @@ class IdentifierExpression : public Expression {
|
|||
void set_intrinsic(Intrinsic i) { intrinsic_ = i; }
|
||||
/// @returns the intrinsic this identifier represents
|
||||
Intrinsic intrinsic() const { return intrinsic_; }
|
||||
|
||||
/// Sets the intrinsic signature
|
||||
/// @param s the intrinsic signature to set
|
||||
void set_intrinsic_signature(std::unique_ptr<intrinsic::Signature> s) {
|
||||
intrinsic_sig_ = std::move(s);
|
||||
}
|
||||
/// @returns the intrinsic signature for this identifier.
|
||||
const intrinsic::Signature* intrinsic_signature() const {
|
||||
return intrinsic_sig_.get();
|
||||
}
|
||||
|
||||
/// @returns true if this identifier is for an intrinsic
|
||||
bool IsIntrinsic() const { return intrinsic_ != Intrinsic::kNone; }
|
||||
|
||||
|
@ -63,6 +76,7 @@ class IdentifierExpression : public Expression {
|
|||
IdentifierExpression(const IdentifierExpression&) = delete;
|
||||
|
||||
Intrinsic intrinsic_ = Intrinsic::kNone;
|
||||
std::unique_ptr<intrinsic::Signature> intrinsic_sig_;
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
|
|
|
@ -216,6 +216,9 @@ std::ostream& operator<<(std::ostream& out, Intrinsic i) {
|
|||
case Intrinsic::kTextureSampleCompare:
|
||||
out << "textureSampleCompare";
|
||||
break;
|
||||
case Intrinsic::kTextureSampleGrad:
|
||||
out << "textureSampleGrad";
|
||||
break;
|
||||
case Intrinsic::kTextureSampleLevel:
|
||||
out << "textureSampleLevel";
|
||||
break;
|
||||
|
@ -231,6 +234,12 @@ std::ostream& operator<<(std::ostream& out, Intrinsic i) {
|
|||
|
||||
namespace intrinsic {
|
||||
|
||||
Signature::~Signature() = default;
|
||||
TextureSignature::~TextureSignature() = default;
|
||||
|
||||
TextureSignature::Parameters::Index::Index() = default;
|
||||
TextureSignature::Parameters::Index::Index(const Index&) = default;
|
||||
|
||||
bool IsCoarseDerivative(ast::Intrinsic i) {
|
||||
return i == Intrinsic::kDpdxCoarse || i == Intrinsic::kDpdyCoarse ||
|
||||
i == Intrinsic::kFwidthCoarse;
|
||||
|
@ -256,7 +265,8 @@ bool IsTextureIntrinsic(ast::Intrinsic i) {
|
|||
return i == Intrinsic::kTextureLoad || i == Intrinsic::kTextureSample ||
|
||||
i == Intrinsic::kTextureSampleLevel ||
|
||||
i == Intrinsic::kTextureSampleBias ||
|
||||
i == Intrinsic::kTextureSampleCompare;
|
||||
i == Intrinsic::kTextureSampleCompare ||
|
||||
i == Intrinsic::kTextureSampleGrad;
|
||||
}
|
||||
|
||||
} // namespace intrinsic
|
||||
|
|
|
@ -89,6 +89,7 @@ enum class Intrinsic {
|
|||
kTextureSample,
|
||||
kTextureSampleBias,
|
||||
kTextureSampleCompare,
|
||||
kTextureSampleGrad,
|
||||
kTextureSampleLevel,
|
||||
kTrunc
|
||||
};
|
||||
|
@ -99,6 +100,64 @@ std::ostream& operator<<(std::ostream& out, Intrinsic i);
|
|||
|
||||
namespace intrinsic {
|
||||
|
||||
/// Signature is the base struct for all intrinsic signature types.
|
||||
/// Signatures are used to identify the particular overload for intrinsics that
|
||||
/// have different signatures with the same function name.
|
||||
struct Signature {
|
||||
virtual ~Signature();
|
||||
};
|
||||
|
||||
/// TextureSignature describes the signature of a texture intrinsic function.
|
||||
struct TextureSignature : public Signature {
|
||||
/// Parameters describes the parameters for the texture function.
|
||||
struct Parameters {
|
||||
/// kNotUsed is the constant that indicates the given parameter is not part
|
||||
/// of the texture function signature.
|
||||
static constexpr const size_t kNotUsed = ~static_cast<size_t>(0u);
|
||||
/// Index holds each of the possible parameter indices. If a parameter index
|
||||
/// is equal to `kNotUsed` then this parameter is not used by the function.
|
||||
struct Index {
|
||||
/// Constructor
|
||||
Index();
|
||||
/// Copy constructor
|
||||
Index(const Index&);
|
||||
/// `array_index` parameter index.
|
||||
size_t array_index = kNotUsed;
|
||||
/// `bias` parameter index.
|
||||
size_t bias = kNotUsed;
|
||||
/// `coords` parameter index.
|
||||
size_t coords = kNotUsed;
|
||||
/// `depth_ref` parameter index.
|
||||
size_t depth_ref = kNotUsed;
|
||||
/// `ddx` parameter index.
|
||||
size_t ddx = kNotUsed;
|
||||
/// `ddy` parameter index.
|
||||
size_t ddy = kNotUsed;
|
||||
/// `level` parameter index.
|
||||
size_t level = kNotUsed;
|
||||
/// `offset` parameter index.
|
||||
size_t offset = kNotUsed;
|
||||
/// `sampler` parameter index.
|
||||
size_t sampler = kNotUsed;
|
||||
/// `texture` parameter index.
|
||||
size_t texture = kNotUsed;
|
||||
};
|
||||
/// The indices of all possible parameters.
|
||||
Index idx;
|
||||
/// Total number of parameters.
|
||||
size_t count = 0;
|
||||
};
|
||||
|
||||
/// Construct an immutable `TextureSignature`.
|
||||
/// @param p the texture intrinsic parameter signature.
|
||||
explicit TextureSignature(const Parameters& p) : params(p) {}
|
||||
|
||||
~TextureSignature() override;
|
||||
|
||||
/// The texture intrinsic parameter signature.
|
||||
const Parameters params;
|
||||
};
|
||||
|
||||
/// Determines if the given |name| is a coarse derivative
|
||||
/// @param i the intrinsic
|
||||
/// @returns true if the given derivative is coarse.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,171 @@
|
|||
// Copyright 2020 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_AST_INTRINSIC_TEXTURE_HELPER_TEST_H_
|
||||
#define SRC_AST_INTRINSIC_TEXTURE_HELPER_TEST_H_
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include "src/ast/builder.h"
|
||||
#include "src/ast/type/sampler_type.h"
|
||||
#include "src/ast/type/texture_type.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
namespace intrinsic {
|
||||
namespace test {
|
||||
|
||||
enum class TextureKind { kRegular, kDepth };
|
||||
|
||||
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 };
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const TextureDataType& ty) {
|
||||
switch (ty) {
|
||||
case TextureDataType::kF32:
|
||||
out << "f32";
|
||||
break;
|
||||
case TextureDataType::kU32:
|
||||
out << "u32";
|
||||
break;
|
||||
case TextureDataType::kI32:
|
||||
out << "i32";
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
enum class ValidTextureOverload {
|
||||
kSample1dF32,
|
||||
kSample1dArrayF32,
|
||||
kSample2dF32,
|
||||
kSample2dOffsetF32,
|
||||
kSample2dArrayF32,
|
||||
kSample2dArrayOffsetF32,
|
||||
kSample3dF32,
|
||||
kSample3dOffsetF32,
|
||||
kSampleCubeF32,
|
||||
kSampleCubeArrayF32,
|
||||
kSampleDepth2dF32,
|
||||
kSampleDepth2dOffsetF32,
|
||||
kSampleDepth2dArrayF32,
|
||||
kSampleDepth2dArrayOffsetF32,
|
||||
kSampleDepthCubeF32,
|
||||
kSampleDepthCubeArrayF32,
|
||||
kSampleBias2dF32,
|
||||
kSampleBias2dOffsetF32,
|
||||
kSampleBias2dArrayF32,
|
||||
kSampleBias2dArrayOffsetF32,
|
||||
kSampleBias3dF32,
|
||||
kSampleBias3dOffsetF32,
|
||||
kSampleBiasCubeF32,
|
||||
kSampleBiasCubeArrayF32,
|
||||
kSampleLevel2dF32,
|
||||
kSampleLevel2dOffsetF32,
|
||||
kSampleLevel2dArrayF32,
|
||||
kSampleLevel2dArrayOffsetF32,
|
||||
kSampleLevel3dF32,
|
||||
kSampleLevel3dOffsetF32,
|
||||
kSampleLevelCubeF32,
|
||||
kSampleLevelCubeArrayF32,
|
||||
kSampleLevelDepth2dF32,
|
||||
kSampleLevelDepth2dOffsetF32,
|
||||
kSampleLevelDepth2dArrayF32,
|
||||
kSampleLevelDepth2dArrayOffsetF32,
|
||||
kSampleLevelDepthCubeF32,
|
||||
kSampleLevelDepthCubeArrayF32,
|
||||
kSampleGrad2dF32,
|
||||
kSampleGrad2dOffsetF32,
|
||||
kSampleGrad2dArrayF32,
|
||||
kSampleGrad2dArrayOffsetF32,
|
||||
kSampleGrad3dF32,
|
||||
kSampleGrad3dOffsetF32,
|
||||
kSampleGradCubeF32,
|
||||
kSampleGradCubeArrayF32,
|
||||
kSampleGradDepth2dF32,
|
||||
kSampleGradDepth2dOffsetF32,
|
||||
kSampleGradDepth2dArrayF32,
|
||||
kSampleGradDepth2dArrayOffsetF32,
|
||||
kSampleGradDepthCubeF32,
|
||||
kSampleGradDepthCubeArrayF32,
|
||||
};
|
||||
|
||||
/// Describes a texture intrinsic overload
|
||||
struct TextureOverloadCase {
|
||||
/// Constructor
|
||||
TextureOverloadCase();
|
||||
/// Constructor
|
||||
TextureOverloadCase(ValidTextureOverload,
|
||||
const char*,
|
||||
TextureKind,
|
||||
ast::type::SamplerKind,
|
||||
ast::type::TextureDimension,
|
||||
TextureDataType,
|
||||
const char*,
|
||||
std::function<ast::ExpressionList(ast::Builder*)>);
|
||||
/// Copy constructor
|
||||
TextureOverloadCase(const TextureOverloadCase&);
|
||||
/// Destructor
|
||||
~TextureOverloadCase();
|
||||
|
||||
/// @return a vector containing a large number of valid texture overloads
|
||||
static std::vector<TextureOverloadCase> ValidCases();
|
||||
|
||||
/// The enumerator for this overload
|
||||
ValidTextureOverload overload;
|
||||
/// A human readable description of the overload
|
||||
const char* description;
|
||||
/// The texture kind for the texture parameter
|
||||
TextureKind texture_kind;
|
||||
/// The sampler kind for the sampler parameter
|
||||
ast::type::SamplerKind sampler_kind;
|
||||
/// The dimensions of the texture parameter
|
||||
ast::type::TextureDimension texture_dimension;
|
||||
/// The data type of the texture parameter
|
||||
TextureDataType texture_data_type;
|
||||
/// Name of the function. e.g. `textureSample`, `textureSampleGrad`, etc
|
||||
const char* function;
|
||||
/// A function that builds the AST arguments for the overload
|
||||
std::function<ast::ExpressionList(ast::Builder*)> args;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out,
|
||||
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 intrinsic
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_AST_INTRINSIC_TEXTURE_HELPER_TEST_H_
|
|
@ -529,6 +529,44 @@ class InspectorHelper {
|
|||
body);
|
||||
}
|
||||
|
||||
/// Generates a function that references a specific sampler variable
|
||||
/// @param func_name name of the function created
|
||||
/// @param texture_name name of the texture to be sampled
|
||||
/// @param sampler_name name of the sampler to use
|
||||
/// @param coords_name name of the coords variable to use
|
||||
/// @param array_index name of the array index variable to use
|
||||
/// @returns a function that references all of the values specified
|
||||
ast::Function* MakeSamplerReferenceBodyFunction(
|
||||
const std::string& func_name,
|
||||
const std::string& texture_name,
|
||||
const std::string& sampler_name,
|
||||
const std::string& coords_name,
|
||||
const std::string& array_index,
|
||||
ast::type::Type* base_type) {
|
||||
std::string result_name = "sampler_result";
|
||||
|
||||
auto* body = create<ast::BlockStatement>();
|
||||
|
||||
auto* call_result = create<ast::Variable>(
|
||||
"sampler_result", ast::StorageClass::kFunction, vec_type(base_type, 4));
|
||||
body->append(create<ast::VariableDeclStatement>(call_result));
|
||||
|
||||
ast::ExpressionList call_params;
|
||||
call_params.push_back(create<ast::IdentifierExpression>(texture_name));
|
||||
call_params.push_back(create<ast::IdentifierExpression>(sampler_name));
|
||||
call_params.push_back(create<ast::IdentifierExpression>(coords_name));
|
||||
call_params.push_back(create<ast::IdentifierExpression>(array_index));
|
||||
auto* call_expr = create<ast::CallExpression>(
|
||||
create<ast::IdentifierExpression>("textureSample"), call_params);
|
||||
|
||||
body->append(create<ast::AssignmentStatement>(
|
||||
create<ast::IdentifierExpression>("sampler_result"), call_expr));
|
||||
body->append(create<ast::ReturnStatement>());
|
||||
|
||||
return create<ast::Function>(func_name, ast::VariableList(), void_type(),
|
||||
body);
|
||||
}
|
||||
|
||||
/// Generates a function that references a specific comparison sampler
|
||||
/// variable.
|
||||
/// @param func_name name of the function created
|
||||
|
@ -683,6 +721,9 @@ class InspectorGetComparisonSamplerResourceBindingsTest
|
|||
public testing::Test {};
|
||||
class InspectorGetSampledTextureResourceBindingsTest : public InspectorHelper,
|
||||
public testing::Test {};
|
||||
class InspectorGetSampledArrayTextureResourceBindingsTest
|
||||
: public InspectorHelper,
|
||||
public testing::Test {};
|
||||
struct GetSampledTextureTestParams {
|
||||
ast::type::TextureDimension type_dim;
|
||||
inspector::ResourceBinding::TextureDimension inspector_dim;
|
||||
|
@ -691,11 +732,19 @@ struct GetSampledTextureTestParams {
|
|||
class InspectorGetSampledTextureResourceBindingsTestWithParam
|
||||
: public InspectorHelper,
|
||||
public testing::TestWithParam<GetSampledTextureTestParams> {};
|
||||
|
||||
class InspectorGetSampledArrayTextureResourceBindingsTestWithParam
|
||||
: public InspectorHelper,
|
||||
public testing::TestWithParam<GetSampledTextureTestParams> {};
|
||||
class InspectorGetMultisampledTextureResourceBindingsTest
|
||||
: public InspectorHelper,
|
||||
public testing::Test {};
|
||||
class InspectorGetMultisampledArrayTextureResourceBindingsTest
|
||||
: public InspectorHelper,
|
||||
public testing::Test {};
|
||||
typedef GetSampledTextureTestParams GetMultisampledTextureTestParams;
|
||||
class InspectorGetMultisampledArrayTextureResourceBindingsTestWithParam
|
||||
: public InspectorHelper,
|
||||
public testing::TestWithParam<GetMultisampledTextureTestParams> {};
|
||||
class InspectorGetMultisampledTextureResourceBindingsTestWithParam
|
||||
: public InspectorHelper,
|
||||
public testing::TestWithParam<GetMultisampledTextureTestParams> {};
|
||||
|
@ -2008,18 +2057,6 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
ast::type::TextureDimension::k1d,
|
||||
inspector::ResourceBinding::TextureDimension::k1d,
|
||||
inspector::ResourceBinding::SampledKind::kUInt},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::SampledKind::kFloat},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::SampledKind::kSInt},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::SampledKind::kUInt},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k2d,
|
||||
inspector::ResourceBinding::TextureDimension::k2d,
|
||||
|
@ -2032,18 +2069,6 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
ast::type::TextureDimension::k2d,
|
||||
inspector::ResourceBinding::TextureDimension::k2d,
|
||||
inspector::ResourceBinding::SampledKind::kUInt},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k2dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k2dArray,
|
||||
inspector::ResourceBinding::SampledKind::kFloat},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k2dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k2dArray,
|
||||
inspector::ResourceBinding::SampledKind::kSInt},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k2dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k2dArray,
|
||||
inspector::ResourceBinding::SampledKind::kUInt},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k3d,
|
||||
inspector::ResourceBinding::TextureDimension::k3d,
|
||||
|
@ -2067,6 +2092,65 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::kCube,
|
||||
inspector::ResourceBinding::TextureDimension::kCube,
|
||||
inspector::ResourceBinding::SampledKind::kUInt}));
|
||||
|
||||
TEST_P(InspectorGetSampledArrayTextureResourceBindingsTestWithParam,
|
||||
textureSample) {
|
||||
auto sampled_texture_type = MakeSampledTextureType(
|
||||
GetParam().type_dim, GetBaseType(GetParam().sampled_kind));
|
||||
AddSampledTexture("foo_texture", sampled_texture_type.get(), 0, 0);
|
||||
AddSampler("foo_sampler", 0, 1);
|
||||
auto* coord_type =
|
||||
GetCoordsType(GetParam().type_dim, GetParam().sampled_kind);
|
||||
AddGlobalVariable("foo_coords", coord_type);
|
||||
AddGlobalVariable("foo_array_index", u32_type());
|
||||
|
||||
auto* func = MakeSamplerReferenceBodyFunction(
|
||||
"ep", "foo_texture", "foo_sampler", "foo_coords", "foo_array_index",
|
||||
GetBaseType(GetParam().sampled_kind));
|
||||
func->add_decoration(
|
||||
create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
|
||||
mod()->AddFunction(func);
|
||||
|
||||
ASSERT_TRUE(td()->Determine()) << td()->error();
|
||||
|
||||
auto result = inspector()->GetSampledTextureResourceBindings("ep");
|
||||
ASSERT_FALSE(inspector()->has_error()) << inspector()->error();
|
||||
|
||||
ASSERT_EQ(1u, result.size());
|
||||
EXPECT_EQ(0u, result[0].bind_group);
|
||||
EXPECT_EQ(0u, result[0].binding);
|
||||
EXPECT_EQ(GetParam().inspector_dim, result[0].dim);
|
||||
EXPECT_EQ(GetParam().sampled_kind, result[0].sampled_kind);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
InspectorGetSampledArrayTextureResourceBindingsTest,
|
||||
InspectorGetSampledArrayTextureResourceBindingsTestWithParam,
|
||||
testing::Values(
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::SampledKind::kFloat},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::SampledKind::kSInt},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::SampledKind::kUInt},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k2dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k2dArray,
|
||||
inspector::ResourceBinding::SampledKind::kFloat},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k2dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k2dArray,
|
||||
inspector::ResourceBinding::SampledKind::kSInt},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::k2dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k2dArray,
|
||||
inspector::ResourceBinding::SampledKind::kUInt},
|
||||
GetSampledTextureTestParams{
|
||||
ast::type::TextureDimension::kCubeArray,
|
||||
|
@ -2081,18 +2165,6 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
inspector::ResourceBinding::TextureDimension::kCubeArray,
|
||||
inspector::ResourceBinding::SampledKind::kUInt}));
|
||||
|
||||
TEST_F(InspectorGetMultisampledTextureResourceBindingsTest, Empty) {
|
||||
auto* foo = MakeEmptyBodyFunction("foo");
|
||||
foo->add_decoration(
|
||||
create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
|
||||
mod()->AddFunction(foo);
|
||||
|
||||
auto result = inspector()->GetSampledTextureResourceBindings("foo");
|
||||
ASSERT_FALSE(inspector()->has_error()) << inspector()->error();
|
||||
|
||||
EXPECT_EQ(0u, result.size());
|
||||
}
|
||||
|
||||
TEST_P(InspectorGetMultisampledTextureResourceBindingsTestWithParam,
|
||||
textureSample) {
|
||||
auto multisampled_texture_type = MakeMultisampledTextureType(
|
||||
|
@ -2138,18 +2210,6 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
ast::type::TextureDimension::k1d,
|
||||
inspector::ResourceBinding::TextureDimension::k1d,
|
||||
inspector::ResourceBinding::SampledKind::kUInt},
|
||||
GetMultisampledTextureTestParams{
|
||||
ast::type::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::SampledKind::kFloat},
|
||||
GetMultisampledTextureTestParams{
|
||||
ast::type::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::SampledKind::kSInt},
|
||||
GetMultisampledTextureTestParams{
|
||||
ast::type::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::SampledKind::kUInt},
|
||||
GetMultisampledTextureTestParams{
|
||||
ast::type::TextureDimension::k2d,
|
||||
inspector::ResourceBinding::TextureDimension::k2d,
|
||||
|
@ -2161,6 +2221,65 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
GetMultisampledTextureTestParams{
|
||||
ast::type::TextureDimension::k2d,
|
||||
inspector::ResourceBinding::TextureDimension::k2d,
|
||||
inspector::ResourceBinding::SampledKind::kUInt}));
|
||||
|
||||
TEST_F(InspectorGetMultisampledArrayTextureResourceBindingsTest, Empty) {
|
||||
auto* foo = MakeEmptyBodyFunction("foo");
|
||||
foo->add_decoration(
|
||||
create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
|
||||
mod()->AddFunction(foo);
|
||||
|
||||
auto result = inspector()->GetSampledTextureResourceBindings("foo");
|
||||
ASSERT_FALSE(inspector()->has_error()) << inspector()->error();
|
||||
|
||||
EXPECT_EQ(0u, result.size());
|
||||
}
|
||||
|
||||
TEST_P(InspectorGetMultisampledArrayTextureResourceBindingsTestWithParam,
|
||||
textureSample) {
|
||||
auto multisampled_texture_type = MakeMultisampledTextureType(
|
||||
GetParam().type_dim, GetBaseType(GetParam().sampled_kind));
|
||||
AddMultisampledTexture("foo_texture", multisampled_texture_type.get(), 0, 0);
|
||||
AddSampler("foo_sampler", 0, 1);
|
||||
auto* coord_type =
|
||||
GetCoordsType(GetParam().type_dim, GetParam().sampled_kind);
|
||||
AddGlobalVariable("foo_coords", coord_type);
|
||||
AddGlobalVariable("foo_array_index", u32_type());
|
||||
|
||||
auto* func = MakeSamplerReferenceBodyFunction(
|
||||
"ep", "foo_texture", "foo_sampler", "foo_coords", "foo_array_index",
|
||||
GetBaseType(GetParam().sampled_kind));
|
||||
func->add_decoration(
|
||||
create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
|
||||
mod()->AddFunction(func);
|
||||
|
||||
ASSERT_TRUE(td()->Determine()) << td()->error();
|
||||
|
||||
auto result = inspector()->GetMultisampledTextureResourceBindings("ep");
|
||||
ASSERT_FALSE(inspector()->has_error()) << inspector()->error();
|
||||
|
||||
ASSERT_EQ(1u, result.size());
|
||||
EXPECT_EQ(0u, result[0].bind_group);
|
||||
EXPECT_EQ(0u, result[0].binding);
|
||||
EXPECT_EQ(GetParam().inspector_dim, result[0].dim);
|
||||
EXPECT_EQ(GetParam().sampled_kind, result[0].sampled_kind);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
InspectorGetMultisampledArrayTextureResourceBindingsTest,
|
||||
InspectorGetMultisampledArrayTextureResourceBindingsTestWithParam,
|
||||
testing::Values(
|
||||
GetMultisampledTextureTestParams{
|
||||
ast::type::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::SampledKind::kFloat},
|
||||
GetMultisampledTextureTestParams{
|
||||
ast::type::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::SampledKind::kSInt},
|
||||
GetMultisampledTextureTestParams{
|
||||
ast::type::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::TextureDimension::k1dArray,
|
||||
inspector::ResourceBinding::SampledKind::kUInt},
|
||||
GetMultisampledTextureTestParams{
|
||||
ast::type::TextureDimension::k2dArray,
|
||||
|
|
|
@ -552,26 +552,7 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
|
|||
return true;
|
||||
}
|
||||
if (ast::intrinsic::IsTextureIntrinsic(ident->intrinsic())) {
|
||||
// TODO(dsinclair): Remove the LOD param from textureLoad on storage
|
||||
// textures when https://github.com/gpuweb/gpuweb/pull/1032 gets merged.
|
||||
uint32_t num_of_params =
|
||||
(ident->intrinsic() == ast::Intrinsic::kTextureLoad ||
|
||||
ident->intrinsic() == ast::Intrinsic::kTextureSample)
|
||||
? 3
|
||||
: 4;
|
||||
if (expr->params().size() != num_of_params) {
|
||||
set_error(expr->source(),
|
||||
"incorrect number of parameters for " + ident->name() +
|
||||
", got " + std::to_string(expr->params().size()) +
|
||||
" and expected " + std::to_string(num_of_params));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ident->intrinsic() == ast::Intrinsic::kTextureSampleCompare) {
|
||||
expr->func()->set_result_type(
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>()));
|
||||
return true;
|
||||
}
|
||||
ast::intrinsic::TextureSignature::Parameters param;
|
||||
|
||||
auto* texture_param = expr->params()[0];
|
||||
if (!texture_param->result_type()->UnwrapPtrIfNeeded()->IsTexture()) {
|
||||
|
@ -581,6 +562,115 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
|
|||
ast::type::TextureType* texture =
|
||||
texture_param->result_type()->UnwrapPtrIfNeeded()->AsTexture();
|
||||
|
||||
bool is_array = false;
|
||||
switch (texture->dim()) {
|
||||
case ast::type::TextureDimension::k1dArray:
|
||||
case ast::type::TextureDimension::k2dArray:
|
||||
case ast::type::TextureDimension::kCubeArray:
|
||||
is_array = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (ident->intrinsic()) {
|
||||
case ast::Intrinsic::kTextureLoad:
|
||||
param.idx.texture = param.count++;
|
||||
param.idx.coords = param.count++;
|
||||
if (is_array) {
|
||||
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) {
|
||||
param.idx.level = param.count++;
|
||||
}
|
||||
|
||||
break;
|
||||
case ast::Intrinsic::kTextureSample:
|
||||
param.idx.texture = param.count++;
|
||||
param.idx.sampler = param.count++;
|
||||
param.idx.coords = param.count++;
|
||||
if (is_array) {
|
||||
param.idx.array_index = param.count++;
|
||||
}
|
||||
if (expr->params().size() > param.count) {
|
||||
param.idx.offset = param.count++;
|
||||
}
|
||||
break;
|
||||
case ast::Intrinsic::kTextureSampleBias:
|
||||
param.idx.texture = param.count++;
|
||||
param.idx.sampler = param.count++;
|
||||
param.idx.coords = param.count++;
|
||||
if (is_array) {
|
||||
param.idx.array_index = param.count++;
|
||||
}
|
||||
param.idx.bias = param.count++;
|
||||
if (expr->params().size() > param.count) {
|
||||
param.idx.offset = param.count++;
|
||||
}
|
||||
break;
|
||||
case ast::Intrinsic::kTextureSampleLevel:
|
||||
param.idx.texture = param.count++;
|
||||
param.idx.sampler = param.count++;
|
||||
param.idx.coords = param.count++;
|
||||
if (is_array) {
|
||||
param.idx.array_index = param.count++;
|
||||
}
|
||||
param.idx.level = param.count++;
|
||||
if (expr->params().size() > param.count) {
|
||||
param.idx.offset = param.count++;
|
||||
}
|
||||
break;
|
||||
case ast::Intrinsic::kTextureSampleCompare:
|
||||
param.idx.texture = param.count++;
|
||||
param.idx.sampler = param.count++;
|
||||
param.idx.coords = param.count++;
|
||||
if (is_array) {
|
||||
param.idx.array_index = param.count++;
|
||||
}
|
||||
param.idx.depth_ref = param.count++;
|
||||
if (expr->params().size() > param.count) {
|
||||
param.idx.offset = param.count++;
|
||||
}
|
||||
break;
|
||||
case ast::Intrinsic::kTextureSampleGrad:
|
||||
param.idx.texture = param.count++;
|
||||
param.idx.sampler = param.count++;
|
||||
param.idx.coords = param.count++;
|
||||
if (is_array) {
|
||||
param.idx.array_index = param.count++;
|
||||
}
|
||||
param.idx.ddx = param.count++;
|
||||
param.idx.ddy = param.count++;
|
||||
if (expr->params().size() > param.count) {
|
||||
param.idx.offset = param.count++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
set_error(expr->source(),
|
||||
"Internal compiler error: Unreachable intrinsic " +
|
||||
std::to_string(static_cast<int>(ident->intrinsic())));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expr->params().size() != param.count) {
|
||||
set_error(expr->source(),
|
||||
"incorrect number of parameters for " + ident->name() +
|
||||
", got " + std::to_string(expr->params().size()) +
|
||||
" and expected " + std::to_string(param.count));
|
||||
return false;
|
||||
}
|
||||
|
||||
ident->set_intrinsic_signature(
|
||||
std::make_unique<ast::intrinsic::TextureSignature>(param));
|
||||
|
||||
if (texture->IsDepth()) {
|
||||
expr->func()->set_result_type(
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>()));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!texture->IsStorage() &&
|
||||
!(texture->IsSampled() || texture->IsMultisampled())) {
|
||||
set_error(expr->source(), "invalid texture for " + ident->name());
|
||||
|
@ -925,6 +1015,8 @@ bool TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) {
|
|||
ident->set_intrinsic(ast::Intrinsic::kTextureSampleBias);
|
||||
} else if (ident->name() == "textureSampleCompare") {
|
||||
ident->set_intrinsic(ast::Intrinsic::kTextureSampleCompare);
|
||||
} else if (ident->name() == "textureSampleGrad") {
|
||||
ident->set_intrinsic(ast::Intrinsic::kTextureSampleGrad);
|
||||
} else if (ident->name() == "textureSampleLevel") {
|
||||
ident->set_intrinsic(ast::Intrinsic::kTextureSampleLevel);
|
||||
} else if (ident->name() == "trunc") {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1749,9 +1749,15 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident,
|
|||
return 0;
|
||||
}
|
||||
|
||||
auto intrinsic = ident->intrinsic();
|
||||
|
||||
if (ast::intrinsic::IsTextureIntrinsic(intrinsic)) {
|
||||
GenerateTextureIntrinsic(ident, call, Operand::Int(result_type_id), result);
|
||||
return result_id;
|
||||
}
|
||||
|
||||
OperandList params = {Operand::Int(result_type_id), result};
|
||||
|
||||
auto intrinsic = ident->intrinsic();
|
||||
if (ast::intrinsic::IsFineDerivative(intrinsic) ||
|
||||
ast::intrinsic::IsCoarseDerivative(intrinsic)) {
|
||||
push_capability(SpvCapabilityDerivativeControl);
|
||||
|
@ -1825,7 +1831,7 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident,
|
|||
op = spv::Op::OpBitReverse;
|
||||
} else if (intrinsic == ast::Intrinsic::kSelect) {
|
||||
op = spv::Op::OpSelect;
|
||||
} else if (!ast::intrinsic::IsTextureIntrinsic(intrinsic)) {
|
||||
} else {
|
||||
GenerateGLSLstd450Import();
|
||||
|
||||
auto set_iter = import_name_to_id_.find(kGLSLstd450);
|
||||
|
@ -1846,7 +1852,8 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident,
|
|||
|
||||
op = spv::Op::OpExtInst;
|
||||
}
|
||||
if (!ast::intrinsic::IsTextureIntrinsic(intrinsic) && op == spv::Op::OpNop) {
|
||||
|
||||
if (op == spv::Op::OpNop) {
|
||||
error_ = "unable to determine operator for: " + ident->name();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1854,15 +1861,11 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident,
|
|||
for (auto* p : call->params()) {
|
||||
auto val_id = GenerateExpression(p);
|
||||
if (val_id == 0) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
val_id = GenerateLoadIfNeeded(p->result_type(), val_id);
|
||||
|
||||
params.push_back(Operand::Int(val_id));
|
||||
}
|
||||
|
||||
if (ast::intrinsic::IsTextureIntrinsic(intrinsic)) {
|
||||
return GenerateTextureIntrinsic(ident, call, result_id, params);
|
||||
params.emplace_back(Operand::Int(val_id));
|
||||
}
|
||||
|
||||
push_function_inst(op, params);
|
||||
|
@ -1870,68 +1873,171 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident,
|
|||
return result_id;
|
||||
}
|
||||
|
||||
uint32_t Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
||||
void Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
||||
ast::CallExpression* call,
|
||||
uint32_t result_id,
|
||||
OperandList wgsl_params) {
|
||||
spirv::Operand result_type,
|
||||
spirv::Operand result_id) {
|
||||
auto* texture_type =
|
||||
call->params()[0]->result_type()->UnwrapAll()->AsTexture();
|
||||
|
||||
// TODO(dsinclair): Remove the LOD param from textureLoad on storage textures
|
||||
// when https://github.com/gpuweb/gpuweb/pull/1032 gets merged.
|
||||
auto* sig = static_cast<const ast::intrinsic::TextureSignature*>(
|
||||
ident->intrinsic_signature());
|
||||
assert(sig != nullptr);
|
||||
auto& pidx = sig->params.idx;
|
||||
auto const kNotUsed = ast::intrinsic::TextureSignature::Parameters::kNotUsed;
|
||||
|
||||
assert(pidx.texture != kNotUsed);
|
||||
|
||||
auto op = spv::Op::OpNop;
|
||||
|
||||
auto gen_param = [&](size_t idx) {
|
||||
auto* p = call->params()[idx];
|
||||
auto val_id = GenerateExpression(p);
|
||||
if (val_id == 0) {
|
||||
return Operand::Int(0);
|
||||
}
|
||||
val_id = GenerateLoadIfNeeded(p->result_type(), val_id);
|
||||
|
||||
return Operand::Int(val_id);
|
||||
};
|
||||
|
||||
// Populate the spirv_params with common parameters
|
||||
OperandList spirv_params;
|
||||
spirv_params.reserve(8); // Enough to fit most parameter lists
|
||||
spirv_params.emplace_back(std::move(result_type)); // result type
|
||||
spirv_params.emplace_back(std::move(result_id)); // result id
|
||||
|
||||
// Extra image operands, appended to spirv_params.
|
||||
uint32_t spirv_operand_mask = 0;
|
||||
OperandList spirv_operands;
|
||||
spirv_operands.reserve(4); // Enough to fit most parameter lists
|
||||
|
||||
if (ident->intrinsic() == ast::Intrinsic::kTextureLoad) {
|
||||
std::vector<Operand> spirv_params = {
|
||||
std::move(wgsl_params[0]), std::move(wgsl_params[1]),
|
||||
std::move(wgsl_params[2]), std::move(wgsl_params[3])};
|
||||
op = texture_type->IsStorage() ? spv::Op::OpImageRead
|
||||
: spv::Op::OpImageFetch;
|
||||
spirv_params.emplace_back(gen_param(pidx.texture));
|
||||
spirv_params.emplace_back(gen_param(pidx.coords));
|
||||
|
||||
// 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 (texture_type->IsMultisampled()) {
|
||||
spirv_params.push_back(Operand::Int(SpvImageOperandsSampleMask));
|
||||
spirv_operand_mask |= SpvImageOperandsSampleMask;
|
||||
} else {
|
||||
spirv_params.push_back(Operand::Int(SpvImageOperandsLodMask));
|
||||
spirv_operand_mask |= SpvImageOperandsLodMask;
|
||||
}
|
||||
spirv_params.push_back(std::move(wgsl_params[4]));
|
||||
spirv_operands.emplace_back(gen_param(pidx.level));
|
||||
}
|
||||
} else {
|
||||
assert(pidx.sampler != kNotUsed);
|
||||
|
||||
auto op = spv::Op::OpImageFetch;
|
||||
if (texture_type->IsStorage()) {
|
||||
op = spv::Op::OpImageRead;
|
||||
}
|
||||
push_function_inst(op, spirv_params);
|
||||
return result_id;
|
||||
auto sampler_param = gen_param(pidx.sampler);
|
||||
auto texture_param = gen_param(pidx.texture);
|
||||
auto sampled_image =
|
||||
GenerateSampledImage(texture_type, texture_param, sampler_param);
|
||||
|
||||
// Populate the spirv_params with the common parameters
|
||||
spirv_params.emplace_back(Operand::Int(sampled_image)); // sampled image
|
||||
|
||||
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];
|
||||
|
||||
uint32_t packed_coords_size;
|
||||
ast::type::Type* packed_coords_el_ty; // Currenly must be f32.
|
||||
if (param_coords->result_type()->IsVector()) {
|
||||
auto* vec = param_coords->result_type()->AsVector();
|
||||
packed_coords_size = vec->size() + 1;
|
||||
packed_coords_el_ty = vec->type();
|
||||
} else {
|
||||
packed_coords_size = 2;
|
||||
packed_coords_el_ty = param_coords->result_type();
|
||||
}
|
||||
|
||||
spv::Op op = spv::Op::OpNop;
|
||||
OperandList spirv_params = {
|
||||
wgsl_params[0], std::move(wgsl_params[1]),
|
||||
Operand::Int(GenerateSampledImage(texture_type, std::move(wgsl_params[2]),
|
||||
std::move(wgsl_params[3]))),
|
||||
std::move(wgsl_params[4])};
|
||||
// Cast param_array_index to the vector element type
|
||||
ast::TypeConstructorExpression array_index_cast(packed_coords_el_ty,
|
||||
{param_array_index});
|
||||
array_index_cast.set_result_type(packed_coords_el_ty);
|
||||
|
||||
if (ident->intrinsic() == ast::Intrinsic::kTextureSample) {
|
||||
ast::type::VectorType packed_coords_ty(packed_coords_el_ty,
|
||||
packed_coords_size);
|
||||
|
||||
ast::TypeConstructorExpression constructor{
|
||||
&packed_coords_ty, {param_coords, &array_index_cast}};
|
||||
auto packed_coords =
|
||||
GenerateTypeConstructorExpression(&constructor, false);
|
||||
|
||||
spirv_params.emplace_back(Operand::Int(packed_coords)); // coordinates
|
||||
|
||||
} else {
|
||||
spirv_params.emplace_back(gen_param(pidx.coords)); // coordinates
|
||||
}
|
||||
|
||||
switch (ident->intrinsic()) {
|
||||
case ast::Intrinsic::kTextureSample: {
|
||||
op = spv::Op::OpImageSampleImplicitLod;
|
||||
} else if (ident->intrinsic() == ast::Intrinsic::kTextureSampleLevel) {
|
||||
break;
|
||||
}
|
||||
case ast::Intrinsic::kTextureSampleBias: {
|
||||
op = spv::Op::OpImageSampleImplicitLod;
|
||||
assert(pidx.bias != kNotUsed);
|
||||
spirv_operand_mask |= SpvImageOperandsBiasMask;
|
||||
spirv_operands.emplace_back(gen_param(pidx.bias));
|
||||
break;
|
||||
}
|
||||
case ast::Intrinsic::kTextureSampleLevel: {
|
||||
op = spv::Op::OpImageSampleExplicitLod;
|
||||
spirv_params.push_back(Operand::Int(SpvImageOperandsLodMask));
|
||||
spirv_params.push_back(std::move(wgsl_params[5]));
|
||||
} else if (ident->intrinsic() == ast::Intrinsic::kTextureSampleBias) {
|
||||
op = spv::Op::OpImageSampleImplicitLod;
|
||||
spirv_params.push_back(Operand::Int(SpvImageOperandsBiasMask));
|
||||
spirv_params.push_back(std::move(wgsl_params[5]));
|
||||
} else if (ident->intrinsic() == ast::Intrinsic::kTextureSampleCompare) {
|
||||
assert(pidx.level != kNotUsed);
|
||||
spirv_operand_mask |= SpvImageOperandsLodMask;
|
||||
spirv_operands.emplace_back(gen_param(pidx.level));
|
||||
break;
|
||||
}
|
||||
case ast::Intrinsic::kTextureSampleGrad: {
|
||||
op = spv::Op::OpImageSampleExplicitLod;
|
||||
assert(pidx.ddx != kNotUsed);
|
||||
assert(pidx.ddy != kNotUsed);
|
||||
spirv_operand_mask |= SpvImageOperandsGradMask;
|
||||
spirv_operands.emplace_back(gen_param(pidx.ddx));
|
||||
spirv_operands.emplace_back(gen_param(pidx.ddy));
|
||||
break;
|
||||
}
|
||||
case ast::Intrinsic::kTextureSampleCompare: {
|
||||
op = spv::Op::OpImageSampleDrefExplicitLod;
|
||||
spirv_params.push_back(std::move(wgsl_params[5]));
|
||||
assert(pidx.depth_ref != kNotUsed);
|
||||
spirv_params.emplace_back(gen_param(pidx.depth_ref));
|
||||
|
||||
spirv_params.push_back(Operand::Int(SpvImageOperandsLodMask));
|
||||
spirv_operand_mask |= SpvImageOperandsLodMask;
|
||||
ast::type::F32Type f32;
|
||||
ast::FloatLiteral float_0(&f32, 0.0);
|
||||
spirv_params.push_back(
|
||||
spirv_operands.emplace_back(
|
||||
Operand::Int(GenerateLiteralIfNeeded(nullptr, &float_0)));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break; // unreachable
|
||||
}
|
||||
}
|
||||
|
||||
if (pidx.offset != kNotUsed) {
|
||||
spirv_operand_mask |= SpvImageOperandsOffsetMask;
|
||||
spirv_operands.emplace_back(gen_param(pidx.offset));
|
||||
}
|
||||
|
||||
if (spirv_operand_mask != 0) {
|
||||
// Note: Order of operands is based on SpvImageXXXOperands value -
|
||||
// smaller-numbered SpvImageXXXOperands bits appear first.
|
||||
spirv_params.emplace_back(Operand::Int(spirv_operand_mask));
|
||||
spirv_params.insert(std::end(spirv_params), std::begin(spirv_operands),
|
||||
std::end(spirv_operands));
|
||||
}
|
||||
|
||||
if (op == spv::Op::OpNop) {
|
||||
error_ = "unable to determine operator for: " + ident->name();
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
push_function_inst(op, spirv_params);
|
||||
|
||||
return result_id;
|
||||
push_function_inst(op, spirv_params);
|
||||
}
|
||||
|
||||
uint32_t Builder::GenerateSampledImage(ast::type::Type* texture_type,
|
||||
|
|
|
@ -231,7 +231,7 @@ class Builder {
|
|||
bool GenerateExecutionModes(ast::Function* func, uint32_t id);
|
||||
/// Generates an expression
|
||||
/// @param expr the expression to generate
|
||||
/// @returns the resulting ID of the exp = {};ression or 0 on error
|
||||
/// @returns the resulting ID of the expression or 0 on error
|
||||
uint32_t GenerateExpression(ast::Expression* expr);
|
||||
/// Generates the instructions for a function
|
||||
/// @param func the function to generate
|
||||
|
@ -335,14 +335,13 @@ class Builder {
|
|||
/// Generates a texture intrinsic call
|
||||
/// @param ident the texture intrinsic
|
||||
/// @param call the call expression
|
||||
/// @param result_id result ID of the texture instruction
|
||||
/// @param wgsl_params SPIR-V arguments for WGSL-specific intrinsic's call
|
||||
/// @param result_type result type operand of the texture instruction
|
||||
/// @param result_id result identifier operand of the texture instruction
|
||||
/// parameters
|
||||
/// @returns the expression ID on success or 0 otherwise
|
||||
uint32_t GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
||||
void GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
||||
ast::CallExpression* call,
|
||||
uint32_t result_id,
|
||||
OperandList wgsl_params);
|
||||
spirv::Operand result_type,
|
||||
spirv::Operand result_id);
|
||||
/// Generates a sampled image
|
||||
/// @param texture_type the texture type
|
||||
/// @param texture_operand the texture operand
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue