softpipe: use the polygon stipple utility module

This is an alternative to the draw module's polygon stipple stage.
The softpipe implementation here is just a test.  The advantange of
using the new polygon stipple utility module (with other drivers)
is we can avoid software vertex processing in the draw module and
get much better performance.
Polygon stipple doesn't require special vertex processing like
the other draw module stage.
This commit is contained in:
Brian Paul 2011-07-21 09:55:22 -06:00
parent c534f11164
commit 57aa597b3d
9 changed files with 131 additions and 14 deletions

View file

@ -60,7 +60,7 @@ softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
return;
#if 0
softpipe_update_derived(softpipe); /* not needed?? */
softpipe_update_derived(softpipe, PIPE_PRIM_TRIANGLES); /* not needed?? */
#endif
if (buffers & PIPE_CLEAR_COLOR) {

View file

@ -35,6 +35,7 @@
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_pstipple.h"
#include "util/u_inlines.h"
#include "tgsi/tgsi_exec.h"
#include "sp_clear.h"
@ -88,6 +89,14 @@ softpipe_destroy( struct pipe_context *pipe )
struct softpipe_context *softpipe = softpipe_context( pipe );
uint i;
#if DO_PSTIPPLE_IN_HELPER_MODULE
if (softpipe->pstipple.sampler)
pipe->delete_sampler_state(pipe, softpipe->pstipple.sampler);
pipe_resource_reference(&softpipe->pstipple.texture, NULL);
pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, NULL);
#endif
if (softpipe->draw)
draw_destroy( softpipe->draw );
@ -341,6 +350,11 @@ softpipe_create_context( struct pipe_screen *screen,
sp_init_surface_functions(softpipe);
#if DO_PSTIPPLE_IN_HELPER_MODULE
/* create the polgon stipple sampler */
softpipe->pstipple.sampler = util_pstipple_create_sampler(&softpipe->pipe);
#endif
return &softpipe->pipe;
fail:

View file

@ -38,8 +38,11 @@
#include "sp_quad_pipe.h"
/** Do polygon stipple in the driver here, or in the draw module? */
#define DO_PSTIPPLE_IN_DRAW_MODULE 1
/** Do polygon stipple in the draw module? */
#define DO_PSTIPPLE_IN_DRAW_MODULE 0
/** Do polygon stipple with the util module? */
#define DO_PSTIPPLE_IN_HELPER_MODULE 1
struct softpipe_vbuf_render;
@ -144,6 +147,13 @@ struct softpipe_context {
struct pipe_query *render_cond_query;
uint render_cond_mode;
/** Polygon stipple items */
struct {
struct pipe_resource *texture;
struct pipe_sampler_state *sampler;
struct pipe_sampler_view *sampler_view;
} pstipple;
/** Software quad rendering pipeline */
struct {
struct quad_stage *shade;

View file

@ -64,7 +64,7 @@ softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode)
sp->reduced_api_prim = u_reduced_prim(mode);
if (sp->dirty) {
softpipe_update_derived(sp);
softpipe_update_derived(sp, sp->reduced_api_prim);
}
softpipe_map_transfers(sp);
@ -122,7 +122,7 @@ softpipe_draw_vbo(struct pipe_context *pipe,
sp->reduced_api_prim = u_reduced_prim(info->mode);
if (sp->dirty) {
softpipe_update_derived(sp);
softpipe_update_derived(sp, sp->reduced_api_prim);
}
softpipe_map_transfers(sp);

View file

@ -61,7 +61,7 @@ sp_build_quad_pipeline(struct softpipe_context *sp)
insert_stage_at_head( sp, sp->quad.shade );
}
#if !DO_PSTIPPLE_IN_DRAW_MODULE
#if !DO_PSTIPPLE_IN_DRAW_MODULE && !DO_PSTIPPLE_IN_HELPER_MODULE
if (sp->rasterizer->poly_stipple_enable)
insert_stage_at_head( sp, sp->quad.pstipple );
#endif

View file

@ -1397,7 +1397,7 @@ sp_setup_prepare(struct setup_context *setup)
struct softpipe_context *sp = setup->softpipe;
if (sp->dirty) {
softpipe_update_derived(sp);
softpipe_update_derived(sp, sp->reduced_api_prim);
}
/* Note: nr_attrs is only used for debugging (vertex printing) */

View file

@ -62,7 +62,7 @@ struct vertex_info;
struct sp_fragment_shader_variant_key
{
int foo; /* XXX temporary */
boolean polygon_stipple;
};
@ -72,6 +72,8 @@ struct sp_fragment_shader_variant
struct sp_fragment_shader_variant_key key;
struct tgsi_shader_info info;
unsigned stipple_sampler_unit;
/* See comments about this elsewhere */
#if 0
struct draw_fragment_shader *draw_shader;
@ -150,7 +152,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, unsigned prim);
void
softpipe_draw_vbo(struct pipe_context *pipe,
@ -179,6 +181,12 @@ 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);
struct sp_fragment_shader_variant *
softpipe_find_fs_variant(struct softpipe_context *softpipe,
struct sp_fragment_shader *fs,

View file

@ -25,8 +25,10 @@
*
**************************************************************************/
#include "util/u_inlines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_pstipple.h"
#include "pipe/p_shader_tokens.h"
#include "draw/draw_context.h"
#include "draw/draw_vertex.h"
@ -242,12 +244,15 @@ update_tgsi_samplers( struct softpipe_context *softpipe )
static void
update_fragment_shader(struct softpipe_context *softpipe)
update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
{
struct sp_fragment_shader_variant_key key;
memset(&key, 0, sizeof(key));
if (prim == PIPE_PRIM_TRIANGLES)
key.polygon_stipple = softpipe->rasterizer->poly_stipple_enable;
if (softpipe->fs) {
softpipe->fs_variant = softpipe_find_fs_variant(softpipe,
softpipe->fs, &key);
@ -276,11 +281,63 @@ update_fragment_shader(struct softpipe_context *softpipe)
}
/**
* This should be called when the polygon stipple pattern changes.
* We create a new texture from the stipple pattern and create a new
* sampler view.
*/
static void
update_polygon_stipple_pattern(struct softpipe_context *softpipe)
{
struct pipe_resource *tex;
struct pipe_sampler_view *view;
tex = util_pstipple_create_stipple_texture(&softpipe->pipe,
softpipe->poly_stipple.stipple);
pipe_resource_reference(&softpipe->pstipple.texture, tex);
view = util_pstipple_create_sampler_view(&softpipe->pipe, tex);
pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, view);
}
/**
* Should be called when polygon stipple is enabled/disabled or when
* the fragment shader changes.
* We add/update the fragment sampler and sampler views to sample from
* the polygon stipple texture. The texture unit that we use depends on
* the fragment shader (we need to use a unit not otherwise used by the
* shader).
*/
static void
update_polygon_stipple_enable(struct softpipe_context *softpipe, unsigned prim)
{
if (prim == PIPE_PRIM_TRIANGLES &&
softpipe->fs_variant->key.polygon_stipple) {
const unsigned unit = softpipe->fs_variant->stipple_sampler_unit;
assert(unit >= softpipe->num_fragment_samplers);
/* sampler state */
softpipe->fragment_samplers[unit] = softpipe->pstipple.sampler;
/* sampler view */
pipe_sampler_view_reference(&softpipe->fragment_sampler_views[unit],
softpipe->pstipple.sampler_view);
sp_tex_tile_cache_set_sampler_view(softpipe->fragment_tex_cache[unit],
softpipe->pstipple.sampler_view);
softpipe->dirty |= SP_NEW_SAMPLER;
}
}
/* 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)
softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim)
{
struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);
@ -290,10 +347,23 @@ softpipe_update_derived(struct softpipe_context *softpipe)
softpipe->tex_timestamp = sp_screen->timestamp;
softpipe->dirty |= SP_NEW_TEXTURE;
}
#if DO_PSTIPPLE_IN_HELPER_MODULE
if (softpipe->dirty & SP_NEW_STIPPLE)
/* before updating samplers! */
update_polygon_stipple_pattern(softpipe);
#endif
if (softpipe->dirty & (SP_NEW_RASTERIZER |
SP_NEW_FS))
update_fragment_shader(softpipe);
update_fragment_shader(softpipe, prim);
#if DO_PSTIPPLE_IN_HELPER_MODULE
if (softpipe->dirty & (SP_NEW_RASTERIZER |
SP_NEW_STIPPLE |
SP_NEW_FS))
update_polygon_stipple_enable(softpipe, prim);
#endif
if (softpipe->dirty & (SP_NEW_SAMPLER |
SP_NEW_TEXTURE |

View file

@ -33,6 +33,7 @@
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_pstipple.h"
#include "draw/draw_context.h"
#include "draw/draw_vs.h"
#include "draw/draw_gs.h"
@ -51,7 +52,15 @@ create_fs_variant(struct softpipe_context *softpipe,
const struct sp_fragment_shader_variant_key *key)
{
struct sp_fragment_shader_variant *var;
struct pipe_shader_state *curfs = &fs->shader;
struct pipe_shader_state *stipple_fs = NULL, *curfs = &fs->shader;
unsigned unit = 0;
if (key->polygon_stipple) {
/* get new shader that implements polygon stippling */
stipple_fs = util_pstipple_create_fragment_shader(&softpipe->pipe,
curfs, &unit);
curfs = stipple_fs;
}
/* codegen, create variant object */
var = softpipe_create_fs_variant_sse(softpipe, curfs);
@ -62,6 +71,7 @@ create_fs_variant(struct softpipe_context *softpipe,
if (var) {
var->key = *key;
var->tokens = tgsi_dup_tokens(curfs->tokens);
var->stipple_sampler_unit = unit;
tgsi_scan_shader(var->tokens, &var->info);
@ -82,6 +92,11 @@ create_fs_variant(struct softpipe_context *softpipe,
fs->variants = var;
}
if (stipple_fs) {
free((void *) stipple_fs->tokens);
free(stipple_fs);
}
return var;
}