mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 11:20:11 +01:00
softpipe: implement fragment shader variants
We'll need shader variants to accomodate the new polygon stipple utility.
This commit is contained in:
parent
3dde6be908
commit
c534f11164
13 changed files with 251 additions and 117 deletions
|
|
@ -64,6 +64,7 @@ struct softpipe_context {
|
|||
struct pipe_depth_stencil_alpha_state *depth_stencil;
|
||||
struct pipe_rasterizer_state *rasterizer;
|
||||
struct sp_fragment_shader *fs;
|
||||
struct sp_fragment_shader_variant *fs_variant;
|
||||
struct sp_vertex_shader *vs;
|
||||
struct sp_geometry_shader *gs;
|
||||
struct sp_velems_state *velems;
|
||||
|
|
|
|||
|
|
@ -31,17 +31,15 @@
|
|||
#ifndef SP_FS_H
|
||||
#define SP_FS_H
|
||||
|
||||
struct sp_fragment_shader *
|
||||
softpipe_create_fs_exec(struct softpipe_context *softpipe,
|
||||
const struct pipe_shader_state *templ);
|
||||
|
||||
struct sp_fragment_shader *
|
||||
softpipe_create_fs_sse(struct softpipe_context *softpipe,
|
||||
const struct pipe_shader_state *templ);
|
||||
struct sp_fragment_shader_variant *
|
||||
softpipe_create_fs_variant_exec(struct softpipe_context *softpipe,
|
||||
const struct pipe_shader_state *templ);
|
||||
|
||||
struct sp_fragment_shader_variant *
|
||||
softpipe_create_fs_variant_sse(struct softpipe_context *softpipe,
|
||||
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_exec_vector;
|
||||
|
|
|
|||
|
|
@ -42,25 +42,25 @@
|
|||
|
||||
|
||||
/**
|
||||
* Subclass of sp_fragment_shader
|
||||
* Subclass of sp_fragment_shader_variant
|
||||
*/
|
||||
struct sp_exec_fragment_shader
|
||||
{
|
||||
struct sp_fragment_shader base;
|
||||
struct sp_fragment_shader_variant base;
|
||||
/* No other members for now */
|
||||
};
|
||||
|
||||
|
||||
/** cast wrapper */
|
||||
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
|
||||
exec_prepare( const struct sp_fragment_shader *base,
|
||||
exec_prepare( const struct sp_fragment_shader_variant *var,
|
||||
struct tgsi_exec_machine *machine,
|
||||
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.
|
||||
* Avoid redundant binding.
|
||||
*/
|
||||
if (machine->Tokens != base->shader.tokens) {
|
||||
if (machine->Tokens != var->tokens) {
|
||||
tgsi_exec_machine_bind_shader( machine,
|
||||
base->shader.tokens,
|
||||
var->tokens,
|
||||
PIPE_MAX_SAMPLERS,
|
||||
samplers );
|
||||
}
|
||||
|
|
@ -118,7 +118,7 @@ setup_pos_vector(const struct tgsi_interp_coef *coef,
|
|||
* interface:
|
||||
*/
|
||||
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 quad_header *quad )
|
||||
{
|
||||
|
|
@ -136,9 +136,9 @@ exec_run( const struct sp_fragment_shader *base,
|
|||
|
||||
/* store outputs */
|
||||
{
|
||||
const ubyte *sem_name = base->info.output_semantic_name;
|
||||
const ubyte *sem_index = base->info.output_semantic_index;
|
||||
const uint n = base->info.num_outputs;
|
||||
const ubyte *sem_name = var->info.output_semantic_name;
|
||||
const ubyte *sem_index = var->info.output_semantic_index;
|
||||
const uint n = var->info.num_outputs;
|
||||
uint i;
|
||||
for (i = 0; i < n; i++) {
|
||||
switch (sem_name[i]) {
|
||||
|
|
@ -180,16 +180,16 @@ exec_run( const struct sp_fragment_shader *base,
|
|||
|
||||
|
||||
static void
|
||||
exec_delete( struct sp_fragment_shader *base )
|
||||
exec_delete( struct sp_fragment_shader_variant *var )
|
||||
{
|
||||
FREE((void *) base->shader.tokens);
|
||||
FREE(base);
|
||||
FREE( (void *) var->tokens );
|
||||
FREE(var);
|
||||
}
|
||||
|
||||
|
||||
struct sp_fragment_shader *
|
||||
softpipe_create_fs_exec(struct softpipe_context *softpipe,
|
||||
const struct pipe_shader_state *templ)
|
||||
struct sp_fragment_shader_variant *
|
||||
softpipe_create_fs_variant_exec(struct softpipe_context *softpipe,
|
||||
const struct pipe_shader_state *templ)
|
||||
{
|
||||
struct sp_exec_fragment_shader *shader;
|
||||
|
||||
|
|
@ -197,8 +197,6 @@ softpipe_create_fs_exec(struct softpipe_context *softpipe,
|
|||
if (!shader)
|
||||
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.run = exec_run;
|
||||
shader->base.delete = exec_delete;
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@
|
|||
|
||||
|
||||
/**
|
||||
* Subclass of sp_fragment_shader
|
||||
* Subclass of sp_fragment_shader_variant
|
||||
*/
|
||||
struct sp_sse_fragment_shader
|
||||
{
|
||||
struct sp_fragment_shader base;
|
||||
struct sp_fragment_shader_variant base;
|
||||
struct x86_function sse2_program;
|
||||
tgsi_sse2_fs_function func;
|
||||
float immediates[TGSI_EXEC_NUM_IMMEDIATES][4];
|
||||
|
|
@ -61,14 +61,14 @@ struct sp_sse_fragment_shader
|
|||
|
||||
/** cast wrapper */
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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_sampler **samplers )
|
||||
{
|
||||
|
|
@ -119,7 +119,7 @@ setup_pos_vector(const struct tgsi_interp_coef *coef,
|
|||
* TODO: process >1 quad at a time
|
||||
*/
|
||||
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 quad_header *quad )
|
||||
{
|
||||
|
|
@ -189,7 +189,7 @@ fs_sse_run( const struct sp_fragment_shader *base,
|
|||
|
||||
|
||||
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);
|
||||
|
||||
|
|
@ -198,9 +198,9 @@ fs_sse_delete( struct sp_fragment_shader *base )
|
|||
}
|
||||
|
||||
|
||||
struct sp_fragment_shader *
|
||||
softpipe_create_fs_sse(struct softpipe_context *softpipe,
|
||||
const struct pipe_shader_state *templ)
|
||||
struct sp_fragment_shader_variant *
|
||||
softpipe_create_fs_variant_sse(struct softpipe_context *softpipe,
|
||||
const struct pipe_shader_state *templ)
|
||||
{
|
||||
struct sp_sse_fragment_shader *shader;
|
||||
|
||||
|
|
@ -226,7 +226,6 @@ softpipe_create_fs_sse(struct softpipe_context *softpipe,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
shader->base.shader.tokens = NULL; /* don't hold reference to templ->tokens */
|
||||
shader->base.prepare = fs_sse_prepare;
|
||||
shader->base.run = fs_sse_run;
|
||||
shader->base.delete = fs_sse_delete;
|
||||
|
|
@ -239,9 +238,9 @@ softpipe_create_fs_sse(struct softpipe_context *softpipe,
|
|||
|
||||
/* Maybe put this variant in the header file.
|
||||
*/
|
||||
struct sp_fragment_shader *
|
||||
softpipe_create_fs_sse(struct softpipe_context *softpipe,
|
||||
const struct pipe_shader_state *templ)
|
||||
struct sp_fragment_shader_variant *
|
||||
softpipe_create_fs_variant_sse(struct softpipe_context *softpipe,
|
||||
const struct pipe_shader_state *templ)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -797,7 +797,7 @@ blend_fallback(struct quad_stage *qs,
|
|||
unsigned cbuf;
|
||||
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++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -726,9 +726,9 @@ depth_test_quads_fallback(struct quad_stage *qs,
|
|||
unsigned nr)
|
||||
{
|
||||
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;
|
||||
const struct tgsi_shader_info *fsInfo = &qs->softpipe->fs_variant->info;
|
||||
boolean interp_depth = !fsInfo->writes_z;
|
||||
boolean shader_stencil_ref = fsInfo->writes_stencil;
|
||||
struct depth_data data;
|
||||
|
||||
data.use_shader_stencil_refs = FALSE;
|
||||
|
|
@ -837,7 +837,9 @@ choose_depth_test(struct quad_stage *qs,
|
|||
struct quad_header *quads[],
|
||||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ shade_quad(struct quad_stage *qs, struct quad_header *quad)
|
|||
struct tgsi_exec_machine *machine = softpipe->fs_machine;
|
||||
|
||||
/* run shader */
|
||||
return softpipe->fs->run( softpipe->fs, machine, quad );
|
||||
return softpipe->fs_variant->run( softpipe->fs_variant, machine, quad );
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -140,10 +140,10 @@ shade_begin(struct quad_stage *qs)
|
|||
{
|
||||
struct softpipe_context *softpipe = qs->softpipe;
|
||||
|
||||
softpipe->fs->prepare( softpipe->fs,
|
||||
softpipe->fs_machine,
|
||||
(struct tgsi_sampler **)
|
||||
softpipe->tgsi.frag_samplers_list );
|
||||
softpipe->fs_variant->prepare( softpipe->fs_variant,
|
||||
softpipe->fs_machine,
|
||||
(struct tgsi_sampler **)
|
||||
softpipe->tgsi.frag_samplers_list );
|
||||
|
||||
qs->next->begin(qs->next);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ sp_build_quad_pipeline(struct softpipe_context *sp)
|
|||
sp->depth_stencil->depth.enabled &&
|
||||
sp->framebuffer.zsbuf &&
|
||||
!sp->depth_stencil->alpha.enabled &&
|
||||
!sp->fs->info.uses_kill &&
|
||||
!sp->fs->info.writes_z &&
|
||||
!sp->fs->info.writes_stencil;
|
||||
!sp->fs_variant->info.uses_kill &&
|
||||
!sp->fs_variant->info.writes_z &&
|
||||
!sp->fs_variant->info.writes_stencil;
|
||||
|
||||
sp->quad.first = sp->quad.blend;
|
||||
|
||||
|
|
|
|||
|
|
@ -568,17 +568,18 @@ tri_persp_coeff(struct setup_context *setup,
|
|||
static void
|
||||
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*/
|
||||
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].dady[0] = 0.0;
|
||||
/*Y*/
|
||||
setup->coef[slot].a0[1] =
|
||||
(spfs->info.origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0)
|
||||
+ (spfs->info.pixel_center_integer ? 0.0 : 0.5);
|
||||
(fsInfo->origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0)
|
||||
+ (fsInfo->pixel_center_integer ? 0.0 : 0.5);
|
||||
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*/
|
||||
setup->coef[slot].a0[2] = setup->posCoef.a0[2];
|
||||
setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
|
||||
|
|
@ -599,7 +600,7 @@ static void
|
|||
setup_tri_coefficients(struct setup_context *setup)
|
||||
{
|
||||
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);
|
||||
uint fragSlot;
|
||||
float v[3];
|
||||
|
|
@ -618,7 +619,7 @@ setup_tri_coefficients(struct setup_context *setup)
|
|||
|
||||
/* 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;
|
||||
uint j;
|
||||
|
||||
|
|
@ -632,7 +633,7 @@ setup_tri_coefficients(struct setup_context *setup)
|
|||
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
|
||||
setup->vmid[vertSlot][j],
|
||||
setup->vmax[vertSlot][j],
|
||||
spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
|
||||
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << 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],
|
||||
setup->vmid[vertSlot][j],
|
||||
setup->vmax[vertSlot][j],
|
||||
spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
|
||||
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
|
||||
v);
|
||||
tri_persp_coeff(setup, &setup->coef[fragSlot], j, v);
|
||||
}
|
||||
|
|
@ -654,7 +655,7 @@ setup_tri_coefficients(struct setup_context *setup)
|
|||
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 */
|
||||
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
|
||||
setup->coef[fragSlot].dadx[0] = 0.0;
|
||||
|
|
@ -939,7 +940,7 @@ setup_line_coefficients(struct setup_context *setup,
|
|||
const float (*v1)[4])
|
||||
{
|
||||
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);
|
||||
uint fragSlot;
|
||||
float area;
|
||||
|
|
@ -974,7 +975,7 @@ setup_line_coefficients(struct setup_context *setup,
|
|||
|
||||
/* 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;
|
||||
uint j;
|
||||
|
||||
|
|
@ -987,7 +988,7 @@ setup_line_coefficients(struct setup_context *setup,
|
|||
for (j = 0; j < NUM_CHANNELS; j++) {
|
||||
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
|
||||
setup->vmax[vertSlot][j],
|
||||
spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
|
||||
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << 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++) {
|
||||
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
|
||||
setup->vmax[vertSlot][j],
|
||||
spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
|
||||
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
|
||||
v);
|
||||
line_persp_coeff(setup, &setup->coef[fragSlot], j, v);
|
||||
}
|
||||
|
|
@ -1008,7 +1009,7 @@ setup_line_coefficients(struct setup_context *setup,
|
|||
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 */
|
||||
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
|
||||
setup->coef[fragSlot].dadx[0] = 0.0;
|
||||
|
|
@ -1188,7 +1189,7 @@ sp_setup_point(struct setup_context *setup,
|
|||
const float (*v0)[4])
|
||||
{
|
||||
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 float size
|
||||
= 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, 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;
|
||||
uint j;
|
||||
|
||||
|
|
@ -1255,7 +1256,7 @@ sp_setup_point(struct setup_context *setup,
|
|||
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 */
|
||||
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
|
||||
setup->coef[fragSlot].dadx[0] = 0.0;
|
||||
|
|
|
|||
|
|
@ -60,31 +60,43 @@ struct tgsi_exec_machine;
|
|||
struct vertex_info;
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of pipe_shader_state (though it doesn't really need to be).
|
||||
*
|
||||
* 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_key
|
||||
{
|
||||
int foo; /* XXX temporary */
|
||||
};
|
||||
|
||||
|
||||
struct sp_fragment_shader_variant
|
||||
{
|
||||
const struct tgsi_token *tokens;
|
||||
struct sp_fragment_shader_variant_key key;
|
||||
struct tgsi_shader_info info;
|
||||
|
||||
/* See comments about this elsewhere */
|
||||
#if 0
|
||||
struct draw_fragment_shader *draw_shader;
|
||||
#endif
|
||||
|
||||
void (*prepare)( const struct sp_fragment_shader *shader,
|
||||
struct tgsi_exec_machine *machine,
|
||||
struct tgsi_sampler **samplers);
|
||||
void (*prepare)(const struct sp_fragment_shader_variant *shader,
|
||||
struct tgsi_exec_machine *machine,
|
||||
struct tgsi_sampler **samplers);
|
||||
|
||||
/* Run the shader - this interface will get cleaned up in the
|
||||
* future:
|
||||
*/
|
||||
unsigned (*run)( const struct sp_fragment_shader *shader,
|
||||
struct tgsi_exec_machine *machine,
|
||||
struct quad_header *quad );
|
||||
unsigned (*run)(const struct sp_fragment_shader_variant *shader,
|
||||
struct tgsi_exec_machine *machine,
|
||||
struct quad_header *quad);
|
||||
|
||||
/* Deletes this instance of the object */
|
||||
void (*delete)(struct sp_fragment_shader_variant *shader);
|
||||
|
||||
struct sp_fragment_shader_variant *next;
|
||||
};
|
||||
|
||||
|
||||
void (*delete)( struct sp_fragment_shader * );
|
||||
/** 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;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -138,7 +150,7 @@ softpipe_set_framebuffer_state(struct pipe_context *,
|
|||
const struct pipe_framebuffer_state *);
|
||||
|
||||
void
|
||||
softpipe_update_derived( struct softpipe_context *softpipe );
|
||||
softpipe_update_derived(struct softpipe_context *softpipe);
|
||||
|
||||
void
|
||||
softpipe_draw_vbo(struct pipe_context *pipe,
|
||||
|
|
@ -167,4 +179,10 @@ struct vertex_info *
|
|||
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
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
|
|||
|
||||
if (vinfo->num_attribs == 0) {
|
||||
/* 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;
|
||||
const uint num = draw_num_shader_outputs(softpipe->draw);
|
||||
uint i;
|
||||
|
|
@ -84,11 +84,11 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
|
|||
* from the vertex shader.
|
||||
*/
|
||||
vinfo->num_attribs = 0;
|
||||
for (i = 0; i < spfs->info.num_inputs; i++) {
|
||||
for (i = 0; i < fsInfo->num_inputs; i++) {
|
||||
int src;
|
||||
enum interp_mode interp;
|
||||
|
||||
switch (spfs->info.input_interpolate[i]) {
|
||||
switch (fsInfo->input_interpolate[i]) {
|
||||
case TGSI_INTERPOLATE_CONSTANT:
|
||||
interp = INTERP_CONSTANT;
|
||||
break;
|
||||
|
|
@ -103,7 +103,7 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
|
|||
interp = INTERP_LINEAR;
|
||||
}
|
||||
|
||||
switch (spfs->info.input_semantic_name[i]) {
|
||||
switch (fsInfo->input_semantic_name[i]) {
|
||||
case TGSI_SEMANTIC_POSITION:
|
||||
interp = INTERP_POS;
|
||||
break;
|
||||
|
|
@ -117,8 +117,8 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
|
|||
|
||||
/* this includes texcoords and varying vars */
|
||||
src = draw_find_shader_output(softpipe->draw,
|
||||
spfs->info.input_semantic_name[i],
|
||||
spfs->info.input_semantic_index[i]);
|
||||
fsInfo->input_semantic_name[i],
|
||||
fsInfo->input_semantic_index[i]);
|
||||
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
|
||||
* 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);
|
||||
|
||||
|
|
@ -255,6 +291,10 @@ void softpipe_update_derived( struct softpipe_context *softpipe )
|
|||
softpipe->dirty |= SP_NEW_TEXTURE;
|
||||
}
|
||||
|
||||
if (softpipe->dirty & (SP_NEW_RASTERIZER |
|
||||
SP_NEW_FS))
|
||||
update_fragment_shader(softpipe);
|
||||
|
||||
if (softpipe->dirty & (SP_NEW_SAMPLER |
|
||||
SP_NEW_TEXTURE |
|
||||
SP_NEW_FS |
|
||||
|
|
|
|||
|
|
@ -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]) {
|
||||
assert(softpipe->fragment_sampler_views[i]->texture);
|
||||
softpipe->tgsi.frag_samplers_list[i] =
|
||||
get_sampler_variant( i,
|
||||
sp_sampler(softpipe->fragment_samplers[i]),
|
||||
|
|
|
|||
|
|
@ -42,37 +42,91 @@
|
|||
#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 *
|
||||
softpipe_create_fs_state(struct pipe_context *pipe,
|
||||
const struct pipe_shader_state *templ)
|
||||
{
|
||||
struct softpipe_context *softpipe = softpipe_context(pipe);
|
||||
struct sp_fragment_shader *state;
|
||||
unsigned i;
|
||||
struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader);
|
||||
|
||||
/* debug */
|
||||
if (softpipe->dump_fs)
|
||||
tgsi_dump(templ->tokens, 0);
|
||||
|
||||
/* codegen */
|
||||
state = softpipe_create_fs_sse( softpipe, templ );
|
||||
if (!state) {
|
||||
state = softpipe_create_fs_exec( softpipe, templ );
|
||||
}
|
||||
|
||||
if (!state)
|
||||
return NULL;
|
||||
/* we need to keep a local copy of the tokens */
|
||||
state->shader.tokens = tgsi_dup_tokens(templ->tokens);
|
||||
|
||||
/* 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) {
|
||||
state->delete( state );
|
||||
FREE((void *) state->shader.tokens);
|
||||
FREE(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get/save the summary info for this shader */
|
||||
tgsi_scan_shader(templ->tokens, &state->info);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
@ -81,6 +135,7 @@ static void
|
|||
softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
|
||||
{
|
||||
struct softpipe_context *softpipe = softpipe_context(pipe);
|
||||
struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs;
|
||||
|
||||
if (softpipe->fs == fs)
|
||||
return;
|
||||
|
|
@ -89,8 +144,14 @@ softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
|
|||
|
||||
softpipe->fs = fs;
|
||||
|
||||
draw_bind_fragment_shader(softpipe->draw,
|
||||
(softpipe->fs ? softpipe->fs->draw_shader : NULL));
|
||||
if (fs == NULL)
|
||||
softpipe->fs_variant = NULL;
|
||||
|
||||
if (state)
|
||||
draw_bind_fragment_shader(softpipe->draw,
|
||||
state->draw_shader);
|
||||
else
|
||||
draw_bind_fragment_shader(softpipe->draw, NULL);
|
||||
|
||||
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 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) {
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
state->delete( state );
|
||||
FREE((void *) state->shader.tokens);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue