i965/gen6+: Switch GLSL from ALT to IEEE floating point mode
authorPaul Berry <stereotype441@gmail.com>
Sat, 8 Oct 2011 00:37:32 +0000 (17:37 -0700)
committerPaul Berry <stereotype441@gmail.com>
Mon, 31 Oct 2011 18:24:03 +0000 (11:24 -0700)
i965 graphics hardware has two floating point modes: ALT and IEEE.  In
ALT mode, floating-point operations never generate infinities or NaNs,
and MOV instructions translate infinities and NaNs to finite values.
In IEEE mode, infinities and NaNs behave as specified in the IEEE 754
spec.

Previously, we used ALT mode for all vertex and fragment programs,
whether they were GLSL programs or ARB programs.  The GLSL spec is
sufficiently vague about how infs and nans are to be handled that it
was unclear whether this mode was compliant with the GLSL 1.30 spec or
not, and it made it very difficult to test the isinf() and isnan()
functions.

This patch changes i965 GLSL programs to use IEEE floating-point mode,
which is clearly compliant with GLSL 1.30's inf/nan requirements.  In
addition to making the Piglit isinf and isnan tests pass, this paves
the way for future support of the ARB_shader_precision extension.

Unfortunately we still have to use ALT floating-point mode when
executing ARB programs, because those programs require 0^0 == 1, and
i965 hardware generates 0^0 == NaN in IEEE mode.

Fixes piglit tests "isinf-and-isnan fs_fbo", "isinf-and-isnan vs_fbo",
and {fs,vs}-{isinf,isnan}-{vec2,vec3,vec4}.

src/mesa/drivers/dri/i965/gen6_vs_state.c
src/mesa/drivers/dri/i965/gen6_wm_state.c
src/mesa/drivers/dri/i965/gen7_vs_state.c
src/mesa/drivers/dri/i965/gen7_wm_state.c

index e06c7b452a0cf986dbf1619da8ac22f690d11e9f..e22fd393ef5bda33bfc6a63b4990c25fd267b4f3 100644 (file)
@@ -131,6 +131,7 @@ static void
 upload_vs_state(struct brw_context *brw)
 {
    struct intel_context *intel = &brw->intel;
+   uint32_t floating_point_mode = 0;
 
    if (brw->vs.push_const_size == 0) {
       /* Disable the push constant buffers. */
@@ -157,11 +158,17 @@ upload_vs_state(struct brw_context *brw)
       ADVANCE_BATCH();
    }
 
+   /* Use ALT floating point mode for ARB vertex programs, because they
+    * require 0^0 == 1.
+    */
+   if (intel->ctx.Shader.CurrentVertexProgram == NULL)
+      floating_point_mode = GEN6_VS_FLOATING_POINT_MODE_ALT;
+
    BEGIN_BATCH(6);
    OUT_BATCH(_3DSTATE_VS << 16 | (6 - 2));
    OUT_BATCH(brw->vs.prog_offset);
    OUT_BATCH((0 << GEN6_VS_SAMPLER_COUNT_SHIFT) |
-            GEN6_VS_FLOATING_POINT_MODE_ALT |
+             floating_point_mode |
             (brw->vs.nr_surfaces << GEN6_VS_BINDING_TABLE_ENTRY_COUNT_SHIFT));
 
    if (brw->vs.prog_data->total_scratch) {
index 25e0fa2909e45c7f5d0f3558e764e64f8a42edb9..714d59492ca31722c45cbdb073bfc45d19c835e5 100644 (file)
@@ -134,8 +134,11 @@ upload_wm_state(struct brw_context *brw)
    dw5 |= GEN6_WM_LINE_AA_WIDTH_1_0;
    dw5 |= GEN6_WM_LINE_END_CAP_AA_WIDTH_0_5;
 
-   /* OpenGL non-ieee floating point mode */
-   dw2 |= GEN6_WM_FLOATING_POINT_MODE_ALT;
+   /* Use ALT floating point mode for ARB fragment programs, because they
+    * require 0^0 == 1.
+    */
+   if (ctx->Shader.CurrentFragmentProgram == NULL)
+      dw2 |= GEN6_WM_FLOATING_POINT_MODE_ALT;
 
    /* BRW_NEW_NR_WM_SURFACES */
    dw2 |= brw->wm.nr_surfaces << GEN6_WM_BINDING_TABLE_ENTRY_COUNT_SHIFT;
index 4ef9c688315b980221c6b3204f853c640ea7b903..dbf93465e49469c33bd414145eddf96a3f26926c 100644 (file)
@@ -33,6 +33,7 @@ static void
 upload_vs_state(struct brw_context *brw)
 {
    struct intel_context *intel = &brw->intel;
+   uint32_t floating_point_mode = 0;
 
    BEGIN_BATCH(2);
    OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS_VS << 16 | (2 - 2));
@@ -65,11 +66,17 @@ upload_vs_state(struct brw_context *brw)
       ADVANCE_BATCH();
    }
 
+   /* Use ALT floating point mode for ARB vertex programs, because they
+    * require 0^0 == 1.
+    */
+   if (intel->ctx.Shader.CurrentVertexProgram == NULL)
+      floating_point_mode = GEN6_VS_FLOATING_POINT_MODE_ALT;
+
    BEGIN_BATCH(6);
    OUT_BATCH(_3DSTATE_VS << 16 | (6 - 2));
    OUT_BATCH(brw->vs.prog_offset);
    OUT_BATCH((0 << GEN6_VS_SAMPLER_COUNT_SHIFT) |
-            GEN6_VS_FLOATING_POINT_MODE_ALT |
+             floating_point_mode |
             (brw->vs.nr_surfaces << GEN6_VS_BINDING_TABLE_ENTRY_COUNT_SHIFT));
 
    if (brw->vs.prog_data->total_scratch) {
index ba83340bde9f8bac5e5dadb95b6fcd9fb253b995..2dce359ea949c52a74bfb77e2b99dbae09664006 100644 (file)
@@ -149,8 +149,11 @@ upload_ps_state(struct brw_context *brw)
    /* BRW_NEW_NR_WM_SURFACES */
    dw2 |= brw->wm.nr_surfaces << GEN7_PS_BINDING_TABLE_ENTRY_COUNT_SHIFT;
 
-   /* OpenGL non-ieee floating point mode */
-   dw2 |= GEN7_PS_FLOATING_POINT_MODE_ALT;
+   /* Use ALT floating point mode for ARB fragment programs, because they
+    * require 0^0 == 1.
+    */
+   if (intel->ctx.Shader.CurrentFragmentProgram == NULL)
+      dw2 |= GEN7_PS_FLOATING_POINT_MODE_ALT;
 
    /* CACHE_NEW_SAMPLER */
    dw4 |= (brw->max_wm_threads - 1) << GEN7_PS_MAX_THREADS_SHIFT;