Mesa (main): llvmpipe: improve polygon-offset precision

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Aug 24 07:55:22 UTC 2021


Module: Mesa
Branch: main
Commit: 4d6e18b6cbde4e2bee8cbc949d32095cd6d02910
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=4d6e18b6cbde4e2bee8cbc949d32095cd6d02910

Author: Erik Faye-Lund <erik.faye-lund at collabora.com>
Date:   Mon Aug 23 16:07:47 2021 +0200

llvmpipe: improve polygon-offset precision

This performs the polygon offset addition after interpolation, which
prevents floating-point cancellation issues completely.

This does mean that we have to perform a single floating-point addition
more per fragment than before, unless we also want to spend a bit in
the fragment-shader variant key to avoid this.

Reviewed-by: Roland Scheidegger <sroland at vmware.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12442>

---

 .../drivers/llvmpipe/ci/deqp-llvmpipe-fails.txt    |  4 --
 src/gallium/drivers/llvmpipe/lp_bld_interp.c       | 26 +++++++----
 src/gallium/drivers/llvmpipe/lp_state_setup.c      | 50 ++++++++++------------
 .../drivers/virgl/ci/deqp-virgl-gl-fails.txt       |  4 --
 .../drivers/zink/ci/deqp-zink-lvp-fails.txt        |  3 --
 5 files changed, 40 insertions(+), 47 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/ci/deqp-llvmpipe-fails.txt b/src/gallium/drivers/llvmpipe/ci/deqp-llvmpipe-fails.txt
index e7c7b53f917..ce277b6bce1 100644
--- a/src/gallium/drivers/llvmpipe/ci/deqp-llvmpipe-fails.txt
+++ b/src/gallium/drivers/llvmpipe/ci/deqp-llvmpipe-fails.txt
@@ -10,7 +10,6 @@ dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.sync_status.v
 dEQP-EGL.functional.robustness.reset_context.shaders.infinite_loop.sync_status.vertex_and_fragment,Fail
 dEQP-GLES2.functional.clipping.line.wide_line_clip_viewport_center,Fail
 dEQP-GLES2.functional.clipping.line.wide_line_clip_viewport_corner,Fail
-dEQP-GLES2.functional.polygon_offset.default_displacement_with_units,Fail
 dEQP-GLES3.functional.clipping.line.wide_line_clip_viewport_center,Fail
 dEQP-GLES3.functional.clipping.line.wide_line_clip_viewport_corner,Fail
 dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_mag,Fail
@@ -23,9 +22,6 @@ dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_dst_x,Fail
 dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_src_dst_x,Fail
 dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_src_dst_y,Fail
 dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_src_x,Fail
-dEQP-GLES3.functional.polygon_offset.default_displacement_with_units,Fail
-dEQP-GLES3.functional.polygon_offset.fixed24_displacement_with_units,Fail
-dEQP-GLES3.functional.polygon_offset.float32_displacement_with_units,Fail
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal,Fail
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger,Fail
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_tessellation_fragment.fbo_bbox_equal,Fail
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.c b/src/gallium/drivers/llvmpipe/lp_bld_interp.c
index 8b02ac9622c..a93879c9382 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_interp.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.c
@@ -413,15 +413,25 @@ attribs_update_simple(struct lp_build_interp_soa_context *bld,
                break;
             }
 
-            if ((attrib == 0) && (chan == 2) && !bld->depth_clamp){
-               /* OpenGL requires clamping z to 0..1 range after polgon offset
-                * is applied if depth-clamping isn't enabled.
-                *
-                * This also fixes the problem that depth values can exceed 1.0,
-                * due to imprecision in the calculations.
-                */
-               a = lp_build_clamp(coeff_bld, a, coeff_bld->zero, coeff_bld->one);
+            if ((attrib == 0) && (chan == 2)) {
+               /* add polygon-offset value, stored in the X component of a0 */
+               LLVMValueRef offset =
+                  lp_build_extract_broadcast(gallivm, setup_bld->type,
+                                             coeff_bld->type, bld->a0aos[0],
+                                             lp_build_const_int32(gallivm, 0));
+               a = LLVMBuildFAdd(builder, a, offset, "");
+
+               if (!bld->depth_clamp){
+                  /* OpenGL requires clamping z to 0..1 range after polgon offset
+                  * is applied if depth-clamping isn't enabled.
+                  *
+                  * This also fixes the problem that depth values can exceed 1.0,
+                  * due to imprecision in the calculations.
+                  */
+                  a = lp_build_clamp(coeff_bld, a, coeff_bld->zero, coeff_bld->one);
+               }
             }
+
             bld->attribs[attrib][chan] = a;
          }
       }
diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.c b/src/gallium/drivers/llvmpipe/lp_state_setup.c
index e0f8b3daad5..87216c04d9e 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_setup.c
@@ -201,7 +201,7 @@ lp_twoside(struct gallivm_state *gallivm,
 
 }
 
-static void
+static LLVMValueRef
 lp_do_offset_tri(struct gallivm_state *gallivm,
                  struct lp_setup_args *args,
                  const struct lp_setup_variant_key *key,
@@ -215,9 +215,7 @@ lp_do_offset_tri(struct gallivm_state *gallivm,
    struct lp_build_context int_scalar_bld;
    struct lp_build_context *bld = &args->bld;
    LLVMValueRef zoffset, mult;
-   LLVMValueRef z0_new, z1_new, z2_new;
    LLVMValueRef dzdxdzdy, dzdx, dzdy, dzxyz20, dyzzx01, dyzzx01_dzxyz20, dzx01_dyz20;
-   LLVMValueRef z0z1, z0z1z2;
    LLVMValueRef max, max_value, res12;
    LLVMValueRef shuffles[4];
    LLVMTypeRef shuf_type = LLVMInt32TypeInContext(gallivm->context);
@@ -323,29 +321,7 @@ lp_do_offset_tri(struct gallivm_state *gallivm,
                              zoffset);
    }
 
-   /* yuck */
-   shuffles[0] = twoi;
-   shuffles[1] = lp_build_const_int32(gallivm, 6);
-   shuffles[2] = LLVMGetUndef(shuf_type);
-   shuffles[3] = LLVMGetUndef(shuf_type);
-   z0z1 = LLVMBuildShuffleVector(b, attribv[0], attribv[1], LLVMConstVector(shuffles, 4), "");
-   shuffles[0] = zeroi;
-   shuffles[1] = onei;
-   shuffles[2] = lp_build_const_int32(gallivm, 6);
-   shuffles[3] = LLVMGetUndef(shuf_type);
-   z0z1z2 = LLVMBuildShuffleVector(b, z0z1, attribv[2], LLVMConstVector(shuffles, 4), "");
-   zoffset = lp_build_broadcast_scalar(bld, zoffset);
-
-   z0z1z2 = LLVMBuildFAdd(b, z0z1z2, zoffset, "");
-
-   /* insert into args->a0.z, a1.z, a2.z:
-    */
-   z0_new = LLVMBuildExtractElement(b, z0z1z2, zeroi, "");
-   z1_new = LLVMBuildExtractElement(b, z0z1z2, onei, "");
-   z2_new = LLVMBuildExtractElement(b, z0z1z2, twoi, "");
-   attribv[0] = LLVMBuildInsertElement(b, attribv[0], z0_new, twoi, "");
-   attribv[1] = LLVMBuildInsertElement(b, attribv[1], z1_new, twoi, "");
-   attribv[2] = LLVMBuildInsertElement(b, attribv[2], z2_new, twoi, "");
+   return zoffset;
 }
 
 static void
@@ -653,6 +629,7 @@ init_args(struct gallivm_state *gallivm,
    LLVMValueRef e, f, ef, ooa;
    LLVMValueRef shuffles[4], shuf10;
    LLVMValueRef attr_pos[3];
+   LLVMValueRef polygon_offset;
    struct lp_type typef4 = lp_type_float_vec(32, 128);
    struct lp_build_context bld;
 
@@ -693,7 +670,9 @@ init_args(struct gallivm_state *gallivm,
 
    /* tri offset calc shares a lot of arithmetic, do it here */
    if (key->pgon_offset_scale != 0.0f || key->pgon_offset_units != 0.0f) {
-      lp_do_offset_tri(gallivm, args, key, ooa, dxy01, dxy20, attr_pos);
+      polygon_offset = lp_do_offset_tri(gallivm, args, key, ooa, dxy01, dxy20, attr_pos);
+   } else {
+      polygon_offset = lp_build_const_float(gallivm, 0.0f);
    }
 
    dxy20 = LLVMBuildFMul(b, dxy20, ooa, "");
@@ -708,7 +687,22 @@ init_args(struct gallivm_state *gallivm,
    args->x0_center = lp_build_extract_broadcast(gallivm, typef4, typef4, xy0_center, zeroi);
    args->y0_center = lp_build_extract_broadcast(gallivm, typef4, typef4, xy0_center, onei);
 
-   emit_linear_coef(gallivm, args, 0, attr_pos);
+   LLVMValueRef coeffs[3];
+   calc_coef4(gallivm, args,
+              attr_pos[0], attr_pos[1], attr_pos[2],
+              coeffs);
+
+   /* This is a bit sneaky:
+    * Because we observe that the X component of A0 is otherwise unused,
+    * we can overwrite it with the computed polygon-offset value, to make
+    * sure it's available in the fragment shader without having to change
+    * the interface (which is error-prone).
+    */
+   coeffs[0] = LLVMBuildInsertElement(b, coeffs[0], polygon_offset,
+                                      lp_build_const_int32(gallivm, 0), "");
+
+   store_coef(gallivm, args, 0,
+              coeffs[0], coeffs[1], coeffs[2]);
 }
 
 /**
diff --git a/src/gallium/drivers/virgl/ci/deqp-virgl-gl-fails.txt b/src/gallium/drivers/virgl/ci/deqp-virgl-gl-fails.txt
index e43a699d7fe..794e0ce8aa4 100644
--- a/src/gallium/drivers/virgl/ci/deqp-virgl-gl-fails.txt
+++ b/src/gallium/drivers/virgl/ci/deqp-virgl-gl-fails.txt
@@ -3,7 +3,6 @@ dEQP-GLES2.functional.clipping.line.wide_line_clip_viewport_corner,Fail
 dEQP-GLES2.functional.clipping.point.wide_point_clip,Fail
 dEQP-GLES2.functional.clipping.point.wide_point_clip_viewport_center,Fail
 dEQP-GLES2.functional.clipping.point.wide_point_clip_viewport_corner,Fail
-dEQP-GLES2.functional.polygon_offset.default_displacement_with_units,Fail
 dEQP-GLES3.functional.clipping.line.wide_line_clip_viewport_center,Fail
 dEQP-GLES3.functional.clipping.line.wide_line_clip_viewport_corner,Fail
 dEQP-GLES3.functional.clipping.point.wide_point_clip,Fail
@@ -19,9 +18,6 @@ dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_dst_x,Fail
 dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_src_dst_x,Fail
 dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_src_dst_y,Fail
 dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_src_x,Fail
-dEQP-GLES3.functional.polygon_offset.default_displacement_with_units,Fail
-dEQP-GLES3.functional.polygon_offset.fixed24_displacement_with_units,Fail
-dEQP-GLES3.functional.polygon_offset.float32_displacement_with_units,Fail
 dEQP-GLES31.functional.draw_buffers_indexed.random.max_required_draw_buffers.4,Fail
 dEQP-GLES31.functional.draw_buffers_indexed.random.max_implementation_draw_buffers.8,Fail
 dEQP-GLES31.functional.image_load_store.buffer.image_size.writeonly_12,Fail
diff --git a/src/gallium/drivers/zink/ci/deqp-zink-lvp-fails.txt b/src/gallium/drivers/zink/ci/deqp-zink-lvp-fails.txt
index 70823d3a26a..60c8b845e2e 100644
--- a/src/gallium/drivers/zink/ci/deqp-zink-lvp-fails.txt
+++ b/src/gallium/drivers/zink/ci/deqp-zink-lvp-fails.txt
@@ -1,9 +1,6 @@
 dEQP-GLES2.functional.clipping.point.wide_point_clip,Fail
 dEQP-GLES2.functional.clipping.point.wide_point_clip_viewport_center,Fail
 dEQP-GLES2.functional.clipping.point.wide_point_clip_viewport_corner,Fail
-dEQP-GLES2.functional.polygon_offset.default_displacement_with_units,Fail
-dEQP-GLES3.functional.polygon_offset.default_displacement_with_units,Fail
-dEQP-GLES3.functional.polygon_offset.float32_displacement_with_units,Fail
 dEQP-GLES3.functional.clipping.line.wide_line_clip_viewport_center,Fail
 dEQP-GLES3.functional.clipping.line.wide_line_clip_viewport_corner,Fail
 dEQP-GLES3.functional.clipping.point.wide_point_clip,Fail



More information about the mesa-commit mailing list