Implement textureWrite()
Bug: tint:368 Bug: tint:140 Bug: tint:143 Bug: tint:144 Bug: tint:145 Bug: tint:146 Bug: tint:147 Change-Id: I1b6943d8663fbac8fbaa77a4804afb5a20fdb5e6 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/35320 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
3a7bba8c98
commit
591268db48
|
@ -266,7 +266,7 @@ bool IsTextureIntrinsic(Intrinsic i) {
|
||||||
i == Intrinsic::kTextureSampleLevel ||
|
i == Intrinsic::kTextureSampleLevel ||
|
||||||
i == Intrinsic::kTextureSampleBias ||
|
i == Intrinsic::kTextureSampleBias ||
|
||||||
i == Intrinsic::kTextureSampleCompare ||
|
i == Intrinsic::kTextureSampleCompare ||
|
||||||
i == Intrinsic::kTextureSampleGrad;
|
i == Intrinsic::kTextureSampleGrad || i == Intrinsic::kTextureStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace intrinsic
|
} // namespace intrinsic
|
||||||
|
|
|
@ -91,6 +91,7 @@ enum class Intrinsic {
|
||||||
kTextureSampleCompare,
|
kTextureSampleCompare,
|
||||||
kTextureSampleGrad,
|
kTextureSampleGrad,
|
||||||
kTextureSampleLevel,
|
kTextureSampleLevel,
|
||||||
|
kTextureStore,
|
||||||
kTrunc
|
kTrunc
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -143,6 +144,8 @@ struct TextureSignature : public Signature {
|
||||||
size_t sample_index = kNotUsed;
|
size_t sample_index = kNotUsed;
|
||||||
/// `texture` parameter index.
|
/// `texture` parameter index.
|
||||||
size_t texture = kNotUsed;
|
size_t texture = kNotUsed;
|
||||||
|
/// `value` parameter index.
|
||||||
|
size_t value = kNotUsed;
|
||||||
};
|
};
|
||||||
/// The indices of all possible parameters.
|
/// The indices of all possible parameters.
|
||||||
Index idx;
|
Index idx;
|
||||||
|
|
|
@ -1976,6 +1976,90 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
|
||||||
b->vec3<i32>(1, 2, 3)); // coords
|
b->vec3<i32>(1, 2, 3)); // coords
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ValidTextureOverload::kStoreWO1dRgba32float,
|
||||||
|
"textureStore(t : texture_storage_wo_1d<F>,\n"
|
||||||
|
" coords : i32,\n"
|
||||||
|
" value : vec4<T>) -> void",
|
||||||
|
ast::AccessControl::kWriteOnly,
|
||||||
|
ast::type::ImageFormat::kRgba32Float,
|
||||||
|
type::TextureDimension::k1d,
|
||||||
|
TextureDataType::kF32,
|
||||||
|
"textureStore",
|
||||||
|
[](Builder* b) {
|
||||||
|
return b->ExprList("texture", // t
|
||||||
|
1, // coords
|
||||||
|
b->vec4<f32>(2.f, 3.f, 4.f, 5.f)); // value
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ValidTextureOverload::kStoreWO1dArrayRgba32float,
|
||||||
|
"textureStore(t : texture_storage_wo_1d_array<F>,\n"
|
||||||
|
" coords : i32,\n"
|
||||||
|
" array_index : i32,\n"
|
||||||
|
" value : vec4<T>) -> void",
|
||||||
|
ast::AccessControl::kWriteOnly,
|
||||||
|
ast::type::ImageFormat::kRgba32Float,
|
||||||
|
type::TextureDimension::k1dArray,
|
||||||
|
TextureDataType::kF32,
|
||||||
|
"textureStore",
|
||||||
|
[](Builder* b) {
|
||||||
|
return b->ExprList("texture", // t
|
||||||
|
1, // coords
|
||||||
|
2, // array_index
|
||||||
|
b->vec4<f32>(3.f, 4.f, 5.f, 6.f)); // value
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ValidTextureOverload::kStoreWO2dRgba32float,
|
||||||
|
"textureStore(t : texture_storage_wo_2d<F>,\n"
|
||||||
|
" coords : vec2<i32>,\n"
|
||||||
|
" value : vec4<T>) -> void",
|
||||||
|
ast::AccessControl::kWriteOnly,
|
||||||
|
ast::type::ImageFormat::kRgba32Float,
|
||||||
|
type::TextureDimension::k2d,
|
||||||
|
TextureDataType::kF32,
|
||||||
|
"textureStore",
|
||||||
|
[](Builder* b) {
|
||||||
|
return b->ExprList("texture", // t
|
||||||
|
b->vec2<i32>(1, 2), // coords
|
||||||
|
b->vec4<f32>(3.f, 4.f, 5.f, 6.f)); // value
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ValidTextureOverload::kStoreWO2dArrayRgba32float,
|
||||||
|
"textureStore(t : texture_storage_wo_2d_array<F>,\n"
|
||||||
|
" coords : vec2<i32>,\n"
|
||||||
|
" array_index : i32,\n"
|
||||||
|
" value : vec4<T>) -> void",
|
||||||
|
ast::AccessControl::kWriteOnly,
|
||||||
|
ast::type::ImageFormat::kRgba32Float,
|
||||||
|
type::TextureDimension::k2dArray,
|
||||||
|
TextureDataType::kF32,
|
||||||
|
"textureStore",
|
||||||
|
[](Builder* b) {
|
||||||
|
return b->ExprList("texture", // t
|
||||||
|
b->vec2<i32>(1, 2), // coords
|
||||||
|
3, // array_index
|
||||||
|
b->vec4<f32>(4.f, 5.f, 6.f, 7.f)); // value
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ValidTextureOverload::kStoreWO3dRgba32float,
|
||||||
|
"textureStore(t : texture_storage_wo_3d<F>,\n"
|
||||||
|
" coords : vec3<i32>,\n"
|
||||||
|
" value : vec4<T>) -> void",
|
||||||
|
ast::AccessControl::kWriteOnly,
|
||||||
|
ast::type::ImageFormat::kRgba32Float,
|
||||||
|
type::TextureDimension::k3d,
|
||||||
|
TextureDataType::kF32,
|
||||||
|
"textureStore",
|
||||||
|
[](Builder* b) {
|
||||||
|
return b->ExprList("texture", // t
|
||||||
|
b->vec3<i32>(1, 2, 3), // coords
|
||||||
|
b->vec4<f32>(4.f, 5.f, 6.f, 7.f)); // value
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,11 @@ enum class ValidTextureOverload {
|
||||||
kLoadStorageRO2dRgba32float,
|
kLoadStorageRO2dRgba32float,
|
||||||
kLoadStorageRO2dArrayRgba32float, // Not permutated for all texel formats
|
kLoadStorageRO2dArrayRgba32float, // Not permutated for all texel formats
|
||||||
kLoadStorageRO3dRgba32float, // Not permutated for all texel formats
|
kLoadStorageRO3dRgba32float, // Not permutated for all texel formats
|
||||||
|
kStoreWO1dRgba32float, // Not permutated for all texel formats
|
||||||
|
kStoreWO1dArrayRgba32float, // Not permutated for all texel formats
|
||||||
|
kStoreWO2dRgba32float, // Not permutated for all texel formats
|
||||||
|
kStoreWO2dArrayRgba32float, // Not permutated for all texel formats
|
||||||
|
kStoreWO3dRgba32float, // Not permutated for all texel formats
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Describes a texture intrinsic overload
|
/// Describes a texture intrinsic overload
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "src/ast/type/texture_type.h"
|
#include "src/ast/type/texture_type.h"
|
||||||
#include "src/ast/type/u32_type.h"
|
#include "src/ast/type/u32_type.h"
|
||||||
#include "src/ast/type/vector_type.h"
|
#include "src/ast/type/vector_type.h"
|
||||||
|
#include "src/ast/type/void_type.h"
|
||||||
#include "src/ast/type_constructor_expression.h"
|
#include "src/ast/type_constructor_expression.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"
|
||||||
|
@ -640,6 +641,14 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
|
||||||
param.idx.offset = param.count++;
|
param.idx.offset = param.count++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ast::Intrinsic::kTextureStore:
|
||||||
|
param.idx.texture = param.count++;
|
||||||
|
param.idx.coords = param.count++;
|
||||||
|
if (is_array) {
|
||||||
|
param.idx.array_index = param.count++;
|
||||||
|
}
|
||||||
|
param.idx.value = param.count++;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
set_error(expr->source(),
|
set_error(expr->source(),
|
||||||
"Internal compiler error: Unreachable intrinsic " +
|
"Internal compiler error: Unreachable intrinsic " +
|
||||||
|
@ -658,23 +667,32 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
|
||||||
ident->set_intrinsic_signature(
|
ident->set_intrinsic_signature(
|
||||||
std::make_unique<ast::intrinsic::TextureSignature>(param));
|
std::make_unique<ast::intrinsic::TextureSignature>(param));
|
||||||
|
|
||||||
if (texture->Is<ast::type::DepthTexture>()) {
|
// Set the function return type
|
||||||
expr->func()->set_result_type(mod_->create<ast::type::F32>());
|
ast::type::Type* return_type = nullptr;
|
||||||
|
if (ident->intrinsic() == ast::Intrinsic::kTextureStore) {
|
||||||
|
return_type = mod_->create<ast::type::Void>();
|
||||||
} else {
|
} else {
|
||||||
ast::type::Type* type = nullptr;
|
if (texture->Is<ast::type::DepthTexture>()) {
|
||||||
if (auto* storage = texture->As<ast::type::StorageTexture>()) {
|
return_type = mod_->create<ast::type::F32>();
|
||||||
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;
|
||||||
|
}
|
||||||
|
return_type = mod_->create<ast::type::Vector>(type, 4);
|
||||||
}
|
}
|
||||||
expr->func()->set_result_type(mod_->create<ast::type::Vector>(type, 4));
|
|
||||||
}
|
}
|
||||||
|
expr->func()->set_result_type(return_type);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ident->intrinsic() == ast::Intrinsic::kDot) {
|
if (ident->intrinsic() == ast::Intrinsic::kDot) {
|
||||||
|
@ -996,6 +1014,8 @@ bool TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) {
|
||||||
ident->set_intrinsic(ast::Intrinsic::kTanh);
|
ident->set_intrinsic(ast::Intrinsic::kTanh);
|
||||||
} else if (ident->name() == "textureLoad") {
|
} else if (ident->name() == "textureLoad") {
|
||||||
ident->set_intrinsic(ast::Intrinsic::kTextureLoad);
|
ident->set_intrinsic(ast::Intrinsic::kTextureLoad);
|
||||||
|
} else if (ident->name() == "textureStore") {
|
||||||
|
ident->set_intrinsic(ast::Intrinsic::kTextureStore);
|
||||||
} else if (ident->name() == "textureSample") {
|
} else if (ident->name() == "textureSample") {
|
||||||
ident->set_intrinsic(ast::Intrinsic::kTextureSample);
|
ident->set_intrinsic(ast::Intrinsic::kTextureSample);
|
||||||
} else if (ident->name() == "textureSampleBias") {
|
} else if (ident->name() == "textureSampleBias") {
|
||||||
|
|
|
@ -4513,6 +4513,7 @@ std::string to_str(const std::string& function,
|
||||||
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.sample_index, "sample_index");
|
||||||
maybe_add_param(sig->params.idx.texture, "texture");
|
maybe_add_param(sig->params.idx.texture, "texture");
|
||||||
|
maybe_add_param(sig->params.idx.value, "value");
|
||||||
std::sort(
|
std::sort(
|
||||||
params.begin(), params.end(),
|
params.begin(), params.end(),
|
||||||
[](const Parameter& a, const Parameter& b) { return a.idx < b.idx; });
|
[](const Parameter& a, const Parameter& b) { return a.idx < b.idx; });
|
||||||
|
@ -4732,6 +4733,16 @@ const char* expected_texture_overload(
|
||||||
return R"(textureLoad(texture, coords, array_index))";
|
return R"(textureLoad(texture, coords, array_index))";
|
||||||
case ValidTextureOverload::kLoadStorageRO3dRgba32float:
|
case ValidTextureOverload::kLoadStorageRO3dRgba32float:
|
||||||
return R"(textureLoad(texture, coords))";
|
return R"(textureLoad(texture, coords))";
|
||||||
|
case ValidTextureOverload::kStoreWO1dRgba32float:
|
||||||
|
return R"(textureStore(texture, coords, value))";
|
||||||
|
case ValidTextureOverload::kStoreWO1dArrayRgba32float:
|
||||||
|
return R"(textureStore(texture, coords, array_index, value))";
|
||||||
|
case ValidTextureOverload::kStoreWO2dRgba32float:
|
||||||
|
return R"(textureStore(texture, coords, value))";
|
||||||
|
case ValidTextureOverload::kStoreWO2dArrayRgba32float:
|
||||||
|
return R"(textureStore(texture, coords, array_index, value))";
|
||||||
|
case ValidTextureOverload::kStoreWO3dRgba32float:
|
||||||
|
return R"(textureStore(texture, coords, value))";
|
||||||
}
|
}
|
||||||
return "<unmatched texture overload>";
|
return "<unmatched texture overload>";
|
||||||
}
|
}
|
||||||
|
@ -4748,18 +4759,23 @@ TEST_P(TypeDeterminerTextureIntrinsicTest, Call) {
|
||||||
ASSERT_TRUE(td()->Determine()) << td()->error();
|
ASSERT_TRUE(td()->Determine()) << td()->error();
|
||||||
ASSERT_TRUE(td()->DetermineResultType(&call)) << td()->error();
|
ASSERT_TRUE(td()->DetermineResultType(&call)) << td()->error();
|
||||||
|
|
||||||
switch (param.texture_kind) {
|
if (std::string(param.function) == "textureStore") {
|
||||||
case ast::intrinsic::test::TextureKind::kRegular:
|
EXPECT_EQ(call.result_type(), ty.void_);
|
||||||
case ast::intrinsic::test::TextureKind::kMultisampled:
|
} else {
|
||||||
case ast::intrinsic::test::TextureKind::kStorage: {
|
switch (param.texture_kind) {
|
||||||
auto* datatype = param.resultVectorComponentType(this);
|
case ast::intrinsic::test::TextureKind::kRegular:
|
||||||
ASSERT_TRUE(call.result_type()->Is<ast::type::Vector>());
|
case ast::intrinsic::test::TextureKind::kMultisampled:
|
||||||
EXPECT_EQ(call.result_type()->As<ast::type::Vector>()->type(), datatype);
|
case ast::intrinsic::test::TextureKind::kStorage: {
|
||||||
break;
|
auto* datatype = param.resultVectorComponentType(this);
|
||||||
}
|
ASSERT_TRUE(call.result_type()->Is<ast::type::Vector>());
|
||||||
case ast::intrinsic::test::TextureKind::kDepth: {
|
EXPECT_EQ(call.result_type()->As<ast::type::Vector>()->type(),
|
||||||
EXPECT_EQ(call.result_type(), ty.f32);
|
datatype);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case ast::intrinsic::test::TextureKind::kDepth: {
|
||||||
|
EXPECT_EQ(call.result_type(), ty.f32);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -719,8 +719,6 @@ bool GeneratorImpl::EmitCall(std::ostream& pre,
|
||||||
bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
|
bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
|
||||||
std::ostream& out,
|
std::ostream& out,
|
||||||
ast::CallExpression* expr) {
|
ast::CallExpression* expr) {
|
||||||
make_indent(out);
|
|
||||||
|
|
||||||
auto* ident = expr->func()->As<ast::IdentifierExpression>();
|
auto* ident = expr->func()->As<ast::IdentifierExpression>();
|
||||||
|
|
||||||
auto params = expr->params();
|
auto params = expr->params();
|
||||||
|
@ -759,6 +757,9 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
|
||||||
pack_mip_in_coords = true;
|
pack_mip_in_coords = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ast::Intrinsic::kTextureStore:
|
||||||
|
out << "[";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error_ = "Internal compiler error: Unhandled texture intrinsic '" +
|
error_ = "Internal compiler error: Unhandled texture intrinsic '" +
|
||||||
ident->name() + "'";
|
ident->name() + "'";
|
||||||
|
@ -815,7 +816,13 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out << ")";
|
if (ident->intrinsic() == ast::Intrinsic::kTextureStore) {
|
||||||
|
out << "] = ";
|
||||||
|
if (!EmitExpression(pre, out, params[pidx.value]))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
out << ")";
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,16 @@ std::string expected_texture_overload(
|
||||||
return R"(texture_tint_0.Load(int3(1, 2, 3)))";
|
return R"(texture_tint_0.Load(int3(1, 2, 3)))";
|
||||||
case ValidTextureOverload::kLoadStorageRO3dRgba32float:
|
case ValidTextureOverload::kLoadStorageRO3dRgba32float:
|
||||||
return R"(texture_tint_0.Load(int3(1, 2, 3)))";
|
return R"(texture_tint_0.Load(int3(1, 2, 3)))";
|
||||||
|
case ValidTextureOverload::kStoreWO1dRgba32float:
|
||||||
|
return R"(texture_tint_0[1] = float4(2.0f, 3.0f, 4.0f, 5.0f))";
|
||||||
|
case ValidTextureOverload::kStoreWO1dArrayRgba32float:
|
||||||
|
return R"(texture_tint_0[int2(1, 2)] = float4(3.0f, 4.0f, 5.0f, 6.0f))";
|
||||||
|
case ValidTextureOverload::kStoreWO2dRgba32float:
|
||||||
|
return R"(texture_tint_0[int2(1, 2)] = float4(3.0f, 4.0f, 5.0f, 6.0f))";
|
||||||
|
case ValidTextureOverload::kStoreWO2dArrayRgba32float:
|
||||||
|
return R"(texture_tint_0[int3(1, 2, 3)] = float4(4.0f, 5.0f, 6.0f, 7.0f))";
|
||||||
|
case ValidTextureOverload::kStoreWO3dRgba32float:
|
||||||
|
return R"(texture_tint_0[int3(1, 2, 3)] = float4(4.0f, 5.0f, 6.0f, 7.0f))";
|
||||||
}
|
}
|
||||||
return "<unmatched texture overload>";
|
return "<unmatched texture overload>";
|
||||||
} // NOLINT - Ignore the length of this function
|
} // NOLINT - Ignore the length of this function
|
||||||
|
|
|
@ -679,6 +679,9 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
|
||||||
out_ << ".read(";
|
out_ << ".read(";
|
||||||
lod_param_is_named = false;
|
lod_param_is_named = false;
|
||||||
break;
|
break;
|
||||||
|
case ast::Intrinsic::kTextureStore:
|
||||||
|
out_ << ".write(";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error_ = "Internal compiler error: Unhandled texture intrinsic '" +
|
error_ = "Internal compiler error: Unhandled texture intrinsic '" +
|
||||||
ident->name() + "'";
|
ident->name() + "'";
|
||||||
|
@ -693,15 +696,8 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
|
||||||
first_arg = false;
|
first_arg = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (pidx.sampler != kNotUsed) {
|
for (auto idx : {pidx.value, pidx.sampler, pidx.coords, pidx.array_index,
|
||||||
if (!EmitExpression(params[pidx.sampler])) {
|
pidx.depth_ref, pidx.sample_index}) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
first_arg = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto idx :
|
|
||||||
{pidx.coords, pidx.array_index, pidx.depth_ref, pidx.sample_index}) {
|
|
||||||
if (idx != kNotUsed) {
|
if (idx != kNotUsed) {
|
||||||
maybe_write_comma();
|
maybe_write_comma();
|
||||||
if (!EmitExpression(params[idx]))
|
if (!EmitExpression(params[idx]))
|
||||||
|
|
|
@ -229,6 +229,16 @@ std::string expected_texture_overload(
|
||||||
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||||
case ValidTextureOverload::kLoadStorageRO3dRgba32float:
|
case ValidTextureOverload::kLoadStorageRO3dRgba32float:
|
||||||
return R"(texture_tint_0.read(int3(1, 2, 3)))";
|
return R"(texture_tint_0.read(int3(1, 2, 3)))";
|
||||||
|
case ValidTextureOverload::kStoreWO1dRgba32float:
|
||||||
|
return R"(texture_tint_0.write(float4(2.0f, 3.0f, 4.0f, 5.0f), 1))";
|
||||||
|
case ValidTextureOverload::kStoreWO1dArrayRgba32float:
|
||||||
|
return R"(texture_tint_0.write(float4(3.0f, 4.0f, 5.0f, 6.0f), 1, 2))";
|
||||||
|
case ValidTextureOverload::kStoreWO2dRgba32float:
|
||||||
|
return R"(texture_tint_0.write(float4(3.0f, 4.0f, 5.0f, 6.0f), int2(1, 2)))";
|
||||||
|
case ValidTextureOverload::kStoreWO2dArrayRgba32float:
|
||||||
|
return R"(texture_tint_0.write(float4(4.0f, 5.0f, 6.0f, 7.0f), int2(1, 2), 3))";
|
||||||
|
case ValidTextureOverload::kStoreWO3dRgba32float:
|
||||||
|
return R"(texture_tint_0.write(float4(4.0f, 5.0f, 6.0f, 7.0f), int3(1, 2, 3)))";
|
||||||
}
|
}
|
||||||
return "<unmatched texture overload>";
|
return "<unmatched texture overload>";
|
||||||
} // NOLINT - Ignore the length of this function
|
} // NOLINT - Ignore the length of this function
|
||||||
|
|
|
@ -1943,8 +1943,10 @@ void Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
||||||
// Populate the spirv_params with common parameters
|
// Populate the spirv_params with common parameters
|
||||||
OperandList spirv_params;
|
OperandList spirv_params;
|
||||||
spirv_params.reserve(8); // Enough to fit most parameter lists
|
spirv_params.reserve(8); // Enough to fit most parameter lists
|
||||||
spirv_params.emplace_back(std::move(result_type)); // result type
|
if (ident->intrinsic() != ast::Intrinsic::kTextureStore) {
|
||||||
spirv_params.emplace_back(std::move(result_id)); // result id
|
spirv_params.emplace_back(std::move(result_type));
|
||||||
|
spirv_params.emplace_back(std::move(result_id));
|
||||||
|
}
|
||||||
|
|
||||||
// Extra image operands, appended to spirv_params.
|
// Extra image operands, appended to spirv_params.
|
||||||
struct ImageOperand {
|
struct ImageOperand {
|
||||||
|
@ -1977,24 +1979,9 @@ void Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ident->intrinsic() == ast::Intrinsic::kTextureLoad) {
|
auto append_image_and_coords_to_spirv_params = [&] {
|
||||||
op = texture_type->Is<ast::type::StorageTexture>() ? spv::Op::OpImageRead
|
|
||||||
: spv::Op::OpImageFetch;
|
|
||||||
spirv_params.emplace_back(gen_param(pidx.texture));
|
|
||||||
append_coords_to_spirv_params();
|
|
||||||
|
|
||||||
if (pidx.level != kNotUsed) {
|
|
||||||
image_operands.emplace_back(
|
|
||||||
ImageOperand{SpvImageOperandsLodMask, gen_param(pidx.level)});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pidx.sample_index != kNotUsed) {
|
|
||||||
image_operands.emplace_back(ImageOperand{SpvImageOperandsSampleMask,
|
|
||||||
gen_param(pidx.sample_index)});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assert(pidx.sampler != kNotUsed);
|
assert(pidx.sampler != kNotUsed);
|
||||||
|
assert(pidx.texture != kNotUsed);
|
||||||
auto sampler_param = gen_param(pidx.sampler);
|
auto sampler_param = gen_param(pidx.sampler);
|
||||||
auto texture_param = gen_param(pidx.texture);
|
auto texture_param = gen_param(pidx.texture);
|
||||||
auto sampled_image =
|
auto sampled_image =
|
||||||
|
@ -2003,51 +1990,82 @@ 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();
|
append_coords_to_spirv_params();
|
||||||
|
};
|
||||||
|
|
||||||
switch (ident->intrinsic()) {
|
switch (ident->intrinsic()) {
|
||||||
case ast::Intrinsic::kTextureSample: {
|
case ast::Intrinsic::kTextureLoad: {
|
||||||
op = spv::Op::OpImageSampleImplicitLod;
|
op = texture_type->Is<ast::type::StorageTexture>()
|
||||||
break;
|
? spv::Op::OpImageRead
|
||||||
}
|
: spv::Op::OpImageFetch;
|
||||||
case ast::Intrinsic::kTextureSampleBias: {
|
spirv_params.emplace_back(gen_param(pidx.texture));
|
||||||
op = spv::Op::OpImageSampleImplicitLod;
|
append_coords_to_spirv_params();
|
||||||
assert(pidx.bias != kNotUsed);
|
|
||||||
image_operands.emplace_back(
|
if (pidx.level != kNotUsed) {
|
||||||
ImageOperand{SpvImageOperandsBiasMask, gen_param(pidx.bias)});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ast::Intrinsic::kTextureSampleLevel: {
|
|
||||||
op = spv::Op::OpImageSampleExplicitLod;
|
|
||||||
assert(pidx.level != kNotUsed);
|
|
||||||
image_operands.emplace_back(
|
image_operands.emplace_back(
|
||||||
ImageOperand{SpvImageOperandsLodMask, gen_param(pidx.level)});
|
ImageOperand{SpvImageOperandsLodMask, gen_param(pidx.level)});
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case ast::Intrinsic::kTextureSampleGrad: {
|
|
||||||
op = spv::Op::OpImageSampleExplicitLod;
|
|
||||||
assert(pidx.ddx != kNotUsed);
|
|
||||||
assert(pidx.ddy != kNotUsed);
|
|
||||||
image_operands.emplace_back(
|
|
||||||
ImageOperand{SpvImageOperandsGradMask, gen_param(pidx.ddx)});
|
|
||||||
image_operands.emplace_back(
|
|
||||||
ImageOperand{SpvImageOperandsGradMask, gen_param(pidx.ddy)});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ast::Intrinsic::kTextureSampleCompare: {
|
|
||||||
op = spv::Op::OpImageSampleDrefExplicitLod;
|
|
||||||
assert(pidx.depth_ref != kNotUsed);
|
|
||||||
spirv_params.emplace_back(gen_param(pidx.depth_ref));
|
|
||||||
|
|
||||||
ast::type::F32 f32;
|
if (pidx.sample_index != kNotUsed) {
|
||||||
ast::FloatLiteral float_0(&f32, 0.0);
|
image_operands.emplace_back(ImageOperand{SpvImageOperandsSampleMask,
|
||||||
image_operands.emplace_back(ImageOperand{
|
gen_param(pidx.sample_index)});
|
||||||
SpvImageOperandsLodMask,
|
|
||||||
Operand::Int(GenerateLiteralIfNeeded(nullptr, &float_0))});
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
break; // unreachable
|
break;
|
||||||
}
|
}
|
||||||
|
case ast::Intrinsic::kTextureStore: {
|
||||||
|
op = spv::Op::OpImageWrite;
|
||||||
|
spirv_params.emplace_back(gen_param(pidx.texture));
|
||||||
|
append_coords_to_spirv_params();
|
||||||
|
spirv_params.emplace_back(gen_param(pidx.value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ast::Intrinsic::kTextureSample: {
|
||||||
|
op = spv::Op::OpImageSampleImplicitLod;
|
||||||
|
append_image_and_coords_to_spirv_params();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ast::Intrinsic::kTextureSampleBias: {
|
||||||
|
op = spv::Op::OpImageSampleImplicitLod;
|
||||||
|
append_image_and_coords_to_spirv_params();
|
||||||
|
assert(pidx.bias != kNotUsed);
|
||||||
|
image_operands.emplace_back(
|
||||||
|
ImageOperand{SpvImageOperandsBiasMask, gen_param(pidx.bias)});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ast::Intrinsic::kTextureSampleLevel: {
|
||||||
|
op = spv::Op::OpImageSampleExplicitLod;
|
||||||
|
append_image_and_coords_to_spirv_params();
|
||||||
|
assert(pidx.level != kNotUsed);
|
||||||
|
image_operands.emplace_back(
|
||||||
|
ImageOperand{SpvImageOperandsLodMask, gen_param(pidx.level)});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ast::Intrinsic::kTextureSampleGrad: {
|
||||||
|
op = spv::Op::OpImageSampleExplicitLod;
|
||||||
|
append_image_and_coords_to_spirv_params();
|
||||||
|
assert(pidx.ddx != kNotUsed);
|
||||||
|
assert(pidx.ddy != kNotUsed);
|
||||||
|
image_operands.emplace_back(
|
||||||
|
ImageOperand{SpvImageOperandsGradMask, gen_param(pidx.ddx)});
|
||||||
|
image_operands.emplace_back(
|
||||||
|
ImageOperand{SpvImageOperandsGradMask, gen_param(pidx.ddy)});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ast::Intrinsic::kTextureSampleCompare: {
|
||||||
|
op = spv::Op::OpImageSampleDrefExplicitLod;
|
||||||
|
append_image_and_coords_to_spirv_params();
|
||||||
|
assert(pidx.depth_ref != kNotUsed);
|
||||||
|
spirv_params.emplace_back(gen_param(pidx.depth_ref));
|
||||||
|
|
||||||
|
ast::type::F32 f32;
|
||||||
|
ast::FloatLiteral float_0(&f32, 0.0);
|
||||||
|
image_operands.emplace_back(ImageOperand{
|
||||||
|
SpvImageOperandsLodMask,
|
||||||
|
Operand::Int(GenerateLiteralIfNeeded(nullptr, &float_0))});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break; // unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pidx.offset != kNotUsed) {
|
if (pidx.offset != kNotUsed) {
|
||||||
|
|
|
@ -2563,8 +2563,138 @@ expected_texture_overload_spirv expected_texture_overload(
|
||||||
R"(
|
R"(
|
||||||
%10 = OpLoad %3 %1
|
%10 = OpLoad %3 %1
|
||||||
%8 = OpImageRead %9 %10 %16
|
%8 = OpImageRead %9 %10 %16
|
||||||
|
)"};
|
||||||
|
case ValidTextureOverload::kStoreWO1dRgba32float:
|
||||||
|
return {R"(
|
||||||
|
%4 = OpTypeVoid
|
||||||
|
%3 = OpTypeImage %4 1D 0 0 0 2 Rgba32f
|
||||||
|
%2 = OpTypePointer Private %3
|
||||||
|
%1 = OpVariable %2 Private
|
||||||
|
%7 = OpTypeSampler
|
||||||
|
%6 = OpTypePointer Private %7
|
||||||
|
%5 = OpVariable %6 Private
|
||||||
|
%10 = OpTypeInt 32 1
|
||||||
|
%11 = OpConstant %10 1
|
||||||
|
%13 = OpTypeFloat 32
|
||||||
|
%12 = OpTypeVector %13 4
|
||||||
|
%14 = OpConstant %13 2
|
||||||
|
%15 = OpConstant %13 3
|
||||||
|
%16 = OpConstant %13 4
|
||||||
|
%17 = OpConstant %13 5
|
||||||
|
%18 = OpConstantComposite %12 %14 %15 %16 %17
|
||||||
|
)",
|
||||||
|
R"(
|
||||||
|
%9 = OpLoad %3 %1
|
||||||
|
OpImageWrite %9 %11 %18
|
||||||
|
)"};
|
||||||
|
case ValidTextureOverload::kStoreWO1dArrayRgba32float:
|
||||||
|
return {R"(
|
||||||
|
%4 = OpTypeVoid
|
||||||
|
%3 = OpTypeImage %4 1D 0 1 0 2 Rgba32f
|
||||||
|
%2 = OpTypePointer Private %3
|
||||||
|
%1 = OpVariable %2 Private
|
||||||
|
%7 = OpTypeSampler
|
||||||
|
%6 = OpTypePointer Private %7
|
||||||
|
%5 = OpVariable %6 Private
|
||||||
|
%11 = OpTypeInt 32 1
|
||||||
|
%10 = OpTypeVector %11 2
|
||||||
|
%12 = OpConstant %11 1
|
||||||
|
%13 = OpConstant %11 2
|
||||||
|
%14 = OpConstantComposite %10 %12 %13
|
||||||
|
%16 = OpTypeFloat 32
|
||||||
|
%15 = OpTypeVector %16 4
|
||||||
|
%17 = OpConstant %16 3
|
||||||
|
%18 = OpConstant %16 4
|
||||||
|
%19 = OpConstant %16 5
|
||||||
|
%20 = OpConstant %16 6
|
||||||
|
%21 = OpConstantComposite %15 %17 %18 %19 %20
|
||||||
|
)",
|
||||||
|
R"(
|
||||||
|
%9 = OpLoad %3 %1
|
||||||
|
OpImageWrite %9 %14 %21
|
||||||
|
)"};
|
||||||
|
case ValidTextureOverload::kStoreWO2dRgba32float:
|
||||||
|
return {R"(
|
||||||
|
%4 = OpTypeVoid
|
||||||
|
%3 = OpTypeImage %4 2D 0 0 0 2 Rgba32f
|
||||||
|
%2 = OpTypePointer Private %3
|
||||||
|
%1 = OpVariable %2 Private
|
||||||
|
%7 = OpTypeSampler
|
||||||
|
%6 = OpTypePointer Private %7
|
||||||
|
%5 = OpVariable %6 Private
|
||||||
|
%11 = OpTypeInt 32 1
|
||||||
|
%10 = OpTypeVector %11 2
|
||||||
|
%12 = OpConstant %11 1
|
||||||
|
%13 = OpConstant %11 2
|
||||||
|
%14 = OpConstantComposite %10 %12 %13
|
||||||
|
%16 = OpTypeFloat 32
|
||||||
|
%15 = OpTypeVector %16 4
|
||||||
|
%17 = OpConstant %16 3
|
||||||
|
%18 = OpConstant %16 4
|
||||||
|
%19 = OpConstant %16 5
|
||||||
|
%20 = OpConstant %16 6
|
||||||
|
%21 = OpConstantComposite %15 %17 %18 %19 %20
|
||||||
|
)",
|
||||||
|
R"(
|
||||||
|
%9 = OpLoad %3 %1
|
||||||
|
OpImageWrite %9 %14 %21
|
||||||
|
)"};
|
||||||
|
case ValidTextureOverload::kStoreWO2dArrayRgba32float:
|
||||||
|
return {R"(
|
||||||
|
%4 = OpTypeVoid
|
||||||
|
%3 = OpTypeImage %4 2D 0 1 0 2 Rgba32f
|
||||||
|
%2 = OpTypePointer Private %3
|
||||||
|
%1 = OpVariable %2 Private
|
||||||
|
%7 = OpTypeSampler
|
||||||
|
%6 = OpTypePointer Private %7
|
||||||
|
%5 = OpVariable %6 Private
|
||||||
|
%11 = OpTypeInt 32 1
|
||||||
|
%10 = OpTypeVector %11 3
|
||||||
|
%12 = OpConstant %11 1
|
||||||
|
%13 = OpConstant %11 2
|
||||||
|
%14 = OpConstant %11 3
|
||||||
|
%15 = OpConstantComposite %10 %12 %13 %14
|
||||||
|
%17 = OpTypeFloat 32
|
||||||
|
%16 = OpTypeVector %17 4
|
||||||
|
%18 = OpConstant %17 4
|
||||||
|
%19 = OpConstant %17 5
|
||||||
|
%20 = OpConstant %17 6
|
||||||
|
%21 = OpConstant %17 7
|
||||||
|
%22 = OpConstantComposite %16 %18 %19 %20 %21
|
||||||
|
)",
|
||||||
|
R"(
|
||||||
|
%9 = OpLoad %3 %1
|
||||||
|
OpImageWrite %9 %15 %22
|
||||||
|
)"};
|
||||||
|
case ValidTextureOverload::kStoreWO3dRgba32float:
|
||||||
|
return {R"(
|
||||||
|
%4 = OpTypeVoid
|
||||||
|
%3 = OpTypeImage %4 3D 0 0 0 2 Rgba32f
|
||||||
|
%2 = OpTypePointer Private %3
|
||||||
|
%1 = OpVariable %2 Private
|
||||||
|
%7 = OpTypeSampler
|
||||||
|
%6 = OpTypePointer Private %7
|
||||||
|
%5 = OpVariable %6 Private
|
||||||
|
%11 = OpTypeInt 32 1
|
||||||
|
%10 = OpTypeVector %11 3
|
||||||
|
%12 = OpConstant %11 1
|
||||||
|
%13 = OpConstant %11 2
|
||||||
|
%14 = OpConstant %11 3
|
||||||
|
%15 = OpConstantComposite %10 %12 %13 %14
|
||||||
|
%17 = OpTypeFloat 32
|
||||||
|
%16 = OpTypeVector %17 4
|
||||||
|
%18 = OpConstant %17 4
|
||||||
|
%19 = OpConstant %17 5
|
||||||
|
%20 = OpConstant %17 6
|
||||||
|
%21 = OpConstant %17 7
|
||||||
|
%22 = OpConstantComposite %16 %18 %19 %20 %21
|
||||||
|
)",
|
||||||
|
R"(
|
||||||
|
%9 = OpLoad %3 %1
|
||||||
|
OpImageWrite %9 %15 %22
|
||||||
)"};
|
)"};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {"<unmatched texture overload>", "<unmatched texture overload>"};
|
return {"<unmatched texture overload>", "<unmatched texture overload>"};
|
||||||
} // NOLINT - Ignore the length of this function
|
} // NOLINT - Ignore the length of this function
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue