summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthew McClure <[email protected]>2013-11-26 10:50:27 -0800
committerJosé Fonseca <[email protected]>2013-12-09 12:57:02 +0000
commit0319ea9ff6a9cc2eba4879fbe09c6fac137d6ce1 (patch)
treeaf651e31eae395fb14550a9e2c3d38a61013135b /src
parent992a2dbba80aba35efe83202e1013bd6143f0dba (diff)
llvmpipe: clamp fragment shader depth write to the current viewport depth range.
With this patch, generate_fs_loop will clamp any fragment shader depth writes to the viewport's min and max depth values. Viewport selection is determined by the geometry shader output for the viewport array index. If no index is specified, then the default viewport index is zero. Semantics for this path can be found in draw_clamp_viewport_idx and lp_clamp_viewport_idx. lp_jit_viewport was created to store viewport information visible to JIT code, and is validated when the LP_NEW_VIEWPORT dirty flag is set. lp_rast_shader_inputs is responsible for passing the viewport_index through the rasterizer stage to fragment stage (via lp_jit_thread_data). Reviewed-by: Roland Scheidegger <[email protected]> Reviewed-by: José Fonseca <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_jit.c48
-rw-r--r--src/gallium/drivers/llvmpipe/lp_jit.h34
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_priv.h5
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c67
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.h7
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_context.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_line.c11
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_point.c11
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_tri.c15
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_derived.c12
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c64
13 files changed, 255 insertions, 29 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c
index fa0f128ee3f..fa36fd3512e 100644
--- a/src/gallium/drivers/llvmpipe/lp_jit.c
+++ b/src/gallium/drivers/llvmpipe/lp_jit.c
@@ -45,7 +45,33 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
{
struct gallivm_state *gallivm = lp->gallivm;
LLVMContextRef lc = gallivm->context;
- LLVMTypeRef texture_type, sampler_type;
+ LLVMTypeRef viewport_type, texture_type, sampler_type;
+
+ /* struct lp_jit_viewport */
+ {
+ LLVMTypeRef elem_types[LP_JIT_VIEWPORT_NUM_FIELDS];
+
+ elem_types[LP_JIT_VIEWPORT_MIN_DEPTH] =
+ elem_types[LP_JIT_VIEWPORT_MAX_DEPTH] = LLVMFloatTypeInContext(lc);
+
+ viewport_type = LLVMStructTypeInContext(lc, elem_types,
+ Elements(elem_types), 0);
+
+#if HAVE_LLVM < 0x0300
+ LLVMAddTypeName(gallivm->module, "viewport", viewport_type);
+
+ LLVMInvalidateStructLayout(gallivm->target, viewport_type);
+#endif
+
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_viewport, min_depth,
+ gallivm->target, viewport_type,
+ LP_JIT_VIEWPORT_MIN_DEPTH);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_viewport, max_depth,
+ gallivm->target, viewport_type,
+ LP_JIT_VIEWPORT_MAX_DEPTH);
+ LP_CHECK_STRUCT_SIZE(struct lp_jit_viewport,
+ gallivm->target, viewport_type);
+ }
/* struct lp_jit_texture */
{
@@ -101,8 +127,8 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
gallivm->target, texture_type);
}
- {
/* struct lp_jit_sampler */
+ {
LLVMTypeRef elem_types[LP_JIT_SAMPLER_NUM_FIELDS];
elem_types[LP_JIT_SAMPLER_MIN_LOD] =
elem_types[LP_JIT_SAMPLER_MAX_LOD] =
@@ -113,22 +139,22 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
sampler_type = LLVMStructTypeInContext(lc, elem_types,
Elements(elem_types), 0);
#if HAVE_LLVM < 0x0300
- LLVMAddTypeName(gallivm->module, "texture", texture_type);
+ LLVMAddTypeName(gallivm->module, "sampler", sampler_type);
- LLVMInvalidateStructLayout(gallivm->target, texture_type);
+ LLVMInvalidateStructLayout(gallivm->target, sampler_type);
#endif
LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, min_lod,
- gallivm->target, texture_type,
+ gallivm->target, sampler_type,
LP_JIT_SAMPLER_MIN_LOD);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, max_lod,
- gallivm->target, texture_type,
+ gallivm->target, sampler_type,
LP_JIT_SAMPLER_MAX_LOD);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, lod_bias,
- gallivm->target, texture_type,
+ gallivm->target, sampler_type,
LP_JIT_SAMPLER_LOD_BIAS);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, border_color,
- gallivm->target, texture_type,
+ gallivm->target, sampler_type,
LP_JIT_SAMPLER_BORDER_COLOR);
LP_CHECK_STRUCT_SIZE(struct lp_jit_sampler,
gallivm->target, sampler_type);
@@ -146,6 +172,7 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
elem_types[LP_JIT_CTX_STENCIL_REF_BACK] = LLVMInt32TypeInContext(lc);
elem_types[LP_JIT_CTX_U8_BLEND_COLOR] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0);
elem_types[LP_JIT_CTX_F_BLEND_COLOR] = LLVMPointerType(LLVMFloatTypeInContext(lc), 0);
+ elem_types[LP_JIT_CTX_VIEWPORTS] = LLVMPointerType(viewport_type, 0);
elem_types[LP_JIT_CTX_TEXTURES] = LLVMArrayType(texture_type,
PIPE_MAX_SHADER_SAMPLER_VIEWS);
elem_types[LP_JIT_CTX_SAMPLERS] = LLVMArrayType(sampler_type,
@@ -178,6 +205,9 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, f_blend_color,
gallivm->target, context_type,
LP_JIT_CTX_F_BLEND_COLOR);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, viewports,
+ gallivm->target, context_type,
+ LP_JIT_CTX_VIEWPORTS);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures,
gallivm->target, context_type,
LP_JIT_CTX_TEXTURES);
@@ -196,6 +226,8 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
LLVMTypeRef thread_data_type;
elem_types[LP_JIT_THREAD_DATA_COUNTER] = LLVMInt64TypeInContext(lc);
+ elem_types[LP_JIT_THREAD_DATA_RASTER_STATE_VIEWPORT_INDEX] =
+ LLVMInt32TypeInContext(lc);
thread_data_type = LLVMStructTypeInContext(lc, elem_types,
Elements(elem_types), 0);
diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h
index 30cfaaef5d6..8eefa7c8479 100644
--- a/src/gallium/drivers/llvmpipe/lp_jit.h
+++ b/src/gallium/drivers/llvmpipe/lp_jit.h
@@ -70,6 +70,13 @@ struct lp_jit_sampler
};
+struct lp_jit_viewport
+{
+ float min_depth;
+ float max_depth;
+};
+
+
enum {
LP_JIT_TEXTURE_WIDTH = 0,
LP_JIT_TEXTURE_HEIGHT,
@@ -93,6 +100,13 @@ enum {
};
+enum {
+ LP_JIT_VIEWPORT_MIN_DEPTH,
+ LP_JIT_VIEWPORT_MAX_DEPTH,
+ LP_JIT_VIEWPORT_NUM_FIELDS /* number of fields above */
+};
+
+
/**
* This structure is passed directly to the generated fragment shader.
*
@@ -115,6 +129,8 @@ struct lp_jit_context
uint8_t *u8_blend_color;
float *f_blend_color;
+ struct lp_jit_viewport *viewports;
+
struct lp_jit_texture textures[PIPE_MAX_SHADER_SAMPLER_VIEWS];
struct lp_jit_sampler samplers[PIPE_MAX_SAMPLERS];
};
@@ -131,6 +147,7 @@ enum {
LP_JIT_CTX_STENCIL_REF_BACK,
LP_JIT_CTX_U8_BLEND_COLOR,
LP_JIT_CTX_F_BLEND_COLOR,
+ LP_JIT_CTX_VIEWPORTS,
LP_JIT_CTX_TEXTURES,
LP_JIT_CTX_SAMPLERS,
LP_JIT_CTX_COUNT
@@ -155,6 +172,9 @@ enum {
#define lp_jit_context_f_blend_color(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_F_BLEND_COLOR, "f_blend_color")
+#define lp_jit_context_viewports(_gallivm, _ptr) \
+ lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_VIEWPORTS, "viewports")
+
#define lp_jit_context_textures(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_TEXTURES, "textures")
@@ -165,11 +185,19 @@ enum {
struct lp_jit_thread_data
{
uint64_t vis_counter;
+
+ /*
+ * Non-interpolated rasterizer state passed through to the fragment shader.
+ */
+ struct {
+ uint32_t viewport_index;
+ } raster_state;
};
enum {
LP_JIT_THREAD_DATA_COUNTER = 0,
+ LP_JIT_THREAD_DATA_RASTER_STATE_VIEWPORT_INDEX,
LP_JIT_THREAD_DATA_COUNT
};
@@ -177,7 +205,11 @@ enum {
#define lp_jit_thread_data_counter(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_THREAD_DATA_COUNTER, "counter")
-
+#define lp_jit_thread_data_raster_state_viewport_index(_gallivm, _ptr) \
+ lp_build_struct_get(_gallivm, _ptr, \
+ LP_JIT_THREAD_DATA_RASTER_STATE_VIEWPORT_INDEX, \
+ "raster_state.viewport_index")
+
/**
* typedef for fragment shader function
*
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 0cd62c2d99f..6feec947137 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -367,6 +367,9 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task,
depth_stride = scene->zsbuf.stride;
}
+ /* Propagate non-interpolated raster state. */
+ task->thread_data.raster_state.viewport_index = inputs->viewport_index;
+
/* run shader on 4x4 block */
BEGIN_JIT_CALL(state, task);
variant->jit_function[RAST_WHOLE]( &state->jit_context,
@@ -462,6 +465,9 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task,
/* always count this not worth bothering? */
task->ps_invocations += 1 * variant->ps_inv_multiplier;
+ /* Propagate non-interpolated raster state. */
+ task->thread_data.raster_state.viewport_index = inputs->viewport_index;
+
/* run shader on 4x4 block */
BEGIN_JIT_CALL(state, task);
variant->jit_function[RAST_EDGE_TEST](&state->jit_context,
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h
index b81d94f50f0..e2a9ec20892 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -102,7 +102,7 @@ struct lp_rast_shader_inputs {
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 viewport_index; /* the active viewport index (from gs, already clamped) */
/* 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 77ec329485d..bc361b6f1b9 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -97,7 +97,7 @@ struct lp_rasterizer_task
/** "my" index */
unsigned thread_index;
- /* occlude counter for visible pixels */
+ /** Non-interpolated passthru state and occlude counter for visible pixels */
struct lp_jit_thread_data thread_data;
uint64_t ps_invocations;
uint8_t ps_inv_multiplier;
@@ -311,6 +311,9 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task,
/* always count this not worth bothering? */
task->ps_invocations += 1 * variant->ps_inv_multiplier;
+ /* Propagate non-interpolated raster state. */
+ task->thread_data.raster_state.viewport_index = inputs->viewport_index;
+
/* run shader on 4x4 block */
BEGIN_JIT_CALL(state, task);
variant->jit_function[RAST_WHOLE]( &state->jit_context,
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index 9b277d32ddc..31aaf963fe9 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -649,6 +649,41 @@ lp_setup_set_vertex_info( struct lp_setup_context *setup,
/**
+ * Called during state validation when LP_NEW_VIEWPORT is set.
+ */
+void
+lp_setup_set_viewports(struct lp_setup_context *setup,
+ unsigned num_viewports,
+ const struct pipe_viewport_state *viewports)
+{
+ unsigned i;
+
+ LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
+
+ assert(num_viewports <= PIPE_MAX_VIEWPORTS);
+ assert(viewports);
+
+ /*
+ * For use in lp_state_fs.c, propagate the viewport values for all viewports.
+ */
+ for (i = 0; i < num_viewports; i++) {
+ float min_depth;
+ float max_depth;
+
+ min_depth = viewports[i].translate[2];
+ max_depth = viewports[i].translate[2] + viewports[i].scale[2];
+
+ if (setup->viewports[i].min_depth != min_depth ||
+ setup->viewports[i].max_depth != max_depth) {
+ setup->viewports[i].min_depth = min_depth;
+ setup->viewports[i].max_depth = max_depth;
+ setup->dirty |= LP_SETUP_NEW_VIEWPORTS;
+ }
+ }
+}
+
+
+/**
* Called during state validation when LP_NEW_SAMPLER_VIEW is set.
*/
void
@@ -863,6 +898,15 @@ lp_setup_is_resource_referenced( const struct lp_setup_context *setup,
/**
* Called by vbuf code when we're about to draw something.
+ *
+ * This function stores all dirty state in the current scene's display list
+ * memory, via lp_scene_alloc(). We can not pass pointers of mutable state to
+ * the JIT functions, as the JIT functions will be called later on, most likely
+ * on a different thread.
+ *
+ * When processing dirty state it is imperative that we don't refer to any
+ * pointers previously allocated with lp_scene_alloc() in this function (or any
+ * function) as they may belong to a scene freed since then.
*/
static boolean
try_update_scene_state( struct lp_setup_context *setup )
@@ -873,6 +917,29 @@ try_update_scene_state( struct lp_setup_context *setup )
assert(scene);
+ if (setup->dirty & LP_SETUP_NEW_VIEWPORTS) {
+ /*
+ * Record new depth range state for changes due to viewport updates.
+ *
+ * TODO: Collapse the existing viewport and depth range information
+ * into one structure, for access by JIT.
+ */
+ struct lp_jit_viewport *stored;
+
+ stored = (struct lp_jit_viewport *)
+ lp_scene_alloc(scene, sizeof setup->viewports);
+
+ if (!stored) {
+ assert(!new_scene);
+ return FALSE;
+ }
+
+ memcpy(stored, setup->viewports, sizeof setup->viewports);
+
+ setup->fs.current.jit_context.viewports = stored;
+ setup->dirty |= LP_SETUP_NEW_FS;
+ }
+
if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) {
uint8_t *stored;
float* fstored;
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h
index 712ed145d8e..f4fbd3dbf65 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup.h
@@ -121,6 +121,11 @@ lp_setup_set_scissors( struct lp_setup_context *setup,
const struct pipe_scissor_state *scissors );
void
+lp_setup_set_viewports(struct lp_setup_context *setup,
+ unsigned num_viewports,
+ const struct pipe_viewport_state *viewports);
+
+void
lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup,
unsigned num,
struct pipe_sampler_view **views);
@@ -155,7 +160,7 @@ lp_setup_end_query(struct lp_setup_context *setup,
struct llvmpipe_query *pq);
static INLINE unsigned
-lp_clamp_scissor_idx(int idx)
+lp_clamp_viewport_idx(int idx)
{
return (PIPE_MAX_VIEWPORTS > idx && idx >= 0) ? idx : 0;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h
index 44be85fde1a..8bb95c15697 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h
@@ -47,6 +47,7 @@
#define LP_SETUP_NEW_CONSTANTS 0x02
#define LP_SETUP_NEW_BLEND_COLOR 0x04
#define LP_SETUP_NEW_SCISSOR 0x08
+#define LP_SETUP_NEW_VIEWPORTS 0x10
struct lp_setup_variant;
@@ -112,6 +113,7 @@ struct lp_setup_context
struct u_rect framebuffer;
struct u_rect scissors[PIPE_MAX_VIEWPORTS];
struct u_rect draw_regions[PIPE_MAX_VIEWPORTS]; /* intersection of fb & scissor */
+ struct lp_jit_viewport viewports[PIPE_MAX_VIEWPORTS];
struct {
unsigned flags;
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_line.c b/src/gallium/drivers/llvmpipe/lp_setup_line.c
index 9b3321e3ec1..7e1f6a36745 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_line.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_line.c
@@ -294,7 +294,7 @@ try_setup_line( struct lp_setup_context *setup,
int y[4];
int i;
int nr_planes = 4;
- unsigned scissor_index = 0;
+ unsigned viewport_index = 0;
unsigned layer = 0;
/* linewidth should be interpreted as integer */
@@ -324,7 +324,7 @@ try_setup_line( struct lp_setup_context *setup,
nr_planes = 8;
if (setup->viewport_index_slot > 0) {
unsigned *udata = (unsigned*)v1[setup->viewport_index_slot];
- scissor_index = lp_clamp_scissor_idx(*udata);
+ viewport_index = lp_clamp_viewport_idx(*udata);
}
}
else {
@@ -573,7 +573,7 @@ try_setup_line( struct lp_setup_context *setup,
return TRUE;
}
- if (!u_rect_test_intersection(&setup->draw_regions[scissor_index], &bbox)) {
+ if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) {
if (0) debug_printf("offscreen\n");
LP_COUNT(nr_culled_tris);
return TRUE;
@@ -635,6 +635,7 @@ try_setup_line( struct lp_setup_context *setup,
line->inputs.disable = FALSE;
line->inputs.opaque = FALSE;
line->inputs.layer = layer;
+ line->inputs.viewport_index = viewport_index;
for (i = 0; i < 4; i++) {
@@ -697,7 +698,7 @@ try_setup_line( struct lp_setup_context *setup,
*/
if (nr_planes == 8) {
const struct u_rect *scissor =
- &setup->scissors[scissor_index];
+ &setup->scissors[viewport_index];
plane[4].dcdx = -1;
plane[4].dcdy = 0;
@@ -720,7 +721,7 @@ try_setup_line( struct lp_setup_context *setup,
plane[7].eo = 0;
}
- return lp_setup_bin_triangle(setup, line, &bbox, nr_planes, scissor_index);
+ return lp_setup_bin_triangle(setup, line, &bbox, nr_planes, viewport_index);
}
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c b/src/gallium/drivers/llvmpipe/lp_setup_point.c
index 45068ec6df3..4b31495a5c8 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_point.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c
@@ -330,12 +330,12 @@ try_setup_point( struct lp_setup_context *setup,
struct u_rect bbox;
unsigned nr_planes = 4;
struct point_info info;
- unsigned scissor_index = 0;
+ unsigned viewport_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);
+ viewport_index = lp_clamp_viewport_idx(*udata);
}
if (setup->layer_slot > 0) {
layer = *(unsigned*)v0[setup->layer_slot];
@@ -362,13 +362,13 @@ try_setup_point( struct lp_setup_context *setup,
bbox.y1--;
}
- if (!u_rect_test_intersection(&setup->draw_regions[scissor_index], &bbox)) {
+ if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) {
if (0) debug_printf("offscreen\n");
LP_COUNT(nr_culled_tris);
return TRUE;
}
- u_rect_find_intersection(&setup->draw_regions[scissor_index], &bbox);
+ u_rect_find_intersection(&setup->draw_regions[viewport_index], &bbox);
point = lp_setup_alloc_triangle(scene,
key->num_inputs,
@@ -413,6 +413,7 @@ try_setup_point( struct lp_setup_context *setup,
point->inputs.disable = FALSE;
point->inputs.opaque = FALSE;
point->inputs.layer = layer;
+ point->inputs.viewport_index = viewport_index;
{
struct lp_rast_plane *plane = GET_PLANES(point);
@@ -438,7 +439,7 @@ try_setup_point( struct lp_setup_context *setup,
plane[3].eo = 0;
}
- return lp_setup_bin_triangle(setup, point, &bbox, nr_planes, scissor_index);
+ return lp_setup_bin_triangle(setup, point, &bbox, nr_planes, viewport_index);
}
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
index 53ab1f1f0c0..e22f14c9ca0 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
@@ -274,7 +274,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
struct u_rect bbox;
unsigned tri_bytes;
int nr_planes = 3;
- unsigned scissor_index = 0;
+ unsigned viewport_index = 0;
unsigned layer = 0;
/* Area should always be positive here */
@@ -287,7 +287,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
nr_planes = 7;
if (setup->viewport_index_slot > 0) {
unsigned *udata = (unsigned*)v0[setup->viewport_index_slot];
- scissor_index = lp_clamp_scissor_idx(*udata);
+ viewport_index = lp_clamp_viewport_idx(*udata);
}
}
else {
@@ -323,7 +323,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
return TRUE;
}
- if (!u_rect_test_intersection(&setup->draw_regions[scissor_index], &bbox)) {
+ if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) {
if (0) debug_printf("offscreen\n");
LP_COUNT(nr_culled_tris);
return TRUE;
@@ -368,6 +368,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
tri->inputs.disable = FALSE;
tri->inputs.opaque = setup->fs.current.variant->opaque;
tri->inputs.layer = layer;
+ tri->inputs.viewport_index = viewport_index;
if (0)
lp_dump_setup_coef(&setup->setup.variant->key,
@@ -547,7 +548,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
* these planes elsewhere.
*/
if (nr_planes == 7) {
- const struct u_rect *scissor = &setup->scissors[scissor_index];
+ const struct u_rect *scissor = &setup->scissors[viewport_index];
plane[3].dcdx = -1;
plane[3].dcdy = 0;
@@ -570,7 +571,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, viewport_index);
}
/*
@@ -605,7 +606,7 @@ lp_setup_bin_triangle( struct lp_setup_context *setup,
struct lp_rast_triangle *tri,
const struct u_rect *bbox,
int nr_planes,
- unsigned scissor_index )
+ unsigned viewport_index )
{
struct lp_scene *scene = setup->scene;
struct u_rect trimmed_box = *bbox;
@@ -628,7 +629,7 @@ lp_setup_bin_triangle( struct lp_setup_context *setup,
* the rasterizer to also respect scissor, etc, just for the rare
* cases where a small triangle extends beyond the scissor.
*/
- u_rect_find_intersection(&setup->draw_regions[scissor_index],
+ u_rect_find_intersection(&setup->draw_regions[viewport_index],
&trimmed_box);
/* Determine which tile(s) intersect the triangle's bounding box
diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
index 47e413b776c..5c3a3a8e3a9 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_derived.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
@@ -219,6 +219,18 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
llvmpipe->num_samplers[PIPE_SHADER_FRAGMENT],
llvmpipe->samplers[PIPE_SHADER_FRAGMENT]);
+ if (llvmpipe->dirty & LP_NEW_VIEWPORT) {
+ /*
+ * Update setup and fragment's view of the active viewport state.
+ *
+ * XXX TODO: It is possible to only loop over the active viewports
+ * instead of all viewports (PIPE_MAX_VIEWPORTS).
+ */
+ lp_setup_set_viewports(llvmpipe->setup,
+ PIPE_MAX_VIEWPORTS,
+ llvmpipe->viewports);
+ }
+
llvmpipe->dirty = 0;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index b5816e038f1..74c7360bfbb 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -215,6 +215,30 @@ find_output_by_semantic( const struct tgsi_shader_info *info,
/**
+ * Fetch the specified lp_jit_viewport structure for a given viewport_index.
+ */
+static LLVMValueRef
+lp_llvm_viewport(LLVMValueRef context_ptr,
+ struct gallivm_state *gallivm,
+ LLVMValueRef viewport_index)
+{
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMValueRef ptr;
+ LLVMValueRef res;
+ struct lp_type viewport_type =
+ lp_type_float_vec(32, 32 * LP_JIT_VIEWPORT_NUM_FIELDS);
+
+ ptr = lp_jit_context_viewports(gallivm, context_ptr);
+ ptr = LLVMBuildPointerCast(builder, ptr,
+ LLVMPointerType(lp_build_vec_type(gallivm, viewport_type), 0), "");
+
+ res = lp_build_pointer_get(builder, ptr, viewport_index);
+
+ return res;
+}
+
+
+/**
* Generate the fragment shader, depth/stencil test, and alpha tests.
*/
static void
@@ -421,7 +445,47 @@ generate_fs_loop(struct gallivm_state *gallivm,
0);
if (pos0 != -1 && outputs[pos0][2]) {
+ LLVMValueRef viewport, min_depth, max_depth;
+ LLVMValueRef viewport_index;
+ struct lp_build_context f32_bld;
+
+ assert(type.floating);
+ lp_build_context_init(&f32_bld, gallivm, type);
+
+ /*
+ * Assumes clamping of the viewport index will occur in setup/gs. Value
+ * is passed through the rasterization stage via lp_rast_shader_inputs.
+ *
+ * See: draw_clamp_viewport_idx and lp_clamp_viewport_idx for clamping
+ * semantics.
+ */
+ viewport_index = lp_jit_thread_data_raster_state_viewport_index(gallivm,
+ thread_data_ptr);
+
+ /*
+ * Load the min and max depth from the lp_jit_context.viewports
+ * array of lp_jit_viewport structures.
+ */
+ viewport = lp_llvm_viewport(context_ptr, gallivm, viewport_index);
+
+ /* viewports[viewport_index].min_depth */
+ min_depth = LLVMBuildExtractElement(builder, viewport,
+ lp_build_const_int32(gallivm, LP_JIT_VIEWPORT_MIN_DEPTH),
+ "");
+ min_depth = lp_build_broadcast_scalar(&f32_bld, min_depth);
+
+ /* viewports[viewport_index].max_depth */
+ max_depth = LLVMBuildExtractElement(builder, viewport,
+ lp_build_const_int32(gallivm, LP_JIT_VIEWPORT_MAX_DEPTH),
+ "");
+ max_depth = lp_build_broadcast_scalar(&f32_bld, max_depth);
+
z = LLVMBuildLoad(builder, outputs[pos0][2], "output.z");
+
+ /*
+ * Clamp to the min and max depth values for the given viewport.
+ */
+ z = lp_build_clamp(&f32_bld, z, min_depth, max_depth);
}
lp_build_depth_stencil_load_swizzled(gallivm, type,