diff options
author | Roland Scheidegger <[email protected]> | 2013-06-07 21:03:40 +0200 |
---|---|---|
committer | Roland Scheidegger <[email protected]> | 2013-06-07 21:15:01 +0200 |
commit | d8146f240e628e70d4c07f7e805a179f70c36e23 (patch) | |
tree | edfc30c3469fc1cb24ff96891453d1c9806e41d3 /src | |
parent | 0f4c08aea2da3bd808109d09dbcdc249d1fb6b74 (diff) |
llvmpipe: add support for layered rendering
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 <[email protected]>
Reviewed-by: Jose Fonseca <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_context.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_jit.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast.c | 198 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast_priv.h | 20 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_scene.c | 12 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_scene.h | 7 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_context.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_line.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_point.c | 7 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_tri.c | 17 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_derived.c | 13 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_texture.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_texture.h | 10 |
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) { |