Przeglądaj źródła

gallium: rework handling of sprite_coord_enable state

Implement the pipe_rasterizer_state::sprite_coord_enable field
in the draw module (and softpipe) according to what's specified
in the documentation.

The draw module can now add any number of extra vertex attributes
to a post-transformed vertex and generate texcoords for those
attributes per sprite_coord_enable.  Auto-generated texcoords
for sprites only worked for one texcoord unit before.

The frag shader gl_PointCoord input is now implemented like any
other generic/texcoord attribute.

The draw module now needs to be informed about fragment shaders
since we need to look at the fragment shader's inputs to know
which ones need auto-generated texcoords.

Only softpipe has been updated so far.
tags/snb-magic
Brian Paul 15 lat temu
rodzic
commit
e22e3927b0

+ 1
- 0
src/gallium/auxiliary/Makefile Wyświetl plik

@@ -8,6 +8,7 @@ C_SOURCES = \
cso_cache/cso_context.c \
cso_cache/cso_hash.c \
draw/draw_context.c \
draw/draw_fs.c \
draw/draw_gs.c \
draw/draw_pipe.c \
draw/draw_pipe_aaline.c \

+ 1
- 0
src/gallium/auxiliary/SConscript Wyświetl plik

@@ -54,6 +54,7 @@ source = [
'cso_cache/cso_context.c',
'cso_cache/cso_hash.c',
'draw/draw_context.c',
'draw/draw_fs.c',
'draw/draw_gs.c',
'draw/draw_pipe.c',
'draw/draw_pipe_aaline.c',

+ 47
- 9
src/gallium/auxiliary/draw/draw_context.c Wyświetl plik

@@ -413,6 +413,42 @@ draw_set_force_passthrough( struct draw_context *draw, boolean enable )
}



/**
* Allocate an extra vertex/geometry shader vertex attribute.
* This is used by some of the optional draw module stages such
* as wide_point which may need to allocate additional generic/texcoord
* attributes.
*/
int
draw_alloc_extra_vertex_attrib(struct draw_context *draw,
uint semantic_name, uint semantic_index)
{
const int num_outputs = draw_current_shader_outputs(draw);
const int n = draw->extra_shader_outputs.num;

assert(n < Elements(draw->extra_shader_outputs.semantic_name));

draw->extra_shader_outputs.semantic_name[n] = semantic_name;
draw->extra_shader_outputs.semantic_index[n] = semantic_index;
draw->extra_shader_outputs.slot[n] = num_outputs + n;
draw->extra_shader_outputs.num++;

return draw->extra_shader_outputs.slot[n];
}


/**
* Remove all extra vertex attributes that were allocated with
* draw_alloc_extra_vertex_attrib().
*/
void
draw_remove_extra_vertex_attribs(struct draw_context *draw)
{
draw->extra_shader_outputs.num = 0;
}


/**
* Ask the draw module for the location/slot of the given vertex attribute in
* a post-transformed vertex.
@@ -446,12 +482,12 @@ draw_find_shader_output(const struct draw_context *draw,
return i;
}

/* XXX there may be more than one extra vertex attrib.
* For example, simulated gl_FragCoord and gl_PointCoord.
*/
if (draw->extra_shader_outputs.semantic_name == semantic_name &&
draw->extra_shader_outputs.semantic_index == semantic_index) {
return draw->extra_shader_outputs.slot;
/* Search the extra vertex attributes */
for (i = 0; i < draw->extra_shader_outputs.num; i++) {
if (draw->extra_shader_outputs.semantic_name[i] == semantic_name &&
draw->extra_shader_outputs.semantic_index[i] == semantic_index) {
return draw->extra_shader_outputs.slot[i];
}
}

return 0;
@@ -470,16 +506,18 @@ draw_find_shader_output(const struct draw_context *draw,
uint
draw_num_shader_outputs(const struct draw_context *draw)
{
uint count = draw->vs.vertex_shader->info.num_outputs;
uint count;

/* If a geometry shader is present, its outputs go to the
* driver, else the vertex shader's outputs.
*/
if (draw->gs.geometry_shader)
count = draw->gs.geometry_shader->info.num_outputs;
else
count = draw->vs.vertex_shader->info.num_outputs;

count += draw->extra_shader_outputs.num;

if (draw->extra_shader_outputs.slot > 0)
count++;
return count;
}


+ 12
- 0
src/gallium/auxiliary/draw/draw_context.h Wyświetl plik

@@ -46,6 +46,7 @@ struct draw_context;
struct draw_stage;
struct draw_vertex_shader;
struct draw_geometry_shader;
struct draw_fragment_shader;
struct tgsi_sampler;

#define DRAW_MAX_TEXTURE_LEVELS 13 /* 4K x 4K for now */
@@ -137,6 +138,17 @@ void draw_delete_vertex_shader(struct draw_context *draw,
struct draw_vertex_shader *dvs);


/*
* Fragment shader functions
*/
struct draw_fragment_shader *
draw_create_fragment_shader(struct draw_context *draw,
const struct pipe_shader_state *shader);
void draw_bind_fragment_shader(struct draw_context *draw,
struct draw_fragment_shader *dvs);
void draw_delete_fragment_shader(struct draw_context *draw,
struct draw_fragment_shader *dvs);

/*
* Geometry shader functions
*/

+ 4
- 5
src/gallium/auxiliary/draw/draw_pipe_aaline.c Wyświetl plik

@@ -688,10 +688,9 @@ aaline_first_line(struct draw_stage *stage, struct prim_header *header)
aaline->tex_slot = draw_current_shader_outputs(draw);
aaline->pos_slot = draw_current_shader_position_output(draw);;

/* advertise the extra post-transformed vertex attribute */
draw->extra_shader_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
draw->extra_shader_outputs.semantic_index = aaline->fs->generic_attrib;
draw->extra_shader_outputs.slot = aaline->tex_slot;
/* allocate the extra post-transformed vertex attribute */
(void) draw_alloc_extra_vertex_attrib(draw, TGSI_SEMANTIC_GENERIC,
aaline->fs->generic_attrib);

/* how many samplers? */
/* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
@@ -744,7 +743,7 @@ aaline_flush(struct draw_stage *stage, unsigned flags)

draw->suspend_flushing = FALSE;

draw->extra_shader_outputs.slot = 0;
draw_remove_extra_vertex_attribs(draw);
}



+ 4
- 4
src/gallium/auxiliary/draw/draw_pipe_aapoint.c Wyświetl plik

@@ -701,9 +701,9 @@ aapoint_first_point(struct draw_stage *stage, struct prim_header *header)

aapoint->pos_slot = draw_current_shader_position_output(draw);

draw->extra_shader_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
draw->extra_shader_outputs.semantic_index = aapoint->fs->generic_attrib;
draw->extra_shader_outputs.slot = aapoint->tex_slot;
/* allocate the extra post-transformed vertex attribute */
(void) draw_alloc_extra_vertex_attrib(draw, TGSI_SEMANTIC_GENERIC,
aapoint->fs->generic_attrib);

/* find psize slot in post-transform vertex */
aapoint->psize_slot = -1;
@@ -754,7 +754,7 @@ aapoint_flush(struct draw_stage *stage, unsigned flags)

draw->suspend_flushing = FALSE;

draw->extra_shader_outputs.slot = 0;
draw_remove_extra_vertex_attribs(draw);
}



+ 54
- 60
src/gallium/auxiliary/draw/draw_pipe_wide_point.c Wyświetl plik

@@ -57,26 +57,24 @@
#include "util/u_memory.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "draw_fs.h"
#include "draw_vs.h"
#include "draw_pipe.h"


struct widepoint_stage {
struct draw_stage stage;
struct draw_stage stage; /**< base class */

float half_point_size;

float xbias;
float ybias;

uint texcoord_slot[PIPE_MAX_SHADER_OUTPUTS];
uint texcoord_enable[PIPE_MAX_SHADER_OUTPUTS];
uint num_texcoords;
uint texcoord_mode;
/** for automatic texcoord generation/replacement */
uint num_texcoord_gen;
uint texcoord_gen_slot[PIPE_MAX_SHADER_OUTPUTS];

int psize_slot;

int point_coord_fs_input; /**< input for pointcoord */
};


@@ -96,30 +94,20 @@ widepoint_stage( struct draw_stage *stage )
static void set_texcoords(const struct widepoint_stage *wide,
struct vertex_header *v, const float tc[4])
{
const struct draw_context *draw = wide->stage.draw;
const struct pipe_rasterizer_state *rast = draw->rasterizer;
const uint texcoord_mode = rast->sprite_coord_mode;
uint i;
for (i = 0; i < wide->num_texcoords; i++) {
if (wide->texcoord_enable[i]) {
uint j = wide->texcoord_slot[i];
v->data[j][0] = tc[0];
if (wide->texcoord_mode == PIPE_SPRITE_COORD_LOWER_LEFT)
v->data[j][1] = 1.0f - tc[1];
else
v->data[j][1] = tc[1];
v->data[j][2] = tc[2];
v->data[j][3] = tc[3];
}
}

if (wide->point_coord_fs_input >= 0) {
/* put gl_PointCoord into the extra vertex slot */
uint slot = wide->stage.draw->extra_shader_outputs.slot;
for (i = 0; i < wide->num_texcoord_gen; i++) {
const uint slot = wide->texcoord_gen_slot[i];
v->data[slot][0] = tc[0];
if (wide->texcoord_mode == PIPE_SPRITE_COORD_LOWER_LEFT)
if (texcoord_mode == PIPE_SPRITE_COORD_LOWER_LEFT)
v->data[slot][1] = 1.0f - tc[1];
else
v->data[slot][1] = tc[1];
v->data[slot][2] = 0.0F;
v->data[slot][3] = 1.0F;
v->data[slot][2] = tc[2];
v->data[slot][3] = tc[3];
}
}

@@ -201,18 +189,9 @@ static void widepoint_point( struct draw_stage *stage,
}


static int
find_pntc_input_attrib(struct draw_context *draw)
{
/* Scan the fragment program's input decls to find the pointcoord
* attribute. The xy components will store the point coord.
*/
return 0; /* XXX fix this */
}


static void widepoint_first_point( struct draw_stage *stage,
struct prim_header *header )
static void
widepoint_first_point(struct draw_stage *stage,
struct prim_header *header)
{
struct widepoint_stage *wide = widepoint_stage(stage);
struct draw_context *draw = stage->draw;
@@ -244,31 +223,45 @@ static void widepoint_first_point( struct draw_stage *stage,
stage->point = draw_pipe_passthrough_point;
}

draw_remove_extra_vertex_attribs(draw);

if (rast->point_quad_rasterization) {
/* find vertex shader texcoord outputs */
const struct draw_vertex_shader *vs = draw->vs.vertex_shader;
uint i, j = 0;
wide->texcoord_mode = rast->sprite_coord_mode;
for (i = 0; i < vs->info.num_outputs; i++) {
if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_GENERIC) {
wide->texcoord_slot[j] = i;
wide->texcoord_enable[j] = (rast->sprite_coord_enable >> j) & 1;
j++;
const struct draw_fragment_shader *fs = draw->fs.fragment_shader;
uint i;

wide->num_texcoord_gen = 0;

/* Loop over fragment shader inputs looking for generic inputs
* for which bit 'k' in sprite_coord_enable is set.
*/
for (i = 0; i < fs->info.num_inputs; i++) {
if (fs->info.input_semantic_name[i] == TGSI_SEMANTIC_GENERIC) {
const int generic_index = fs->info.input_semantic_index[i];
if (rast->sprite_coord_enable & (1 << generic_index)) {
/* OK, this generic attribute needs to be replaced with a
* texcoord (see above).
*/
int slot = draw_find_shader_output(draw,
TGSI_SEMANTIC_GENERIC,
generic_index);

if (slot > 0) {
/* there's already a post-vertex shader attribute
* for this fragment shader input attribute.
*/
}
else {
/* need to allocate a new post-vertex shader attribute */
slot = draw_alloc_extra_vertex_attrib(draw,
TGSI_SEMANTIC_GENERIC,
generic_index);
}

/* add this slot to the texcoord-gen list */
wide->texcoord_gen_slot[wide->num_texcoord_gen++] = slot;
}
}
}
wide->num_texcoords = j;

/* find fragment shader PointCoord input */
wide->point_coord_fs_input = find_pntc_input_attrib(draw);

/* setup extra vp output (point coord implemented as a texcoord) */
draw->extra_shader_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
draw->extra_shader_outputs.semantic_index = 0;
draw->extra_shader_outputs.slot = draw_current_shader_outputs(draw);
}
else {
wide->point_coord_fs_input = -1;
draw->extra_shader_outputs.slot = 0;
}

wide->psize_slot = -1;
@@ -295,7 +288,8 @@ static void widepoint_flush( struct draw_stage *stage, unsigned flags )

stage->point = widepoint_first_point;
stage->next->flush( stage->next, flags );
stage->draw->extra_shader_outputs.slot = 0;

draw_remove_extra_vertex_attribs(draw);

/* restore original rasterizer state */
if (draw->rast_handle) {

+ 14
- 3
src/gallium/auxiliary/draw/draw_private.h Wyświetl plik

@@ -250,6 +250,11 @@ struct draw_context
struct tgsi_sampler **samplers;
} gs;

/** Fragment shader state */
struct {
struct draw_fragment_shader *fragment_shader;
} fs;

/** Stream output (vertex feedback) state */
struct {
struct pipe_stream_output_state state;
@@ -266,9 +271,10 @@ struct draw_context
/* If a prim stage introduces new vertex attributes, they'll be stored here
*/
struct {
uint semantic_name;
uint semantic_index;
int slot;
uint num;
uint semantic_name[10];
uint semantic_index[10];
uint slot[10];
} extra_shader_outputs;

unsigned reduced_prim;
@@ -362,6 +368,11 @@ void draw_gs_destroy( struct draw_context *draw );
uint draw_current_shader_outputs(const struct draw_context *draw);
uint draw_current_shader_position_output(const struct draw_context *draw);

int draw_alloc_extra_vertex_attrib(struct draw_context *draw,
uint semantic_name, uint semantic_index);
void draw_remove_extra_vertex_attribs(struct draw_context *draw);


/*******************************************************************************
* Vertex processing (was passthrough) code:
*/

+ 2
- 0
src/gallium/drivers/softpipe/sp_state.h Wyświetl plik

@@ -70,6 +70,8 @@ struct sp_fragment_shader {

struct tgsi_shader_info info;

struct draw_fragment_shader *draw_shader;

boolean origin_lower_left; /**< fragment shader uses lower left position origin? */
boolean pixel_center_integer; /**< fragment shader uses integer pixel center? */


+ 14
- 1
src/gallium/drivers/softpipe/sp_state_fs.c Wyświetl plik

@@ -60,7 +60,15 @@ softpipe_create_fs_state(struct pipe_context *pipe,
state = softpipe_create_fs_exec( softpipe, templ );
}

assert(state);
if (!state)
return NULL;

/* draw's fs state */
state->draw_shader = draw_create_fragment_shader(softpipe->draw, templ);
if (!state->draw_shader) {
state->delete( state );
return NULL;
}

/* get/save the summary info for this shader */
tgsi_scan_shader(templ->tokens, &state->info);
@@ -90,6 +98,9 @@ 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));

softpipe->dirty |= SP_NEW_FS;
}

@@ -109,6 +120,8 @@ softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
tgsi_exec_machine_bind_shader(softpipe->fs_machine, NULL, 0, NULL);
}

draw_delete_fragment_shader(softpipe->draw, state->draw_shader);

state->delete( state );
}


+ 14
- 0
src/mesa/state_tracker/st_atom_rasterizer.c Wyświetl plik

@@ -60,6 +60,7 @@ static void update_raster_state( struct st_context *st )
GLcontext *ctx = st->ctx;
struct pipe_rasterizer_state *raster = &st->state.rasterizer;
const struct gl_vertex_program *vertProg = ctx->VertexProgram._Current;
const struct gl_fragment_program *fragProg = ctx->FragmentProgram._Current;
uint i;

memset(raster, 0, sizeof(*raster));
@@ -175,17 +176,30 @@ static void update_raster_state( struct st_context *st )
if (!ctx->Point.PointSprite && ctx->Point.SmoothFlag)
raster->point_smooth = 1;

/* _NEW_POINT | _NEW_PROGRAM
*/
if (ctx->Point.PointSprite) {
/* origin */
if ((ctx->Point.SpriteOrigin == GL_UPPER_LEFT) ^
(st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM))
raster->sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT;
else
raster->sprite_coord_mode = PIPE_SPRITE_COORD_LOWER_LEFT;

/* Coord replacement flags. If bit 'k' is set that means
* that we need to replace GENERIC[k] attrib with an automatically
* computed texture coord.
*/
for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
if (ctx->Point.CoordReplace[i]) {
raster->sprite_coord_enable |= 1 << i;
}
}
if (fragProg->Base.InputsRead & FRAG_BIT_PNTC) {
raster->sprite_coord_enable |=
1 << (FRAG_ATTRIB_PNTC - FRAG_ATTRIB_TEX0);
}

raster->point_quad_rasterization = 1;
}


+ 5
- 12
src/mesa/state_tracker/st_program.c Wyświetl plik

@@ -338,17 +338,6 @@ st_translate_fragment_program(struct st_context *st,
input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
break;
case FRAG_ATTRIB_PNTC:
/* This is a hack. We really need a new semantic label for
* point coord. The draw module needs to know which fragment
* shader input is the point coord attribute so that it can set
* up the right vertex attribute values.
*/
input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
break;

/* In most cases, there is nothing special about these
* inputs, so adopt a convention to use the generic
* semantic name and the mesa FRAG_ATTRIB_ number as the
@@ -364,6 +353,7 @@ st_translate_fragment_program(struct st_context *st,
* zero or be restricted to a particular range -- nobody
* should be building tables based on semantic index.
*/
case FRAG_ATTRIB_PNTC:
case FRAG_ATTRIB_TEX0:
case FRAG_ATTRIB_TEX1:
case FRAG_ATTRIB_TEX2:
@@ -380,7 +370,10 @@ st_translate_fragment_program(struct st_context *st,
assert(attr >= FRAG_ATTRIB_TEX0);
input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);
input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
if (attr == FRAG_ATTRIB_PNTC)
interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
else
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
break;
}
}

Ładowanie…
Anuluj
Zapisz