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::kTextureSampleBias ||
|
||||
i == Intrinsic::kTextureSampleCompare ||
|
||||
i == Intrinsic::kTextureSampleGrad;
|
||||
i == Intrinsic::kTextureSampleGrad || i == Intrinsic::kTextureStore;
|
||||
}
|
||||
|
||||
} // namespace intrinsic
|
||||
|
|
|
@ -91,6 +91,7 @@ enum class Intrinsic {
|
|||
kTextureSampleCompare,
|
||||
kTextureSampleGrad,
|
||||
kTextureSampleLevel,
|
||||
kTextureStore,
|
||||
kTrunc
|
||||
};
|
||||
|
||||
|
@ -143,6 +144,8 @@ struct TextureSignature : public Signature {
|
|||
size_t sample_index = kNotUsed;
|
||||
/// `texture` parameter index.
|
||||
size_t texture = kNotUsed;
|
||||
/// `value` parameter index.
|
||||
size_t value = kNotUsed;
|
||||
};
|
||||
/// The indices of all possible parameters.
|
||||
Index idx;
|
||||
|
|
|
@ -1976,6 +1976,90 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
|
|||
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,
|
||||
kLoadStorageRO2dArrayRgba32float, // 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
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "src/ast/type/texture_type.h"
|
||||
#include "src/ast/type/u32_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/unary_op_expression.h"
|
||||
#include "src/ast/variable_decl_statement.h"
|
||||
|
@ -640,6 +641,14 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
|
|||
param.idx.offset = param.count++;
|
||||
}
|
||||
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:
|
||||
set_error(expr->source(),
|
||||
"Internal compiler error: Unreachable intrinsic " +
|
||||
|
@ -658,23 +667,32 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
|
|||
ident->set_intrinsic_signature(
|
||||
std::make_unique<ast::intrinsic::TextureSignature>(param));
|
||||
|
||||
if (texture->Is<ast::type::DepthTexture>()) {
|
||||
expr->func()->set_result_type(mod_->create<ast::type::F32>());
|
||||
// Set the function return type
|
||||
ast::type::Type* return_type = nullptr;
|
||||
if (ident->intrinsic() == ast::Intrinsic::kTextureStore) {
|
||||
return_type = mod_->create<ast::type::Void>();
|
||||
} else {
|
||||
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();
|
||||
if (texture->Is<ast::type::DepthTexture>()) {
|
||||
return_type = mod_->create<ast::type::F32>();
|
||||
} else {
|
||||
set_error(expr->source(), "unknown texture type for texture sampling");
|
||||
return false;
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
if (ident->intrinsic() == ast::Intrinsic::kDot) {
|
||||
|
@ -996,6 +1014,8 @@ bool TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) {
|
|||
ident->set_intrinsic(ast::Intrinsic::kTanh);
|
||||
} else if (ident->name() == "textureLoad") {
|
||||
ident->set_intrinsic(ast::Intrinsic::kTextureLoad);
|
||||
} else if (ident->name() == "textureStore") {
|
||||
ident->set_intrinsic(ast::Intrinsic::kTextureStore);
|
||||
} else if (ident->name() == "textureSample") {
|
||||
ident->set_intrinsic(ast::Intrinsic::kTextureSample);
|
||||
} 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.sample_index, "sample_index");
|
||||
maybe_add_param(sig->params.idx.texture, "texture");
|
||||
maybe_add_param(sig->params.idx.value, "value");
|
||||
std::sort(
|
||||
params.begin(), params.end(),
|
||||
[](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))";
|
||||
case ValidTextureOverload::kLoadStorageRO3dRgba32float:
|
||||
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>";
|
||||
}
|
||||
|
@ -4748,18 +4759,23 @@ TEST_P(TypeDeterminerTextureIntrinsicTest, Call) {
|
|||
ASSERT_TRUE(td()->Determine()) << td()->error();
|
||||
ASSERT_TRUE(td()->DetermineResultType(&call)) << td()->error();
|
||||
|
||||
switch (param.texture_kind) {
|
||||
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>());
|
||||
EXPECT_EQ(call.result_type()->As<ast::type::Vector>()->type(), datatype);
|
||||
break;
|
||||
}
|
||||
case ast::intrinsic::test::TextureKind::kDepth: {
|
||||
EXPECT_EQ(call.result_type(), ty.f32);
|
||||
break;
|
||||
if (std::string(param.function) == "textureStore") {
|
||||
EXPECT_EQ(call.result_type(), ty.void_);
|
||||
} else {
|
||||
switch (param.texture_kind) {
|
||||
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>());
|
||||
EXPECT_EQ(call.result_type()->As<ast::type::Vector>()->type(),
|
||||
datatype);
|
||||
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,
|
||||
std::ostream& out,
|
||||
ast::CallExpression* expr) {
|
||||
make_indent(out);
|
||||
|
||||
auto* ident = expr->func()->As<ast::IdentifierExpression>();
|
||||
|
||||
auto params = expr->params();
|
||||
|
@ -759,6 +757,9 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
|
|||
pack_mip_in_coords = true;
|
||||
}
|
||||
break;
|
||||
case ast::Intrinsic::kTextureStore:
|
||||
out << "[";
|
||||
break;
|
||||
default:
|
||||
error_ = "Internal compiler error: Unhandled texture intrinsic '" +
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -229,6 +229,16 @@ std::string expected_texture_overload(
|
|||
return R"(texture_tint_0.Load(int3(1, 2, 3)))";
|
||||
case ValidTextureOverload::kLoadStorageRO3dRgba32float:
|
||||
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>";
|
||||
} // NOLINT - Ignore the length of this function
|
||||
|
|
|
@ -679,6 +679,9 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
|
|||
out_ << ".read(";
|
||||
lod_param_is_named = false;
|
||||
break;
|
||||
case ast::Intrinsic::kTextureStore:
|
||||
out_ << ".write(";
|
||||
break;
|
||||
default:
|
||||
error_ = "Internal compiler error: Unhandled texture intrinsic '" +
|
||||
ident->name() + "'";
|
||||
|
@ -693,15 +696,8 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
|
|||
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}) {
|
||||
for (auto idx : {pidx.value, pidx.sampler, pidx.coords, pidx.array_index,
|
||||
pidx.depth_ref, pidx.sample_index}) {
|
||||
if (idx != kNotUsed) {
|
||||
maybe_write_comma();
|
||||
if (!EmitExpression(params[idx]))
|
||||
|
|
|
@ -229,6 +229,16 @@ std::string expected_texture_overload(
|
|||
return R"(texture_tint_0.read(int2(1, 2), 3))";
|
||||
case ValidTextureOverload::kLoadStorageRO3dRgba32float:
|
||||
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>";
|
||||
} // NOLINT - Ignore the length of this function
|
||||
|
|
|
@ -1943,8 +1943,10 @@ void Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
|||
// 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
|
||||
if (ident->intrinsic() != ast::Intrinsic::kTextureStore) {
|
||||
spirv_params.emplace_back(std::move(result_type));
|
||||
spirv_params.emplace_back(std::move(result_id));
|
||||
}
|
||||
|
||||
// Extra image operands, appended to spirv_params.
|
||||
struct ImageOperand {
|
||||
|
@ -1977,24 +1979,9 @@ void Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
|||
}
|
||||
};
|
||||
|
||||
if (ident->intrinsic() == ast::Intrinsic::kTextureLoad) {
|
||||
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 {
|
||||
auto append_image_and_coords_to_spirv_params = [&] {
|
||||
assert(pidx.sampler != kNotUsed);
|
||||
|
||||
assert(pidx.texture != kNotUsed);
|
||||
auto sampler_param = gen_param(pidx.sampler);
|
||||
auto texture_param = gen_param(pidx.texture);
|
||||
auto sampled_image =
|
||||
|
@ -2003,51 +1990,82 @@ void Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
|
|||
// Populate the spirv_params with the common parameters
|
||||
spirv_params.emplace_back(Operand::Int(sampled_image)); // sampled image
|
||||
append_coords_to_spirv_params();
|
||||
};
|
||||
|
||||
switch (ident->intrinsic()) {
|
||||
case ast::Intrinsic::kTextureSample: {
|
||||
op = spv::Op::OpImageSampleImplicitLod;
|
||||
break;
|
||||
}
|
||||
case ast::Intrinsic::kTextureSampleBias: {
|
||||
op = spv::Op::OpImageSampleImplicitLod;
|
||||
assert(pidx.bias != kNotUsed);
|
||||
image_operands.emplace_back(
|
||||
ImageOperand{SpvImageOperandsBiasMask, gen_param(pidx.bias)});
|
||||
break;
|
||||
}
|
||||
case ast::Intrinsic::kTextureSampleLevel: {
|
||||
op = spv::Op::OpImageSampleExplicitLod;
|
||||
assert(pidx.level != kNotUsed);
|
||||
switch (ident->intrinsic()) {
|
||||
case ast::Intrinsic::kTextureLoad: {
|
||||
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)});
|
||||
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;
|
||||
ast::FloatLiteral float_0(&f32, 0.0);
|
||||
image_operands.emplace_back(ImageOperand{
|
||||
SpvImageOperandsLodMask,
|
||||
Operand::Int(GenerateLiteralIfNeeded(nullptr, &float_0))});
|
||||
break;
|
||||
if (pidx.sample_index != kNotUsed) {
|
||||
image_operands.emplace_back(ImageOperand{SpvImageOperandsSampleMask,
|
||||
gen_param(pidx.sample_index)});
|
||||
}
|
||||
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) {
|
||||
|
|
|
@ -2563,8 +2563,138 @@ expected_texture_overload_spirv expected_texture_overload(
|
|||
R"(
|
||||
%10 = OpLoad %3 %1
|
||||
%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>"};
|
||||
} // NOLINT - Ignore the length of this function
|
||||
|
||||
|
|
Loading…
Reference in New Issue