diff options
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_jit.c | 48 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_jit.h | 34 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast_priv.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup.c | 67 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup.h | 7 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_context.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_line.c | 11 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_point.c | 11 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_tri.c | 15 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_derived.c | 12 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_fs.c | 64 |
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, |