gallium: Implement 2D constant buffers for fragment shader in softpipe.

This commit is contained in:
Michal Krol 2010-01-19 13:20:15 +01:00
parent 4367de152c
commit 835bab0143
10 changed files with 156 additions and 175 deletions

View file

@ -302,7 +302,7 @@ void draw_geometry_shader_run(struct draw_geometry_shader *shader,
unsigned num_primitives = count/num_vertices;
unsigned inputs_from_vs = 0;
machine->Consts = constants;
machine->Consts[0] = constants;
for (i = 0; i < shader->info.num_inputs; ++i) {
if (shader->info.input_semantic_name[i] != TGSI_SEMANTIC_PRIMID)

View file

@ -95,7 +95,7 @@ vs_exec_run_linear( struct draw_vertex_shader *shader,
unsigned int i, j;
unsigned slot;
machine->Consts = constants;
machine->Consts[0] = constants;
for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);

View file

@ -953,107 +953,90 @@ micro_sub(
}
static void
fetch_src_file_channel(
const struct tgsi_exec_machine *mach,
const uint file,
const uint swizzle,
const union tgsi_exec_channel *index,
union tgsi_exec_channel *chan )
fetch_src_file_channel(const struct tgsi_exec_machine *mach,
const uint file,
const uint swizzle,
const union tgsi_exec_channel *index,
const union tgsi_exec_channel *index2D,
union tgsi_exec_channel *chan)
{
switch( swizzle ) {
case TGSI_SWIZZLE_X:
case TGSI_SWIZZLE_Y:
case TGSI_SWIZZLE_Z:
case TGSI_SWIZZLE_W:
switch( file ) {
case TGSI_FILE_CONSTANT:
assert(mach->Consts);
if (index->i[0] < 0)
chan->f[0] = 0.0f;
else
chan->f[0] = mach->Consts[index->i[0]][swizzle];
if (index->i[1] < 0)
chan->f[1] = 0.0f;
else
chan->f[1] = mach->Consts[index->i[1]][swizzle];
if (index->i[2] < 0)
chan->f[2] = 0.0f;
else
chan->f[2] = mach->Consts[index->i[2]][swizzle];
if (index->i[3] < 0)
chan->f[3] = 0.0f;
else
chan->f[3] = mach->Consts[index->i[3]][swizzle];
break;
uint i;
case TGSI_FILE_INPUT:
case TGSI_FILE_SYSTEM_VALUE:
chan->u[0] = mach->Inputs[index->i[0]].xyzw[swizzle].u[0];
chan->u[1] = mach->Inputs[index->i[1]].xyzw[swizzle].u[1];
chan->u[2] = mach->Inputs[index->i[2]].xyzw[swizzle].u[2];
chan->u[3] = mach->Inputs[index->i[3]].xyzw[swizzle].u[3];
break;
switch (file) {
case TGSI_FILE_CONSTANT:
for (i = 0; i < QUAD_SIZE; i++) {
assert(index2D->i[i] >= 0 && index2D->i[i] < PIPE_MAX_CONSTANT);
assert(mach->Consts[index2D->i[i]]);
case TGSI_FILE_TEMPORARY:
assert(index->i[0] < TGSI_EXEC_NUM_TEMPS);
chan->u[0] = mach->Temps[index->i[0]].xyzw[swizzle].u[0];
chan->u[1] = mach->Temps[index->i[1]].xyzw[swizzle].u[1];
chan->u[2] = mach->Temps[index->i[2]].xyzw[swizzle].u[2];
chan->u[3] = mach->Temps[index->i[3]].xyzw[swizzle].u[3];
break;
if (index->i[i] < 0) {
chan->u[i] = 0;
} else {
const uint *p = (const uint *)mach->Consts[index2D->i[i]];
case TGSI_FILE_IMMEDIATE:
assert( index->i[0] < (int) mach->ImmLimit );
chan->f[0] = mach->Imms[index->i[0]][swizzle];
assert( index->i[1] < (int) mach->ImmLimit );
chan->f[1] = mach->Imms[index->i[1]][swizzle];
assert( index->i[2] < (int) mach->ImmLimit );
chan->f[2] = mach->Imms[index->i[2]][swizzle];
assert( index->i[3] < (int) mach->ImmLimit );
chan->f[3] = mach->Imms[index->i[3]][swizzle];
break;
chan->u[i] = p[index->i[i] * 4 + swizzle];
}
}
break;
case TGSI_FILE_ADDRESS:
chan->u[0] = mach->Addrs[index->i[0]].xyzw[swizzle].u[0];
chan->u[1] = mach->Addrs[index->i[1]].xyzw[swizzle].u[1];
chan->u[2] = mach->Addrs[index->i[2]].xyzw[swizzle].u[2];
chan->u[3] = mach->Addrs[index->i[3]].xyzw[swizzle].u[3];
break;
case TGSI_FILE_INPUT:
case TGSI_FILE_SYSTEM_VALUE:
for (i = 0; i < QUAD_SIZE; i++) {
/* XXX: 2D indexing */
chan->u[i] = mach->Inputs[index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i]].xyzw[swizzle].u[i];
}
break;
case TGSI_FILE_PREDICATE:
assert(index->i[0] < TGSI_EXEC_NUM_PREDS);
assert(index->i[1] < TGSI_EXEC_NUM_PREDS);
assert(index->i[2] < TGSI_EXEC_NUM_PREDS);
assert(index->i[3] < TGSI_EXEC_NUM_PREDS);
chan->u[0] = mach->Predicates[0].xyzw[swizzle].u[0];
chan->u[1] = mach->Predicates[0].xyzw[swizzle].u[1];
chan->u[2] = mach->Predicates[0].xyzw[swizzle].u[2];
chan->u[3] = mach->Predicates[0].xyzw[swizzle].u[3];
break;
case TGSI_FILE_TEMPORARY:
for (i = 0; i < QUAD_SIZE; i++) {
assert(index->i[i] < TGSI_EXEC_NUM_TEMPS);
assert(index2D->i[i] == 0);
case TGSI_FILE_OUTPUT:
/* vertex/fragment output vars can be read too */
chan->u[0] = mach->Outputs[index->i[0]].xyzw[swizzle].u[0];
chan->u[1] = mach->Outputs[index->i[1]].xyzw[swizzle].u[1];
chan->u[2] = mach->Outputs[index->i[2]].xyzw[swizzle].u[2];
chan->u[3] = mach->Outputs[index->i[3]].xyzw[swizzle].u[3];
break;
chan->u[i] = mach->Temps[index->i[i]].xyzw[swizzle].u[i];
}
break;
default:
assert( 0 );
chan->u[0] = 0;
chan->u[1] = 0;
chan->u[2] = 0;
chan->u[3] = 0;
case TGSI_FILE_IMMEDIATE:
for (i = 0; i < QUAD_SIZE; i++) {
assert(index->i[i] >= 0 && index->i[i] < (int)mach->ImmLimit);
assert(index2D->i[i] == 0);
chan->f[i] = mach->Imms[index->i[i]][swizzle];
}
break;
case TGSI_FILE_ADDRESS:
for (i = 0; i < QUAD_SIZE; i++) {
assert(index->i[i] >= 0);
assert(index2D->i[i] == 0);
chan->u[i] = mach->Addrs[index->i[i]].xyzw[swizzle].u[i];
}
break;
case TGSI_FILE_PREDICATE:
for (i = 0; i < QUAD_SIZE; i++) {
assert(index->i[i] >= 0 && index->i[i] < TGSI_EXEC_NUM_PREDS);
assert(index2D->i[i] == 0);
chan->u[i] = mach->Predicates[0].xyzw[swizzle].u[i];
}
break;
case TGSI_FILE_OUTPUT:
/* vertex/fragment output vars can be read too */
for (i = 0; i < QUAD_SIZE; i++) {
assert(index->i[i] >= 0);
assert(index2D->i[i] == 0);
chan->u[i] = mach->Outputs[index->i[i]].xyzw[swizzle].u[i];
}
break;
default:
assert( 0 );
chan->u[0] = 0;
chan->u[1] = 0;
chan->u[2] = 0;
chan->u[3] = 0;
assert(0);
for (i = 0; i < QUAD_SIZE; i++) {
chan->u[i] = 0;
}
}
}
@ -1065,6 +1048,7 @@ fetch_source(const struct tgsi_exec_machine *mach,
enum tgsi_exec_datatype src_datatype)
{
union tgsi_exec_channel index;
union tgsi_exec_channel index2D;
uint swizzle;
/* We start with a direct index into a register file.
@ -1103,12 +1087,12 @@ fetch_source(const struct tgsi_exec_machine *mach,
/* get current value of address register[swizzle] */
swizzle = tgsi_util_get_src_register_swizzle( &reg->Indirect, CHAN_X );
fetch_src_file_channel(
mach,
reg->Indirect.File,
swizzle,
&index2,
&indir_index );
fetch_src_file_channel(mach,
reg->Indirect.File,
swizzle,
&index2,
&ZeroVec,
&indir_index);
/* add value of address register to the offset */
index.i[0] += indir_index.i[0];
@ -1129,35 +1113,15 @@ fetch_source(const struct tgsi_exec_machine *mach,
* subscript to a register file. Effectively it means that
* the register file is actually a 2D array of registers.
*
* file[3][1] == file[3*sizeof(file[1])+1],
* file[3][1],
* where:
* [3] = Dimension.Index
*/
if (reg->Register.Dimension) {
int array_size;
union tgsi_exec_channel dim_index;
/* The size of the first-order array depends on the register file type.
* We need to multiply the index to the first array to get an effective,
* "flat" index that points to the beginning of the second-order array.
*/
switch (reg->Register.File) {
case TGSI_FILE_INPUT:
case TGSI_FILE_SYSTEM_VALUE:
array_size = TGSI_EXEC_MAX_INPUT_ATTRIBS;
break;
case TGSI_FILE_CONSTANT:
array_size = TGSI_EXEC_MAX_CONST_BUFFER;
break;
default:
assert( 0 );
array_size = 0;
}
dim_index.i[0] =
dim_index.i[1] =
dim_index.i[2] =
dim_index.i[3] = reg->Dimension.Index;
index2D.i[0] =
index2D.i[1] =
index2D.i[2] =
index2D.i[3] = reg->Dimension.Index;
/* Again, the second subscript index can be addressed indirectly
* identically to the first one.
@ -1182,45 +1146,46 @@ fetch_source(const struct tgsi_exec_machine *mach,
index2.i[3] = reg->DimIndirect.Index;
swizzle = tgsi_util_get_src_register_swizzle( &reg->DimIndirect, CHAN_X );
fetch_src_file_channel(
mach,
reg->DimIndirect.File,
swizzle,
&index2,
&indir_index );
fetch_src_file_channel(mach,
reg->DimIndirect.File,
swizzle,
&index2,
&ZeroVec,
&indir_index);
dim_index.i[0] += indir_index.i[0];
dim_index.i[1] += indir_index.i[1];
dim_index.i[2] += indir_index.i[2];
dim_index.i[3] += indir_index.i[3];
index2D.i[0] += indir_index.i[0];
index2D.i[1] += indir_index.i[1];
index2D.i[2] += indir_index.i[2];
index2D.i[3] += indir_index.i[3];
/* for disabled execution channels, zero-out the index to
* avoid using a potential garbage value.
*/
for (i = 0; i < QUAD_SIZE; i++) {
if ((execmask & (1 << i)) == 0)
dim_index.i[i] = 0;
if ((execmask & (1 << i)) == 0) {
index2D.i[i] = 0;
}
}
}
index.i[0] += dim_index.i[0] * array_size;
index.i[1] += dim_index.i[1] * array_size;
index.i[2] += dim_index.i[2] * array_size;
index.i[3] += dim_index.i[3] * array_size;
/* If by any chance there was a need for a 3D array of register
* files, we would have to check whether Dimension is followed
* by a dimension register and continue the saga.
*/
} else {
index2D.i[0] =
index2D.i[1] =
index2D.i[2] =
index2D.i[3] = 0;
}
swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index );
fetch_src_file_channel(
mach,
reg->Register.File,
swizzle,
&index,
chan );
fetch_src_file_channel(mach,
reg->Register.File,
swizzle,
&index,
&index2D,
chan);
if (reg->Register.Absolute) {
if (src_datatype == TGSI_EXEC_DATA_FLOAT) {
@ -1283,12 +1248,12 @@ store_dest(struct tgsi_exec_machine *mach,
swizzle = tgsi_util_get_src_register_swizzle( &reg->Indirect, CHAN_X );
/* fetch values from the address/indirection register */
fetch_src_file_channel(
mach,
reg->Indirect.File,
swizzle,
&index,
&indir_index );
fetch_src_file_channel(mach,
reg->Indirect.File,
swizzle,
&index,
&ZeroVec,
&indir_index);
/* save indirection offset */
offset = indir_index.i[0];

View file

@ -260,7 +260,7 @@ struct tgsi_exec_machine
struct tgsi_sampler **Samplers;
unsigned ImmLimit;
const float (*Consts)[4];
const void *Consts[PIPE_MAX_CONSTANT];
const struct tgsi_token *Tokens; /**< Declarations, instructions */
unsigned Processor; /**< TGSI_PROCESSOR_x */

View file

@ -111,9 +111,13 @@ softpipe_destroy( struct pipe_context *pipe )
pipe_texture_reference(&softpipe->vertex_textures[i], NULL);
}
for (i = 0; i < Elements(softpipe->constants); i++) {
if (softpipe->constants[i]) {
pipe_buffer_reference(&softpipe->constants[i], NULL);
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
uint j;
for (j = 0; j < PIPE_MAX_CONSTANT; j++) {
if (softpipe->constants[i][j]) {
pipe_buffer_reference(&softpipe->constants[i][j], NULL);
}
}
}

View file

@ -63,7 +63,7 @@ struct softpipe_context {
/** Other rendering state */
struct pipe_blend_color blend_color;
struct pipe_clip_state clip;
struct pipe_buffer *constants[PIPE_SHADER_TYPES];
struct pipe_buffer *constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
@ -92,7 +92,7 @@ struct softpipe_context {
ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS];
/** Mapped constant buffers */
void *mapped_constants[PIPE_SHADER_TYPES];
void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT];
/** Vertex format */
struct vertex_info vertex_info;

View file

@ -52,26 +52,32 @@ softpipe_map_constant_buffers(struct softpipe_context *sp)
uint i, vssize, gssize;
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
if (sp->constants[i] && sp->constants[i]->size)
sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i],
PIPE_BUFFER_USAGE_CPU_READ);
uint j;
for (j = 0; j < PIPE_MAX_CONSTANT; j++) {
if (sp->constants[i][j] && sp->constants[i][j]->size) {
sp->mapped_constants[i][j] = ws->buffer_map(ws,
sp->constants[i][j],
PIPE_BUFFER_USAGE_CPU_READ);
}
}
}
if (sp->constants[PIPE_SHADER_VERTEX])
vssize = sp->constants[PIPE_SHADER_VERTEX]->size;
if (sp->constants[PIPE_SHADER_VERTEX][0])
vssize = sp->constants[PIPE_SHADER_VERTEX][0]->size;
else
vssize = 0;
if (sp->constants[PIPE_SHADER_GEOMETRY])
gssize = sp->constants[PIPE_SHADER_GEOMETRY]->size;
if (sp->constants[PIPE_SHADER_GEOMETRY][0])
gssize = sp->constants[PIPE_SHADER_GEOMETRY][0]->size;
else
gssize = 0;
draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX,
sp->mapped_constants[PIPE_SHADER_VERTEX],
sp->mapped_constants[PIPE_SHADER_VERTEX][0],
vssize);
draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_GEOMETRY,
sp->mapped_constants[PIPE_SHADER_GEOMETRY],
sp->mapped_constants[PIPE_SHADER_GEOMETRY][0],
gssize);
}
@ -91,9 +97,14 @@ softpipe_unmap_constant_buffers(struct softpipe_context *sp)
draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_GEOMETRY, NULL, 0);
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
if (sp->constants[i] && sp->constants[i]->size)
ws->buffer_unmap(ws, sp->constants[i]);
sp->mapped_constants[i] = NULL;
uint j;
for (j = 0; j < PIPE_MAX_CONSTANT; j++) {
if (sp->constants[i][j] && sp->constants[i][j]->size) {
ws->buffer_unmap(ws, sp->constants[i][j]);
}
sp->mapped_constants[i][j] = NULL;
}
}
}

View file

@ -135,7 +135,7 @@ fs_sse_run( const struct sp_fragment_shader *base,
tgsi_set_exec_mask(machine, 1, 1, 1, 1);
shader->func( machine,
machine->Consts,
(const float (*)[4])machine->Consts[0],
(const float (*)[4])shader->immediates,
machine->InterpCoefs
/*, &machine->QuadPos*/

View file

@ -107,10 +107,11 @@ shade_quads(struct quad_stage *qs,
struct quad_shade_stage *qss = quad_shade_stage( qs );
struct softpipe_context *softpipe = qs->softpipe;
struct tgsi_exec_machine *machine = qss->machine;
unsigned i, pass = 0;
machine->Consts = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT];
for (i = 0; i < PIPE_MAX_CONSTANT; i++) {
machine->Consts[i] = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT][i];
}
machine->InterpCoefs = quads[0]->coef;
for (i = 0; i < nr; i++) {

View file

@ -164,12 +164,12 @@ softpipe_set_constant_buffer(struct pipe_context *pipe,
struct softpipe_context *softpipe = softpipe_context(pipe);
assert(shader < PIPE_SHADER_TYPES);
assert(index == 0);
assert(index < PIPE_MAX_CONSTANT);
draw_flush(softpipe->draw);
/* note: reference counting */
pipe_buffer_reference(&softpipe->constants[shader], buf);
pipe_buffer_reference(&softpipe->constants[shader][index], buf);
softpipe->dirty |= SP_NEW_CONSTANTS;
}