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>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 77c0d84..39a06ef 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -478,12 +478,16 @@
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 @@
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 @@
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 @@
}
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 @@
<< 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 @@
// 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));
- return ToSignedIfUnsigned({swizzle_type, swizzle}).expr;
+ 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 @@
// 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 {
diff --git a/src/reader/spirv/parser_impl_handle_test.cc b/src/reader/spirv/parser_impl_handle_test.cc
index 99c7d53..4c84b8e 100644
--- a/src/reader/spirv/parser_impl_handle_test.cc
+++ b/src/reader/spirv/parser_impl_handle_test.cc
@@ -3170,6 +3170,864 @@
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 @@
"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"