spirv-reader: float array layer conversion uses round-to-even

Vulkan requires round-to-nearest when converting from a float
coordinate to an integer array layer. It prefers round-to-nearest-even.
Use round-to-nearest-even, instad of relying on the rounding behaviour
of the i32(f32) overload.

Fixes: tint:1316
Change-Id: I43624e25e8ea27d3a6e04841a911bbb9418810d0
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/70343
Auto-Submit: David Neto <dneto@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
David Neto 2021-11-22 10:14:36 +00:00 committed by Tint LUCI CQ
parent 1bf5af25ad
commit c87dc10ce3
2 changed files with 34 additions and 27 deletions

View File

@ -5697,9 +5697,16 @@ ast::ExpressionList FunctionEmitter::MakeCoordinateOperandsForImageAccess(
result.push_back(prefix_swizzle_expr()); result.push_back(prefix_swizzle_expr());
// Now get the array index. // Now get the array index.
const ast::Expression* array_index = create<ast::MemberAccessorExpression>( const ast::Expression* array_index =
Source{}, raw_coords.expr, Swizzle(num_axes)); builder_.MemberAccessor(raw_coords.expr, Swizzle(num_axes));
// Convert it to a signed integer type, if needed if (component_type->IsFloatScalar()) {
// When converting from a float array layer to integer, Vulkan requires
// round-to-nearest, with preference for round-to-nearest-even.
// But i32(f32) in WGSL has unspecified rounding mode, so we have to
// explicitly specify the rounding.
array_index = builder_.Call("round", array_index);
}
// Convert it to a signed integer type, if needed.
result.push_back(ToI32({component_type, array_index}).expr); result.push_back(ToI32({component_type, array_index}).expr);
} else { } else {
if (num_coords_supplied == num_coords_required && !is_proj) { if (num_coords_supplied == num_coords_required && !is_proj) {

View File

@ -1607,7 +1607,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler; R"([[group(0), binding(0)]] var x_10 : sampler;
[[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)", [[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)",
"textureSample(x_20, x_10, coords123.xy, i32(coords123.z))"}, "textureSample(x_20, x_10, coords123.xy, i32(round(coords123.z)))"},
// OpImageSampleImplicitLod with ConstOffset // OpImageSampleImplicitLod with ConstOffset
ImageAccessCase{ ImageAccessCase{
@ -1627,7 +1627,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler; R"([[group(0), binding(0)]] var x_10 : sampler;
[[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)", [[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)",
R"(textureSample(x_20, x_10, coords123.xy, i32(coords123.z), vec2<i32>(3, 4)))"}, R"(textureSample(x_20, x_10, coords123.xy, i32(round(coords123.z)), vec2<i32>(3, 4)))"},
// OpImageSampleImplicitLod with Bias // OpImageSampleImplicitLod with Bias
ImageAccessCase{"%float 2D 0 0 0 1 Unknown", ImageAccessCase{"%float 2D 0 0 0 1 Unknown",
@ -1646,7 +1646,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler; R"([[group(0), binding(0)]] var x_10 : sampler;
[[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)", [[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)",
R"(textureSampleBias(x_20, x_10, coords123.xy, i32(coords123.z), 7.0))"}, R"(textureSampleBias(x_20, x_10, coords123.xy, i32(round(coords123.z)), 7.0))"},
// OpImageSampleImplicitLod with Bias and signed ConstOffset // OpImageSampleImplicitLod with Bias and signed ConstOffset
ImageAccessCase{ ImageAccessCase{
@ -1679,7 +1679,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler; R"([[group(0), binding(0)]] var x_10 : sampler;
[[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)", [[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)",
R"(textureSampleBias(x_20, x_10, coords123.xy, i32(coords123.z), 7.0, vec2<i32>(3, 4))"})); R"(textureSampleBias(x_20, x_10, coords123.xy, i32(round(coords123.z)), 7.0, vec2<i32>(3, 4))"}));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
// This test shows the use of a sampled image used with both regular // This test shows the use of a sampled image used with both regular
@ -1730,7 +1730,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler_comparison; R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
[[group(2), binding(1)]] var x_20 : texture_depth_2d_array;)", [[group(2), binding(1)]] var x_20 : texture_depth_2d_array;)",
R"(textureSampleCompare(x_20, x_10, coords123.xy, i32(coords123.z), 0.200000003))"}, R"(textureSampleCompare(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.200000003))"},
// ImageSampleDrefImplicitLod with ConstOffset // ImageSampleDrefImplicitLod with ConstOffset
ImageAccessCase{ ImageAccessCase{
"%float 2D 0 0 0 1 Unknown", "%float 2D 0 0 0 1 Unknown",
@ -1749,7 +1749,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler_comparison; R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
[[group(2), binding(1)]] var x_20 : texture_depth_2d_array;)", [[group(2), binding(1)]] var x_20 : texture_depth_2d_array;)",
R"(textureSampleCompare(x_20, x_10, coords123.xy, i32(coords123.z), 0.200000003, vec2<i32>(3, 4)))"})); R"(textureSampleCompare(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.200000003, vec2<i32>(3, 4)))"}));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
ImageSampleDrefExplicitLod, ImageSampleDrefExplicitLod,
@ -1775,7 +1775,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler_comparison; R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
[[group(2), binding(1)]] var x_20 : texture_depth_2d_array;)", [[group(2), binding(1)]] var x_20 : texture_depth_2d_array;)",
R"(textureSampleCompareLevel(x_20, x_10, coords123.xy, i32(coords123.z), 0.200000003))"}, R"(textureSampleCompareLevel(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.200000003))"},
// 2D, ConstOffset // 2D, ConstOffset
ImageAccessCase{ ImageAccessCase{
"%float 2D 1 0 0 1 Unknown", "%float 2D 1 0 0 1 Unknown",
@ -1796,7 +1796,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler_comparison; R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
[[group(2), binding(1)]] var x_20 : texture_depth_2d_array;)", [[group(2), binding(1)]] var x_20 : texture_depth_2d_array;)",
R"(textureSampleCompareLevel(x_20, x_10, coords123.xy, i32(coords123.z), 0.200000003, vec2<i32>(3, 4)))"}, R"(textureSampleCompareLevel(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.200000003, vec2<i32>(3, 4)))"},
// Cube // Cube
ImageAccessCase{ ImageAccessCase{
"%float Cube 1 0 0 1 Unknown", "%float Cube 1 0 0 1 Unknown",
@ -1814,7 +1814,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler_comparison; R"([[group(0), binding(0)]] var x_10 : sampler_comparison;
[[group(2), binding(1)]] var x_20 : texture_depth_cube_array;)", [[group(2), binding(1)]] var x_20 : texture_depth_cube_array;)",
R"(textureSampleCompareLevel(x_20, x_10, coords1234.xyz, i32(coords1234.w), 0.200000003))"})); R"(textureSampleCompareLevel(x_20, x_10, coords1234.xyz, i32(round(coords1234.w)), 0.200000003))"}));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
ImageSampleExplicitLod_UsingLod, ImageSampleExplicitLod_UsingLod,
@ -1838,7 +1838,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler; R"([[group(0), binding(0)]] var x_10 : sampler;
[[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)", [[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)",
R"(textureSampleLevel(x_20, x_10, coords123.xy, i32(coords123.z), 0.0))"}, R"(textureSampleLevel(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.0))"},
// OpImageSampleExplicitLod - using Lod and ConstOffset // OpImageSampleExplicitLod - using Lod and ConstOffset
ImageAccessCase{ ImageAccessCase{
@ -1872,7 +1872,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler; R"([[group(0), binding(0)]] var x_10 : sampler;
[[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)", [[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)",
R"(textureSampleLevel(x_20, x_10, coords123.xy, i32(coords123.z), 0.0, vec2<i32>(3, 4)))"})); R"(textureSampleLevel(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.0, vec2<i32>(3, 4)))"}));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
ImageSampleExplicitLod_UsingGrad, ImageSampleExplicitLod_UsingGrad,
@ -1897,7 +1897,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler; R"([[group(0), binding(0)]] var x_10 : sampler;
[[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)", [[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)",
R"(textureSampleGrad(x_20, x_10, coords123.xy, i32(coords123.z), vf12, vf21))"}, R"(textureSampleGrad(x_20, x_10, coords123.xy, i32(round(coords123.z)), vf12, vf21))"},
// OpImageSampleExplicitLod - using Grad and ConstOffset // OpImageSampleExplicitLod - using Grad and ConstOffset
ImageAccessCase{ ImageAccessCase{
@ -1930,7 +1930,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler; R"([[group(0), binding(0)]] var x_10 : sampler;
[[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)", [[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)",
R"(textureSampleGrad(x_20, x_10, coords123.xy, i32(coords123.z), vf12, vf21, vec2<i32>(3, 4)))"}, R"(textureSampleGrad(x_20, x_10, coords123.xy, i32(round(coords123.z)), vf12, vf21, vec2<i32>(3, 4)))"},
// OpImageSampleExplicitLod arrayed - using Grad and unsigned // OpImageSampleExplicitLod arrayed - using Grad and unsigned
// ConstOffset // ConstOffset
@ -1942,7 +1942,7 @@ INSTANTIATE_TEST_SUITE_P(
R"([[group(0), binding(0)]] var x_10 : sampler; R"([[group(0), binding(0)]] var x_10 : sampler;
[[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)", [[group(2), binding(1)]] var x_20 : texture_2d_array<f32>;)",
R"(textureSampleGrad(x_20, x_10, coords123.xy, i32(coords123.z), vf12, vf21, vec2<i32>(vec2<u32>(3u, 4u))))"})); R"(textureSampleGrad(x_20, x_10, coords123.xy, i32(round(coords123.z)), vf12, vf21, vec2<i32>(vec2<u32>(3u, 4u))))"}));
// Test crbug.com/378: // Test crbug.com/378:
// In WGSL, sampling from depth texture with explicit level of detail // In WGSL, sampling from depth texture with explicit level of detail
@ -3088,17 +3088,17 @@ INSTANTIATE_TEST_SUITE_P(Good_1DArray,
"%result = OpImageSampleImplicitLod %v4float " "%result = OpImageSampleImplicitLod %v4float "
"%sampled_image %vf12", "%sampled_image %vf12",
"", "",
{"vf12.x", "i32(vf12.y)"}}, {"vf12.x", "i32(round(vf12.y))"}},
{"%float 1D 0 1 0 1 Unknown", {"%float 1D 0 1 0 1 Unknown",
"%result = OpImageSampleImplicitLod %v4float " "%result = OpImageSampleImplicitLod %v4float "
"%sampled_image %vf123", // one excess arg "%sampled_image %vf123", // one excess arg
"", "",
{"vf123.x", "i32(vf123.y)"}}, {"vf123.x", "i32(round(vf123.y))"}},
{"%float 1D 0 1 0 1 Unknown", {"%float 1D 0 1 0 1 Unknown",
"%result = OpImageSampleImplicitLod %v4float " "%result = OpImageSampleImplicitLod %v4float "
"%sampled_image %vf1234", // two excess args "%sampled_image %vf1234", // two excess args
"", "",
{"vf1234.x", "i32(vf1234.y)"}}})); {"vf1234.x", "i32(round(vf1234.y))"}}}));
INSTANTIATE_TEST_SUITE_P(Good_2D, INSTANTIATE_TEST_SUITE_P(Good_2D,
SpvParserHandleTest_ImageCoordsTest, SpvParserHandleTest_ImageCoordsTest,
@ -3126,12 +3126,12 @@ INSTANTIATE_TEST_SUITE_P(Good_2DArray,
"%result = OpImageSampleImplicitLod %v4float " "%result = OpImageSampleImplicitLod %v4float "
"%sampled_image %vf123", "%sampled_image %vf123",
"", "",
{"vf123.xy", "i32(vf123.z)"}}, {"vf123.xy", "i32(round(vf123.z))"}},
{"%float 2D 0 1 0 1 Unknown", {"%float 2D 0 1 0 1 Unknown",
"%result = OpImageSampleImplicitLod %v4float " "%result = OpImageSampleImplicitLod %v4float "
"%sampled_image %vf1234", // one excess arg "%sampled_image %vf1234", // one excess arg
"", "",
{"vf1234.xy", "i32(vf1234.z)"}}})); {"vf1234.xy", "i32(round(vf1234.z))"}}}));
INSTANTIATE_TEST_SUITE_P(Good_3D, INSTANTIATE_TEST_SUITE_P(Good_3D,
SpvParserHandleTest_ImageCoordsTest, SpvParserHandleTest_ImageCoordsTest,
@ -3175,7 +3175,7 @@ INSTANTIATE_TEST_SUITE_P(Good_CubeArray,
"%v4float " "%v4float "
"%sampled_image %vf1234", "%sampled_image %vf1234",
"", "",
{"vf1234.xyz", "i32(vf1234.w)"}}})); {"vf1234.xyz", "i32(round(vf1234.w))"}}}));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
PreserveFloatCoords_NonArrayed, PreserveFloatCoords_NonArrayed,
@ -3228,23 +3228,23 @@ INSTANTIATE_TEST_SUITE_P(
{"%float 2D 0 1 0 1 Unknown", {"%float 2D 0 1 0 1 Unknown",
"%result = OpImageSampleImplicitLod %v4float %sampled_image %vf123", "%result = OpImageSampleImplicitLod %v4float %sampled_image %vf123",
"", "",
{"vf123.xy", "i32(vf123.z)"}}, {"vf123.xy", "i32(round(vf123.z))"}},
{"%float 2D 0 1 0 1 Unknown", {"%float 2D 0 1 0 1 Unknown",
"%result = OpImageSampleExplicitLod %v4float %sampled_image %vf123 " "%result = OpImageSampleExplicitLod %v4float %sampled_image %vf123 "
"Lod %f1", "Lod %f1",
"", "",
{"vf123.xy", "i32(vf123.z)"}}, {"vf123.xy", "i32(round(vf123.z))"}},
{"%float 2D 1 1 0 1 Unknown", {"%float 2D 1 1 0 1 Unknown",
"%result = OpImageSampleDrefImplicitLod %float %sampled_image " "%result = OpImageSampleDrefImplicitLod %float %sampled_image "
"%vf123 %depth", "%vf123 %depth",
"", "",
{"vf123.xy", "i32(vf123.z)"}}, {"vf123.xy", "i32(round(vf123.z))"}},
{"%float 2D 1 1 0 1 Unknown", {"%float 2D 1 1 0 1 Unknown",
"%result = OpImageSampleDrefExplicitLod %float %sampled_image " "%result = OpImageSampleDrefExplicitLod %float %sampled_image "
"%vf123 %depth Lod %float_0", "%vf123 %depth Lod %float_0",
"", "",
{"vf123.xy", "i32(vf123.z)"}}})); {"vf123.xy", "i32(round(vf123.z))"}}}));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
PreserveIntCoords_NonArrayed, PreserveIntCoords_NonArrayed,