OSDN Git Service

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 54f3830..abfe852 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 4e9ca76..2ecfde7 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 981dd71..dcd66ab 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 9fe89e5..50917a7 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 4876d74..6f03023 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 771ad08..2abbd25 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 fa5bbca..2d63c00 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 bafcf56..e2fb257 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 62d5a3c..cc2b973 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 57a96d5..a9809a0 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 b8040ae..789caa8 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 e0aaa19..2ca47bc 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 ea24ffc..dc80358 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 f1a1ed0..2263e0a 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 e73d449..2960574 100644 (file)
@@ -181,6 +181,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)
 {