softpipe: implement fragment shader variants

We'll need shader variants to accomodate the new polygon stipple utility.
This commit is contained in:
Brian Paul 2011-07-21 09:55:22 -06:00
parent 3dde6be908
commit c534f11164
13 changed files with 251 additions and 117 deletions

View file

@ -64,6 +64,7 @@ struct softpipe_context {
struct pipe_depth_stencil_alpha_state *depth_stencil; struct pipe_depth_stencil_alpha_state *depth_stencil;
struct pipe_rasterizer_state *rasterizer; struct pipe_rasterizer_state *rasterizer;
struct sp_fragment_shader *fs; struct sp_fragment_shader *fs;
struct sp_fragment_shader_variant *fs_variant;
struct sp_vertex_shader *vs; struct sp_vertex_shader *vs;
struct sp_geometry_shader *gs; struct sp_geometry_shader *gs;
struct sp_velems_state *velems; struct sp_velems_state *velems;

View file

@ -31,17 +31,15 @@
#ifndef SP_FS_H #ifndef SP_FS_H
#define SP_FS_H #define SP_FS_H
struct sp_fragment_shader *
softpipe_create_fs_exec(struct softpipe_context *softpipe, struct sp_fragment_shader_variant *
softpipe_create_fs_variant_exec(struct softpipe_context *softpipe,
const struct pipe_shader_state *templ); const struct pipe_shader_state *templ);
struct sp_fragment_shader * struct sp_fragment_shader_variant *
softpipe_create_fs_sse(struct softpipe_context *softpipe, softpipe_create_fs_variant_sse(struct softpipe_context *softpipe,
const struct pipe_shader_state *templ); const struct pipe_shader_state *templ);
struct sp_fragment_shader *
softpipe_create_fs_llvm(struct softpipe_context *softpipe,
const struct pipe_shader_state *templ);
struct tgsi_interp_coef; struct tgsi_interp_coef;
struct tgsi_exec_vector; struct tgsi_exec_vector;

View file

@ -42,25 +42,25 @@
/** /**
* Subclass of sp_fragment_shader * Subclass of sp_fragment_shader_variant
*/ */
struct sp_exec_fragment_shader struct sp_exec_fragment_shader
{ {
struct sp_fragment_shader base; struct sp_fragment_shader_variant base;
/* No other members for now */ /* No other members for now */
}; };
/** cast wrapper */ /** cast wrapper */
static INLINE struct sp_exec_fragment_shader * static INLINE struct sp_exec_fragment_shader *
sp_exec_fragment_shader(const struct sp_fragment_shader *base) sp_exec_fragment_shader(const struct sp_fragment_shader_variant *var)
{ {
return (struct sp_exec_fragment_shader *) base; return (struct sp_exec_fragment_shader *) var;
} }
static void static void
exec_prepare( const struct sp_fragment_shader *base, exec_prepare( const struct sp_fragment_shader_variant *var,
struct tgsi_exec_machine *machine, struct tgsi_exec_machine *machine,
struct tgsi_sampler **samplers ) struct tgsi_sampler **samplers )
{ {
@ -68,9 +68,9 @@ exec_prepare( const struct sp_fragment_shader *base,
* Bind tokens/shader to the interpreter's machine state. * Bind tokens/shader to the interpreter's machine state.
* Avoid redundant binding. * Avoid redundant binding.
*/ */
if (machine->Tokens != base->shader.tokens) { if (machine->Tokens != var->tokens) {
tgsi_exec_machine_bind_shader( machine, tgsi_exec_machine_bind_shader( machine,
base->shader.tokens, var->tokens,
PIPE_MAX_SAMPLERS, PIPE_MAX_SAMPLERS,
samplers ); samplers );
} }
@ -118,7 +118,7 @@ setup_pos_vector(const struct tgsi_interp_coef *coef,
* interface: * interface:
*/ */
static unsigned static unsigned
exec_run( const struct sp_fragment_shader *base, exec_run( const struct sp_fragment_shader_variant *var,
struct tgsi_exec_machine *machine, struct tgsi_exec_machine *machine,
struct quad_header *quad ) struct quad_header *quad )
{ {
@ -136,9 +136,9 @@ exec_run( const struct sp_fragment_shader *base,
/* store outputs */ /* store outputs */
{ {
const ubyte *sem_name = base->info.output_semantic_name; const ubyte *sem_name = var->info.output_semantic_name;
const ubyte *sem_index = base->info.output_semantic_index; const ubyte *sem_index = var->info.output_semantic_index;
const uint n = base->info.num_outputs; const uint n = var->info.num_outputs;
uint i; uint i;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
switch (sem_name[i]) { switch (sem_name[i]) {
@ -180,15 +180,15 @@ exec_run( const struct sp_fragment_shader *base,
static void static void
exec_delete( struct sp_fragment_shader *base ) exec_delete( struct sp_fragment_shader_variant *var )
{ {
FREE((void *) base->shader.tokens); FREE( (void *) var->tokens );
FREE(base); FREE(var);
} }
struct sp_fragment_shader * struct sp_fragment_shader_variant *
softpipe_create_fs_exec(struct softpipe_context *softpipe, softpipe_create_fs_variant_exec(struct softpipe_context *softpipe,
const struct pipe_shader_state *templ) const struct pipe_shader_state *templ)
{ {
struct sp_exec_fragment_shader *shader; struct sp_exec_fragment_shader *shader;
@ -197,8 +197,6 @@ softpipe_create_fs_exec(struct softpipe_context *softpipe,
if (!shader) if (!shader)
return NULL; return NULL;
/* we need to keep a local copy of the tokens */
shader->base.shader.tokens = tgsi_dup_tokens(templ->tokens);
shader->base.prepare = exec_prepare; shader->base.prepare = exec_prepare;
shader->base.run = exec_run; shader->base.run = exec_run;
shader->base.delete = exec_delete; shader->base.delete = exec_delete;

View file

@ -48,11 +48,11 @@
/** /**
* Subclass of sp_fragment_shader * Subclass of sp_fragment_shader_variant
*/ */
struct sp_sse_fragment_shader struct sp_sse_fragment_shader
{ {
struct sp_fragment_shader base; struct sp_fragment_shader_variant base;
struct x86_function sse2_program; struct x86_function sse2_program;
tgsi_sse2_fs_function func; tgsi_sse2_fs_function func;
float immediates[TGSI_EXEC_NUM_IMMEDIATES][4]; float immediates[TGSI_EXEC_NUM_IMMEDIATES][4];
@ -61,14 +61,14 @@ struct sp_sse_fragment_shader
/** cast wrapper */ /** cast wrapper */
static INLINE struct sp_sse_fragment_shader * static INLINE struct sp_sse_fragment_shader *
sp_sse_fragment_shader(const struct sp_fragment_shader *base) sp_sse_fragment_shader(const struct sp_fragment_shader_variant *base)
{ {
return (struct sp_sse_fragment_shader *) base; return (struct sp_sse_fragment_shader *) base;
} }
static void static void
fs_sse_prepare( const struct sp_fragment_shader *base, fs_sse_prepare( const struct sp_fragment_shader_variant *base,
struct tgsi_exec_machine *machine, struct tgsi_exec_machine *machine,
struct tgsi_sampler **samplers ) struct tgsi_sampler **samplers )
{ {
@ -119,7 +119,7 @@ setup_pos_vector(const struct tgsi_interp_coef *coef,
* TODO: process >1 quad at a time * TODO: process >1 quad at a time
*/ */
static unsigned static unsigned
fs_sse_run( const struct sp_fragment_shader *base, fs_sse_run( const struct sp_fragment_shader_variant *base,
struct tgsi_exec_machine *machine, struct tgsi_exec_machine *machine,
struct quad_header *quad ) struct quad_header *quad )
{ {
@ -189,7 +189,7 @@ fs_sse_run( const struct sp_fragment_shader *base,
static void static void
fs_sse_delete( struct sp_fragment_shader *base ) fs_sse_delete( struct sp_fragment_shader_variant *base )
{ {
struct sp_sse_fragment_shader *shader = sp_sse_fragment_shader(base); struct sp_sse_fragment_shader *shader = sp_sse_fragment_shader(base);
@ -198,8 +198,8 @@ fs_sse_delete( struct sp_fragment_shader *base )
} }
struct sp_fragment_shader * struct sp_fragment_shader_variant *
softpipe_create_fs_sse(struct softpipe_context *softpipe, softpipe_create_fs_variant_sse(struct softpipe_context *softpipe,
const struct pipe_shader_state *templ) const struct pipe_shader_state *templ)
{ {
struct sp_sse_fragment_shader *shader; struct sp_sse_fragment_shader *shader;
@ -226,7 +226,6 @@ softpipe_create_fs_sse(struct softpipe_context *softpipe,
return NULL; return NULL;
} }
shader->base.shader.tokens = NULL; /* don't hold reference to templ->tokens */
shader->base.prepare = fs_sse_prepare; shader->base.prepare = fs_sse_prepare;
shader->base.run = fs_sse_run; shader->base.run = fs_sse_run;
shader->base.delete = fs_sse_delete; shader->base.delete = fs_sse_delete;
@ -239,8 +238,8 @@ softpipe_create_fs_sse(struct softpipe_context *softpipe,
/* Maybe put this variant in the header file. /* Maybe put this variant in the header file.
*/ */
struct sp_fragment_shader * struct sp_fragment_shader_variant *
softpipe_create_fs_sse(struct softpipe_context *softpipe, softpipe_create_fs_variant_sse(struct softpipe_context *softpipe,
const struct pipe_shader_state *templ) const struct pipe_shader_state *templ)
{ {
return NULL; return NULL;

View file

@ -797,7 +797,7 @@ blend_fallback(struct quad_stage *qs,
unsigned cbuf; unsigned cbuf;
boolean write_all; boolean write_all;
write_all = softpipe->fs->info.color0_writes_all_cbufs; write_all = softpipe->fs_variant->info.color0_writes_all_cbufs;
for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++)
{ {

View file

@ -726,9 +726,9 @@ depth_test_quads_fallback(struct quad_stage *qs,
unsigned nr) unsigned nr)
{ {
unsigned i, pass = 0; unsigned i, pass = 0;
const struct sp_fragment_shader *fs = qs->softpipe->fs; const struct tgsi_shader_info *fsInfo = &qs->softpipe->fs_variant->info;
boolean interp_depth = !fs->info.writes_z; boolean interp_depth = !fsInfo->writes_z;
boolean shader_stencil_ref = fs->info.writes_stencil; boolean shader_stencil_ref = fsInfo->writes_stencil;
struct depth_data data; struct depth_data data;
data.use_shader_stencil_refs = FALSE; data.use_shader_stencil_refs = FALSE;
@ -837,7 +837,9 @@ choose_depth_test(struct quad_stage *qs,
struct quad_header *quads[], struct quad_header *quads[],
unsigned nr) unsigned nr)
{ {
boolean interp_depth = !qs->softpipe->fs->info.writes_z; const struct tgsi_shader_info *fsInfo = &qs->softpipe->fs_variant->info;
boolean interp_depth = !fsInfo->writes_z;
boolean alpha = qs->softpipe->depth_stencil->alpha.enabled; boolean alpha = qs->softpipe->depth_stencil->alpha.enabled;

View file

@ -74,7 +74,7 @@ shade_quad(struct quad_stage *qs, struct quad_header *quad)
struct tgsi_exec_machine *machine = softpipe->fs_machine; struct tgsi_exec_machine *machine = softpipe->fs_machine;
/* run shader */ /* run shader */
return softpipe->fs->run( softpipe->fs, machine, quad ); return softpipe->fs_variant->run( softpipe->fs_variant, machine, quad );
} }
@ -140,7 +140,7 @@ shade_begin(struct quad_stage *qs)
{ {
struct softpipe_context *softpipe = qs->softpipe; struct softpipe_context *softpipe = qs->softpipe;
softpipe->fs->prepare( softpipe->fs, softpipe->fs_variant->prepare( softpipe->fs_variant,
softpipe->fs_machine, softpipe->fs_machine,
(struct tgsi_sampler **) (struct tgsi_sampler **)
softpipe->tgsi.frag_samplers_list ); softpipe->tgsi.frag_samplers_list );

View file

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

View file

@ -568,17 +568,18 @@ tri_persp_coeff(struct setup_context *setup,
static void static void
setup_fragcoord_coeff(struct setup_context *setup, uint slot) setup_fragcoord_coeff(struct setup_context *setup, uint slot)
{ {
struct sp_fragment_shader* spfs = setup->softpipe->fs; const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
/*X*/ /*X*/
setup->coef[slot].a0[0] = spfs->info.pixel_center_integer ? 0.0 : 0.5; setup->coef[slot].a0[0] = fsInfo->pixel_center_integer ? 0.0 : 0.5;
setup->coef[slot].dadx[0] = 1.0; setup->coef[slot].dadx[0] = 1.0;
setup->coef[slot].dady[0] = 0.0; setup->coef[slot].dady[0] = 0.0;
/*Y*/ /*Y*/
setup->coef[slot].a0[1] = setup->coef[slot].a0[1] =
(spfs->info.origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0) (fsInfo->origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0)
+ (spfs->info.pixel_center_integer ? 0.0 : 0.5); + (fsInfo->pixel_center_integer ? 0.0 : 0.5);
setup->coef[slot].dadx[1] = 0.0; setup->coef[slot].dadx[1] = 0.0;
setup->coef[slot].dady[1] = spfs->info.origin_lower_left ? -1.0 : 1.0; setup->coef[slot].dady[1] = fsInfo->origin_lower_left ? -1.0 : 1.0;
/*Z*/ /*Z*/
setup->coef[slot].a0[2] = setup->posCoef.a0[2]; setup->coef[slot].a0[2] = setup->posCoef.a0[2];
setup->coef[slot].dadx[2] = setup->posCoef.dadx[2]; setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
@ -599,7 +600,7 @@ static void
setup_tri_coefficients(struct setup_context *setup) setup_tri_coefficients(struct setup_context *setup)
{ {
struct softpipe_context *softpipe = setup->softpipe; struct softpipe_context *softpipe = setup->softpipe;
const struct sp_fragment_shader *spfs = softpipe->fs; const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe); const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot; uint fragSlot;
float v[3]; float v[3];
@ -618,7 +619,7 @@ setup_tri_coefficients(struct setup_context *setup)
/* setup interpolation for all the remaining attributes: /* setup interpolation for all the remaining attributes:
*/ */
for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) { for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
const uint vertSlot = vinfo->attrib[fragSlot].src_index; const uint vertSlot = vinfo->attrib[fragSlot].src_index;
uint j; uint j;
@ -632,7 +633,7 @@ setup_tri_coefficients(struct setup_context *setup)
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j], tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmid[vertSlot][j], setup->vmid[vertSlot][j],
setup->vmax[vertSlot][j], setup->vmax[vertSlot][j],
spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j), fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v); v);
tri_linear_coeff(setup, &setup->coef[fragSlot], j, v); tri_linear_coeff(setup, &setup->coef[fragSlot], j, v);
} }
@ -642,7 +643,7 @@ setup_tri_coefficients(struct setup_context *setup)
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j], tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmid[vertSlot][j], setup->vmid[vertSlot][j],
setup->vmax[vertSlot][j], setup->vmax[vertSlot][j],
spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j), fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v); v);
tri_persp_coeff(setup, &setup->coef[fragSlot], j, v); tri_persp_coeff(setup, &setup->coef[fragSlot], j, v);
} }
@ -654,7 +655,7 @@ setup_tri_coefficients(struct setup_context *setup)
assert(0); assert(0);
} }
if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
/* convert 0 to 1.0 and 1 to -1.0 */ /* convert 0 to 1.0 and 1 to -1.0 */
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f; setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0; setup->coef[fragSlot].dadx[0] = 0.0;
@ -939,7 +940,7 @@ setup_line_coefficients(struct setup_context *setup,
const float (*v1)[4]) const float (*v1)[4])
{ {
struct softpipe_context *softpipe = setup->softpipe; struct softpipe_context *softpipe = setup->softpipe;
const struct sp_fragment_shader *spfs = softpipe->fs; const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe); const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot; uint fragSlot;
float area; float area;
@ -974,7 +975,7 @@ setup_line_coefficients(struct setup_context *setup,
/* setup interpolation for all the remaining attributes: /* setup interpolation for all the remaining attributes:
*/ */
for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) { for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
const uint vertSlot = vinfo->attrib[fragSlot].src_index; const uint vertSlot = vinfo->attrib[fragSlot].src_index;
uint j; uint j;
@ -987,7 +988,7 @@ setup_line_coefficients(struct setup_context *setup,
for (j = 0; j < NUM_CHANNELS; j++) { for (j = 0; j < NUM_CHANNELS; j++) {
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j], line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmax[vertSlot][j], setup->vmax[vertSlot][j],
spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j), fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v); v);
line_linear_coeff(setup, &setup->coef[fragSlot], j, v); line_linear_coeff(setup, &setup->coef[fragSlot], j, v);
} }
@ -996,7 +997,7 @@ setup_line_coefficients(struct setup_context *setup,
for (j = 0; j < NUM_CHANNELS; j++) { for (j = 0; j < NUM_CHANNELS; j++) {
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j], line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmax[vertSlot][j], setup->vmax[vertSlot][j],
spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j), fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v); v);
line_persp_coeff(setup, &setup->coef[fragSlot], j, v); line_persp_coeff(setup, &setup->coef[fragSlot], j, v);
} }
@ -1008,7 +1009,7 @@ setup_line_coefficients(struct setup_context *setup,
assert(0); assert(0);
} }
if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
/* convert 0 to 1.0 and 1 to -1.0 */ /* convert 0 to 1.0 and 1 to -1.0 */
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f; setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0; setup->coef[fragSlot].dadx[0] = 0.0;
@ -1188,7 +1189,7 @@ sp_setup_point(struct setup_context *setup,
const float (*v0)[4]) const float (*v0)[4])
{ {
struct softpipe_context *softpipe = setup->softpipe; struct softpipe_context *softpipe = setup->softpipe;
const struct sp_fragment_shader *spfs = softpipe->fs; const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
const int sizeAttr = setup->softpipe->psize_slot; const int sizeAttr = setup->softpipe->psize_slot;
const float size const float size
= sizeAttr > 0 ? v0[sizeAttr][0] = sizeAttr > 0 ? v0[sizeAttr][0]
@ -1232,7 +1233,7 @@ sp_setup_point(struct setup_context *setup,
const_coeff(setup, &setup->posCoef, 0, 2); const_coeff(setup, &setup->posCoef, 0, 2);
const_coeff(setup, &setup->posCoef, 0, 3); const_coeff(setup, &setup->posCoef, 0, 3);
for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) { for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
const uint vertSlot = vinfo->attrib[fragSlot].src_index; const uint vertSlot = vinfo->attrib[fragSlot].src_index;
uint j; uint j;
@ -1255,7 +1256,7 @@ sp_setup_point(struct setup_context *setup,
assert(0); assert(0);
} }
if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
/* convert 0 to 1.0 and 1 to -1.0 */ /* convert 0 to 1.0 and 1 to -1.0 */
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f; setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0; setup->coef[fragSlot].dadx[0] = 0.0;

View file

@ -60,31 +60,43 @@ struct tgsi_exec_machine;
struct vertex_info; struct vertex_info;
/** struct sp_fragment_shader_variant_key
* Subclass of pipe_shader_state (though it doesn't really need to be). {
* int foo; /* XXX temporary */
* This is starting to look an awful lot like a quad pipeline stage... };
*/
struct sp_fragment_shader {
struct pipe_shader_state shader;
struct sp_fragment_shader_variant
{
const struct tgsi_token *tokens;
struct sp_fragment_shader_variant_key key;
struct tgsi_shader_info info; struct tgsi_shader_info info;
/* See comments about this elsewhere */
#if 0
struct draw_fragment_shader *draw_shader; struct draw_fragment_shader *draw_shader;
#endif
void (*prepare)( const struct sp_fragment_shader *shader, void (*prepare)(const struct sp_fragment_shader_variant *shader,
struct tgsi_exec_machine *machine, struct tgsi_exec_machine *machine,
struct tgsi_sampler **samplers); struct tgsi_sampler **samplers);
/* Run the shader - this interface will get cleaned up in the unsigned (*run)(const struct sp_fragment_shader_variant *shader,
* future:
*/
unsigned (*run)( const struct sp_fragment_shader *shader,
struct tgsi_exec_machine *machine, struct tgsi_exec_machine *machine,
struct quad_header *quad); struct quad_header *quad);
/* Deletes this instance of the object */
void (*delete)(struct sp_fragment_shader_variant *shader);
void (*delete)( struct sp_fragment_shader * ); struct sp_fragment_shader_variant *next;
};
/** Subclass of pipe_shader_state */
struct sp_fragment_shader {
struct pipe_shader_state shader;
struct sp_fragment_shader_variant *variants;
struct draw_fragment_shader *draw_shader;
}; };
@ -167,4 +179,10 @@ struct vertex_info *
softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe); softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe);
struct sp_fragment_shader_variant *
softpipe_find_fs_variant(struct softpipe_context *softpipe,
struct sp_fragment_shader *fs,
const struct sp_fragment_shader_variant_key *key);
#endif #endif

View file

@ -64,7 +64,7 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
if (vinfo->num_attribs == 0) { if (vinfo->num_attribs == 0) {
/* compute vertex layout now */ /* compute vertex layout now */
const struct sp_fragment_shader *spfs = softpipe->fs; const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info;
struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf; struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
const uint num = draw_num_shader_outputs(softpipe->draw); const uint num = draw_num_shader_outputs(softpipe->draw);
uint i; uint i;
@ -84,11 +84,11 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
* from the vertex shader. * from the vertex shader.
*/ */
vinfo->num_attribs = 0; vinfo->num_attribs = 0;
for (i = 0; i < spfs->info.num_inputs; i++) { for (i = 0; i < fsInfo->num_inputs; i++) {
int src; int src;
enum interp_mode interp; enum interp_mode interp;
switch (spfs->info.input_interpolate[i]) { switch (fsInfo->input_interpolate[i]) {
case TGSI_INTERPOLATE_CONSTANT: case TGSI_INTERPOLATE_CONSTANT:
interp = INTERP_CONSTANT; interp = INTERP_CONSTANT;
break; break;
@ -103,7 +103,7 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
interp = INTERP_LINEAR; interp = INTERP_LINEAR;
} }
switch (spfs->info.input_semantic_name[i]) { switch (fsInfo->input_semantic_name[i]) {
case TGSI_SEMANTIC_POSITION: case TGSI_SEMANTIC_POSITION:
interp = INTERP_POS; interp = INTERP_POS;
break; break;
@ -117,8 +117,8 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
/* this includes texcoords and varying vars */ /* this includes texcoords and varying vars */
src = draw_find_shader_output(softpipe->draw, src = draw_find_shader_output(softpipe->draw,
spfs->info.input_semantic_name[i], fsInfo->input_semantic_name[i],
spfs->info.input_semantic_index[i]); fsInfo->input_semantic_index[i]);
draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src); draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src);
} }
@ -241,10 +241,46 @@ update_tgsi_samplers( struct softpipe_context *softpipe )
} }
static void
update_fragment_shader(struct softpipe_context *softpipe)
{
struct sp_fragment_shader_variant_key key;
memset(&key, 0, sizeof(key));
if (softpipe->fs) {
softpipe->fs_variant = softpipe_find_fs_variant(softpipe,
softpipe->fs, &key);
}
else {
softpipe->fs_variant = NULL;
}
/* This would be the logical place to pass the fragment shader
* to the draw module. However, doing this here, during state
* validation, causes problems with the 'draw' module helpers for
* wide/AA/stippled lines.
* In principle, the draw's fragment shader should be per-variant
* but that doesn't work. So we use a single draw fragment shader
* per fragment shader, not per variant.
*/
#if 0
if (softpipe->fs_variant) {
draw_bind_fragment_shader(softpipe->draw,
softpipe->fs_variant->draw_shader);
}
else {
draw_bind_fragment_shader(softpipe->draw, NULL);
}
#endif
}
/* Hopefully this will remain quite simple, otherwise need to pull in /* Hopefully this will remain quite simple, otherwise need to pull in
* something like the state tracker mechanism. * something like the state tracker mechanism.
*/ */
void softpipe_update_derived( struct softpipe_context *softpipe ) void
softpipe_update_derived(struct softpipe_context *softpipe)
{ {
struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen); struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);
@ -255,6 +291,10 @@ void softpipe_update_derived( struct softpipe_context *softpipe )
softpipe->dirty |= SP_NEW_TEXTURE; softpipe->dirty |= SP_NEW_TEXTURE;
} }
if (softpipe->dirty & (SP_NEW_RASTERIZER |
SP_NEW_FS))
update_fragment_shader(softpipe);
if (softpipe->dirty & (SP_NEW_SAMPLER | if (softpipe->dirty & (SP_NEW_SAMPLER |
SP_NEW_TEXTURE | SP_NEW_TEXTURE |
SP_NEW_FS | SP_NEW_FS |

View file

@ -373,8 +373,9 @@ softpipe_reset_sampler_variants(struct softpipe_context *softpipe)
} }
} }
for (i = 0; i <= softpipe->fs->info.file_max[TGSI_FILE_SAMPLER]; i++) { for (i = 0; i <= softpipe->fs_variant->info.file_max[TGSI_FILE_SAMPLER]; i++) {
if (softpipe->fragment_samplers[i]) { if (softpipe->fragment_samplers[i]) {
assert(softpipe->fragment_sampler_views[i]->texture);
softpipe->tgsi.frag_samplers_list[i] = softpipe->tgsi.frag_samplers_list[i] =
get_sampler_variant( i, get_sampler_variant( i,
sp_sampler(softpipe->fragment_samplers[i]), sp_sampler(softpipe->fragment_samplers[i]),

View file

@ -42,37 +42,91 @@
#include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_parse.h"
/**
* Create a new fragment shader variant.
*/
static struct sp_fragment_shader_variant *
create_fs_variant(struct softpipe_context *softpipe,
struct sp_fragment_shader *fs,
const struct sp_fragment_shader_variant_key *key)
{
struct sp_fragment_shader_variant *var;
struct pipe_shader_state *curfs = &fs->shader;
/* codegen, create variant object */
var = softpipe_create_fs_variant_sse(softpipe, curfs);
if (!var) {
var = softpipe_create_fs_variant_exec(softpipe, curfs);
}
if (var) {
var->key = *key;
var->tokens = tgsi_dup_tokens(curfs->tokens);
tgsi_scan_shader(var->tokens, &var->info);
/* See comments elsewhere about draw fragment shaders */
#if 0
/* draw's fs state */
var->draw_shader = draw_create_fragment_shader(softpipe->draw,
&fs->shader);
if (!var->draw_shader) {
var->delete(var);
FREE((void *) var->tokens);
return NULL;
}
#endif
/* insert variant into linked list */
var->next = fs->variants;
fs->variants = var;
}
return var;
}
struct sp_fragment_shader_variant *
softpipe_find_fs_variant(struct softpipe_context *sp,
struct sp_fragment_shader *fs,
const struct sp_fragment_shader_variant_key *key)
{
struct sp_fragment_shader_variant *var;
for (var = fs->variants; var; var = var->next) {
if (memcmp(&var->key, key, sizeof(*key)) == 0) {
/* found it */
return var;
}
}
return create_fs_variant(sp, fs, key);
}
static void * static void *
softpipe_create_fs_state(struct pipe_context *pipe, softpipe_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ) const struct pipe_shader_state *templ)
{ {
struct softpipe_context *softpipe = softpipe_context(pipe); struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_fragment_shader *state; struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader);
unsigned i;
/* debug */ /* debug */
if (softpipe->dump_fs) if (softpipe->dump_fs)
tgsi_dump(templ->tokens, 0); tgsi_dump(templ->tokens, 0);
/* codegen */ /* we need to keep a local copy of the tokens */
state = softpipe_create_fs_sse( softpipe, templ ); state->shader.tokens = tgsi_dup_tokens(templ->tokens);
if (!state) {
state = softpipe_create_fs_exec( softpipe, templ );
}
if (!state)
return NULL;
/* draw's fs state */ /* draw's fs state */
state->draw_shader = draw_create_fragment_shader(softpipe->draw, templ); state->draw_shader = draw_create_fragment_shader(softpipe->draw,
&state->shader);
if (!state->draw_shader) { if (!state->draw_shader) {
state->delete( state ); FREE((void *) state->shader.tokens);
FREE(state);
return NULL; return NULL;
} }
/* get/save the summary info for this shader */
tgsi_scan_shader(templ->tokens, &state->info);
return state; return state;
} }
@ -81,6 +135,7 @@ static void
softpipe_bind_fs_state(struct pipe_context *pipe, void *fs) softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
{ {
struct softpipe_context *softpipe = softpipe_context(pipe); struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs;
if (softpipe->fs == fs) if (softpipe->fs == fs)
return; return;
@ -89,8 +144,14 @@ softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
softpipe->fs = fs; softpipe->fs = fs;
if (fs == NULL)
softpipe->fs_variant = NULL;
if (state)
draw_bind_fragment_shader(softpipe->draw, draw_bind_fragment_shader(softpipe->draw,
(softpipe->fs ? softpipe->fs->draw_shader : NULL)); state->draw_shader);
else
draw_bind_fragment_shader(softpipe->draw, NULL);
softpipe->dirty |= SP_NEW_FS; softpipe->dirty |= SP_NEW_FS;
} }
@ -101,8 +162,9 @@ softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
{ {
struct softpipe_context *softpipe = softpipe_context(pipe); struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_fragment_shader *state = fs; struct sp_fragment_shader *state = fs;
struct sp_fragment_shader_variant *var, *next_var;
assert(fs != softpipe_context(pipe)->fs); assert(fs != softpipe->fs);
if (softpipe->fs_machine->Tokens == state->shader.tokens) { if (softpipe->fs_machine->Tokens == state->shader.tokens) {
/* unbind the shader from the tgsi executor if we're /* unbind the shader from the tgsi executor if we're
@ -111,9 +173,23 @@ softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
tgsi_exec_machine_bind_shader(softpipe->fs_machine, NULL, 0, NULL); tgsi_exec_machine_bind_shader(softpipe->fs_machine, NULL, 0, NULL);
} }
/* delete variants */
for (var = state->variants; var; var = next_var) {
next_var = var->next;
assert(var != softpipe->fs_variant);
/* See comments elsewhere about draw fragment shaders */
#if 0
draw_delete_fragment_shader(softpipe->draw, var->draw_shader);
#endif
var->delete(var);
}
draw_delete_fragment_shader(softpipe->draw, state->draw_shader); draw_delete_fragment_shader(softpipe->draw, state->draw_shader);
state->delete( state ); FREE((void *) state->shader.tokens);
} }