From e529170c11d3cb5812aabeff0a6ee2d7a2ea66f2 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Thu, 8 Oct 2009 11:47:33 +0100 Subject: [PATCH] llvmpipe: more wipping --- src/gallium/drivers/llvmpipe/lp_prim_vbuf.c | 2 +- .../llvmpipe/{lp_rasterizer.c => lp_rast.c} | 44 +-- .../llvmpipe/{lp_rasterizer.h => lp_rast.h} | 59 ++-- src/gallium/drivers/llvmpipe/lp_rast_priv.h | 31 ++ src/gallium/drivers/llvmpipe/lp_rast_tri.c | 348 +++++++++++++++++++++ src/gallium/drivers/llvmpipe/lp_setup.c | 17 + src/gallium/drivers/llvmpipe/lp_setup_rasterize.c | 19 +- src/gallium/drivers/llvmpipe/lp_setup_tri.c | 6 +- src/gallium/drivers/llvmpipe/lp_state_derived.c | 27 ++ 9 files changed, 484 insertions(+), 69 deletions(-) rename src/gallium/drivers/llvmpipe/{lp_rasterizer.c => lp_rast.c} (74%) rename src/gallium/drivers/llvmpipe/{lp_rasterizer.h => lp_rast.h} (55%) create mode 100644 src/gallium/drivers/llvmpipe/lp_rast_priv.h create mode 100644 src/gallium/drivers/llvmpipe/lp_rast_tri.c diff --git a/src/gallium/drivers/llvmpipe/lp_prim_vbuf.c b/src/gallium/drivers/llvmpipe/lp_prim_vbuf.c index e244ac9..8cccb29 100644 --- a/src/gallium/drivers/llvmpipe/lp_prim_vbuf.c +++ b/src/gallium/drivers/llvmpipe/lp_prim_vbuf.c @@ -138,7 +138,7 @@ lp_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim) struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr); struct setup_context *setup_ctx = cvbr->setup; - llvmpipe_setup_prepare( setup_ctx ); + llvmpipe_update_state( setup_ctx->llvmpipe ); cvbr->llvmpipe->reduced_prim = u_reduced_prim(prim); cvbr->prim = prim; diff --git a/src/gallium/drivers/llvmpipe/lp_rasterizer.c b/src/gallium/drivers/llvmpipe/lp_rast.c similarity index 74% rename from src/gallium/drivers/llvmpipe/lp_rasterizer.c rename to src/gallium/drivers/llvmpipe/lp_rast.c index 089ea59..4771f82 100644 --- a/src/gallium/drivers/llvmpipe/lp_rasterizer.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -1,29 +1,4 @@ -struct lp_rasterizer { - - /* We can choose whatever layout for the internal tile storage we - * prefer: - */ - struct { - unsigned color[TILESIZE][TILESIZE]; - unsigned depth[TILESIZE][TILESIZE]; - char stencil[TILESIZE][TILESIZE]; - } tile; - - - unsigned x; - unsigned y; - - - struct { - struct pipe_surface *color; - struct pipe_surface *zstencil; - unsigned clear_color; - unsigned clear_depth; - char clear_stencil; - } state; -}; - struct lp_rasterizer *lp_rast_create( void ) { return CALLOC_STRUCT(lp_rasterizer); @@ -96,31 +71,18 @@ void lp_rast_set_state( struct lp_rasterizer *rast, const struct lp_rast_state *state ) { rast->shader_state = state; -} - -void lp_rast_triangle( struct lp_rasterizer *rast, - const struct lp_rast_triangle *inputs ) -{ - /* Set up the silly quad coef pointers - */ - for (i = 0; i < 4; i++) { - rast->quads[i].posCoef = inputs->posCoef; - rast->quads[i].coef = inputs->coef; - } - - /* Scan the tile in 4x4 chunks (?) and figure out which bits to - * rasterize: - */ + lp->quad.first->begin( lp->quad.first ); } + void lp_rast_shade_tile( struct lp_rasterizer *rast, const struct lp_rast_shader_inputs *inputs ) { /* Set up the silly quad coef pointers */ for (i = 0; i < 4; i++) { - rast->quads[i].posCoef = inputs->posCoef; + rast->quads[i].posCoef = &inputs->posCoef; rast->quads[i].coef = inputs->coef; } diff --git a/src/gallium/drivers/llvmpipe/lp_rasterizer.h b/src/gallium/drivers/llvmpipe/lp_rast.h similarity index 55% rename from src/gallium/drivers/llvmpipe/lp_rasterizer.h rename to src/gallium/drivers/llvmpipe/lp_rast.h index b3ae06a..8f4bd52 100644 --- a/src/gallium/drivers/llvmpipe/lp_rasterizer.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -1,4 +1,7 @@ +#ifndef LP_RAST_H +#define LP_RAST_H + /* Initially create and program a single rasterizer directly. Later * will want multiple of these, one or two per core. At that stage * will probably pass command buffers into the rasterizers rather than @@ -7,12 +10,16 @@ struct lp_rasterizer; struct lp_rast_state { - /* State: + /* State for the shader: */ struct lp_jit_context jc; - /* Shader itself: + /* The shader itself. Probably we also need to pass a pointer to + * the tile color/z/stencil data somehow: */ + void (*run)( struct lp_jit_context *jc, + struct quad_header **quads, + unsigned nr ); }; /* Coefficients necessary to run the shader at a given location: @@ -25,10 +32,6 @@ struct lp_rast_shader_inputs { /* Attribute interpolation: */ - float oneoverarea; - float x1; - float y1; - struct tgsi_interp_coef position_coef; struct tgsi_interp_coef *coef; }; @@ -79,34 +82,48 @@ void lp_rast_start_tile( struct lp_rasterizer *, unsigned x, unsigned y ); -void lp_rast_clear_color( struct lp_rasterizer * ); - -void lp_rast_clear_zstencil( struct lp_rasterizer * ); -void lp_rast_load_color( struct lp_rasterizer * ); -void lp_rast_load_zstencil( struct lp_rasterizer * ); +union lp_rast_cmd_arg { + const struct lp_rast_shader_inputs *shade_tile; + const struct lp_rast_triangle *triangle; + const struct lp_rast_state *set_state; +}; -/* Within a tile: +/* Binnable Commands: */ -void lp_rast_set_state( struct lp_rasterizer *, - const struct lp_rast_state * ); +void lp_rast_clear_color( struct lp_rasterizer *, + const union lp_rast_cmd_arg *); + +void lp_rast_clear_zstencil( struct lp_rasterizer *, + const union lp_rast_cmd_arg *); -void lp_rast_triangle( struct lp_rasterizer *, - const struct lp_rast_triangle * ); +void lp_rast_load_color( struct lp_rasterizer *, + const union lp_rast_cmd_arg *); + +void lp_rast_load_zstencil( struct lp_rasterizer *, + const union lp_rast_cmd_arg *); + +void lp_rast_set_state( struct lp_rasterizer *, + const union lp_rast_cmd_arg * ); + +void lp_rast_triangle( struct lp_rasterizer *, + const union lp_rast_cmd_arg * ); void lp_rast_shade_tile( struct lp_rasterizer *, - const struct lp_rast_shader_inputs * ); + const union lp_rast_cmd_arg * ); -/* End of tile: - */ -void lp_rast_store_color( struct lp_rasterizer * ); +void lp_rast_store_color( struct lp_rasterizer *, + const union lp_rast_cmd_arg *); -void lp_rast_store_zstencil( struct lp_rasterizer * ); +void lp_rast_store_zstencil( struct lp_rasterizer *, + const union lp_rast_cmd_arg *); /* Shutdown: */ void lp_rast_destroy( struct lp_rasterizer * ); + +#endif diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h new file mode 100644 index 0000000..538ec22 --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h @@ -0,0 +1,31 @@ +#ifndef LP_RAST_PRIV_H +#define LP_RAST_PRIV_H + +#include "lp_rast.h" + +struct lp_rasterizer { + + /* We can choose whatever layout for the internal tile storage we + * prefer: + */ + struct { + unsigned color[TILESIZE][TILESIZE]; + unsigned depth[TILESIZE][TILESIZE]; + char stencil[TILESIZE][TILESIZE]; + } tile; + + + unsigned x; + unsigned y; + + + struct { + struct pipe_surface *color; + struct pipe_surface *zstencil; + unsigned clear_color; + unsigned clear_depth; + char clear_stencil; + } state; +}; + +#endif diff --git a/src/gallium/drivers/llvmpipe/lp_rast_tri.c b/src/gallium/drivers/llvmpipe/lp_rast_tri.c new file mode 100644 index 0000000..4b7b371 --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_rast_tri.c @@ -0,0 +1,348 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Rasterization for binned triangles within a tile + */ + +#include "lp_context.h" +#include "lp_quad.h" +#include "lp_quad_pipe.h" +#include "lp_setup.h" +#include "lp_state.h" +#include "draw/draw_context.h" +#include "draw/draw_private.h" +#include "draw/draw_vertex.h" +#include "pipe/p_shader_tokens.h" +#include "pipe/p_thread.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +#define BLOCKSIZE 4 + + +/* Convert 8x8 block into four runs of quads and render each in turn. + */ +#if (BLOCKSIZE == 8) +static void block_full( struct triangle *tri, int x, int y ) +{ + struct quad_header *ptrs[4]; + int i; + + tri->quad[0].input.x0 = x + 0; + tri->quad[1].input.x0 = x + 2; + tri->quad[2].input.x0 = x + 4; + tri->quad[3].input.x0 = x + 6; + + for (i = 0; i < 4; i++, y += 2) { + tri->quad[0].inout.mask = 0xf; + tri->quad[1].inout.mask = 0xf; + tri->quad[2].inout.mask = 0xf; + tri->quad[3].inout.mask = 0xf; + + tri->quad[0].input.y0 = y; + tri->quad[1].input.y0 = y; + tri->quad[2].input.y0 = y; + tri->quad[3].input.y0 = y; + + /* XXX: don't bother with this ptrs business */ + ptrs[0] = &tri->quad[0]; + ptrs[1] = &tri->quad[1]; + ptrs[2] = &tri->quad[2]; + ptrs[3] = &tri->quad[3]; + + tri->llvmpipe->quad.first->run( tri->llvmpipe->quad.first, ptrs, 4 ); + } +} +#else +static void block_full( struct triangle *tri, int x, int y ) +{ + struct quad_header *ptrs[4]; + int iy; + + tri->quad[0].input.x0 = x + 0; + tri->quad[1].input.x0 = x + 2; + + for (iy = 0; iy < 4; iy += 2) { + tri->quad[0].inout.mask = 0xf; + tri->quad[1].inout.mask = 0xf; + + tri->quad[0].input.y0 = y + iy; + tri->quad[1].input.y0 = y + iy; + + /* XXX: don't bother with this ptrs business */ + ptrs[0] = &tri->quad[0]; + ptrs[1] = &tri->quad[1]; + + tri->llvmpipe->quad.first->run( tri->llvmpipe->quad.first, ptrs, 2 ); + } +} +#endif + +static void +do_quad( struct lp_rasterizer *rast, + int x, int y, + float c1, float c2, float c3 ) +{ + struct triangle *tri = rast->tri; + struct quad_header *quad = &rast->quad[0]; + + float xstep1 = -tri->dy12; + float xstep2 = -tri->dy23; + float xstep3 = -tri->dy31; + + float ystep1 = tri->dx12; + float ystep2 = tri->dx23; + float ystep3 = tri->dx31; + + quad->input.x0 = x; + quad->input.y0 = y; + quad->inout.mask = 0; + + if (c1 > 0 && + c2 > 0 && + c3 > 0) + quad->inout.mask |= 1; + + if (c1 + xstep1 > 0 && + c2 + xstep2 > 0 && + c3 + xstep3 > 0) + quad->inout.mask |= 2; + + if (c1 + ystep1 > 0 && + c2 + ystep2 > 0 && + c3 + ystep3 > 0) + quad->inout.mask |= 4; + + if (c1 + ystep1 + xstep1 > 0 && + c2 + ystep2 + xstep2 > 0 && + c3 + ystep3 + xstep3 > 0) + quad->inout.mask |= 8; + + if (quad->inout.mask) + rast->state->run( rast->state->state, &quad, 1 ); +} + +/* Evaluate each pixel in a block, generate a mask and possibly render + * the quad: + */ +static void +do_block( struct triangle *tri, + int x, int y, + float c1, + float c2, + float c3 ) +{ + const int step = 2; + + float xstep1 = -step * tri->dy12; + float xstep2 = -step * tri->dy23; + float xstep3 = -step * tri->dy31; + + float ystep1 = step * tri->dx12; + float ystep2 = step * tri->dx23; + float ystep3 = step * tri->dx31; + + int ix, iy; + + for (iy = 0; iy < BLOCKSIZE; iy += 2) { + float cx1 = c1; + float cx2 = c2; + float cx3 = c3; + + for (ix = 0; ix < BLOCKSIZE; ix += 2) { + + do_quad(tri, x+ix, y+iy, cx1, cx2, cx3); + + cx1 += xstep1; + cx2 += xstep2; + cx3 += xstep3; + } + + c1 += ystep1; + c2 += ystep2; + c3 += ystep3; + } +} + + + +/* Scan the tile in chunks and figure out which pixels to rasterize + * for this triangle: + */ +void lp_rast_triangle( struct lp_rasterizer *rast, + const struct lp_rast_triangle *tri ) +{ + int minx, maxx, miny, maxy; + + /* Clamp to tile dimensions: + */ + minx = MAX2(tri->maxx, rast->x); + miny = MAX2(tri->miny, rast->y); + maxx = MIN2(tri->maxx, rast->x + TILESIZE); + maxy = MIN2(tri->maxy, rast->y + TILESIZE); + + if (miny == maxy || + minx == maxx) { + debug_printf("%s: non-intersecting triangle in bin\n", __FUNCTION__); + //assert(0); + return; + } + + /* Bind parameter interpolants: + */ + for (i = 0; i < Elements(rast->quad); i++) { + rast->quad[i].coef = tri->coef; + rast->quad[i].posCoef = &tri->position_coef; + } + + /* Small area? + */ + if (miny + 16 > maxy && + minx + 16 > maxx) + { + const int step = 2; + + float xstep1 = -step * tri->dy12; + float xstep2 = -step * tri->dy23; + float xstep3 = -step * tri->dy31; + + float ystep1 = step * tri->dx12; + float ystep2 = step * tri->dx23; + float ystep3 = step * tri->dx31; + + float eo1 = tri->eo1 * step; + float eo2 = tri->eo2 * step; + float eo3 = tri->eo3 * step; + + int x, y; + + minx &= ~(step-1); + maxx &= ~(step-1); + + /* Subdivide space into NxM blocks, where each block is square and + * power-of-four in dimension. + * + * Trivially accept or reject blocks, else jump to per-pixel + * examination above. + */ + for (y = miny; y < maxy; y += step) + { + float cx1 = c1; + float cx2 = c2; + float cx3 = c3; + + for (x = minx; x < maxx; x += step) + { + if (cx1 + eo1 < 0 || + cx2 + eo2 < 0 || + cx3 + eo3 < 0) + { + } + else + { + do_quad(&tri, x, y, cx1, cx2, cx3); + } + + /* Iterate cx values across the region: + */ + cx1 += xstep1; + cx2 += xstep2; + cx3 += xstep3; + } + + /* Iterate c values down the region: + */ + c1 += ystep1; + c2 += ystep2; + c3 += ystep3; + } + } + else + { + const int step = BLOCKSIZE; + + float ei1 = tri->ei1 * step; + float ei2 = tri->ei2 * step; + float ei3 = tri->ei3 * step; + + float eo1 = tri->eo1 * step; + float eo2 = tri->eo2 * step; + float eo3 = tri->eo3 * step; + + float xstep1 = -step * tri->dy12; + float xstep2 = -step * tri->dy23; + float xstep3 = -step * tri->dy31; + + float ystep1 = step * tri->dx12; + float ystep2 = step * tri->dx23; + float ystep3 = step * tri->dx31; + int x, y; + + minx &= ~(step-1); + miny &= ~(step-1); + + for (y = miny; y < maxy; y += step) + { + float cx1 = c1; + float cx2 = c2; + float cx3 = c3; + + for (x = minx; x < maxx; x += step) + { + if (cx1 + eo1 < 0 || + cx2 + eo2 < 0 || + cx3 + eo3 < 0) + { + } + else if (cx1 + ei1 > 0 && + cx2 + ei2 > 0 && + cx3 + ei3 > 0) + { + block_full(&tri, x, y); /* trivial accept */ + } + else + { + do_block(&tri, x, y, cx1, cx2, cx3); + } + + /* Iterate cx values across the region: + */ + cx1 += xstep1; + cx2 += xstep2; + cx3 += xstep3; + } + + /* Iterate c values down the region: + */ + c1 += ystep1; + c2 += ystep2; + c3 += ystep3; + } + } +} + diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 8c67524..d6e5188 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -48,6 +48,23 @@ #define DEBUG_VERTS 0 + +void +llvmpipe_setup_flush() +{ +} + +void +llvmpipe_setup_bind_framebuffer() +{ +} + +void +llvmpipe_setup_clear() +{ +} + + /* Stubs for lines & points for now: */ void diff --git a/src/gallium/drivers/llvmpipe/lp_setup_rasterize.c b/src/gallium/drivers/llvmpipe/lp_setup_rasterize.c index 5b4faf4..bb7a4fe 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_rasterize.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_rasterize.c @@ -1,7 +1,20 @@ void -rasterize( struct llvmpipe_context *llvmpipe, - struct binned_scene *scene ) +lp_setup_rasterize( struct llvmpipe_context *llvmpipe, + struct binned_scene *scene ) { - + lp_rast_bind_surfaces( rast, scene->framebuffer ); + + for (i = 0; i < scene->tiles_x; i++) { + for (j = 0; j < scene->tiles_y; j++) { + + lp_rast_start_tile( rast, i * TILESIZE, j * TILESIZE ); + + for (block = scene->tile[i][j].first; block; block = block->next) { + for (k = 0; k < block->nr_cmds; k++) { + block->cmd[k].func( rast, block->cmd[k].arg ); + } + } + } + } } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c index a09e0fa..d43db7b 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -728,9 +728,9 @@ static void triangle_nop( struct llvmpipe_context *llvmpipe, { } -/** - * Do setup for triangle rasterization, then render the triangle. - */ + + + void setup_prepare_tri( struct llvmpipe_context *llvmpipe ) { llvmpipe->ccw_is_frontface = (llvmpipe->rasterizer->front_winding == diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index 31eaadd..fcd3113 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -232,6 +232,22 @@ update_tgsi_samplers( struct llvmpipe_context *llvmpipe ) llvmpipe->jit_context.samplers = (struct tgsi_sampler **)llvmpipe->tgsi.frag_samplers_list; } +static void +update_culling() +{ + if (lp->reduced_api_prim == PIPE_PRIM_TRIANGLES && + lp->rasterizer->fill_cw == PIPE_POLYGON_MODE_FILL && + lp->rasterizer->fill_ccw == PIPE_POLYGON_MODE_FILL) { + /* we'll do culling */ + setup->winding = lp->rasterizer->cull_mode; + } + else { + /* 'draw' will do culling */ + setup->winding = PIPE_WINDING_NONE; + } +} + + /* Hopefully this will remain quite simple, otherwise need to pull in * something like the state tracker mechanism. */ @@ -270,3 +286,14 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) llvmpipe->dirty = 0; } + + +void llvmpipe_prepare( ) +{ + struct llvmpipe_context *lp = setup->llvmpipe; + + if (lp->dirty) { + llvmpipe_update_derived(lp); + } + +} -- 2.7.4