llvmpipe: add support for layered rendering
authorRoland Scheidegger <sroland@vmware.com>
Fri, 7 Jun 2013 19:03:40 +0000 (21:03 +0200)
committerRoland Scheidegger <sroland@vmware.com>
Fri, 7 Jun 2013 19:15:01 +0000 (21:15 +0200)
Mostly just make sure the layer parameter gets passed through to the right
places (and get clamped, can do this at setup time), fix up clears to
clear all layers and disable opaque optimization. Luckily don't need to
touch the jitted code.
(Clears invoked via pipe's clear_render_target method will not work however
since the pipe_util_clear function used for it doesn't handle clearing
multiple layers yet.)

v2: per Brian's suggestion, prettify var initialization and add some comments,
add assertion for impossible layer specification for surface.

Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
15 files changed:
src/gallium/drivers/llvmpipe/lp_context.h
src/gallium/drivers/llvmpipe/lp_jit.h
src/gallium/drivers/llvmpipe/lp_rast.c
src/gallium/drivers/llvmpipe/lp_rast.h
src/gallium/drivers/llvmpipe/lp_rast_priv.h
src/gallium/drivers/llvmpipe/lp_scene.c
src/gallium/drivers/llvmpipe/lp_scene.h
src/gallium/drivers/llvmpipe/lp_setup.c
src/gallium/drivers/llvmpipe/lp_setup_context.h
src/gallium/drivers/llvmpipe/lp_setup_line.c
src/gallium/drivers/llvmpipe/lp_setup_point.c
src/gallium/drivers/llvmpipe/lp_setup_tri.c
src/gallium/drivers/llvmpipe/lp_state_derived.c
src/gallium/drivers/llvmpipe/lp_texture.c
src/gallium/drivers/llvmpipe/lp_texture.h

index 54f38303ae520a3e5092418be75ac23adebfe58a..abfe852bae513e26da98b888578973e915430998 100644 (file)
@@ -119,6 +119,9 @@ struct llvmpipe_context {
    /** Which vertex shader output slot contains viewport index */
    int viewport_index_slot;
 
+   /** Which geometry shader output slot contains layer */
+   int layer_slot;
+
    /**< minimum resolvable depth value, for polygon offset */   
    double mrd;
    
index 4e9ca764fe72a496ac1f64ef1d5ec43fe8236841..2ecfde75a09cd1a4e9b7fcb9c7e2b90c789682fe 100644 (file)
@@ -204,7 +204,7 @@ typedef void
                     const void *dadx,
                     const void *dady,
                     uint8_t **color,
-                    void *depth,
+                    uint8_t *depth,
                     uint32_t mask,
                     struct lp_jit_thread_data *thread_data,
                     unsigned *stride,
index 981dd712126fadda5572636c22ec1a0e7a87a6c1..dcd66ab00c1149c774c63d876f1ecbe05571a45b 100644 (file)
@@ -109,6 +109,7 @@ lp_rast_tile_begin(struct lp_rasterizer_task *task,
 /**
  * Clear the rasterizer's current color tile.
  * This is a bin command called during bin processing.
+ * Clear commands always clear all bound layers.
  */
 static void
 lp_rast_clear_color(struct lp_rasterizer_task *task,
@@ -134,6 +135,8 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
 
          for (i = 0; i < scene->fb.nr_cbufs; i++) {
             enum pipe_format format = scene->fb.cbufs[i]->format;
+            unsigned layer;
+            uint8_t *map_layer = scene->cbufs[i].map;
 
             if (util_format_is_pure_sint(format)) {
                util_format_write_4i(format, arg.clear_color.i, 0, &uc, 0, 0, 0, 1, 1);
@@ -143,14 +146,17 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
                util_format_write_4ui(format, arg.clear_color.ui, 0, &uc, 0, 0, 0, 1, 1);
             }
 
-            util_fill_rect(scene->cbufs[i].map,
-                           scene->fb.cbufs[i]->format,
-                           scene->cbufs[i].stride,
-                           task->x,
-                           task->y,
-                           task->width,
-                           task->height,
-                           &uc);
+            for (layer = 0; layer <= scene->fb_max_layer; layer++) {
+               util_fill_rect(map_layer,
+                              scene->fb.cbufs[i]->format,
+                              scene->cbufs[i].stride,
+                              task->x,
+                              task->y,
+                              task->width,
+                              task->height,
+                              &uc);
+               map_layer += scene->cbufs[i].layer_stride;
+            }
          }
       }
       else {
@@ -167,18 +173,22 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
                     clear_color[3]);
 
          for (i = 0; i < scene->fb.nr_cbufs; i++) {
-
-            util_pack_color(arg.clear_color.f,
-                            scene->fb.cbufs[i]->format, &uc);
-
-            util_fill_rect(scene->cbufs[i].map,
-                           scene->fb.cbufs[i]->format,
-                           scene->cbufs[i].stride,
-                           task->x,
-                           task->y,
-                           task->width,
-                           task->height,
-                           &uc);
+            unsigned layer;
+            uint8_t *map_layer = scene->cbufs[i].map;
+
+            for (layer = 0; layer <= scene->fb_max_layer; layer++) {
+               util_pack_color(arg.clear_color.f,
+                               scene->fb.cbufs[i]->format, &uc);
+               util_fill_rect(map_layer,
+                              scene->fb.cbufs[i]->format,
+                              scene->cbufs[i].stride,
+                              task->x,
+                              task->y,
+                              task->width,
+                              task->height,
+                              &uc);
+               map_layer += scene->cbufs[i].layer_stride;
+            }
          }
       }
    }
@@ -192,6 +202,7 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
 /**
  * Clear the rasterizer's current z/stencil tile.
  * This is a bin command called during bin processing.
+ * Clear commands always clear all bound layers.
  */
 static void
 lp_rast_clear_zstencil(struct lp_rasterizer_task *task,
@@ -204,10 +215,10 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task,
    uint32_t clear_mask = (uint32_t) clear_mask64;
    const unsigned height = task->height;
    const unsigned width = task->width;
-   const unsigned block_size = scene->zsbuf.blocksize;
    const unsigned dst_stride = scene->zsbuf.stride;
    uint8_t *dst;
    unsigned i, j;
+   unsigned block_size;
 
    LP_DBG(DEBUG_RAST, "%s: value=0x%08x, mask=0x%08x\n",
            __FUNCTION__, clear_value, clear_mask);
@@ -217,81 +228,87 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task,
     */
 
    if (scene->fb.zsbuf) {
-
-      dst = lp_rast_get_unswizzled_depth_tile_pointer(task, LP_TEX_USAGE_READ_WRITE);
+      unsigned layer;
+      uint8_t *dst_layer = lp_rast_get_unswizzled_depth_tile_pointer(task, LP_TEX_USAGE_READ_WRITE);
+      block_size = util_format_get_blocksize(scene->fb.zsbuf->format);
 
       clear_value &= clear_mask;
 
-      switch (block_size) {
-      case 1:
-         assert(clear_mask == 0xff);
-         memset(dst, (uint8_t) clear_value, height * width);
-         break;
-      case 2:
-         if (clear_mask == 0xffff) {
-            for (i = 0; i < height; i++) {
-               uint16_t *row = (uint16_t *)dst;
-               for (j = 0; j < width; j++)
-                  *row++ = (uint16_t) clear_value;
-               dst += dst_stride;
+      for (layer = 0; layer <= scene->fb_max_layer; layer++) {
+         dst = dst_layer;
+
+         switch (block_size) {
+         case 1:
+            assert(clear_mask == 0xff);
+            memset(dst, (uint8_t) clear_value, height * width);
+            break;
+         case 2:
+            if (clear_mask == 0xffff) {
+               for (i = 0; i < height; i++) {
+                  uint16_t *row = (uint16_t *)dst;
+                  for (j = 0; j < width; j++)
+                     *row++ = (uint16_t) clear_value;
+                  dst += dst_stride;
+               }
             }
-         }
-         else {
-            for (i = 0; i < height; i++) {
-               uint16_t *row = (uint16_t *)dst;
-               for (j = 0; j < width; j++) {
-                  uint16_t tmp = ~clear_mask & *row;
-                  *row++ = clear_value | tmp;
+            else {
+               for (i = 0; i < height; i++) {
+                  uint16_t *row = (uint16_t *)dst;
+                  for (j = 0; j < width; j++) {
+                     uint16_t tmp = ~clear_mask & *row;
+                     *row++ = clear_value | tmp;
+                  }
+                  dst += dst_stride;
                }
-               dst += dst_stride;
             }
-         }
-         break;
-      case 4:
-         if (clear_mask == 0xffffffff) {
-            for (i = 0; i < height; i++) {
-               uint32_t *row = (uint32_t *)dst;
-               for (j = 0; j < width; j++)
-                  *row++ = clear_value;
-               dst += dst_stride;
+            break;
+         case 4:
+            if (clear_mask == 0xffffffff) {
+               for (i = 0; i < height; i++) {
+                  uint32_t *row = (uint32_t *)dst;
+                  for (j = 0; j < width; j++)
+                     *row++ = clear_value;
+                  dst += dst_stride;
+               }
             }
-         }
-         else {
-            for (i = 0; i < height; i++) {
-               uint32_t *row = (uint32_t *)dst;
-               for (j = 0; j < width; j++) {
-                  uint32_t tmp = ~clear_mask & *row;
-                  *row++ = clear_value | tmp;
+            else {
+               for (i = 0; i < height; i++) {
+                  uint32_t *row = (uint32_t *)dst;
+                  for (j = 0; j < width; j++) {
+                     uint32_t tmp = ~clear_mask & *row;
+                     *row++ = clear_value | tmp;
+                  }
+                  dst += dst_stride;
                }
-               dst += dst_stride;
             }
-         }
-         break;
-      case 8:
-         clear_value64 &= clear_mask64;
-         if (clear_mask64 == 0xffffffffffULL) {
-            for (i = 0; i < height; i++) {
-               uint64_t *row = (uint64_t *)dst;
-               for (j = 0; j < width; j++)
-                  *row++ = clear_value64;
-               dst += dst_stride;
+            break;
+         case 8:
+            clear_value64 &= clear_mask64;
+            if (clear_mask64 == 0xffffffffffULL) {
+               for (i = 0; i < height; i++) {
+                  uint64_t *row = (uint64_t *)dst;
+                  for (j = 0; j < width; j++)
+                     *row++ = clear_value64;
+                  dst += dst_stride;
+               }
             }
-         }
-         else {
-            for (i = 0; i < height; i++) {
-               uint64_t *row = (uint64_t *)dst;
-               for (j = 0; j < width; j++) {
-                  uint64_t tmp = ~clear_mask64 & *row;
-                  *row++ = clear_value64 | tmp;
+            else {
+               for (i = 0; i < height; i++) {
+                  uint64_t *row = (uint64_t *)dst;
+                  for (j = 0; j < width; j++) {
+                     uint64_t tmp = ~clear_mask64 & *row;
+                     *row++ = clear_value64 | tmp;
+                  }
+                  dst += dst_stride;
                }
-               dst += dst_stride;
             }
-         }
-         break;
+            break;
 
-      default:
-         assert(0);
-         break;
+         default:
+            assert(0);
+            break;
+         }
+         dst_layer += scene->zsbuf.layer_stride;
       }
    }
 }
@@ -340,17 +357,17 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task,
          /* color buffer */
          for (i = 0; i < scene->fb.nr_cbufs; i++){
             stride[i] = scene->cbufs[i].stride;
-
-            color[i] = lp_rast_get_unswizzled_color_block_pointer(task, i, tile_x + x, tile_y + y);
+            color[i] = lp_rast_get_unswizzled_color_block_pointer(task, i, tile_x + x,
+                                                                  tile_y + y, inputs->layer);
          }
 
          /* depth buffer */
          if (scene->zsbuf.map) {
-            depth = lp_rast_get_unswizzled_depth_block_pointer(task, tile_x + x, tile_y + y);
+            depth = lp_rast_get_unswizzled_depth_block_pointer(task, tile_x + x,
+                                                               tile_y + y, inputs->layer);
             depth_stride = scene->zsbuf.stride;
          }
 
-
          /* run shader on 4x4 block */
          BEGIN_JIT_CALL(state, task);
          variant->jit_function[RAST_WHOLE]( &state->jit_context,
@@ -408,7 +425,7 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task,
    const struct lp_scene *scene = task->scene;
    uint8_t *color[PIPE_MAX_COLOR_BUFS];
    unsigned stride[PIPE_MAX_COLOR_BUFS];
-   void *depth = NULL;
+   uint8_t *depth = NULL;
    unsigned depth_stride = 0;
    unsigned i;
 
@@ -426,14 +443,13 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task,
    /* color buffer */
    for (i = 0; i < scene->fb.nr_cbufs; i++) {
       stride[i] = scene->cbufs[i].stride;
-
-      color[i] = lp_rast_get_unswizzled_color_block_pointer(task, i, x, y);
+      color[i] = lp_rast_get_unswizzled_color_block_pointer(task, i, x, y, inputs->layer);
    }
 
    /* depth buffer */
    if (scene->zsbuf.map) {
       depth_stride = scene->zsbuf.stride;
-      depth = lp_rast_get_unswizzled_depth_block_pointer(task, x, y);
+      depth = lp_rast_get_unswizzled_depth_block_pointer(task, x, y, inputs->layer);
    }
 
    assert(lp_check_alignment(state->jit_context.u8_blend_color, 16));
index 9fe89e5b6f1f7e16130ca94b694cdb366572a154..50917a7c633ae1e9975ab538701ed19d912bdd4e 100644 (file)
@@ -86,8 +86,8 @@ struct lp_rast_shader_inputs {
    unsigned opaque:1;           /** Is opaque */
    unsigned pad0:29;            /* wasted space */
    unsigned stride;             /* how much to advance data between a0, dadx, dady */
+   unsigned layer;              /* the layer to render to (from gs, already clamped) */
    unsigned pad2;               /* wasted space */
-   unsigned pad3;               /* wasted space */
    /* followed by a0, dadx, dady and planes[] */
 };
 
index 4876d7472fb04c4d3ce690917b81627439317461..6f03023eafe721af743436aa4c151ab4f60e631e 100644 (file)
@@ -203,7 +203,8 @@ lp_rast_get_unswizzled_depth_tile_pointer(struct lp_rasterizer_task *task,
  */
 static INLINE uint8_t *
 lp_rast_get_unswizzled_color_block_pointer(struct lp_rasterizer_task *task,
-                                           unsigned buf, unsigned x, unsigned y)
+                                           unsigned buf, unsigned x, unsigned y,
+                                           unsigned layer)
 {
    unsigned px, py, pixel_offset, format_bytes;
    uint8_t *color;
@@ -225,6 +226,10 @@ lp_rast_get_unswizzled_color_block_pointer(struct lp_rasterizer_task *task,
 
    color = color + pixel_offset;
 
+   if (layer) {
+      color += layer * task->scene->cbufs[buf].layer_stride;
+   }
+
    assert(lp_check_alignment(color, llvmpipe_get_format_alignment(task->scene->fb.cbufs[buf]->format)));
    return color;
 }
@@ -236,7 +241,7 @@ lp_rast_get_unswizzled_color_block_pointer(struct lp_rasterizer_task *task,
  */
 static INLINE uint8_t *
 lp_rast_get_unswizzled_depth_block_pointer(struct lp_rasterizer_task *task,
-                                           unsigned x, unsigned y)
+                                           unsigned x, unsigned y, unsigned layer)
 {
    unsigned px, py, pixel_offset, format_bytes;
    uint8_t *depth;
@@ -257,6 +262,10 @@ lp_rast_get_unswizzled_depth_block_pointer(struct lp_rasterizer_task *task,
 
    depth = depth + pixel_offset;
 
+   if (layer) {
+      depth += layer * task->scene->zsbuf.layer_stride;
+   }
+
    assert(lp_check_alignment(depth, llvmpipe_get_format_alignment(task->scene->fb.zsbuf->format)));
    return depth;
 }
@@ -278,19 +287,18 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task,
    struct lp_fragment_shader_variant *variant = state->variant;
    uint8_t *color[PIPE_MAX_COLOR_BUFS];
    unsigned stride[PIPE_MAX_COLOR_BUFS];
-   void *depth = NULL;
+   uint8_t *depth = NULL;
    unsigned depth_stride = 0;
    unsigned i;
 
    /* color buffer */
    for (i = 0; i < scene->fb.nr_cbufs; i++) {
       stride[i] = scene->cbufs[i].stride;
-
-      color[i] = lp_rast_get_unswizzled_color_block_pointer(task, i, x, y);
+      color[i] = lp_rast_get_unswizzled_color_block_pointer(task, i, x, y, inputs->layer);
    }
 
    if (scene->zsbuf.map) {
-      depth = lp_rast_get_unswizzled_depth_block_pointer(task, x, y);
+      depth = lp_rast_get_unswizzled_depth_block_pointer(task, x, y, inputs->layer);
       depth_stride = scene->zsbuf.stride;
    }
 
index 771ad085a120138a03b639dbd483cdb01ba3c2d8..2abbd25f9292cc489797927c87b4ecb99ec13679 100644 (file)
@@ -151,6 +151,7 @@ lp_scene_begin_rasterization(struct lp_scene *scene)
 {
    const struct pipe_framebuffer_state *fb = &scene->fb;
    int i;
+   unsigned max_layer = ~0;
 
    //LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
 
@@ -159,6 +160,9 @@ lp_scene_begin_rasterization(struct lp_scene *scene)
       if (llvmpipe_resource_is_texture(cbuf->texture)) {
          scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture,
                                                            cbuf->u.tex.level);
+         scene->cbufs[i].layer_stride = llvmpipe_layer_stride(cbuf->texture,
+                                                              cbuf->u.tex.level);
+         max_layer = MIN2(max_layer, cbuf->u.tex.last_layer - cbuf->u.tex.first_layer);
 
          scene->cbufs[i].map = llvmpipe_resource_map(cbuf->texture,
                                                      cbuf->u.tex.level,
@@ -169,6 +173,8 @@ lp_scene_begin_rasterization(struct lp_scene *scene)
          struct llvmpipe_resource *lpr = llvmpipe_resource(cbuf->texture);
          unsigned pixstride = util_format_get_blocksize(cbuf->format);
          scene->cbufs[i].stride = cbuf->texture->width0;
+         max_layer = 0;
+
          scene->cbufs[i].map = lpr->data;
          scene->cbufs[i].map += cbuf->u.buf.first_element * pixstride;
       }
@@ -177,14 +183,16 @@ lp_scene_begin_rasterization(struct lp_scene *scene)
    if (fb->zsbuf) {
       struct pipe_surface *zsbuf = scene->fb.zsbuf;
       scene->zsbuf.stride = llvmpipe_resource_stride(zsbuf->texture, zsbuf->u.tex.level);
-      scene->zsbuf.blocksize = 
-         util_format_get_blocksize(zsbuf->texture->format);
+      scene->zsbuf.layer_stride = llvmpipe_layer_stride(zsbuf->texture, zsbuf->u.tex.level);
+      max_layer = MIN2(max_layer, zsbuf->u.tex.last_layer - zsbuf->u.tex.first_layer);
 
       scene->zsbuf.map = llvmpipe_resource_map(zsbuf->texture,
                                                zsbuf->u.tex.level,
                                                zsbuf->u.tex.first_layer,
                                                LP_TEX_USAGE_READ_WRITE);
    }
+
+   scene->fb_max_layer = max_layer;
 }
 
 
index fa5bbcaf013a518b7c4a686524aa3bc9b3d8805d..2d63c002ce299b874c456a54c3044c2384b924f4 100644 (file)
@@ -135,9 +135,12 @@ struct lp_scene {
    struct {
       uint8_t *map;
       unsigned stride;
-      unsigned blocksize;
+      unsigned layer_stride;
    } zsbuf, cbufs[PIPE_MAX_COLOR_BUFS];
-   
+
+   /* OpenGL permits different amount of layers per rt, but rendering limited to minimum */
+   unsigned fb_max_layer;
+
    /** the framebuffer to render the scene into */
    struct pipe_framebuffer_state fb;
 
index bafcf56b8033265ef51397863174eeec061d91e7..e2fb257e1c110eca34784a516e2d1215872cff54 100644 (file)
@@ -1056,6 +1056,7 @@ lp_setup_update_state( struct lp_setup_context *setup,
        */
       setup->psize = lp->psize_slot;
       setup->viewport_index_slot = lp->viewport_index_slot;
+      setup->layer_slot = lp->layer_slot;
 
       assert(lp->dirty == 0);
 
index 62d5a3c5796595e9fa90bd79f50b1625745f6d2a..cc2b97390c0cc16dd243c04ecdc1f3722159379f 100644 (file)
@@ -104,6 +104,7 @@ struct lp_setup_context
    float point_size;
    float psize;
    unsigned viewport_index_slot;
+   unsigned layer_slot;
 
    struct pipe_framebuffer_state fb;
    struct u_rect framebuffer;
index 57a96d57ce7b524e5ee8e73204bcd773de91d036..a9809a0ed12f2d7b01386192f3afec77f94fcfa8 100644 (file)
@@ -290,6 +290,7 @@ try_setup_line( struct lp_setup_context *setup,
    int i;
    int nr_planes = 4;
    unsigned scissor_index = 0;
+   unsigned layer = 0;
    
    /* linewidth should be interpreted as integer */
    int fixed_width = util_iround(width) * FIXED_ONE;
@@ -325,6 +326,10 @@ try_setup_line( struct lp_setup_context *setup,
       nr_planes = 4;
    }
 
+   if (setup->layer_slot > 0) {
+      layer = *(unsigned*)v1[setup->layer_slot];
+      layer = MIN2(layer, scene->fb_max_layer);
+   }
 
    dx = v1[0][0] - v2[0][0];
    dy = v1[0][1] - v2[0][1];
@@ -616,6 +621,7 @@ try_setup_line( struct lp_setup_context *setup,
    line->inputs.frontfacing = TRUE;
    line->inputs.disable = FALSE;
    line->inputs.opaque = FALSE;
+   line->inputs.layer = layer;
 
    for (i = 0; i < 4; i++) {
 
index b8040ae56f6d627f95f5db348a0dbe7df2b04988..789caa80761b49409789c08534086d7b7c1ce8af 100644 (file)
@@ -325,11 +325,17 @@ try_setup_point( struct lp_setup_context *setup,
    unsigned nr_planes = 4;
    struct point_info info;
    unsigned scissor_index = 0;
+   unsigned layer = 0;
 
    if (setup->viewport_index_slot > 0) {
       unsigned *udata = (unsigned*)v0[setup->viewport_index_slot];
       scissor_index = lp_clamp_scissor_idx(*udata);
    }
+   if (setup->layer_slot > 0) {
+      layer = *(unsigned*)v0[setup->layer_slot];
+      layer = MIN2(layer, scene->fb_max_layer);
+   }
+
    /* Bounding rectangle (in pixels) */
    {
       /* Yes this is necessary to accurately calculate bounding boxes
@@ -386,6 +392,7 @@ try_setup_point( struct lp_setup_context *setup,
    point->inputs.frontfacing = TRUE;
    point->inputs.disable = FALSE;
    point->inputs.opaque = FALSE;
+   point->inputs.layer = layer;
 
    {
       struct lp_rast_plane *plane = GET_PLANES(point);
index e0aaa196c9ac6dbc3543753bbe5b2520b955cf8c..2ca47bca43efb66451d6a6fd34c0821f0b49f204 100644 (file)
@@ -203,7 +203,14 @@ lp_setup_whole_tile(struct lp_setup_context *setup,
    LP_COUNT(nr_fully_covered_64);
 
    /* if variant is opaque and scissor doesn't effect the tile */
-   if (inputs->opaque) {
+   /*
+    * Need to disable this optimization for layered rendering and cannot use
+    * setup->layer_slot here to determine it, because it could incorrectly
+    * reset the tile if a previous shader used layer_slot but not this one
+    * (or maybe even "undo" clears). So determine this from presence of layers
+    * instead (in which case layer_slot will have no effect).
+    */
+   if (inputs->opaque && scene->fb_max_layer == 0) {
       if (!scene->fb.zsbuf) {
          /*
           * All previous rendering will be overwritten so reset the bin.
@@ -247,6 +254,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
    unsigned tri_bytes;
    int nr_planes = 3;
    unsigned scissor_index = 0;
+   unsigned layer = 0;
 
    /* Area should always be positive here */
    assert(position->area > 0);
@@ -264,6 +272,10 @@ do_triangle_ccw(struct lp_setup_context *setup,
    else {
       nr_planes = 3;
    }
+   if (setup->layer_slot > 0) {
+      layer = *(unsigned*)v1[setup->layer_slot];
+      layer = MIN2(layer, scene->fb_max_layer);
+   }
 
    /* Bounding rectangle (in pixels) */
    {
@@ -334,6 +346,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
    tri->inputs.frontfacing = frontfacing;
    tri->inputs.disable = FALSE;
    tri->inputs.opaque = setup->fs.current.variant->opaque;
+   tri->inputs.layer = layer;
 
    if (0)
       lp_dump_setup_coef(&setup->setup.variant->key,
@@ -519,7 +532,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
       plane[6].eo = 0;
    }
 
-   return lp_setup_bin_triangle( setup, tri, &bbox, nr_planes, scissor_index );
+   return lp_setup_bin_triangle(setup, tri, &bbox, nr_planes, scissor_index);
 }
 
 /*
index ea24ffcd6b6c2ebd532a0f02570312ac9902d026..dc80358c7be6dd07f286b2a63f7a637166686c99 100644 (file)
@@ -126,7 +126,18 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe)
    } else {
       llvmpipe->viewport_index_slot = 0;
    }
-   
+
+   /* Figure out if we need layer */
+   vs_index = draw_find_shader_output(llvmpipe->draw,
+                                      TGSI_SEMANTIC_LAYER,
+                                      0);
+   if (vs_index >= 0) {
+      llvmpipe->layer_slot = vinfo->num_attribs;
+      draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
+   } else {
+      llvmpipe->layer_slot = 0;
+   }
+
 
    draw_compute_vertex_size(vinfo);
    lp_setup_set_vertex_info(llvmpipe->setup, vinfo);
index f1a1ed0960aba1013a3366d7f44855fc614b62a6..2263e0a5b474d941369feda196ae36afa8efa060 100644 (file)
@@ -496,14 +496,12 @@ llvmpipe_create_surface(struct pipe_context *pipe,
       ps->format = surf_tmpl->format;
       if (llvmpipe_resource_is_texture(pt)) {
          assert(surf_tmpl->u.tex.level <= pt->last_level);
+         assert(surf_tmpl->u.tex.first_layer <= surf_tmpl->u.tex.last_layer);
          ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
          ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
          ps->u.tex.level = surf_tmpl->u.tex.level;
          ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
          ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
-         if (ps->u.tex.first_layer != ps->u.tex.last_layer) {
-            debug_printf("creating surface with multiple layers, rendering to first layer only\n");
-         }
       }
       else {
          /* setting width as number of elements should get us correct renderbuffer width */
@@ -520,7 +518,7 @@ llvmpipe_create_surface(struct pipe_context *pipe,
 }
 
 
-static void 
+static void
 llvmpipe_surface_destroy(struct pipe_context *pipe,
                          struct pipe_surface *surf)
 {
index e73d44946d25f844ae8d36cee72b79bbe1f9088f..2960574fb2c0441475a49a5b12074cceeb4b307d 100644 (file)
@@ -180,6 +180,16 @@ llvmpipe_resource_is_1d(const struct pipe_resource *resource)
 }
 
 
+static INLINE unsigned
+llvmpipe_layer_stride(struct pipe_resource *resource,
+                      unsigned level)
+{
+   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
+   assert(level < LP_MAX_TEXTURE_2D_LEVELS);
+   return lpr->img_stride[level];
+}
+
+
 static INLINE unsigned
 llvmpipe_resource_stride(struct pipe_resource *resource,
                          unsigned level)