[Mesa-dev] [PATCH 5/5] amd/common: add workaround for cube map array layer clamping

Nicolai Hähnle nhaehnle at gmail.com
Wed Sep 13 17:04:34 UTC 2017


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

Fixes dEQP-GLES31.functional.texture.filtering.cube_array.*

Cc: mesa-stable at lists.freedesktop.org
---
 src/amd/common/ac_llvm_build.c | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/src/amd/common/ac_llvm_build.c b/src/amd/common/ac_llvm_build.c
index 6c010e8c3a6..8a329515b57 100644
--- a/src/amd/common/ac_llvm_build.c
+++ b/src/amd/common/ac_llvm_build.c
@@ -491,22 +491,49 @@ ac_prepare_cube_coords(struct ac_llvm_context *ctx,
 		       LLVMValueRef *coords_arg,
 		       LLVMValueRef *derivs_arg)
 {
 
 	LLVMBuilderRef builder = ctx->builder;
 	struct cube_selection_coords selcoords;
 	LLVMValueRef coords[3];
 	LLVMValueRef invma;
 
 	if (is_array && !is_lod) {
-		coords_arg[3] = ac_build_intrinsic(ctx, "llvm.rint.f32", ctx->f32,
-						   &coords_arg[3], 1, 0);
+		LLVMValueRef tmp = coords_arg[3];
+		tmp = ac_build_intrinsic(ctx, "llvm.rint.f32", ctx->f32, &tmp, 1, 0);
+
+		/* Section 8.9 (Texture Functions) of the GLSL 4.50 spec says:
+		 *
+		 *    "For Array forms, the array layer used will be
+		 *
+		 *       max(0, min(d−1, floor(layer+0.5)))
+		 *
+		 *     where d is the depth of the texture array and layer
+		 *     comes from the component indicated in the tables below.
+		 *     Workaroudn for an issue where the layer is taken from a
+		 *     helper invocation which happens to fall on a different
+		 *     layer due to extrapolation."
+		 *
+		 * VI and earlier attempt to implement this in hardware by
+		 * clamping the value of coords[2] = (8 * layer) + face.
+		 * Unfortunately, this means that the we end up with the wrong
+		 * face when clamping occurs.
+		 *
+		 * Clamp the layer earlier to work around the issue.
+		 */
+		if (ctx->chip_class <= VI) {
+			LLVMValueRef ge0;
+			ge0 = LLVMBuildFCmp(builder, LLVMRealOGE, tmp, ctx->f32_0, "");
+			tmp = LLVMBuildSelect(builder, ge0, tmp, ctx->f32_0, "");
+		}
+
+		coords_arg[3] = tmp;
 	}
 
 	build_cube_intrinsic(ctx, coords_arg, &selcoords);
 
 	invma = ac_build_intrinsic(ctx, "llvm.fabs.f32",
 			ctx->f32, &selcoords.ma, 1, AC_FUNC_ATTR_READNONE);
 	invma = ac_build_fdiv(ctx, LLVMConstReal(ctx->f32, 1.0), invma);
 
 	for (int i = 0; i < 2; ++i)
 		coords[i] = LLVMBuildFMul(builder, selcoords.stc[i], invma, "");
-- 
2.11.0



More information about the mesa-dev mailing list