summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/llvmpipe
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/llvmpipe')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.h3
-rw-r--r--src/gallium/drivers/llvmpipe/lp_jit.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c198
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_priv.h20
-rw-r--r--src/gallium/drivers/llvmpipe/lp_scene.c12
-rw-r--r--src/gallium/drivers/llvmpipe/lp_scene.h7
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c1
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_context.h1
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_line.c6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_point.c7
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_tri.c17
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_derived.c13
-rw-r--r--src/gallium/drivers/llvmpipe/lp_texture.c6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_texture.h10
15 files changed, 195 insertions, 110 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
index 54f38303ae5..abfe852bae5 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -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;
diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h
index 4e9ca764fe7..2ecfde75a09 100644
--- a/src/gallium/drivers/llvmpipe/lp_jit.h
+++ b/src/gallium/drivers/llvmpipe/lp_jit.h
@@ -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,
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 981dd712126..dcd66ab00c1 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -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));
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h
index 9fe89e5b6f1..50917a7c633 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -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[] */
};
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index 4876d7472fb..6f03023eafe 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -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;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c
index 771ad085a12..2abbd25f929 100644
--- a/src/gallium/drivers/llvmpipe/lp_scene.c
+++ b/src/gallium/drivers/llvmpipe/lp_scene.c
@@ -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;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h
index fa5bbcaf013..2d63c002ce2 100644
--- a/src/gallium/drivers/llvmpipe/lp_scene.h
+++ b/src/gallium/drivers/llvmpipe/lp_scene.h
@@ -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;
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index bafcf56b803..e2fb257e1c1 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h
index 62d5a3c5796..cc2b97390c0 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h
@@ -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;
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_line.c b/src/gallium/drivers/llvmpipe/lp_setup_line.c
index 57a96d57ce7..a9809a0ed12 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_line.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_line.c
@@ -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++) {
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c b/src/gallium/drivers/llvmpipe/lp_setup_point.c
index b8040ae56f6..789caa80761 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_point.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
index e0aaa196c9a..2ca47bca43e 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
@@ -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);
}
/*
diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
index ea24ffcd6b6..dc80358c7be 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_derived.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c
index f1a1ed0960a..2263e0a5b47 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.c
+++ b/src/gallium/drivers/llvmpipe/lp_texture.c
@@ -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)
{
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h
index e73d44946d2..2960574fb2c 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.h
+++ b/src/gallium/drivers/llvmpipe/lp_texture.h
@@ -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)
{