spirv-reader: support OpImageDrefGather
Also, issue an error when a gather or dref-gather operation is used with a Bias or Grad image operand. Fixed: tint:1336 Change-Id: Ife11d2f52a1a2d1b75e26269373db5cc4b3440bf Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/74801 Reviewed-by: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: David Neto <dneto@google.com> Auto-Submit: David Neto <dneto@google.com>
This commit is contained in:
parent
5791197e80
commit
4beeaea9da
|
@ -5286,9 +5286,24 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
|
||||||
|
|
||||||
const auto num_args = inst.NumInOperands();
|
const auto num_args = inst.NumInOperands();
|
||||||
|
|
||||||
|
// Consumes the depth-reference argument, pushing it onto the end of
|
||||||
|
// the parameter list. Issues a diagnostic and returns false on error.
|
||||||
|
auto consume_dref = [&]() -> bool {
|
||||||
|
if (arg_index < num_args) {
|
||||||
|
params.push_back(MakeOperand(inst, arg_index).expr);
|
||||||
|
arg_index++;
|
||||||
|
} else {
|
||||||
|
return Fail()
|
||||||
|
<< "image depth-compare instruction is missing a Dref operand: "
|
||||||
|
<< inst.PrettyPrint();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
std::string builtin_name;
|
std::string builtin_name;
|
||||||
bool use_level_of_detail_suffix = true;
|
bool use_level_of_detail_suffix = true;
|
||||||
bool is_dref_sample = false;
|
bool is_dref_sample = false;
|
||||||
|
bool is_gather_or_dref_gather = false;
|
||||||
bool is_non_dref_sample = false;
|
bool is_non_dref_sample = false;
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case SpvOpImageSampleImplicitLod:
|
case SpvOpImageSampleImplicitLod:
|
||||||
|
@ -5304,16 +5319,12 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
|
||||||
case SpvOpImageSampleProjDrefExplicitLod:
|
case SpvOpImageSampleProjDrefExplicitLod:
|
||||||
is_dref_sample = true;
|
is_dref_sample = true;
|
||||||
builtin_name = "textureSampleCompare";
|
builtin_name = "textureSampleCompare";
|
||||||
if (arg_index < num_args) {
|
if (!consume_dref()) {
|
||||||
params.push_back(MakeOperand(inst, arg_index).expr);
|
return false;
|
||||||
arg_index++;
|
|
||||||
} else {
|
|
||||||
return Fail()
|
|
||||||
<< "image depth-compare instruction is missing a Dref operand: "
|
|
||||||
<< inst.PrettyPrint();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SpvOpImageGather:
|
case SpvOpImageGather:
|
||||||
|
is_gather_or_dref_gather = true;
|
||||||
builtin_name = "textureGather";
|
builtin_name = "textureGather";
|
||||||
if (!texture_type->Is<DepthTexture>()) {
|
if (!texture_type->Is<DepthTexture>()) {
|
||||||
// The explicit component is the *first* argument in WGSL.
|
// The explicit component is the *first* argument in WGSL.
|
||||||
|
@ -5323,7 +5334,12 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
|
||||||
arg_index++;
|
arg_index++;
|
||||||
break;
|
break;
|
||||||
case SpvOpImageDrefGather:
|
case SpvOpImageDrefGather:
|
||||||
return Fail() << " image dref gather is not yet supported";
|
is_gather_or_dref_gather = true;
|
||||||
|
builtin_name = "textureGatherCompare";
|
||||||
|
if (!consume_dref()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SpvOpImageFetch:
|
case SpvOpImageFetch:
|
||||||
case SpvOpImageRead:
|
case SpvOpImageRead:
|
||||||
// Read a single texel from a sampled or storage image.
|
// Read a single texel from a sampled or storage image.
|
||||||
|
@ -5367,6 +5383,11 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
|
||||||
"level-of-detail bias: "
|
"level-of-detail bias: "
|
||||||
<< inst.PrettyPrint();
|
<< inst.PrettyPrint();
|
||||||
}
|
}
|
||||||
|
if (is_gather_or_dref_gather) {
|
||||||
|
return Fail() << "WGSL does not support image gather with "
|
||||||
|
"level-of-detail bias: "
|
||||||
|
<< inst.PrettyPrint();
|
||||||
|
}
|
||||||
builtin_name += "Bias";
|
builtin_name += "Bias";
|
||||||
params.push_back(MakeOperand(inst, arg_index).expr);
|
params.push_back(MakeOperand(inst, arg_index).expr);
|
||||||
image_operands_mask ^= SpvImageOperandsBiasMask;
|
image_operands_mask ^= SpvImageOperandsBiasMask;
|
||||||
|
@ -5376,9 +5397,11 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
|
||||||
if (use_level_of_detail_suffix) {
|
if (use_level_of_detail_suffix) {
|
||||||
builtin_name += "Level";
|
builtin_name += "Level";
|
||||||
}
|
}
|
||||||
if (is_dref_sample) {
|
if (is_dref_sample || is_gather_or_dref_gather) {
|
||||||
// Metal only supports Lod = 0 for comparison sampling without
|
// Metal only supports Lod = 0 for comparison sampling without
|
||||||
// derivatives.
|
// derivatives.
|
||||||
|
// Vulkan SPIR-V does not allow Lod with OpImageGather or
|
||||||
|
// OpImageDrefGather.
|
||||||
if (!IsFloatZero(inst.GetSingleWordInOperand(arg_index))) {
|
if (!IsFloatZero(inst.GetSingleWordInOperand(arg_index))) {
|
||||||
return Fail() << "WGSL comparison sampling without derivatives "
|
return Fail() << "WGSL comparison sampling without derivatives "
|
||||||
"requires level-of-detail 0.0"
|
"requires level-of-detail 0.0"
|
||||||
|
@ -5412,6 +5435,11 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
|
||||||
"explicit gradient: "
|
"explicit gradient: "
|
||||||
<< inst.PrettyPrint();
|
<< inst.PrettyPrint();
|
||||||
}
|
}
|
||||||
|
if (is_gather_or_dref_gather) {
|
||||||
|
return Fail() << "WGSL does not support image gather with "
|
||||||
|
"explicit gradient: "
|
||||||
|
<< inst.PrettyPrint();
|
||||||
|
}
|
||||||
builtin_name += "Grad";
|
builtin_name += "Grad";
|
||||||
params.push_back(MakeOperand(inst, arg_index).expr);
|
params.push_back(MakeOperand(inst, arg_index).expr);
|
||||||
params.push_back(MakeOperand(inst, arg_index + 1).expr);
|
params.push_back(MakeOperand(inst, arg_index + 1).expr);
|
||||||
|
@ -5475,8 +5503,8 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
|
||||||
// compare sample f32 DrefImplicitLod f32
|
// compare sample f32 DrefImplicitLod f32
|
||||||
// compare sample f32 DrefExplicitLod f32
|
// compare sample f32 DrefExplicitLod f32
|
||||||
// texel load vec4 ImageFetch f32
|
// texel load vec4 ImageFetch f32
|
||||||
// normal gather vec4 ImageGather vec4 TODO(dneto)
|
// normal gather vec4 ImageGather vec4
|
||||||
// dref gather vec4 ImageFetch vec4 TODO(dneto)
|
// dref gather vec4 ImageDrefGather vec4
|
||||||
// Construct a 4-element vector with the result from the builtin in the
|
// Construct a 4-element vector with the result from the builtin in the
|
||||||
// first component.
|
// first component.
|
||||||
if (texture_type->IsAnyOf<DepthTexture, DepthMultisampledTexture>()) {
|
if (texture_type->IsAnyOf<DepthTexture, DepthMultisampledTexture>()) {
|
||||||
|
|
|
@ -929,12 +929,6 @@ TEST_P(SpvParserHandleTest_RegisterHandleUsage_SampledImage, Variable) {
|
||||||
EXPECT_THAT(su.to_str(), Eq(GetParam().expected_sampler_usage));
|
EXPECT_THAT(su.to_str(), Eq(GetParam().expected_sampler_usage));
|
||||||
EXPECT_THAT(iu.to_str(), Eq(GetParam().expected_image_usage));
|
EXPECT_THAT(iu.to_str(), Eq(GetParam().expected_image_usage));
|
||||||
|
|
||||||
// TODO(dneto): remove this. crbug.com/tint/1336
|
|
||||||
if (inst.find("Gather") != std::string::npos) {
|
|
||||||
// WGSL does not support Gather instructions yet.
|
|
||||||
// So don't emit them as part of a "passing" corpus.
|
|
||||||
p->DeliberatelyInvalidSpirv();
|
|
||||||
}
|
|
||||||
if (inst.find("ImageQueryLod") != std::string::npos) {
|
if (inst.find("ImageQueryLod") != std::string::npos) {
|
||||||
// WGSL does not support querying image level of detail.
|
// WGSL does not support querying image level of detail.
|
||||||
// So don't emit them as part of a "passing" corpus.
|
// So don't emit them as part of a "passing" corpus.
|
||||||
|
@ -987,12 +981,6 @@ TEST_P(SpvParserHandleTest_RegisterHandleUsage_SampledImage, FunctionParam) {
|
||||||
EXPECT_THAT(su.to_str(), Eq(GetParam().expected_sampler_usage));
|
EXPECT_THAT(su.to_str(), Eq(GetParam().expected_sampler_usage));
|
||||||
EXPECT_THAT(iu.to_str(), Eq(GetParam().expected_image_usage));
|
EXPECT_THAT(iu.to_str(), Eq(GetParam().expected_image_usage));
|
||||||
|
|
||||||
// TODO(dneto): remove this. crbug.com/tint/1336
|
|
||||||
if (inst.find("Gather") != std::string::npos) {
|
|
||||||
// WGSL does not support Gather instructions yet.
|
|
||||||
// So don't emit them as part of a "passing" corpus.
|
|
||||||
p->DeliberatelyInvalidSpirv();
|
|
||||||
}
|
|
||||||
if (inst.find("ImageQueryLod") != std::string::npos) {
|
if (inst.find("ImageQueryLod") != std::string::npos) {
|
||||||
// WGSL does not support querying image level of detail.
|
// WGSL does not support querying image level of detail.
|
||||||
// So don't emit them as part of a "passing" corpus.
|
// So don't emit them as part of a "passing" corpus.
|
||||||
|
@ -1721,15 +1709,87 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
ImageDrefGather,
|
ImageDrefGather,
|
||||||
SpvParserHandleTest_SampledImageAccessTest,
|
SpvParserHandleTest_SampledImageAccessTest,
|
||||||
::testing::ValuesIn(std::vector<ImageAccessCase>{
|
::testing::ValuesIn(std::vector<ImageAccessCase>{
|
||||||
// TODO(dneto): OpImageDrefGather 2DDepth
|
// OpImageDrefGather 2DDepth
|
||||||
// TODO(dneto): OpImageDrefGather 2DDepth ConstOffset signed
|
ImageAccessCase{
|
||||||
// TODO(dneto): OpImageDrefGather 2DDepth ConstOffset unsigned
|
"%float 2D 1 0 0 1 Unknown",
|
||||||
// TODO(dneto): OpImageDrefGather 2DDepth Array
|
"%result = OpImageDrefGather "
|
||||||
// TODO(dneto): OpImageDrefGather 2DDepth Array ConstOffset signed
|
"%v4float %sampled_image %coords12 %depth",
|
||||||
// TODO(dneto): OpImageDrefGather 2DDepth Array ConstOffset unsigned
|
R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
|
||||||
// TODO(dneto): OpImageDrefGather DepthCube
|
|
||||||
// TODO(dneto): OpImageDrefGather DepthCube Array
|
[[group(2), binding(1)]] var x_20 : texture_depth_2d;)",
|
||||||
}));
|
"textureGatherCompare(x_20, x_10, coords12, 0.200000003)"},
|
||||||
|
// OpImageDrefGather 2DDepth ConstOffset signed
|
||||||
|
ImageAccessCase{
|
||||||
|
"%float 2D 1 0 0 1 Unknown",
|
||||||
|
"%result = OpImageDrefGather "
|
||||||
|
"%v4float %sampled_image %coords12 %depth ConstOffset %offsets2d",
|
||||||
|
R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
|
||||||
|
|
||||||
|
[[group(2), binding(1)]] var x_20 : texture_depth_2d;)",
|
||||||
|
"textureGatherCompare(x_20, x_10, coords12, 0.200000003, "
|
||||||
|
"vec2<i32>(3, 4))"},
|
||||||
|
// OpImageDrefGather 2DDepth ConstOffset unsigned
|
||||||
|
ImageAccessCase{
|
||||||
|
"%float 2D 1 0 0 1 Unknown",
|
||||||
|
"%result = OpImageDrefGather "
|
||||||
|
"%v4float %sampled_image %coords12 %depth ConstOffset "
|
||||||
|
"%u_offsets2d",
|
||||||
|
R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
|
||||||
|
|
||||||
|
[[group(2), binding(1)]] var x_20 : texture_depth_2d;)",
|
||||||
|
"textureGatherCompare(x_20, x_10, coords12, 0.200000003, "
|
||||||
|
"vec2<i32>(vec2<u32>(3u, 4u)))"},
|
||||||
|
// OpImageDrefGather 2DDepth Array
|
||||||
|
ImageAccessCase{
|
||||||
|
"%float 2D 1 1 0 1 Unknown",
|
||||||
|
"%result = OpImageDrefGather "
|
||||||
|
"%v4float %sampled_image %coords123 %depth",
|
||||||
|
R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
|
||||||
|
|
||||||
|
[[group(2), binding(1)]] var x_20 : texture_depth_2d_array;)",
|
||||||
|
"textureGatherCompare(x_20, x_10, coords123.xy, "
|
||||||
|
"i32(round(coords123.z)), 0.200000003)"},
|
||||||
|
// OpImageDrefGather 2DDepth Array ConstOffset signed
|
||||||
|
ImageAccessCase{
|
||||||
|
"%float 2D 1 1 0 1 Unknown",
|
||||||
|
"%result = OpImageDrefGather "
|
||||||
|
"%v4float %sampled_image %coords123 %depth ConstOffset %offsets2d",
|
||||||
|
R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
|
||||||
|
|
||||||
|
[[group(2), binding(1)]] var x_20 : texture_depth_2d_array;)",
|
||||||
|
"textureGatherCompare(x_20, x_10, coords123.xy, "
|
||||||
|
"i32(round(coords123.z)), 0.200000003, vec2<i32>(3, 4))"},
|
||||||
|
// OpImageDrefGather 2DDepth Array ConstOffset unsigned
|
||||||
|
ImageAccessCase{
|
||||||
|
"%float 2D 1 1 0 1 Unknown",
|
||||||
|
"%result = OpImageDrefGather "
|
||||||
|
"%v4float %sampled_image %coords123 %depth ConstOffset "
|
||||||
|
"%u_offsets2d",
|
||||||
|
R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
|
||||||
|
|
||||||
|
[[group(2), binding(1)]] var x_20 : texture_depth_2d_array;)",
|
||||||
|
"textureGatherCompare(x_20, x_10, coords123.xy, "
|
||||||
|
"i32(round(coords123.z)), 0.200000003, "
|
||||||
|
"vec2<i32>(vec2<u32>(3u, 4u)))"},
|
||||||
|
// OpImageDrefGather DepthCube
|
||||||
|
ImageAccessCase{
|
||||||
|
"%float Cube 1 0 0 1 Unknown",
|
||||||
|
"%result = OpImageDrefGather "
|
||||||
|
"%v4float %sampled_image %coords123 %depth",
|
||||||
|
R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
|
||||||
|
|
||||||
|
[[group(2), binding(1)]] var x_20 : texture_depth_cube;)",
|
||||||
|
"textureGatherCompare(x_20, x_10, coords123, 0.200000003)"},
|
||||||
|
// OpImageDrefGather DepthCube Array
|
||||||
|
ImageAccessCase{
|
||||||
|
"%float Cube 1 1 0 1 Unknown",
|
||||||
|
"%result = OpImageDrefGather "
|
||||||
|
"%v4float %sampled_image %coords1234 %depth",
|
||||||
|
R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
|
||||||
|
|
||||||
|
[[group(2), binding(1)]] var x_20 : texture_depth_cube_array;)",
|
||||||
|
"textureGatherCompare(x_20, x_10, coords1234.xyz, "
|
||||||
|
"i32(round(coords1234.w)), 0.200000003)"}}));
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
ImageSampleImplicitLod,
|
ImageSampleImplicitLod,
|
||||||
|
@ -3776,6 +3836,49 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
"WGSL does not support querying the level of detail of an image: ",
|
"WGSL does not support querying the level of detail of an image: ",
|
||||||
{}}}));
|
{}}}));
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
ImageGather_Bias_IsError,
|
||||||
|
SpvParserHandleTest_ImageCoordsTest,
|
||||||
|
::testing::ValuesIn(std::vector<ImageCoordsCase>{
|
||||||
|
{"%float 2D 0 0 0 1 Unknown",
|
||||||
|
"%result = OpImageGather %v4float %sampled_image %vf12 %int_1 "
|
||||||
|
"Bias %float_null",
|
||||||
|
"WGSL does not support image gather with level-of-detail bias: ",
|
||||||
|
{}}}));
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
ImageDrefGather_Bias_IsError,
|
||||||
|
SpvParserHandleTest_ImageCoordsTest,
|
||||||
|
::testing::ValuesIn(std::vector<ImageCoordsCase>{
|
||||||
|
{"%float 2D 1 0 0 1 Unknown",
|
||||||
|
"%result = OpImageDrefGather %v4float %sampled_image %vf12 %depth "
|
||||||
|
"Bias %float_null",
|
||||||
|
"WGSL does not support image gather with level-of-detail bias: ",
|
||||||
|
{}}}));
|
||||||
|
|
||||||
|
// Note: Vulkan SPIR-V ImageGather and ImageDrefGather do not allow explicit
|
||||||
|
// Lod. The SPIR-V validator should reject those cases already.
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
ImageGather_Grad_IsError,
|
||||||
|
SpvParserHandleTest_ImageCoordsTest,
|
||||||
|
::testing::ValuesIn(std::vector<ImageCoordsCase>{
|
||||||
|
{"%float 2D 0 0 0 1 Unknown",
|
||||||
|
"%result = OpImageGather %v4float %sampled_image %vf12 %int_1 "
|
||||||
|
"Grad %vf12 %vf12",
|
||||||
|
"WGSL does not support image gather with explicit gradient: ",
|
||||||
|
{}}}));
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
ImageDrefGather_Grad_IsError,
|
||||||
|
SpvParserHandleTest_ImageCoordsTest,
|
||||||
|
::testing::ValuesIn(std::vector<ImageCoordsCase>{
|
||||||
|
{"%float 2D 1 0 0 1 Unknown",
|
||||||
|
"%result = OpImageDrefGather %v4float %sampled_image %vf12 %depth "
|
||||||
|
"Grad %vf12 %vf12",
|
||||||
|
"WGSL does not support image gather with explicit gradient: ",
|
||||||
|
{}}}));
|
||||||
|
|
||||||
TEST_F(SpvParserHandleTest,
|
TEST_F(SpvParserHandleTest,
|
||||||
NeverGenerateConstDeclForHandle_UseVariableDirectly) {
|
NeverGenerateConstDeclForHandle_UseVariableDirectly) {
|
||||||
// An ad-hoc test to prove we never had the issue
|
// An ad-hoc test to prove we never had the issue
|
||||||
|
|
Loading…
Reference in New Issue