spirv-reader: Restrict use of ConstOffset
Only permitted for image sampling (and later gather). Only permitted for 2D, 2D Array, and 3D textures Fixed: tint:408 Change-Id: Ib97bd17e45046ec8a2147b46899bf52ad9a8f883 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/35980 Auto-Submit: David Neto <dneto@google.com> Commit-Queue: Ryan Harrison <rharrison@chromium.org> Reviewed-by: Ryan Harrison <rharrison@chromium.org>
This commit is contained in:
parent
3ec1d5eae7
commit
9a644c7903
|
@ -500,6 +500,22 @@ bool IsSampledImageAccess(SpvOp opcode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @param opcode a SPIR-V opcode
|
||||||
|
// @returns true if the given instruction is an image sampling operation.
|
||||||
|
bool IsImageSampling(SpvOp opcode) {
|
||||||
|
switch (opcode) {
|
||||||
|
case SpvOpImageSampleImplicitLod:
|
||||||
|
case SpvOpImageSampleExplicitLod:
|
||||||
|
case SpvOpImageSampleDrefImplicitLod:
|
||||||
|
case SpvOpImageSampleDrefExplicitLod:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
// WGSL doesn't have *Proj* texturing.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// @param opcode a SPIR-V opcode
|
// @param opcode a SPIR-V opcode
|
||||||
// @returns true if the given instruction is an image access instruction
|
// @returns true if the given instruction is an image access instruction
|
||||||
// whose first input operand is an OpImage value.
|
// whose first input operand is an OpImage value.
|
||||||
|
@ -3989,7 +4005,8 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
|
||||||
params.push_back(create<ast::IdentifierExpression>(
|
params.push_back(create<ast::IdentifierExpression>(
|
||||||
Source{}, ast_module_.RegisterSymbol(name), name));
|
Source{}, ast_module_.RegisterSymbol(name), name));
|
||||||
|
|
||||||
if (IsSampledImageAccess(inst.opcode())) {
|
const auto opcode = inst.opcode();
|
||||||
|
if (IsSampledImageAccess(opcode)) {
|
||||||
// Form the sampler operand.
|
// Form the sampler operand.
|
||||||
const auto* sampler = parser_impl_.GetMemoryObjectDeclarationForHandle(
|
const auto* sampler = parser_impl_.GetMemoryObjectDeclarationForHandle(
|
||||||
image_or_sampled_image_operand_id, false);
|
image_or_sampled_image_operand_id, false);
|
||||||
|
@ -4029,7 +4046,7 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
|
||||||
|
|
||||||
std::string builtin_name;
|
std::string builtin_name;
|
||||||
bool use_load_suffix = true;
|
bool use_load_suffix = true;
|
||||||
switch (inst.opcode()) {
|
switch (opcode) {
|
||||||
case SpvOpImageSampleImplicitLod:
|
case SpvOpImageSampleImplicitLod:
|
||||||
case SpvOpImageSampleExplicitLod:
|
case SpvOpImageSampleExplicitLod:
|
||||||
builtin_name = "textureSample";
|
builtin_name = "textureSample";
|
||||||
|
@ -4121,12 +4138,28 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
|
||||||
}
|
}
|
||||||
if (arg_index < num_args &&
|
if (arg_index < num_args &&
|
||||||
(image_operands_mask & SpvImageOperandsConstOffsetMask)) {
|
(image_operands_mask & SpvImageOperandsConstOffsetMask)) {
|
||||||
|
if (!IsImageSampling(opcode)) {
|
||||||
|
return Fail() << "ConstOffset is only permitted for sampling operations: "
|
||||||
|
<< inst.PrettyPrint();
|
||||||
|
}
|
||||||
|
switch (texture_type->dim()) {
|
||||||
|
case ast::type::TextureDimension::k2d:
|
||||||
|
case ast::type::TextureDimension::k2dArray:
|
||||||
|
case ast::type::TextureDimension::k3d:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return Fail() << "ConstOffset is only permitted for 2D, 2D Arrayed, "
|
||||||
|
"and 3D textures: "
|
||||||
|
<< inst.PrettyPrint();
|
||||||
|
}
|
||||||
|
|
||||||
params.push_back(ToSignedIfUnsigned(MakeOperand(inst, arg_index)).expr);
|
params.push_back(ToSignedIfUnsigned(MakeOperand(inst, arg_index)).expr);
|
||||||
image_operands_mask ^= SpvImageOperandsConstOffsetMask;
|
image_operands_mask ^= SpvImageOperandsConstOffsetMask;
|
||||||
arg_index++;
|
arg_index++;
|
||||||
}
|
}
|
||||||
if (arg_index < num_args &&
|
if (arg_index < num_args &&
|
||||||
(image_operands_mask & SpvImageOperandsSampleMask)) {
|
(image_operands_mask & SpvImageOperandsSampleMask)) {
|
||||||
|
// TODO(dneto): only permitted with ImageFetch
|
||||||
params.push_back(ToI32(MakeOperand(inst, arg_index)).expr);
|
params.push_back(ToI32(MakeOperand(inst, arg_index)).expr);
|
||||||
image_operands_mask ^= SpvImageOperandsSampleMask;
|
image_operands_mask ^= SpvImageOperandsSampleMask;
|
||||||
arg_index++;
|
arg_index++;
|
||||||
|
@ -4184,7 +4217,7 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
|
||||||
value = create<ast::BitcastExpression>(Source{}, result_type, call_expr);
|
value = create<ast::BitcastExpression>(Source{}, result_type, call_expr);
|
||||||
}
|
}
|
||||||
if (!expected_component_type->Is<ast::type::F32>() &&
|
if (!expected_component_type->Is<ast::type::F32>() &&
|
||||||
IsSampledImageAccess(inst.opcode())) {
|
IsSampledImageAccess(opcode)) {
|
||||||
// WGSL permits sampled image access only on float textures.
|
// WGSL permits sampled image access only on float textures.
|
||||||
// Reject this case in the SPIR-V reader, at least until SPIR-V validation
|
// Reject this case in the SPIR-V reader, at least until SPIR-V validation
|
||||||
// catches up with this rule and can reject it earlier in the workflow.
|
// catches up with this rule and can reject it earlier in the workflow.
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace {
|
||||||
using ::testing::Eq;
|
using ::testing::Eq;
|
||||||
using ::testing::HasSubstr;
|
using ::testing::HasSubstr;
|
||||||
using ::testing::Not;
|
using ::testing::Not;
|
||||||
|
using ::testing::StartsWith;
|
||||||
|
|
||||||
std::string Preamble() {
|
std::string Preamble() {
|
||||||
return R"(
|
return R"(
|
||||||
|
@ -2617,28 +2618,6 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
Identifier[not set]{vi12}
|
Identifier[not set]{vi12}
|
||||||
Identifier[not set]{vf1234}
|
Identifier[not set]{vf1234}
|
||||||
)
|
)
|
||||||
})"},
|
|
||||||
// OpImageWrite with ConstOffset
|
|
||||||
{"%float 2D 0 0 0 2 Rgba32f",
|
|
||||||
"OpImageWrite %im %vi12 %vf1234 ConstOffset %offsets2d",
|
|
||||||
R"(
|
|
||||||
Variable{
|
|
||||||
Decorations{
|
|
||||||
SetDecoration{2}
|
|
||||||
BindingDecoration{1}
|
|
||||||
}
|
|
||||||
x_20
|
|
||||||
uniform_constant
|
|
||||||
__storage_texture_write_only_2d_rgba32float
|
|
||||||
})",
|
|
||||||
R"(Call[not set]{
|
|
||||||
Identifier[not set]{textureStore}
|
|
||||||
(
|
|
||||||
Identifier[not set]{x_20}
|
|
||||||
Identifier[not set]{vi12}
|
|
||||||
Identifier[not set]{vf1234}
|
|
||||||
Identifier[not set]{offsets2d}
|
|
||||||
)
|
|
||||||
})"}}));
|
})"}}));
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
@ -3085,35 +3064,6 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})"},
|
|
||||||
// OpImageRead with ConstOffset
|
|
||||||
{"%float 2D 0 0 0 2 Rgba32f",
|
|
||||||
"%99 = OpImageRead %v4float %im %vi12 ConstOffset %offsets2d",
|
|
||||||
R"(Variable{
|
|
||||||
Decorations{
|
|
||||||
SetDecoration{2}
|
|
||||||
BindingDecoration{1}
|
|
||||||
}
|
|
||||||
x_20
|
|
||||||
uniform_constant
|
|
||||||
__storage_texture_read_only_2d_rgba32float
|
|
||||||
})",
|
|
||||||
R"(VariableDeclStatement{
|
|
||||||
VariableConst{
|
|
||||||
x_99
|
|
||||||
none
|
|
||||||
__vec_4__f32
|
|
||||||
{
|
|
||||||
Call[not set]{
|
|
||||||
Identifier[not set]{textureLoad}
|
|
||||||
(
|
|
||||||
Identifier[not set]{x_20}
|
|
||||||
Identifier[not set]{vi12}
|
|
||||||
Identifier[not set]{offsets2d}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})"}}));
|
})"}}));
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
@ -3146,36 +3096,6 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})"},
|
|
||||||
// OpImageFetch with ConstOffset
|
|
||||||
// TODO(dneto): Seems this is not valid in WGSL.
|
|
||||||
{"%float 2D 0 0 0 1 Unknown",
|
|
||||||
"%99 = OpImageFetch %v4float %im %vi12 ConstOffset %offsets2d",
|
|
||||||
R"(Variable{
|
|
||||||
Decorations{
|
|
||||||
SetDecoration{2}
|
|
||||||
BindingDecoration{1}
|
|
||||||
}
|
|
||||||
x_20
|
|
||||||
uniform_constant
|
|
||||||
__sampled_texture_2d__f32
|
|
||||||
})",
|
|
||||||
R"(VariableDeclStatement{
|
|
||||||
VariableConst{
|
|
||||||
x_99
|
|
||||||
none
|
|
||||||
__vec_4__f32
|
|
||||||
{
|
|
||||||
Call[not set]{
|
|
||||||
Identifier[not set]{textureLoad}
|
|
||||||
(
|
|
||||||
Identifier[not set]{x_20}
|
|
||||||
Identifier[not set]{vi12}
|
|
||||||
Identifier[not set]{offsets2d}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})"},
|
})"},
|
||||||
// OpImageFetch with explicit level
|
// OpImageFetch with explicit level
|
||||||
{"%float 2D 0 0 0 1 Unknown",
|
{"%float 2D 0 0 0 1 Unknown",
|
||||||
|
@ -3760,7 +3680,7 @@ TEST_P(SpvParserTest_ImageCoordsTest, MakeCoordinateOperandsForImageAccess) {
|
||||||
)";
|
)";
|
||||||
auto p = parser(test::Assemble(assembly));
|
auto p = parser(test::Assemble(assembly));
|
||||||
if (!p->BuildAndParseInternalModule()) {
|
if (!p->BuildAndParseInternalModule()) {
|
||||||
EXPECT_THAT(p->error(), Eq(GetParam().expected_error)) << assembly;
|
EXPECT_THAT(p->error(), StartsWith(GetParam().expected_error)) << assembly;
|
||||||
} else {
|
} else {
|
||||||
EXPECT_TRUE(p->error().empty()) << p->error();
|
EXPECT_TRUE(p->error().empty()) << p->error();
|
||||||
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
@ -4456,6 +4376,59 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
"sampled image must have float component type",
|
"sampled image must have float component type",
|
||||||
{}}}));
|
{}}}));
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
ConstOffset_BadInstruction_Errors,
|
||||||
|
SpvParserTest_ImageCoordsTest,
|
||||||
|
::testing::ValuesIn(std::vector<ImageCoordsCase>{
|
||||||
|
// ImageFetch
|
||||||
|
{"%uint 2D 0 0 0 1 Unknown",
|
||||||
|
"%result = OpImageFetch %v4uint %sampled_image %vf12 ConstOffset "
|
||||||
|
"%the_vu12",
|
||||||
|
"ConstOffset is only permitted for sampling operations: ",
|
||||||
|
{}},
|
||||||
|
// ImageRead
|
||||||
|
{"%uint 2D 0 0 0 2 Rgba32ui",
|
||||||
|
"%result = OpImageRead %v4uint %im %vu12 ConstOffset %the_vu12",
|
||||||
|
"ConstOffset is only permitted for sampling operations: ",
|
||||||
|
{}},
|
||||||
|
// ImageWrite
|
||||||
|
{"%uint 2D 0 0 0 2 Rgba32ui",
|
||||||
|
"OpImageWrite %im %vu12 %vu1234 ConstOffset %the_vu12",
|
||||||
|
"ConstOffset is only permitted for sampling operations: ",
|
||||||
|
{}}
|
||||||
|
// TODO(dneto): Gather
|
||||||
|
// TODO(dneto): DrefGather
|
||||||
|
}));
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
ConstOffset_BadDim_Errors,
|
||||||
|
SpvParserTest_ImageCoordsTest,
|
||||||
|
::testing::ValuesIn(std::vector<ImageCoordsCase>{
|
||||||
|
// 1D
|
||||||
|
{"%uint 1D 0 0 0 1 Unknown",
|
||||||
|
"%result = OpImageSampleImplicitLod %v4float %sampled_image %vf1234 "
|
||||||
|
"ConstOffset %the_vu12",
|
||||||
|
"ConstOffset is only permitted for 2D, 2D Arrayed, and 3D textures: ",
|
||||||
|
{}},
|
||||||
|
// 1D Array
|
||||||
|
{"%uint 1D 0 1 0 1 Unknown",
|
||||||
|
"%result = OpImageSampleImplicitLod %v4float %sampled_image %vf1234 "
|
||||||
|
"ConstOffset %the_vu12",
|
||||||
|
"ConstOffset is only permitted for 2D, 2D Arrayed, and 3D textures: ",
|
||||||
|
{}},
|
||||||
|
// Cube
|
||||||
|
{"%uint Cube 0 0 0 1 Unknown",
|
||||||
|
"%result = OpImageSampleImplicitLod %v4float %sampled_image %vf1234 "
|
||||||
|
"ConstOffset %the_vu12",
|
||||||
|
"ConstOffset is only permitted for 2D, 2D Arrayed, and 3D textures: ",
|
||||||
|
{}},
|
||||||
|
// Cube Array
|
||||||
|
{"%uint Cube 0 1 0 1 Unknown",
|
||||||
|
"%result = OpImageSampleImplicitLod %v4float %sampled_image %vf1234 "
|
||||||
|
"ConstOffset %the_vu12",
|
||||||
|
"ConstOffset is only permitted for 2D, 2D Arrayed, and 3D textures: ",
|
||||||
|
{}}}));
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace reader
|
} // namespace reader
|
||||||
|
|
Loading…
Reference in New Issue