llvmpipe: implement scissor testing
The scissor test is implemented as another per-quad operation in the JIT code. The four scissor box params are passed via the lp_jit_context. In the JIT code we compare the quad's x/y coords against the clip bounds and create a new in/out mask that's AND'd with the main quad mask. Note: we should also do scissor testing in the triangle setup code to improve efficiency. That's not done yet.
This commit is contained in:
parent
ca12e30d97
commit
4461442849
|
@ -79,13 +79,16 @@ lp_jit_init_globals(struct llvmpipe_screen *screen)
|
|||
|
||||
/* struct lp_jit_context */
|
||||
{
|
||||
LLVMTypeRef elem_types[4];
|
||||
LLVMTypeRef elem_types[8];
|
||||
LLVMTypeRef context_type;
|
||||
|
||||
elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* constants */
|
||||
elem_types[1] = LLVMFloatType(); /* alpha_ref_value */
|
||||
elem_types[2] = LLVMPointerType(LLVMInt8Type(), 0); /* blend_color */
|
||||
elem_types[3] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */
|
||||
elem_types[1] = LLVMFloatType(); /* alpha_ref_value */ elem_types[2] = LLVMFloatType(); /* scissor_xmin */
|
||||
elem_types[3] = LLVMFloatType(); /* scissor_ymin */
|
||||
elem_types[4] = LLVMFloatType(); /* scissor_xmax */
|
||||
elem_types[5] = LLVMFloatType(); /* scissor_ymax */
|
||||
elem_types[6] = LLVMPointerType(LLVMInt8Type(), 0); /* blend_color */
|
||||
elem_types[7] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */
|
||||
|
||||
context_type = LLVMStructType(elem_types, Elements(elem_types), 0);
|
||||
|
||||
|
@ -93,8 +96,16 @@ lp_jit_init_globals(struct llvmpipe_screen *screen)
|
|||
screen->target, context_type, 0);
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value,
|
||||
screen->target, context_type, 1);
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, blend_color,
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_xmin,
|
||||
screen->target, context_type, 2);
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_ymin,
|
||||
screen->target, context_type, 3);
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_xmax,
|
||||
screen->target, context_type, 4);
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_ymax,
|
||||
screen->target, context_type, 5);
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, blend_color,
|
||||
screen->target, context_type, 6);
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures,
|
||||
screen->target, context_type,
|
||||
LP_JIT_CONTEXT_TEXTURES_INDEX);
|
||||
|
|
|
@ -79,6 +79,9 @@ struct lp_jit_context
|
|||
|
||||
float alpha_ref_value;
|
||||
|
||||
/** floats, not ints */
|
||||
float scissor_xmin, scissor_ymin, scissor_xmax, scissor_ymax;
|
||||
|
||||
/* FIXME: store (also?) in floats */
|
||||
uint8_t *blend_color;
|
||||
|
||||
|
@ -92,10 +95,22 @@ struct lp_jit_context
|
|||
#define lp_jit_context_alpha_ref_value(_builder, _ptr) \
|
||||
lp_build_struct_get(_builder, _ptr, 1, "alpha_ref_value")
|
||||
|
||||
#define lp_jit_context_blend_color(_builder, _ptr) \
|
||||
lp_build_struct_get(_builder, _ptr, 2, "blend_color")
|
||||
#define lp_jit_context_scissor_xmin_value(_builder, _ptr) \
|
||||
lp_build_struct_get(_builder, _ptr, 2, "scissor_xmin")
|
||||
|
||||
#define LP_JIT_CONTEXT_TEXTURES_INDEX 3
|
||||
#define lp_jit_context_scissor_ymin_value(_builder, _ptr) \
|
||||
lp_build_struct_get(_builder, _ptr, 3, "scissor_ymin")
|
||||
|
||||
#define lp_jit_context_scissor_xmax_value(_builder, _ptr) \
|
||||
lp_build_struct_get(_builder, _ptr, 4, "scissor_xmax")
|
||||
|
||||
#define lp_jit_context_scissor_ymax_value(_builder, _ptr) \
|
||||
lp_build_struct_get(_builder, _ptr, 5, "scissor_ymax")
|
||||
|
||||
#define lp_jit_context_blend_color(_builder, _ptr) \
|
||||
lp_build_struct_get(_builder, _ptr, 6, "blend_color")
|
||||
|
||||
#define LP_JIT_CONTEXT_TEXTURES_INDEX 7
|
||||
|
||||
#define lp_jit_context_textures(_builder, _ptr) \
|
||||
lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES_INDEX, "textures")
|
||||
|
|
|
@ -413,6 +413,21 @@ lp_setup_set_blend_color( struct setup_context *setup,
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
lp_setup_set_scissor( struct setup_context *setup,
|
||||
const struct pipe_scissor_state *scissor )
|
||||
{
|
||||
LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
|
||||
|
||||
assert(scissor);
|
||||
|
||||
if (memcmp(&setup->scissor.current, scissor, sizeof(*scissor)) != 0) {
|
||||
setup->scissor.current = *scissor; /* struct copy */
|
||||
setup->dirty |= LP_SETUP_NEW_SCISSOR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_setup_set_flatshade_first( struct setup_context *setup,
|
||||
boolean flatshade_first )
|
||||
|
@ -534,6 +549,25 @@ lp_setup_update_state( struct setup_context *setup )
|
|||
setup->dirty |= LP_SETUP_NEW_FS;
|
||||
}
|
||||
|
||||
if (setup->dirty & LP_SETUP_NEW_SCISSOR) {
|
||||
float *stored;
|
||||
|
||||
stored = lp_scene_alloc_aligned(scene, 4 * sizeof(int32_t), 16);
|
||||
|
||||
stored[0] = (float) setup->scissor.current.minx;
|
||||
stored[1] = (float) setup->scissor.current.miny;
|
||||
stored[2] = (float) setup->scissor.current.maxx;
|
||||
stored[3] = (float) setup->scissor.current.maxy;
|
||||
|
||||
setup->scissor.stored = stored;
|
||||
|
||||
setup->fs.current.jit_context.scissor_xmin = stored[0];
|
||||
setup->fs.current.jit_context.scissor_ymin = stored[1];
|
||||
setup->fs.current.jit_context.scissor_xmax = stored[2];
|
||||
setup->fs.current.jit_context.scissor_ymax = stored[3];
|
||||
|
||||
setup->dirty |= LP_SETUP_NEW_FS;
|
||||
}
|
||||
|
||||
if(setup->dirty & LP_SETUP_NEW_CONSTANTS) {
|
||||
struct pipe_buffer *buffer = setup->constants.current;
|
||||
|
|
|
@ -113,6 +113,10 @@ void
|
|||
lp_setup_set_blend_color( struct setup_context *setup,
|
||||
const struct pipe_blend_color *blend_color );
|
||||
|
||||
void
|
||||
lp_setup_set_scissor( struct setup_context *setup,
|
||||
const struct pipe_scissor_state *scissor );
|
||||
|
||||
void
|
||||
lp_setup_set_sampler_textures( struct setup_context *setup,
|
||||
unsigned num, struct pipe_texture **texture);
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#define LP_SETUP_NEW_FS 0x01
|
||||
#define LP_SETUP_NEW_CONSTANTS 0x02
|
||||
#define LP_SETUP_NEW_BLEND_COLOR 0x04
|
||||
#define LP_SETUP_NEW_SCISSOR 0x08
|
||||
|
||||
|
||||
struct lp_scene_queue;
|
||||
|
@ -122,6 +123,11 @@ struct setup_context
|
|||
uint8_t *stored;
|
||||
} blend_color;
|
||||
|
||||
struct {
|
||||
struct pipe_scissor_state current;
|
||||
const void *stored;
|
||||
} scissor;
|
||||
|
||||
unsigned dirty; /**< bitmask of LP_SETUP_NEW_x bits */
|
||||
|
||||
void (*point)( struct setup_context *,
|
||||
|
|
|
@ -72,6 +72,7 @@ struct lp_fragment_shader_variant_key
|
|||
enum pipe_format zsbuf_format;
|
||||
unsigned nr_cbufs:8;
|
||||
unsigned flatshade:1;
|
||||
unsigned scissor:1;
|
||||
|
||||
struct {
|
||||
ubyte colormask;
|
||||
|
|
|
@ -160,6 +160,7 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
|
|||
|
||||
if (llvmpipe->dirty & (LP_NEW_FS |
|
||||
LP_NEW_BLEND |
|
||||
LP_NEW_SCISSOR |
|
||||
LP_NEW_DEPTH_STENCIL_ALPHA |
|
||||
LP_NEW_RASTERIZER |
|
||||
LP_NEW_SAMPLER |
|
||||
|
@ -170,6 +171,9 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
|
|||
lp_setup_set_blend_color(llvmpipe->setup,
|
||||
&llvmpipe->blend_color);
|
||||
|
||||
if (llvmpipe->dirty & LP_NEW_SCISSOR)
|
||||
lp_setup_set_scissor(llvmpipe->setup, &llvmpipe->scissor);
|
||||
|
||||
if (llvmpipe->dirty & LP_NEW_DEPTH_STENCIL_ALPHA)
|
||||
lp_setup_set_alpha_ref_value(llvmpipe->setup,
|
||||
llvmpipe->depth_stencil->alpha.ref_value);
|
||||
|
|
|
@ -304,6 +304,51 @@ generate_tri_edge_mask(LLVMBuilderRef builder,
|
|||
}
|
||||
|
||||
|
||||
static LLVMValueRef
|
||||
generate_scissor_test(LLVMBuilderRef builder,
|
||||
LLVMValueRef context_ptr,
|
||||
const struct lp_build_interp_soa_context *interp,
|
||||
struct lp_type type)
|
||||
{
|
||||
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
||||
LLVMValueRef xpos = interp->pos[0], ypos = interp->pos[1];
|
||||
LLVMValueRef xmin, ymin, xmax, ymax;
|
||||
LLVMValueRef m0, m1, m2, m3, m;
|
||||
|
||||
/* xpos, ypos contain the window coords for the four pixels in the quad */
|
||||
assert(xpos);
|
||||
assert(ypos);
|
||||
|
||||
/* get the current scissor bounds, convert to vectors */
|
||||
xmin = lp_jit_context_scissor_xmin_value(builder, context_ptr);
|
||||
xmin = lp_build_broadcast(builder, vec_type, xmin);
|
||||
|
||||
ymin = lp_jit_context_scissor_ymin_value(builder, context_ptr);
|
||||
ymin = lp_build_broadcast(builder, vec_type, ymin);
|
||||
|
||||
xmax = lp_jit_context_scissor_xmax_value(builder, context_ptr);
|
||||
xmax = lp_build_broadcast(builder, vec_type, xmax);
|
||||
|
||||
ymax = lp_jit_context_scissor_ymax_value(builder, context_ptr);
|
||||
ymax = lp_build_broadcast(builder, vec_type, ymax);
|
||||
|
||||
/* compare the fragment's position coordinates against the scissor bounds */
|
||||
m0 = lp_build_compare(builder, type, PIPE_FUNC_GEQUAL, xpos, xmin);
|
||||
m1 = lp_build_compare(builder, type, PIPE_FUNC_GEQUAL, ypos, ymin);
|
||||
m2 = lp_build_compare(builder, type, PIPE_FUNC_LESS, xpos, xmax);
|
||||
m3 = lp_build_compare(builder, type, PIPE_FUNC_LESS, ypos, ymax);
|
||||
|
||||
/* AND all the masks together */
|
||||
m = LLVMBuildAnd(builder, m0, m1, "");
|
||||
m = LLVMBuildAnd(builder, m, m2, "");
|
||||
m = LLVMBuildAnd(builder, m, m3, "");
|
||||
|
||||
lp_build_name(m, "scissormask");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the fragment shader, depth/stencil test, and alpha tests.
|
||||
* \param i which quad in the tile, in range [0,3]
|
||||
|
@ -372,6 +417,11 @@ generate_fs(struct llvmpipe_context *lp,
|
|||
/* 'mask' will control execution based on quad's pixel alive/killed state */
|
||||
lp_build_mask_begin(&mask, flow, type, *pmask);
|
||||
|
||||
if (key->scissor) {
|
||||
LLVMValueRef smask =
|
||||
generate_scissor_test(builder, context_ptr, interp, type);
|
||||
lp_build_mask_update(&mask, smask);
|
||||
}
|
||||
|
||||
early_depth_test =
|
||||
key->depth.enabled &&
|
||||
|
@ -968,6 +1018,7 @@ make_variant_key(struct llvmpipe_context *lp,
|
|||
/* alpha.ref_value is passed in jit_context */
|
||||
|
||||
key->flatshade = lp->rasterizer->flatshade;
|
||||
key->scissor = lp->rasterizer->scissor;
|
||||
|
||||
if (lp->framebuffer.nr_cbufs) {
|
||||
memcpy(&key->blend, lp->blend, sizeof key->blend);
|
||||
|
@ -1033,6 +1084,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp)
|
|||
key.blend.colormask == 0xf &&
|
||||
!key.alpha.enabled &&
|
||||
!key.depth.enabled &&
|
||||
!key.scissor &&
|
||||
!shader->info.uses_kill
|
||||
? TRUE : FALSE;
|
||||
|
||||
|
|
Loading…
Reference in New Issue