[Mesa-dev] [PATCH 2/2] i965: Fix clears of layered framebuffers with mismatched layer counts.

Paul Berry stereotype441 at gmail.com
Tue Jan 7 07:33:46 PST 2014


Previously, Mesa enforced the following rule (from
ARB_geometry_shader4's list of criteria for framebuffer completeness):

  * If any framebuffer attachment is layered, all attachments must have
    the same layer count.  For three-dimensional textures, the layer count
    is the depth of the attached volume.  For cube map textures, the layer
    count is always six.  For one- and two-dimensional array textures, the
    layer count is simply the number of layers in the array texture.
    { FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB }

However, when ARB_geometry_shader4 was adopted into GL 3.2, this rule
was dropped; GL 3.2 permits different attachments to have different
layer counts.  This patch brings Mesa in line with GL 3.2.

In order to ensure that layered clears properly clear all layers, we
now have to keep track of the maximum number of layers in a layered
framebuffer.

Fixes the following piglit tests in spec/!OpenGL 3.2/layered-rendering:
- clear-color-all-types 1d_array mipmapped
- clear-color-all-types 1d_array single_level
- clear-color-mismatched-layer-count
- framebuffer-layer-count-mismatch
---
 src/mesa/drivers/common/meta.c                   |  4 ++--
 src/mesa/drivers/dri/i965/brw_blorp_clear.cpp    |  8 ++++----
 src/mesa/drivers/dri/i965/brw_clear.c            |  6 +++---
 src/mesa/drivers/dri/i965/brw_wm_surface_state.c |  2 +-
 src/mesa/drivers/dri/i965/gen6_clip_state.c      |  2 +-
 src/mesa/drivers/dri/i965/gen7_misc_state.c      |  2 +-
 src/mesa/main/fbobject.c                         | 26 ++++++++++++------------
 src/mesa/main/mtypes.h                           |  9 ++++----
 8 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index 7b41876..1294514 100644
--- a/src/mesa/drivers/common/meta.c
+++ b/src/mesa/drivers/common/meta.c
@@ -2407,9 +2407,9 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers)
 		       GL_DYNAMIC_DRAW_ARB);
 
    /* draw quad(s) */
-   if (fb->NumLayers > 0) {
+   if (fb->MaxNumLayers > 0) {
       unsigned layer;
-      for (layer = 0; layer < fb->NumLayers; layer++) {
+      for (layer = 0; layer < fb->MaxNumLayers; layer++) {
          if (fb->_IntegerColor)
             _mesa_Uniform1i(clear->IntegerLayerLocation, layer);
          else
diff --git a/src/mesa/drivers/dri/i965/brw_blorp_clear.cpp b/src/mesa/drivers/dri/i965/brw_blorp_clear.cpp
index 072ad55..c55108a 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp_clear.cpp
+++ b/src/mesa/drivers/dri/i965/brw_blorp_clear.cpp
@@ -573,14 +573,14 @@ brw_blorp_clear_color(struct brw_context *brw, struct gl_framebuffer *fb,
       if (rb == NULL)
          continue;
 
-      if (fb->NumLayers > 0) {
+      if (fb->MaxNumLayers > 0) {
          unsigned layer_multiplier =
             (irb->mt->msaa_layout == INTEL_MSAA_LAYOUT_UMS ||
              irb->mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) ?
             irb->mt->num_samples : 1;
-         assert(fb->NumLayers * layer_multiplier ==
-                irb->mt->level[irb->mt_level].depth);
-         for (unsigned layer = 0; layer < fb->NumLayers; layer++) {
+         unsigned num_layers =
+            irb->mt->level[irb->mt_level].depth / layer_multiplier;
+         for (unsigned layer = 0; layer < num_layers; layer++) {
             if (!do_single_blorp_clear(brw, fb, rb, buf, partial_clear,
                                        layer * layer_multiplier)) {
                return false;
diff --git a/src/mesa/drivers/dri/i965/brw_clear.c b/src/mesa/drivers/dri/i965/brw_clear.c
index 1cac996..fe68d9e 100644
--- a/src/mesa/drivers/dri/i965/brw_clear.c
+++ b/src/mesa/drivers/dri/i965/brw_clear.c
@@ -181,9 +181,9 @@ brw_fast_clear_depth(struct gl_context *ctx)
     */
    intel_batchbuffer_emit_mi_flush(brw);
 
-   if (fb->NumLayers > 0) {
-      assert(fb->NumLayers == depth_irb->mt->level[depth_irb->mt_level].depth);
-      for (unsigned layer = 0; layer < fb->NumLayers; layer++) {
+   if (fb->MaxNumLayers > 0) {
+      unsigned num_layers = depth_irb->mt->level[depth_irb->mt_level].depth;
+      for (unsigned layer = 0; layer < num_layers; layer++) {
          intel_hiz_exec(brw, mt, depth_irb->mt_level, layer,
                         GEN6_HIZ_OP_DEPTH_CLEAR);
       }
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 5236eda..6bd4a29 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -700,7 +700,7 @@ brw_update_renderbuffer_surfaces(struct brw_context *brw)
       for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
 	 if (intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[i])) {
 	    brw->vtbl.update_renderbuffer_surface(brw, ctx->DrawBuffer->_ColorDrawBuffers[i],
-                                                  ctx->DrawBuffer->NumLayers > 0, i);
+                                                  ctx->DrawBuffer->MaxNumLayers > 0, i);
 	 } else {
 	    brw->vtbl.update_null_renderbuffer_surface(brw, i);
 	 }
diff --git a/src/mesa/drivers/dri/i965/gen6_clip_state.c b/src/mesa/drivers/dri/i965/gen6_clip_state.c
index 37a39b8..6cec0ff 100644
--- a/src/mesa/drivers/dri/i965/gen6_clip_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_clip_state.c
@@ -121,7 +121,7 @@ upload_clip_state(struct brw_context *brw)
 	     dw2);
    OUT_BATCH(U_FIXED(0.125, 3) << GEN6_CLIP_MIN_POINT_WIDTH_SHIFT |
              U_FIXED(255.875, 3) << GEN6_CLIP_MAX_POINT_WIDTH_SHIFT |
-             (fb->NumLayers > 0 ? 0 : GEN6_CLIP_FORCE_ZERO_RTAINDEX));
+             (fb->MaxNumLayers > 0 ? 0 : GEN6_CLIP_FORCE_ZERO_RTAINDEX));
    ADVANCE_BATCH();
 }
 
diff --git a/src/mesa/drivers/dri/i965/gen7_misc_state.c b/src/mesa/drivers/dri/i965/gen7_misc_state.c
index 4251949..8fb0eec 100644
--- a/src/mesa/drivers/dri/i965/gen7_misc_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_misc_state.c
@@ -81,7 +81,7 @@ gen7_emit_depth_stencil_hiz(struct brw_context *brw,
       break;
    }
 
-   if (fb->NumLayers > 0 || !irb) {
+   if (fb->MaxNumLayers > 0 || !irb) {
       min_array_element = 0;
    } else if (irb->mt->num_samples > 1) {
       /* Convert physical layer to logical layer. */
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index c3f634f..7bc5b1b 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -877,8 +877,10 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
    GLint fixedSampleLocations = -1;
    GLint i;
    GLuint j;
-   bool layer_info_valid = false; /* Covers layer_count and layer_tex_target */
-   GLuint layer_count = 0, att_layer_count;
+   /* Covers max_layer_count, is_layered, and layer_tex_target */
+   bool layer_info_valid = false;
+   GLuint max_layer_count = 0, att_layer_count;
+   bool is_layered;
    GLenum layer_tex_target = 0;
 
    assert(_mesa_is_user_fbo(fb));
@@ -1064,26 +1066,24 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
          att_layer_count = 0;
       }
       if (!layer_info_valid) {
-         layer_count = att_layer_count;
+         is_layered = att->Layered;
+         max_layer_count = att_layer_count;
          layer_tex_target = att_tex_target;
          layer_info_valid = true;
-      } else if (layer_count > 0 && layer_tex_target != att_tex_target) {
+      } else if (max_layer_count > 0 && layer_tex_target != att_tex_target) {
          fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
          fbo_incomplete(ctx, "layered framebuffer has mismatched targets", i);
          return;
-      } else if (layer_count != att_layer_count) {
-         if (layer_count == 0 || att_layer_count == 0) {
-            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
-            fbo_incomplete(ctx, "framebuffer attachment layer mode is inconsistent", i);
-         } else {
-            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB;
-            fbo_incomplete(ctx, "framebuffer attachment layer count is inconsistent", i);
-         }
+      } else if (is_layered != att->Layered) {
+         fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
+         fbo_incomplete(ctx, "framebuffer attachment layer mode is inconsistent", i);
          return;
+      } else if (att_layer_count > max_layer_count) {
+         max_layer_count = att_layer_count;
       }
    }
 
-   fb->NumLayers = layer_count;
+   fb->MaxNumLayers = max_layer_count;
 
    if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
       /* Check that all DrawBuffers are present */
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index a5294b0..0db7070 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -3007,12 +3007,11 @@ struct gl_framebuffer
    struct gl_renderbuffer *_ColorReadBuffer;
 
    /**
-    * The number of layers in the framebuffer, or 0 if the framebuffer is not
-    * layered.  For cube maps, this value is 6.  For cube map arrays, this
-    * value is the "depth" value passed to TexImage3D (always a multiple of
-    * 6).
+    * The maximum number of layers in the framebuffer, or 0 if the framebuffer
+    * is not layered.  For cube maps and cube map arrays, each cube face
+    * counts as a layer.
     */
-   GLuint NumLayers;
+   GLuint MaxNumLayers;
 
    /** Delete this framebuffer */
    void (*Delete)(struct gl_framebuffer *fb);
-- 
1.8.5.2



More information about the mesa-dev mailing list