ilo: offset to layers only when necessary
authorChia-I Wu <olvaffe@gmail.com>
Fri, 20 Dec 2013 06:45:59 +0000 (14:45 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Wed, 8 Jan 2014 10:11:34 +0000 (18:11 +0800)
GEN6 has several requirements regarding the LOD/Depth/Width/Height of the
render targets and the depth buffer.  We used to offset to the layers in
question unconditionally to meet the requirements.  With this commit,
offseting is done only when the requirements are not met.

src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c
src/gallium/drivers/ilo/ilo_gpe.h
src/gallium/drivers/ilo/ilo_gpe_gen6.c
src/gallium/drivers/ilo/ilo_state.c

index b585fd6052d0615afb85ea296cc677a4e4dc7a06..ce12dd46e51d20f85def8dc87f1595fe67af9ebc 100644 (file)
@@ -723,13 +723,27 @@ gen6_pipeline_wm_depth(struct ilo_3d_pipeline *p,
    /* 3DSTATE_DEPTH_BUFFER and 3DSTATE_CLEAR_PARAMS */
    if (DIRTY(FB) || session->batch_bo_changed) {
       const struct ilo_zs_surface *zs;
+      struct ilo_zs_surface layer;
 
       if (ilo->fb.state.zsbuf) {
          const struct ilo_surface_cso *surface =
             (const struct ilo_surface_cso *) ilo->fb.state.zsbuf;
 
-         assert(!surface->is_rt);
-         zs = &surface->u.zs;
+         if (ilo->fb.offset_to_layers) {
+            assert(surface->base.u.tex.first_layer ==
+                  surface->base.u.tex.last_layer);
+
+            ilo_gpe_init_zs_surface(ilo->dev,
+                  ilo_texture(surface->base.texture),
+                  surface->base.format, surface->base.u.tex.level,
+                  surface->base.u.tex.first_layer, 1, true, &layer);
+
+            zs = &layer;
+         }
+         else {
+            assert(!surface->is_rt);
+            zs = &surface->u.zs;
+         }
       }
       else {
          zs = &ilo->fb.null_zs;
@@ -875,9 +889,27 @@ gen6_pipeline_state_surfaces_rt(struct ilo_3d_pipeline *p,
          const struct ilo_surface_cso *surface =
             (const struct ilo_surface_cso *) fb->state.cbufs[i];
 
-         assert(surface && surface->is_rt);
-         surface_state[i] =
-            gen6_emit_SURFACE_STATE(p->dev, &surface->u.rt, true, p->cp);
+         if (fb->offset_to_layers) {
+            struct ilo_view_surface layer;
+
+            assert(surface->base.u.tex.first_layer ==
+                  surface->base.u.tex.last_layer);
+
+            ilo_gpe_init_view_surface_for_texture(ilo->dev,
+                  ilo_texture(surface->base.texture),
+                  surface->base.format,
+                  surface->base.u.tex.level, 1,
+                  surface->base.u.tex.first_layer, 1,
+                  true, true, &layer);
+
+            surface_state[i] =
+               gen6_emit_SURFACE_STATE(p->dev, &layer, true, p->cp);
+         }
+         else {
+            assert(surface && surface->is_rt);
+            surface_state[i] =
+               gen6_emit_SURFACE_STATE(p->dev, &surface->u.rt, true, p->cp);
+         }
       }
 
       /*
index 9347d889d83c1042d074fe4f2acf9506371f0b5e..d8ddd06eed0b972f6c1ebd59e13d0ac4beb61c70 100644 (file)
@@ -257,7 +257,9 @@ struct ilo_fb_state {
    struct pipe_framebuffer_state state;
 
    struct ilo_zs_surface null_zs;
+
    unsigned num_samples;
+   bool offset_to_layers;
 };
 
 struct ilo_global_binding {
@@ -525,4 +527,9 @@ ilo_gpe_init_fs_cso(const struct ilo_dev_info *dev,
    }
 }
 
+void
+ilo_gpe_init_fb(const struct ilo_dev_info *dev,
+                const struct pipe_framebuffer_state *state,
+                struct ilo_fb_state *fb);
+
 #endif /* ILO_GPE_H */
index a84cb4d565e43adee369539c5a43b4145b195d78..d4c0398a1f2d53571b17fe645e7d743357429289 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include "util/u_dual_blend.h"
+#include "util/u_framebuffer.h"
 #include "util/u_half.h"
 #include "brw_defines.h"
 #include "intel_reg.h"
@@ -2454,6 +2455,94 @@ ilo_gpe_init_sampler_cso(const struct ilo_dev_info *dev,
    }
 }
 
+void
+ilo_gpe_init_fb(const struct ilo_dev_info *dev,
+                const struct pipe_framebuffer_state *state,
+                struct ilo_fb_state *fb)
+{
+   const struct pipe_surface *first;
+   unsigned num_surfaces;
+
+   ILO_GPE_VALID_GEN(dev, 6, 7.5);
+
+   util_copy_framebuffer_state(&fb->state, state);
+
+   first = (state->nr_cbufs) ? state->cbufs[0] :
+           (state->zsbuf) ? state->zsbuf :
+           NULL;
+   num_surfaces = state->nr_cbufs + !!state->zsbuf;
+
+   fb->num_samples = (first) ? first->texture->nr_samples : 1;
+   if (!fb->num_samples)
+      fb->num_samples = 1;
+
+   fb->offset_to_layers = false;
+
+   if (num_surfaces > 1) {
+      const unsigned first_depth =
+         (first->texture->target == PIPE_TEXTURE_3D) ?
+         first->texture->depth0 :
+         first->u.tex.last_layer - first->u.tex.first_layer + 1;
+      bool has_3d_target = (first->texture->target == PIPE_TEXTURE_3D);
+      unsigned i;
+
+      for (i = 1; i < num_surfaces; i++) {
+         const struct pipe_surface *surf =
+            (i < state->nr_cbufs) ? state->cbufs[i] : state->zsbuf;
+         const unsigned depth =
+            (surf->texture->target == PIPE_TEXTURE_3D) ?
+            surf->texture->depth0 :
+            surf->u.tex.last_layer - surf->u.tex.first_layer + 1;
+
+         has_3d_target |= (surf->texture->target == PIPE_TEXTURE_3D);
+
+         /*
+          * From the Sandy Bridge PRM, volume 4 part 1, page 79:
+          *
+          *     "The LOD of a render target must be the same as the LOD of the
+          *      other render target(s) and of the depth buffer (defined in
+          *      3DSTATE_DEPTH_BUFFER)."
+          *
+          * From the Sandy Bridge PRM, volume 4 part 1, page 81:
+          *
+          *     "The Depth of a render target must be the same as the Depth of
+          *      the other render target(s) and of the depth buffer (defined
+          *      in 3DSTATE_DEPTH_BUFFER)."
+          */
+         if (surf->u.tex.level != first->u.tex.level ||
+             depth != first_depth) {
+            fb->offset_to_layers = true;
+            break;
+         }
+
+         /*
+          * From the Sandy Bridge PRM, volume 4 part 1, page 77:
+          *
+          *     "The Height of a render target must be the same as the Height
+          *      of the other render targets and the depth buffer (defined in
+          *      3DSTATE_DEPTH_BUFFER), unless Surface Type is SURFTYPE_1D or
+          *      SURFTYPE_2D with Depth = 0 (non-array) and LOD = 0 (non-mip
+          *      mapped)."
+          *
+          * From the Sandy Bridge PRM, volume 4 part 1, page 78:
+          *
+          *     "The Width of a render target must be the same as the Width of
+          *      the other render target(s) and the depth buffer (defined in
+          *      3DSTATE_DEPTH_BUFFER), unless Surface Type is SURFTYPE_1D or
+          *      SURFTYPE_2D with Depth = 0 (non-array) and LOD = 0 (non-mip
+          *      mapped)."
+          */
+         if (surf->texture->width0 != first->texture->width0 ||
+             surf->texture->height0 != first->texture->height0) {
+            if (has_3d_target || first->u.tex.level || first_depth > 1) {
+               fb->offset_to_layers = true;
+               break;
+            }
+         }
+      }
+   }
+}
+
 int
 ilo_gpe_gen6_estimate_command_size(const struct ilo_dev_info *dev,
                                    enum ilo_gpe_gen6_command cmd,
index 4953e52ec68e39be7cdbe5b541cc89527a5057cc..f9aa76d53820861befd1bb14ea283a4aa0980c22 100644 (file)
@@ -25,7 +25,6 @@
  *    Chia-I Wu <olv@lunarg.com>
  */
 
-#include "util/u_framebuffer.h"
 #include "util/u_helpers.h"
 #include "util/u_upload_mgr.h"
 
@@ -645,17 +644,7 @@ ilo_set_framebuffer_state(struct pipe_context *pipe,
 {
    struct ilo_context *ilo = ilo_context(pipe);
 
-   util_copy_framebuffer_state(&ilo->fb.state, state);
-
-   if (state->nr_cbufs)
-      ilo->fb.num_samples = state->cbufs[0]->texture->nr_samples;
-   else if (state->zsbuf)
-      ilo->fb.num_samples = state->zsbuf->texture->nr_samples;
-   else
-      ilo->fb.num_samples = 1;
-
-   if (!ilo->fb.num_samples)
-      ilo->fb.num_samples = 1;
+   ilo_gpe_init_fb(ilo->dev, state, &ilo->fb);
 
    ilo->dirty |= ILO_DIRTY_FB;
 }
@@ -943,7 +932,7 @@ ilo_create_sampler_view(struct pipe_context *pipe,
             templ->u.tex.last_level - templ->u.tex.first_level + 1,
             templ->u.tex.first_layer,
             templ->u.tex.last_layer - templ->u.tex.first_layer + 1,
-            false, true, &view->surface);
+            false, false, &view->surface);
    }
 
    return &view->base;
@@ -991,7 +980,7 @@ ilo_create_surface(struct pipe_context *pipe,
             templ->format, templ->u.tex.level, 1,
             templ->u.tex.first_layer,
             templ->u.tex.last_layer - templ->u.tex.first_layer + 1,
-            true, true, &surf->u.rt);
+            true, false, &surf->u.rt);
    }
    else {
       assert(res->target != PIPE_BUFFER);
@@ -1000,7 +989,7 @@ ilo_create_surface(struct pipe_context *pipe,
             templ->format, templ->u.tex.level,
             templ->u.tex.first_layer,
             templ->u.tex.last_layer - templ->u.tex.first_layer + 1,
-            true, &surf->u.zs);
+            false, &surf->u.zs);
    }
 
    return &surf->base;