spirv-reader: Implement OpImageSampleProj* instructions

Bug: tint:1143
Change-Id: Ic07245a2c5afdb2400f3a9777b6fd42f70dab3c8
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/64700
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: David Neto <dneto@google.com>
This commit is contained in:
Austin Eng 2021-09-24 18:00:04 +00:00 committed by Tint LUCI CQ
parent 594e010cfb
commit b9a2f5946e
2 changed files with 951 additions and 7 deletions

View File

@ -478,12 +478,16 @@ bool IsSampledImageAccess(SpvOp opcode) {
case SpvOpImageSampleExplicitLod:
case SpvOpImageSampleDrefImplicitLod:
case SpvOpImageSampleDrefExplicitLod:
// WGSL doesn't have *Proj* texturing; spirv reader emulates it.
case SpvOpImageSampleProjImplicitLod:
case SpvOpImageSampleProjExplicitLod:
case SpvOpImageSampleProjDrefImplicitLod:
case SpvOpImageSampleProjDrefExplicitLod:
case SpvOpImageGather:
case SpvOpImageDrefGather:
case SpvOpImageQueryLod:
return true;
default:
// WGSL doesn't have *Proj* texturing.
break;
}
return false;
@ -497,9 +501,13 @@ bool IsImageSampling(SpvOp opcode) {
case SpvOpImageSampleExplicitLod:
case SpvOpImageSampleDrefImplicitLod:
case SpvOpImageSampleDrefExplicitLod:
// WGSL doesn't have *Proj* texturing; spirv reader emulates it.
case SpvOpImageSampleProjImplicitLod:
case SpvOpImageSampleProjExplicitLod:
case SpvOpImageSampleProjDrefImplicitLod:
case SpvOpImageSampleProjDrefExplicitLod:
return true;
default:
// WGSL doesn't have *Proj* texturing.
break;
}
return false;
@ -5256,11 +5264,15 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
switch (opcode) {
case SpvOpImageSampleImplicitLod:
case SpvOpImageSampleExplicitLod:
case SpvOpImageSampleProjImplicitLod:
case SpvOpImageSampleProjExplicitLod:
is_non_dref_sample = true;
builtin_name = "textureSample";
break;
case SpvOpImageSampleDrefImplicitLod:
case SpvOpImageSampleDrefExplicitLod:
case SpvOpImageSampleProjDrefImplicitLod:
case SpvOpImageSampleProjDrefExplicitLod:
is_dref_sample = true;
builtin_name = "textureSampleCompare";
if (arg_index < num_args) {
@ -5304,7 +5316,8 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
}
break;
default:
return Fail() << "internal error: sampled image access";
return Fail() << "internal error: unrecognized image access: "
<< inst.PrettyPrint();
}
// Loop over the image operands, looking for extra operands to the builtin.
@ -5601,7 +5614,20 @@ ast::ExpressionList FunctionEmitter::MakeCoordinateOperandsForImageAccess(
<< texture_type->TypeInfo().name << " prompted by "
<< inst.PrettyPrint();
}
const auto num_coords_required = num_axes + (is_arrayed ? 1 : 0);
bool is_proj = false;
switch (inst.opcode()) {
case SpvOpImageSampleProjImplicitLod:
case SpvOpImageSampleProjExplicitLod:
case SpvOpImageSampleProjDrefImplicitLod:
case SpvOpImageSampleProjDrefExplicitLod:
is_proj = true;
break;
default:
break;
}
const auto num_coords_required =
num_axes + (is_arrayed ? 1 : 0) + (is_proj ? 1 : 0);
uint32_t num_coords_supplied = 0;
auto* component_type = raw_coords.type;
if (component_type->IsFloatScalar() || component_type->IsIntegerScalar()) {
@ -5629,13 +5655,20 @@ ast::ExpressionList FunctionEmitter::MakeCoordinateOperandsForImageAccess(
// it to a signed value of the same shape (scalar or vector).
// Use a lambda to make it easy to only generate the expressions when we
// will actually use them.
auto prefix_swizzle_expr = [this, num_axes, component_type,
auto prefix_swizzle_expr = [this, num_axes, component_type, is_proj,
raw_coords]() -> ast::Expression* {
auto* swizzle_type =
(num_axes == 1) ? component_type : ty_.Vector(component_type, num_axes);
auto* swizzle = create<ast::MemberAccessorExpression>(
Source{}, raw_coords.expr, PrefixSwizzle(num_axes));
if (is_proj) {
auto* q = create<ast::MemberAccessorExpression>(Source{}, raw_coords.expr,
Swizzle(num_axes));
auto* proj_div = builder_.Div(swizzle, q);
return ToSignedIfUnsigned({swizzle_type, proj_div}).expr;
} else {
return ToSignedIfUnsigned({swizzle_type, swizzle}).expr;
}
};
if (is_arrayed) {
@ -5650,7 +5683,7 @@ ast::ExpressionList FunctionEmitter::MakeCoordinateOperandsForImageAccess(
// Convert it to a signed integer type, if needed
result.push_back(ToI32({component_type, array_index}).expr);
} else {
if (num_coords_supplied == num_coords_required) {
if (num_coords_supplied == num_coords_required && !is_proj) {
// Pass the value through, with possible unsigned->signed conversion.
result.push_back(ToSignedIfUnsigned(raw_coords).expr);
} else {

View File

@ -3170,6 +3170,864 @@ INSTANTIATE_TEST_SUITE_P(
ScalarConstructor[not set]{0.000000}
})"}}));
/////
// Projection sampling
/////
// Test matrix for projection sampling:
// sampling
// Dimensions: 1D, 2D, 3D, 2DShadow
// Variations: Proj { ImplicitLod { | Bias } | ExplicitLod { Lod | Grad | } }
// x { | ConstOffset }
// depth-compare sampling
// Dimensions: 2D
// Variations: Proj Dref { ImplicitLod { | Bias } | ExplicitLod { Lod | Grad |
// } } x { | ConstOffset }
//
// Expanded:
// ImageSampleProjImplicitLod // { | ConstOffset }
// ImageSampleProjImplicitLod_Bias // { | ConstOffset }
// ImageSampleProjExplicitLod_Lod // { | ConstOffset }
// ImageSampleProjExplicitLod_Grad // { | ConstOffset }
//
// ImageSampleProjImplicitLod_DepthTexture
//
// ImageSampleProjDrefImplicitLod // { | ConstOffset }
// ImageSampleProjDrefExplicitLod_Lod // { | ConstOffset }
INSTANTIATE_TEST_SUITE_P(
ImageSampleProjImplicitLod,
SpvParserHandleTest_SampledImageAccessTest,
::testing::Values(
// OpImageSampleProjImplicitLod 1D
ImageAccessCase{"%float 1D 0 0 0 1 Unknown",
"%result = OpImageSampleProjImplicitLod "
"%v4float %sampled_image %coords12",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_sampler
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__sampled_texture_1d__f32
})",
R"(
Call[not set]{
Identifier[not set]{textureSample}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords12}
Identifier[not set]{x}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords12}
Identifier[not set]{y}
}
}
)
})"},
// OpImageSampleProjImplicitLod 2D
ImageAccessCase{"%float 2D 0 0 0 1 Unknown",
"%result = OpImageSampleProjImplicitLod "
"%v4float %sampled_image %coords123",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_sampler
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__sampled_texture_2d__f32
})",
R"(
Call[not set]{
Identifier[not set]{textureSample}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
)
})"},
// OpImageSampleProjImplicitLod 3D
ImageAccessCase{"%float 3D 0 0 0 1 Unknown",
"%result = OpImageSampleProjImplicitLod "
"%v4float %sampled_image %coords1234",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_sampler
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__sampled_texture_3d__f32
})",
R"(
Call[not set]{
Identifier[not set]{textureSample}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords1234}
Identifier[not set]{xyz}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords1234}
Identifier[not set]{w}
}
}
)
})"},
// OpImageSampleProjImplicitLod 2D with ConstOffset
// (Don't need to test with 1D or 3D, as the hard part was the splatted
// division.) This case tests handling of the ConstOffset
ImageAccessCase{
"%float 2D 0 0 0 1 Unknown",
"%result = OpImageSampleProjImplicitLod "
"%v4float %sampled_image %coords123 ConstOffset %offsets2d",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_sampler
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__sampled_texture_2d__f32
})",
R"(
Call[not set]{
Identifier[not set]{textureSample}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
TypeConstructor[not set]{
__vec_2__i32
ScalarConstructor[not set]{3}
ScalarConstructor[not set]{4}
}
)
})"}));
INSTANTIATE_TEST_SUITE_P(
ImageSampleProjImplicitLod_Bias,
SpvParserHandleTest_SampledImageAccessTest,
::testing::Values(
// OpImageSampleProjImplicitLod with Bias
// Only testing 2D
ImageAccessCase{"%float 2D 0 0 0 1 Unknown",
"%result = OpImageSampleProjImplicitLod "
"%v4float %sampled_image %coords123 Bias %float_7",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_sampler
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__sampled_texture_2d__f32
})",
R"(
Call[not set]{
Identifier[not set]{textureSampleBias}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
ScalarConstructor[not set]{7.000000}
)
})"},
// OpImageSampleProjImplicitLod with Bias and signed ConstOffset
ImageAccessCase{"%float 2D 0 0 0 1 Unknown",
"%result = OpImageSampleProjImplicitLod "
"%v4float %sampled_image %coords123 Bias|ConstOffset "
"%float_7 %offsets2d",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_sampler
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__sampled_texture_2d__f32
})",
R"(
Call[not set]{
Identifier[not set]{textureSampleBias}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
ScalarConstructor[not set]{7.000000}
TypeConstructor[not set]{
__vec_2__i32
ScalarConstructor[not set]{3}
ScalarConstructor[not set]{4}
}
)
})"},
// OpImageSampleProjImplicitLod with Bias and unsigned ConstOffset
// Convert ConstOffset to signed
ImageAccessCase{"%float 2D 0 0 0 1 Unknown",
"%result = OpImageSampleProjImplicitLod "
"%v4float %sampled_image %coords123 Bias|ConstOffset "
"%float_7 %u_offsets2d",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_sampler
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__sampled_texture_2d__f32
})",
R"(
Call[not set]{
Identifier[not set]{textureSampleBias}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
ScalarConstructor[not set]{7.000000}
TypeConstructor[not set]{
__vec_2__i32
TypeConstructor[not set]{
__vec_2__u32
ScalarConstructor[not set]{3u}
ScalarConstructor[not set]{4u}
}
}
)
})"}));
INSTANTIATE_TEST_SUITE_P(
ImageSampleProjExplicitLod_Lod,
SpvParserHandleTest_SampledImageAccessTest,
::testing::Values(
// OpImageSampleProjExplicitLod 2D
ImageAccessCase{"%float 2D 0 0 0 1 Unknown",
"%result = OpImageSampleProjExplicitLod "
"%v4float %sampled_image %coords123 Lod %f1",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_sampler
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__sampled_texture_2d__f32
})",
R"(
Call[not set]{
Identifier[not set]{textureSampleLevel}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
Identifier[not set]{f1}
)
})"},
// OpImageSampleProjExplicitLod 2D Lod with ConstOffset
ImageAccessCase{
"%float 2D 0 0 0 1 Unknown",
"%result = OpImageSampleProjExplicitLod "
"%v4float %sampled_image %coords123 Lod|ConstOffset %f1 %offsets2d",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_sampler
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__sampled_texture_2d__f32
})",
R"(
Call[not set]{
Identifier[not set]{textureSampleLevel}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
Identifier[not set]{f1}
TypeConstructor[not set]{
__vec_2__i32
ScalarConstructor[not set]{3}
ScalarConstructor[not set]{4}
}
)
})"}));
INSTANTIATE_TEST_SUITE_P(
ImageSampleProjExplicitLod_Grad,
SpvParserHandleTest_SampledImageAccessTest,
::testing::Values(
// OpImageSampleProjExplicitLod 2D Grad
ImageAccessCase{"%float 2D 0 0 0 1 Unknown",
"%result = OpImageSampleProjExplicitLod "
"%v4float %sampled_image %coords123 Grad %vf12 %vf21",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_sampler
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__sampled_texture_2d__f32
})",
R"(
Call[not set]{
Identifier[not set]{textureSampleGrad}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
Identifier[not set]{vf12}
Identifier[not set]{vf21}
)
})"},
// OpImageSampleProjExplicitLod 2D Lod Grad ConstOffset
ImageAccessCase{"%float 2D 0 0 0 1 Unknown",
"%result = OpImageSampleProjExplicitLod "
"%v4float %sampled_image %coords123 Grad|ConstOffset "
"%vf12 %vf21 %offsets2d",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_sampler
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__sampled_texture_2d__f32
})",
R"(
Call[not set]{
Identifier[not set]{textureSampleGrad}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
Identifier[not set]{vf12}
Identifier[not set]{vf21}
TypeConstructor[not set]{
__vec_2__i32
ScalarConstructor[not set]{3}
ScalarConstructor[not set]{4}
}
)
})"}));
INSTANTIATE_TEST_SUITE_P(
// Ordinary (non-comparison) sampling on a depth texture.
ImageSampleProjImplicitLod_DepthTexture,
SpvParserHandleTest_SampledImageAccessTest,
::testing::Values(
// OpImageSampleProjImplicitLod 2D depth
ImageAccessCase{"%float 2D 1 0 0 1 Unknown",
"%result = OpImageSampleProjImplicitLod "
"%v4float %sampled_image %coords123",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_sampler
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__depth_texture_2d
})",
// Sampling the depth texture yields an f32, but the
// SPIR-V operation yiedls vec4<f32>, so fill out the
// remaining components with 0.
R"(
TypeConstructor[not set]{
__vec_4__f32
Call[not set]{
Identifier[not set]{textureSample}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
)
}
ScalarConstructor[not set]{0.000000}
ScalarConstructor[not set]{0.000000}
ScalarConstructor[not set]{0.000000}
})"}));
INSTANTIATE_TEST_SUITE_P(
ImageSampleProjDrefImplicitLod,
SpvParserHandleTest_SampledImageAccessTest,
::testing::Values(
// OpImageSampleProjDrefImplicitLod 2D depth-texture
ImageAccessCase{"%float 2D 1 0 0 1 Unknown",
"%result = OpImageSampleProjDrefImplicitLod "
"%float %sampled_image %coords123 %f1",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_comparison
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__depth_texture_2d
})",
R"(
Call[not set]{
Identifier[not set]{textureSampleCompare}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
Identifier[not set]{f1}
)
})"},
// OpImageSampleProjDrefImplicitLod 2D depth-texture, ConstOffset
ImageAccessCase{
"%float 2D 1 0 0 1 Unknown",
"%result = OpImageSampleProjDrefImplicitLod "
"%float %sampled_image %coords123 %f1 ConstOffset %offsets2d",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_comparison
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__depth_texture_2d
})",
R"(
Call[not set]{
Identifier[not set]{textureSampleCompare}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
Identifier[not set]{f1}
TypeConstructor[not set]{
__vec_2__i32
ScalarConstructor[not set]{3}
ScalarConstructor[not set]{4}
}
)
})"}));
INSTANTIATE_TEST_SUITE_P(
DISABLED_ImageSampleProjDrefExplicitLod_Lod,
SpvParserHandleTest_SampledImageAccessTest,
::testing::Values(
// Lod must be float constant 0 due to a Metal constraint.
// Another test checks cases where the Lod is not float constant 0.
// OpImageSampleProjDrefExplicitLod 2D depth-texture Lod
ImageAccessCase{"%float 2D 1 0 0 1 Unknown",
"%result = OpImageSampleProjDrefExplicitLod "
"%float %sampled_image %coords123 %depth Lod %float_0",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_comparison
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__depth_texture_2d
})",
R"(
Call[not set]{
Identifier[not set]{textureSampleCompare}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
ScalarConstructor[not set]{0.200000}
ScalarConstructor[not set]{0.000000}
)
})"},
// OpImageSampleProjDrefImplicitLod 2D depth-texture, Lod ConstOffset
ImageAccessCase{"%float 2D 1 0 0 1 Unknown",
"%result = OpImageSampleProjDrefExplicitLod "
"%float %sampled_image %coords123 %depth "
"Lod|ConstOffset %float_0 %offsets2d",
R"(
Variable{
Decorations{
GroupDecoration{0}
BindingDecoration{0}
}
x_10
none
undefined
__sampler_comparison
}
Variable{
Decorations{
GroupDecoration{2}
BindingDecoration{1}
}
x_20
none
undefined
__depth_texture_2d
})",
R"(
Call[not set]{
Identifier[not set]{textureSampleCompareLevel}
(
Identifier[not set]{x_20}
Identifier[not set]{x_10}
Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{coords123}
Identifier[not set]{z}
}
}
ScalarConstructor[not set]{0.200000}
ScalarConstructor[not set]{0.000000}
TypeConstructor[not set]{
__vec_2__i32
ScalarConstructor[not set]{3}
ScalarConstructor[not set]{4}
}
)
})"}));
/////
// End projection sampling
/////
using SpvParserHandleTest_ImageAccessTest =
SpvParserTestBase<::testing::TestWithParam<ImageAccessCase>>;
@ -6368,6 +7226,59 @@ INSTANTIATE_TEST_SUITE_P(
"0.0",
{}}}));
INSTANTIATE_TEST_SUITE_P(
ImageSampleProjDrefExplicitLod_CheckForLod0,
// This is like the previous test, but for Projection sampling.
//
// Metal requires comparison sampling with explicit Level-of-detail to use
// Lod 0. The SPIR-V reader requires the operand to be parsed as a constant
// 0 value. SPIR-V validation requires the Lod parameter to be a floating
// point value for non-fetch operations. So only test float values.
SpvParserHandleTest_ImageCoordsTest,
::testing::ValuesIn(std::vector<ImageCoordsCase>{
// float 0.0 works
{"%float 2D 1 0 0 1 Unknown",
"%result = OpImageSampleProjDrefExplicitLod %float %sampled_image "
"%vf1234 %depth Lod %float_0",
"",
{R"(Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{vf1234}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{vf1234}
Identifier[not set]{z}
}
}
)"}},
// float null works
{"%float 2D 1 0 0 1 Unknown",
"%result = OpImageSampleProjDrefExplicitLod %float %sampled_image "
"%vf1234 %depth Lod %float_0",
"",
{R"(Binary[not set]{
MemberAccessor[not set]{
Identifier[not set]{vf1234}
Identifier[not set]{xy}
}
divide
MemberAccessor[not set]{
Identifier[not set]{vf1234}
Identifier[not set]{z}
}
}
)"}},
// float 1.0 fails.
{"%float 2D 1 0 0 1 Unknown",
"%result = OpImageSampleProjDrefExplicitLod %float %sampled_image "
"%vf1234 %depth Lod %float_1",
"WGSL comparison sampling without derivatives requires "
"level-of-detail "
"0.0",
{}}}));
TEST_F(SpvParserHandleTest, CombinedImageSampler_IsError) {
const auto assembly = Preamble() + R"(
OpEntryPoint Fragment %100 "main"