draw: remove draw_vertex_cache.c

This commit is contained in:
Keith Whitwell 2008-04-18 20:39:13 +01:00
parent b11d89dc6d
commit 6689182642
4 changed files with 18 additions and 722 deletions

View File

@ -31,7 +31,6 @@ C_SOURCES = \
draw_validate.c \
draw_vbuf.c \
draw_vertex.c \
draw_vertex_cache.c \
draw_vertex_fetch.c \
draw_vertex_shader.c \
draw_wide_line.c \

View File

@ -103,7 +103,6 @@ struct draw_context *draw_create( void )
draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */
draw_vertex_cache_invalidate( draw );
draw_set_mapped_element_buffer( draw, 0, NULL );
tgsi_exec_machine_init(&draw->machine);
@ -446,7 +445,6 @@ void draw_reset_vertex_ids(struct draw_context *draw)
stage = stage->next;
}
draw_vertex_cache_reset_vertex_ids(draw); /* going away soon */
draw_pt_reset_vertex_ids(draw);
}
@ -473,3 +471,21 @@ boolean draw_get_edgeflag( struct draw_context *draw,
return 1;
}
/**
* Tell the drawing context about the index/element buffer to use
* (ala glDrawElements)
* If no element buffer is to be used (i.e. glDrawArrays) then this
* should be called with eltSize=0 and elements=NULL.
*
* \param draw the drawing context
* \param eltSize size of each element (1, 2 or 4 bytes)
* \param elements the element buffer ptr
*/
void
draw_set_mapped_element_buffer( struct draw_context *draw,
unsigned eltSize, void *elements )
{
draw->user.elts = elements;
draw->user.eltSize = eltSize;
}

View File

@ -1,500 +0,0 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "pipe/p_debug.h"
#include "pipe/p_util.h"
#include "draw_private.h"
#include "draw_context.h"
#define RP_NONE 0
#define RP_POINT 1
#define RP_LINE 2
#define RP_TRI 3
static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = {
RP_POINT,
RP_LINE,
RP_LINE,
RP_LINE,
RP_TRI,
RP_TRI,
RP_TRI,
RP_TRI,
RP_TRI,
RP_TRI
};
static void draw_prim_queue_flush( struct draw_context *draw )
{
unsigned i;
if (0)
debug_printf("Flushing with %d prims, %d verts\n",
draw->pq.queue_nr, draw->vs.queue_nr);
assert (draw->pq.queue_nr != 0);
/* NOTE: we cannot save draw->pipeline->first in a local var because
* draw->pipeline->first is often changed by the first call to tri(),
* line(), etc.
*/
if (draw->rasterizer->line_stipple_enable) {
switch (draw->reduced_prim) {
case RP_TRI:
for (i = 0; i < draw->pq.queue_nr; i++) {
if (draw->pq.queue[i].reset_line_stipple)
draw->pipeline.first->reset_stipple_counter( draw->pipeline.first );
draw->pipeline.first->tri( draw->pipeline.first, &draw->pq.queue[i] );
}
break;
case RP_LINE:
for (i = 0; i < draw->pq.queue_nr; i++) {
if (draw->pq.queue[i].reset_line_stipple)
draw->pipeline.first->reset_stipple_counter( draw->pipeline.first );
draw->pipeline.first->line( draw->pipeline.first, &draw->pq.queue[i] );
}
break;
case RP_POINT:
draw->pipeline.first->reset_stipple_counter( draw->pipeline.first );
for (i = 0; i < draw->pq.queue_nr; i++)
draw->pipeline.first->point( draw->pipeline.first, &draw->pq.queue[i] );
break;
}
}
else {
switch (draw->reduced_prim) {
case RP_TRI:
for (i = 0; i < draw->pq.queue_nr; i++)
draw->pipeline.first->tri( draw->pipeline.first, &draw->pq.queue[i] );
break;
case RP_LINE:
for (i = 0; i < draw->pq.queue_nr; i++)
draw->pipeline.first->line( draw->pipeline.first, &draw->pq.queue[i] );
break;
case RP_POINT:
for (i = 0; i < draw->pq.queue_nr; i++)
draw->pipeline.first->point( draw->pipeline.first, &draw->pq.queue[i] );
break;
}
}
draw->pq.queue_nr = 0;
draw->vs.post_nr = 0;
draw_vertex_cache_unreference( draw );
}
void draw_do_flush( struct draw_context *draw, unsigned flags )
{
if (0)
debug_printf("Flushing with %d verts, %d prims\n",
draw->vs.queue_nr,
draw->pq.queue_nr );
if (draw->flushing)
return;
draw->flushing = TRUE;
if (flags >= DRAW_FLUSH_SHADER_QUEUE) {
if (draw->vs.queue_nr) {
(*draw->shader_queue_flush)(draw);
}
if (flags >= DRAW_FLUSH_PRIM_QUEUE) {
if (draw->pq.queue_nr)
draw_prim_queue_flush(draw);
if (flags >= DRAW_FLUSH_VERTEX_CACHE) {
draw_vertex_cache_invalidate(draw);
if (flags >= DRAW_FLUSH_STATE_CHANGE) {
draw->pipeline.first->flush( draw->pipeline.first, flags );
draw->pipeline.first = draw->pipeline.validate;
draw->reduced_prim = ~0;
}
}
}
}
draw->flushing = FALSE;
}
/* Return a pointer to a freshly queued primitive header. Ensure that
* there is room in the vertex cache for a maximum of "nr_verts" new
* vertices. Flush primitive and/or vertex queues if necessary to
* make space.
*/
static struct prim_header *get_queued_prim( struct draw_context *draw,
unsigned nr_verts )
{
if (!draw_vertex_cache_check_space( draw, nr_verts )) {
// debug_printf("v");
draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE );
}
else if (draw->pq.queue_nr == PRIM_QUEUE_LENGTH) {
// debug_printf("p");
draw_do_flush( draw, DRAW_FLUSH_PRIM_QUEUE );
}
assert(draw->pq.queue_nr < PRIM_QUEUE_LENGTH);
return &draw->pq.queue[draw->pq.queue_nr++];
}
/**
* Add a point to the primitive queue.
* \param i0 index into user's vertex arrays
*/
static void do_point( struct draw_context *draw,
unsigned i0 )
{
struct prim_header *prim = get_queued_prim( draw, 1 );
prim->reset_line_stipple = 0;
prim->edgeflags = 1;
prim->pad = 0;
prim->v[0] = draw->vcache.get_vertex( draw, i0 );
}
/**
* Add a line to the primitive queue.
* \param i0 index into user's vertex arrays
* \param i1 index into user's vertex arrays
*/
static void do_line( struct draw_context *draw,
boolean reset_stipple,
unsigned i0,
unsigned i1 )
{
struct prim_header *prim = get_queued_prim( draw, 2 );
prim->reset_line_stipple = reset_stipple;
prim->edgeflags = 1;
prim->pad = 0;
prim->v[0] = draw->vcache.get_vertex( draw, i0 );
prim->v[1] = draw->vcache.get_vertex( draw, i1 );
}
/**
* Add a triangle to the primitive queue.
*/
static void do_triangle( struct draw_context *draw,
unsigned i0,
unsigned i1,
unsigned i2 )
{
struct prim_header *prim = get_queued_prim( draw, 3 );
// _mesa_printf("tri %d %d %d\n", i0, i1, i2);
prim->reset_line_stipple = 1;
prim->edgeflags = ~0;
prim->pad = 0;
prim->v[0] = draw->vcache.get_vertex( draw, i0 );
prim->v[1] = draw->vcache.get_vertex( draw, i1 );
prim->v[2] = draw->vcache.get_vertex( draw, i2 );
}
static void do_ef_triangle( struct draw_context *draw,
boolean reset_stipple,
unsigned ef_mask,
unsigned i0,
unsigned i1,
unsigned i2 )
{
struct prim_header *prim = get_queued_prim( draw, 3 );
struct vertex_header *v0 = draw->vcache.get_vertex( draw, i0 );
struct vertex_header *v1 = draw->vcache.get_vertex( draw, i1 );
struct vertex_header *v2 = draw->vcache.get_vertex( draw, i2 );
prim->reset_line_stipple = reset_stipple;
prim->edgeflags = ef_mask & ((v0->edgeflag << 0) |
(v1->edgeflag << 1) |
(v2->edgeflag << 2));
prim->pad = 0;
prim->v[0] = v0;
prim->v[1] = v1;
prim->v[2] = v2;
}
static void do_ef_quad( struct draw_context *draw,
unsigned v0,
unsigned v1,
unsigned v2,
unsigned v3 )
{
const unsigned omitEdge2 = ~(1 << 1);
const unsigned omitEdge3 = ~(1 << 2);
do_ef_triangle( draw, 1, omitEdge2, v0, v1, v3 );
do_ef_triangle( draw, 0, omitEdge3, v1, v2, v3 );
}
static void do_quad( struct draw_context *draw,
unsigned v0,
unsigned v1,
unsigned v2,
unsigned v3 )
{
do_triangle( draw, v0, v1, v3 );
do_triangle( draw, v1, v2, v3 );
}
/**
* Main entrypoint to draw some number of points/lines/triangles
*/
static void
draw_prim( struct draw_context *draw,
unsigned prim, unsigned start, unsigned count )
{
unsigned i;
boolean unfilled = (draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL);
boolean flatfirst =
(draw->rasterizer->flatshade & draw->rasterizer->flatshade_first) ? TRUE : FALSE;
// debug_printf("%s (%d) %d/%d\n", __FUNCTION__, draw->prim, start, count );
switch (prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < count; i ++) {
do_point( draw,
start + i );
}
break;
case PIPE_PRIM_LINES:
for (i = 0; i+1 < count; i += 2) {
do_line( draw,
TRUE,
start + i + 0,
start + i + 1);
}
break;
case PIPE_PRIM_LINE_LOOP:
if (count >= 2) {
for (i = 1; i < count; i++) {
do_line( draw,
i == 1, /* XXX: only if vb not split */
start + i - 1,
start + i );
}
do_line( draw,
0,
start + count - 1,
start + 0 );
}
break;
case PIPE_PRIM_LINE_STRIP:
for (i = 1; i < count; i++) {
do_line( draw,
i == 1,
start + i - 1,
start + i );
}
break;
case PIPE_PRIM_TRIANGLES:
if (unfilled) {
for (i = 0; i+2 < count; i += 3) {
do_ef_triangle( draw,
1,
~0,
start + i + 0,
start + i + 1,
start + i + 2 );
}
}
else {
for (i = 0; i+2 < count; i += 3) {
do_triangle( draw,
start + i + 0,
start + i + 1,
start + i + 2 );
}
}
break;
case PIPE_PRIM_TRIANGLE_STRIP:
if (flatfirst) {
for (i = 0; i+2 < count; i++) {
if (i & 1) {
do_triangle( draw,
start + i + 0,
start + i + 2,
start + i + 1 );
}
else {
do_triangle( draw,
start + i + 0,
start + i + 1,
start + i + 2 );
}
}
}
else {
for (i = 0; i+2 < count; i++) {
if (i & 1) {
do_triangle( draw,
start + i + 1,
start + i + 0,
start + i + 2 );
}
else {
do_triangle( draw,
start + i + 0,
start + i + 1,
start + i + 2 );
}
}
}
break;
case PIPE_PRIM_TRIANGLE_FAN:
if (count >= 3) {
if (flatfirst) {
for (i = 0; i+2 < count; i++) {
do_triangle( draw,
start + i + 1,
start + i + 2,
start + 0 );
}
}
else {
for (i = 0; i+2 < count; i++) {
do_triangle( draw,
start + 0,
start + i + 1,
start + i + 2 );
}
}
}
break;
case PIPE_PRIM_QUADS:
if (unfilled) {
for (i = 0; i+3 < count; i += 4) {
do_ef_quad( draw,
start + i + 0,
start + i + 1,
start + i + 2,
start + i + 3);
}
}
else {
for (i = 0; i+3 < count; i += 4) {
do_quad( draw,
start + i + 0,
start + i + 1,
start + i + 2,
start + i + 3);
}
}
break;
case PIPE_PRIM_QUAD_STRIP:
if (unfilled) {
for (i = 0; i+3 < count; i += 2) {
do_ef_quad( draw,
start + i + 2,
start + i + 0,
start + i + 1,
start + i + 3);
}
}
else {
for (i = 0; i+3 < count; i += 2) {
do_quad( draw,
start + i + 2,
start + i + 0,
start + i + 1,
start + i + 3);
}
}
break;
case PIPE_PRIM_POLYGON:
if (unfilled) {
unsigned ef_mask = (1<<2) | (1<<0);
for (i = 0; i+2 < count; i++) {
if (i + 3 >= count)
ef_mask |= (1<<1);
do_ef_triangle( draw,
i == 0,
ef_mask,
start + i + 1,
start + i + 2,
start + 0);
ef_mask &= ~(1<<2);
}
}
else {
for (i = 0; i+2 < count; i++) {
do_triangle( draw,
start + i + 1,
start + i + 2,
start + 0);
}
}
break;
default:
assert(0);
break;
}
}

View File

@ -1,219 +0,0 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "pipe/p_util.h"
#include "draw_private.h"
#include "draw_context.h"
void draw_vertex_cache_invalidate( struct draw_context *draw )
{
assert(draw->pq.queue_nr == 0);
assert(draw->vs.queue_nr == 0);
assert(draw->vcache.referenced == 0);
/* There's an error somewhere in the vcache code that requires this
* memset. The bug is exposed in q3demo demo001, but probably
* elsewhere as well. Will track it down later.
*/
memset(draw->vcache.idx, ~0, sizeof(draw->vcache.idx));
}
/**
* Check if vertex is in cache, otherwise add it. It won't go through
* VS yet, not until there is a flush operation or the VS queue fills up.
*
* Note that cache entries are basically just two pointers: the first
* an index into the user's vertex arrays, the second a location in
* the vertex shader cache for the post-transformed vertex.
*
* \return pointer to location of (post-transformed) vertex header in the cache
*/
static struct vertex_header *get_vertex( struct draw_context *draw,
unsigned i )
{
unsigned slot = (i + (i>>5)) % VCACHE_SIZE;
assert(slot < 32); /* so we don't exceed the bitfield size below */
if (draw->vcache.referenced & (1<<slot))
{
/* Cache hit?
*/
if (draw->vcache.idx[slot].in == i) {
/*debug_printf("HIT %d %d\n", slot, i);*/
assert(draw->vcache.idx[slot].out < draw->vs.queue_nr);
return draw_header_from_block(draw->vs.vertex_cache,
MAX_VERTEX_ALLOCATION,
draw->vcache.idx[slot].out);
}
/* Otherwise a collision
*/
slot = VCACHE_SIZE + draw->vcache.overflow++;
/*debug_printf("XXX %d --> %d\n", i, slot);*/
}
/* Deal with the cache miss:
*/
{
unsigned out;
struct vertex_header *header;
assert(slot < Elements(draw->vcache.idx));
/*debug_printf("NEW %d %d\n", slot, i);*/
draw->vcache.idx[slot].in = i;
draw->vcache.idx[slot].out = out = draw->vs.queue_nr++;
draw->vcache.referenced |= (1 << slot);
/* Add to vertex shader queue:
*/
assert(draw->vs.queue_nr < VS_QUEUE_LENGTH);
header = draw_header_from_block(draw->vs.vertex_cache, MAX_VERTEX_ALLOCATION,
out);
draw->vs.elts[out] = i;
header->clipmask = 0;
header->edgeflag = draw_get_edgeflag(draw, i);
header->pad = 0;
header->vertex_id = UNDEFINED_VERTEX_ID;
/* Need to set the vertex's edge flag here. If we're being called
* by do_ef_triangle(), that function needs edge flag info!
*/
return draw_header_from_block(draw->vs.vertex_cache,
MAX_VERTEX_ALLOCATION,
draw->vcache.idx[slot].out);
}
}
static struct vertex_header *get_uint_elt_vertex( struct draw_context *draw,
unsigned i )
{
const unsigned *elts = (const unsigned *) draw->user.elts;
return get_vertex( draw, elts[i] );
}
static struct vertex_header *get_ushort_elt_vertex( struct draw_context *draw,
unsigned i )
{
const ushort *elts = (const ushort *) draw->user.elts;
return get_vertex( draw, elts[i] );
}
static struct vertex_header *get_ubyte_elt_vertex( struct draw_context *draw,
unsigned i )
{
const ubyte *elts = (const ubyte *) draw->user.elts;
return get_vertex( draw, elts[i] );
}
void draw_vertex_cache_reset_vertex_ids( struct draw_context *draw )
{
unsigned i;
for (i = 0; i < draw->vs.post_nr; i++) {
struct vertex_header * header =
draw_header_from_block(draw->vs.vertex_cache,
MAX_VERTEX_ALLOCATION, i);
header->vertex_id = UNDEFINED_VERTEX_ID;
}
}
void draw_vertex_cache_unreference( struct draw_context *draw )
{
draw->vcache.referenced = 0;
draw->vcache.overflow = 0;
}
int draw_vertex_cache_check_space( struct draw_context *draw,
unsigned nr_verts )
{
if (draw->vcache.overflow + nr_verts < VCACHE_OVERFLOW) {
/* The vs queue is sized so that this can never happen:
*/
assert(draw->vs.queue_nr + nr_verts < VS_QUEUE_LENGTH);
return TRUE;
}
else
return FALSE;
}
/**
* Tell the drawing context about the index/element buffer to use
* (ala glDrawElements)
* If no element buffer is to be used (i.e. glDrawArrays) then this
* should be called with eltSize=0 and elements=NULL.
*
* \param draw the drawing context
* \param eltSize size of each element (1, 2 or 4 bytes)
* \param elements the element buffer ptr
*/
void
draw_set_mapped_element_buffer( struct draw_context *draw,
unsigned eltSize, void *elements )
{
// draw_statechange( draw );
/* choose the get_vertex() function to use */
switch (eltSize) {
case 0:
draw->vcache.get_vertex = get_vertex;
break;
case 1:
draw->vcache.get_vertex = get_ubyte_elt_vertex;
break;
case 2:
draw->vcache.get_vertex = get_ushort_elt_vertex;
break;
case 4:
draw->vcache.get_vertex = get_uint_elt_vertex;
break;
default:
assert(0);
}
draw->user.elts = elements;
draw->user.eltSize = eltSize;
}