softpipe: add support for shader stencil export capability

this allows softpipe to be used to test shader stencil ref exporting.

Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Dave Airlie 2010-10-06 09:32:32 +10:00
parent c79e681a68
commit d8f6ef4565
5 changed files with 67 additions and 12 deletions

View file

@ -169,9 +169,15 @@ fs_sse_run( const struct sp_fragment_shader *base,
case TGSI_SEMANTIC_POSITION:
{
uint j;
for (j = 0; j < 4; j++) {
quad->output.depth[j] = machine->Outputs[0].xyzw[2].f[j];
}
for (j = 0; j < 4; j++)
quad->output.depth[j] = machine->Outputs[i].xyzw[2].f[j];
}
break;
case TGSI_SEMANTIC_STENCIL:
{
uint j;
for (j = 0; j < 4; j++)
quad->output.stencil[j] = machine->Outputs[i].xyzw[1].f[j];
}
break;
}

View file

@ -85,6 +85,7 @@ struct quad_header_output
/** colors in SOA format (rrrr, gggg, bbbb, aaaa) */
float color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS][QUAD_SIZE];
float depth[QUAD_SIZE];
uint8_t stencil[QUAD_SIZE];
};

View file

@ -47,6 +47,8 @@ struct depth_data {
unsigned bzzzz[QUAD_SIZE]; /**< Z values fetched from depth buffer */
unsigned qzzzz[QUAD_SIZE]; /**< Z values from the quad */
ubyte stencilVals[QUAD_SIZE];
boolean use_shader_stencil_refs;
ubyte shader_stencil_refs[QUAD_SIZE];
struct softpipe_cached_tile *tile;
};
@ -186,6 +188,33 @@ convert_quad_depth( struct depth_data *data,
}
/**
* Compute the depth_data::shader_stencil_refs[] values from the float fragment stencil values.
*/
static void
convert_quad_stencil( struct depth_data *data,
const struct quad_header *quad )
{
unsigned j;
data->use_shader_stencil_refs = TRUE;
/* Copy quads stencil values
*/
switch (data->format) {
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
{
for (j = 0; j < QUAD_SIZE; j++) {
data->shader_stencil_refs[j] = ((unsigned)(quad->output.stencil[j]));
}
}
break;
default:
assert(0);
}
}
/**
* Write data->bzzzz[] values and data->stencilVals into the Z/stencil buffer.
@ -272,8 +301,14 @@ do_stencil_test(struct depth_data *data,
{
unsigned passMask = 0x0;
unsigned j;
ubyte refs[QUAD_SIZE];
ref &= valMask;
for (j = 0; j < QUAD_SIZE; j++) {
if (data->use_shader_stencil_refs)
refs[j] = data->shader_stencil_refs[j] & valMask;
else
refs[j] = ref & valMask;
}
switch (func) {
case PIPE_FUNC_NEVER:
@ -281,42 +316,42 @@ do_stencil_test(struct depth_data *data,
break;
case PIPE_FUNC_LESS:
for (j = 0; j < QUAD_SIZE; j++) {
if (ref < (data->stencilVals[j] & valMask)) {
if (refs[j] < (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_EQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (ref == (data->stencilVals[j] & valMask)) {
if (refs[j] == (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_LEQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (ref <= (data->stencilVals[j] & valMask)) {
if (refs[j] <= (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_GREATER:
for (j = 0; j < QUAD_SIZE; j++) {
if (ref > (data->stencilVals[j] & valMask)) {
if (refs[j] > (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_NOTEQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (ref != (data->stencilVals[j] & valMask)) {
if (refs[j] != (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_GEQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (ref >= (data->stencilVals[j] & valMask)) {
if (refs[j] >= (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
@ -348,9 +383,14 @@ apply_stencil_op(struct depth_data *data,
{
unsigned j;
ubyte newstencil[QUAD_SIZE];
ubyte refs[QUAD_SIZE];
for (j = 0; j < QUAD_SIZE; j++) {
newstencil[j] = data->stencilVals[j];
if (data->use_shader_stencil_refs)
refs[j] = data->shader_stencil_refs[j];
else
refs[j] = ref;
}
switch (op) {
@ -367,7 +407,7 @@ apply_stencil_op(struct depth_data *data,
case PIPE_STENCIL_OP_REPLACE:
for (j = 0; j < QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = ref;
newstencil[j] = refs[j];
}
}
break;
@ -688,8 +728,10 @@ depth_test_quads_fallback(struct quad_stage *qs,
unsigned i, pass = 0;
const struct sp_fragment_shader *fs = qs->softpipe->fs;
boolean interp_depth = !fs->info.writes_z;
boolean shader_stencil_ref = fs->info.writes_stencil;
struct depth_data data;
data.use_shader_stencil_refs = FALSE;
if (qs->softpipe->depth_stencil->alpha.enabled) {
nr = alpha_test_quads(qs, quads, nr);
@ -716,6 +758,9 @@ depth_test_quads_fallback(struct quad_stage *qs,
}
if (qs->softpipe->depth_stencil->stencil[0].enabled) {
if (shader_stencil_ref)
convert_quad_stencil(&data, quads[i]);
depth_stencil_test_quad(qs, &data, quads[i]);
write_depth_stencil_values(&data, quads[i]);
}

View file

@ -47,7 +47,8 @@ sp_build_quad_pipeline(struct softpipe_context *sp)
sp->framebuffer.zsbuf &&
!sp->depth_stencil->alpha.enabled &&
!sp->fs->info.uses_kill &&
!sp->fs->info.writes_z;
!sp->fs->info.writes_z &&
!sp->fs->info.writes_stencil;
sp->quad.first = sp->quad.blend;

View file

@ -114,6 +114,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
return 1;
case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
return 0;
case PIPE_CAP_SHADER_STENCIL_EXPORT:
return 1;
default:
return 0;
}