Previously, programs were translated independently during validation.
The problem is the translation to TGSI format, which packs shader
input/outputs into continuous slots, depends on which vertex program is
being paired with which fragment shader. Now, we look at the outputs
of the vertex program in conjunction with the inputs of the fragment shader
to be sure the attributes match up correctly.
The new 'linked_program_pair' class keeps track of the associations
between vertex and fragment shaders. It's also the place where the TGSI
tokens are kept since they're no longer per-program state but per-linkage.
Still a few loose ends, like implementing some kind of hash/lookup table
for linked_program_pairs.
* we can either address output buffer 0 (for interleaving) or
* output buffer i (for non-interleaved).
*/
-#if 0
for (i = 0; i < feedback->num_attribs; i++) {
- const uint attr = feedback->attrib[i];
- const uint slot = stage->draw->vertex_info.attrib_to_slot[attr];
- const float *src = attr ? vertex->data[slot] : vertex->clip;
+ const uint slot = feedback->attrib[i];
+ const float *src = slot ? vertex->data[slot] : vertex->clip;
const uint size = feedback->size[i];
float *dest = fs->dest[i * select];
}
fs->dest[i * select] += size;
}
-#endif
fs->num_vert_emitted++;
}
{\r
struct tgsi_full_declaration decl;\r
\r
+ assert(semantic_name < TGSI_SEMANTIC_COUNT);\r
+\r
decl = tgsi_default_full_declaration();\r
decl.Declaration.File = TGSI_FILE_INPUT;\r
decl.Declaration.Declare = TGSI_DECLARE_RANGE;\r
{\r
struct tgsi_full_declaration decl;\r
\r
+ assert(semantic_name < TGSI_SEMANTIC_COUNT);\r
+\r
decl = tgsi_default_full_declaration();\r
decl.Declaration.File = TGSI_FILE_OUTPUT;\r
decl.Declaration.Declare = TGSI_DECLARE_RANGE;\r
state_tracker/st_atom_depth.c \
state_tracker/st_atom_fixedfunction.c \
state_tracker/st_atom_framebuffer.c \
- state_tracker/st_atom_fs.c \
state_tracker/st_atom_sampler.c \
state_tracker/st_atom_scissor.c \
+ state_tracker/st_atom_shader.c \
state_tracker/st_atom_rasterizer.c \
state_tracker/st_atom_stipple.c \
state_tracker/st_atom_texture.c \
state_tracker/st_atom_viewport.c \
- state_tracker/st_atom_vs.c \
state_tracker/st_cb_bufferobjects.c \
state_tracker/st_cb_clear.c \
state_tracker/st_cb_flush.c \
state_tracker/st_context.c \
state_tracker/st_draw.c \
state_tracker/st_format.c \
+ state_tracker/st_program.c \
state_tracker/st_mipmap_tree.c
SHADER_SOURCES = \
&st_update_clip,
&st_update_tnl,
- &st_update_vs,
- &st_update_fs,
+ &st_update_shader,
&st_update_rasterizer,
&st_update_polygon_stipple,
const struct st_tracked_state st_update_clear_color;
const struct st_tracked_state st_update_depth_stencil;
const struct st_tracked_state st_update_tnl;
-const struct st_tracked_state st_update_fs;
-const struct st_tracked_state st_update_vs;
+const struct st_tracked_state st_update_shader;
const struct st_tracked_state st_update_rasterizer;
const struct st_tracked_state st_update_polygon_stipple;
const struct st_tracked_state st_update_viewport;
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
- /*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- * Brian Paul
- */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
#include "shader/prog_parameter.h"
/**
* Translate a Mesa fragment shader into a TGSI shader.
+ * \param inputMapping to map fragment program input registers to TGSI
+ * input slots
+ * \param tokensOut destination for TGSI tokens
* \return pointer to cached pipe_shader object.
*/
const struct cso_fragment_shader *
-st_translate_fragment_shader(struct st_context *st,
- struct st_fragment_program *stfp)
+st_translate_fragment_shader(const struct st_context *st,
+ struct st_fragment_program *stfp,
+ const GLuint inputMapping[],
+ struct tgsi_token *tokensOut,
+ GLuint maxTokens)
{
GLuint outputMapping[FRAG_RESULT_MAX];
- GLuint inputMapping[PIPE_MAX_SHADER_INPUTS];
+ GLuint defaultInputMapping[FRAG_ATTRIB_MAX];
struct pipe_shader_state fs;
const struct cso_fragment_shader *cso;
GLuint interpMode[16]; /* XXX size? */
/* Check if all fragment programs need the fragment position (in order
* to do perspective-corrected interpolation).
*/
+ /* XXX temporary! */
if (st->pipe->get_param(st->pipe, PIPE_PARAM_FS_NEEDS_POS))
inputsRead |= FRAG_BIT_WPOS;
*/
for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
if (inputsRead & (1 << attr)) {
- inputMapping[attr] = fs.num_inputs;
+ const GLuint slot = fs.num_inputs;
+
+ fs.num_inputs++;
+
+ defaultInputMapping[attr] = slot;
switch (attr) {
case FRAG_ATTRIB_WPOS:
- fs.input_semantic_name[fs.num_inputs] = TGSI_SEMANTIC_POSITION;
- fs.input_semantic_index[fs.num_inputs] = 0;
- interpMode[fs.num_inputs] = TGSI_INTERPOLATE_CONSTANT;
+ fs.input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ fs.input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
break;
case FRAG_ATTRIB_COL0:
- fs.input_semantic_name[fs.num_inputs] = TGSI_SEMANTIC_COLOR;
- fs.input_semantic_index[fs.num_inputs] = 0;
- interpMode[fs.num_inputs] = TGSI_INTERPOLATE_LINEAR;
+ fs.input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ fs.input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
break;
case FRAG_ATTRIB_COL1:
- fs.input_semantic_name[fs.num_inputs] = TGSI_SEMANTIC_COLOR;
- fs.input_semantic_index[fs.num_inputs] = 1;
- interpMode[fs.num_inputs] = TGSI_INTERPOLATE_LINEAR;
+ fs.input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ fs.input_semantic_index[slot] = 1;
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
break;
case FRAG_ATTRIB_FOGC:
- fs.input_semantic_name[fs.num_inputs] = TGSI_SEMANTIC_FOG;
- fs.input_semantic_index[fs.num_inputs] = 0;
- interpMode[fs.num_inputs] = TGSI_INTERPOLATE_PERSPECTIVE;
+ fs.input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ fs.input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
break;
case FRAG_ATTRIB_TEX0:
case FRAG_ATTRIB_TEX1:
case FRAG_ATTRIB_TEX5:
case FRAG_ATTRIB_TEX6:
case FRAG_ATTRIB_TEX7:
- fs.input_semantic_name[fs.num_inputs] = TGSI_SEMANTIC_GENERIC;
- fs.input_semantic_index[fs.num_inputs] = attr - FRAG_ATTRIB_TEX0;
- interpMode[fs.num_inputs] = TGSI_INTERPOLATE_PERSPECTIVE;
+ fs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ fs.input_semantic_index[slot] = attr - FRAG_ATTRIB_TEX0;
+ interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
break;
case FRAG_ATTRIB_VAR0:
/* fall-through */
default:
- fs.input_semantic_name[fs.num_inputs] = TGSI_SEMANTIC_GENERIC;
- fs.input_semantic_index[fs.num_inputs] = attr - FRAG_ATTRIB_VAR0;
- interpMode[fs.num_inputs] = TGSI_INTERPOLATE_PERSPECTIVE;
+ fs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ fs.input_semantic_index[slot] = attr - FRAG_ATTRIB_VAR0;
+ interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
}
-
- fs.num_inputs++;
}
}
}
}
+ if (!inputMapping)
+ inputMapping = defaultInputMapping;
+
/* XXX: fix static allocation of tokens:
*/
tgsi_mesa_compile_fp_program( &stfp->Base,
+ /* inputs */
fs.num_inputs,
inputMapping,
fs.input_semantic_name,
fs.input_semantic_index,
interpMode,
+ /* outputs */
outputMapping,
- stfp->tokens, ST_FP_MAX_TOKENS );
+ /* tokenized result */
+ tokensOut, maxTokens);
+
- fs.tokens = &stfp->tokens[0];
+ fs.tokens = tokensOut;
cso = st_cached_fs_state(st, &fs);
stfp->fs = cso;
if (TGSI_DEBUG)
- tgsi_dump( stfp->tokens, 0/*TGSI_DUMP_VERBOSE*/ );
+ tgsi_dump( tokensOut, 0/*TGSI_DUMP_VERBOSE*/ );
#if defined(USE_X86_ASM) || defined(SLANG_X86)
if (stfp->sse2_program.csr == stfp->sse2_program.store)
- tgsi_emit_sse2_fs( stfp->tokens, &stfp->sse2_program );
+ tgsi_emit_sse2_fs( tokensOut, &stfp->sse2_program );
if (!cso->state.executable)
((struct cso_fragment_shader*)cso)->state.executable = (void *) x86_get_func( &stfp->sse2_program );
#endif
- stfp->dirty = 0;
-
return cso;
}
}
/* if new binding, or shader has changed */
- if (st->fp != stfp || stfp->dirty) {
+ if (st->fp != stfp /**|| stfp->dirty**/) {
+#if 0
if (stfp->dirty)
(void) st_translate_fragment_shader( st, stfp );
st->state.fs = stfp->fs;
st->pipe->bind_fs_state(st->pipe, st->state.fs->data);
+#else
+
+ /* NEW */
+ st->dirty.st |= ST_NEW_LINKAGE;
+
+#endif
}
}
+#if 0
const struct st_tracked_state st_update_fs = {
.name = "st_update_fs",
.dirty = {
},
.update = update_fs
};
+#endif
/**
* Translate a Mesa vertex shader into a TGSI shader.
+ * \param outputMapping to map vertex program output registers to TGSI
+ * output slots
+ * \param tokensOut destination for TGSI tokens
* \return pointer to cached pipe_shader object.
*/
const struct cso_vertex_shader *
-st_translate_vertex_shader(struct st_context *st,
- struct st_vertex_program *stvp)
+st_translate_vertex_shader(const struct st_context *st,
+ struct st_vertex_program *stvp,
+ const GLuint outputMapping[],
+ struct tgsi_token *tokensOut,
+ GLuint maxTokens)
{
+ GLuint defaultOutputMapping[VERT_RESULT_MAX];
struct pipe_shader_state vs;
const struct cso_vertex_shader *cso;
- GLuint attr;
+ GLuint attr, i;
memset(&vs, 0, sizeof(vs));
*/
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
if (stvp->Base.Base.InputsRead & (1 << attr)) {
- stvp->input_to_index[attr] = vs.num_inputs;
- stvp->index_to_input[vs.num_inputs] = attr;
+ const GLuint slot = vs.num_inputs;
+
+ vs.num_inputs++;
+
+ stvp->input_to_index[attr] = slot;
+ stvp->index_to_input[slot] = attr;
+
switch (attr) {
case VERT_ATTRIB_POS:
- vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_POSITION;
- vs.input_semantic_index[vs.num_inputs] = 0;
+ vs.input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ vs.input_semantic_index[slot] = 0;
break;
case VERT_ATTRIB_WEIGHT:
/* fall-through */
case VERT_ATTRIB_NORMAL:
/* just label as a generic */
- vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_GENERIC;
- vs.input_semantic_index[vs.num_inputs] = 0;
+ vs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs.input_semantic_index[slot] = 0;
break;
case VERT_ATTRIB_COLOR0:
- vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_COLOR;
- vs.input_semantic_index[vs.num_inputs] = 0;
+ vs.input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ vs.input_semantic_index[slot] = 0;
break;
case VERT_ATTRIB_COLOR1:
- vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_COLOR;
- vs.input_semantic_index[vs.num_inputs] = 1;
+ vs.input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ vs.input_semantic_index[slot] = 1;
break;
case VERT_ATTRIB_FOG:
- vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_FOG;
- vs.input_semantic_index[vs.num_inputs] = 0;
+ vs.input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ vs.input_semantic_index[slot] = 0;
break;
case VERT_ATTRIB_TEX0:
case VERT_ATTRIB_TEX1:
case VERT_ATTRIB_TEX5:
case VERT_ATTRIB_TEX6:
case VERT_ATTRIB_TEX7:
- vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_GENERIC;
- vs.input_semantic_index[vs.num_inputs] = attr - VERT_ATTRIB_TEX0;
+ vs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs.input_semantic_index[slot] = attr - VERT_ATTRIB_TEX0;
break;
case VERT_ATTRIB_GENERIC0:
case VERT_ATTRIB_GENERIC1:
case VERT_ATTRIB_GENERIC6:
case VERT_ATTRIB_GENERIC7:
assert(attr < VERT_ATTRIB_MAX);
- vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_GENERIC;
- vs.input_semantic_index[vs.num_inputs] = attr - VERT_ATTRIB_GENERIC0;
+ vs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs.input_semantic_index[slot] = attr - VERT_ATTRIB_GENERIC0;
break;
default:
assert(0);
}
- vs.num_inputs++;
}
}
+ /* initialize output semantics to defaults */
+ for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
+ vs.output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
+ vs.output_semantic_index[i] = 0;
+ }
+
/*
- * Determine number of outputs, the register mapping and
- * the semantic information for each vertex output/result.
+ * Determine number of outputs, the (default) output register
+ * mapping and the semantic information for each output.
*/
for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
if (stvp->Base.Base.OutputsWritten & (1 << attr)) {
- /* put this attrib in the next available slot */
- st->vertex_attrib_to_slot[attr] = vs.num_outputs;
+ GLuint slot;
+
+ if (outputMapping) {
+ slot = outputMapping[attr];
+ assert(slot != ~0);
+ }
+ else {
+ slot = vs.num_outputs;
+ vs.num_outputs++;
+ defaultOutputMapping[attr] = slot;
+ }
+
+ /*
+ printf("Output %u -> slot %u\n", attr, slot);
+ */
switch (attr) {
case VERT_RESULT_HPOS:
- vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_POSITION;
- vs.output_semantic_index[vs.num_outputs] = 0;
+ vs.output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ vs.output_semantic_index[slot] = 0;
break;
case VERT_RESULT_COL0:
- vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_COLOR;
- vs.output_semantic_index[vs.num_outputs] = 0;
+ vs.output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ vs.output_semantic_index[slot] = 0;
break;
case VERT_RESULT_COL1:
- vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_COLOR;
- vs.output_semantic_index[vs.num_outputs] = 1;
+ vs.output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ vs.output_semantic_index[slot] = 1;
break;
case VERT_RESULT_BFC0:
- vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_BCOLOR;
- vs.output_semantic_index[vs.num_outputs] = 0;
+ vs.output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+ vs.output_semantic_index[slot] = 0;
break;
case VERT_RESULT_BFC1:
- vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_BCOLOR;
- vs.output_semantic_index[vs.num_outputs] = 1;
+ vs.output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+ vs.output_semantic_index[slot] = 1;
break;
case VERT_RESULT_FOGC:
- vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_FOG;
- vs.output_semantic_index[vs.num_outputs] = 0;
+ vs.output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ vs.output_semantic_index[slot] = 0;
break;
case VERT_RESULT_PSIZ:
- vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_PSIZE;
- vs.output_semantic_index[vs.num_outputs] = 0;
+ vs.output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
+ vs.output_semantic_index[slot] = 0;
break;
case VERT_RESULT_EDGE:
assert(0);
case VERT_RESULT_TEX5:
case VERT_RESULT_TEX6:
case VERT_RESULT_TEX7:
- vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_GENERIC;
- vs.output_semantic_index[vs.num_outputs] = attr - VERT_RESULT_TEX0;
+ vs.output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs.output_semantic_index[slot] = attr - VERT_RESULT_TEX0;
break;
case VERT_RESULT_VAR0:
/* fall-through */
default:
assert(attr - VERT_RESULT_VAR0 < MAX_VARYING);
- vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_GENERIC;
- vs.output_semantic_index[vs.num_outputs] = attr - VERT_RESULT_VAR0;
+ vs.output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs.output_semantic_index[slot] = attr - VERT_RESULT_VAR0;
}
-
- vs.num_outputs++;
}
}
+ if (outputMapping) {
+ /* find max output slot referenced to compute vs.num_outputs */
+ GLuint maxSlot = 0;
+ for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
+ if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
+ maxSlot = outputMapping[attr];
+ }
+ vs.num_outputs = maxSlot + 1;
+ }
+ else {
+ outputMapping = defaultOutputMapping;
+ }
+
/* XXX: fix static allocation of tokens:
*/
tgsi_mesa_compile_vp_program( &stvp->Base,
+ /* inputs */
vs.num_inputs,
stvp->input_to_index,
vs.input_semantic_name,
vs.input_semantic_index,
+ /* outputs */
vs.num_outputs,
- st->vertex_attrib_to_slot,
+ outputMapping,
vs.output_semantic_name,
vs.output_semantic_index,
- stvp->tokens, ST_FP_MAX_TOKENS );
-
- vs.tokens = &stvp->tokens[0];
+ /* tokenized result */
+ tokensOut, maxTokens);
+ vs.tokens = tokensOut;
cso = st_cached_vs_state(st, &vs);
stvp->vs = cso;
if (TGSI_DEBUG)
- tgsi_dump( stvp->tokens, 0 );
+ tgsi_dump( tokensOut, 0 );
#if defined(USE_X86_ASM) || defined(SLANG_X86)
if (stvp->sse2_program.csr == stvp->sse2_program.store)
- tgsi_emit_sse2( stvp->tokens, &stvp->sse2_program );
+ tgsi_emit_sse2( tokensOut, &stvp->sse2_program );
if (!cso->state.executable)
((struct cso_vertex_shader*)cso)->state.executable = (void *) x86_get_func( &stvp->sse2_program );
}
if (st->vp != stvp || stvp->dirty) {
+#if 0
if (stvp->dirty)
(void) st_translate_vertex_shader( st, stvp );
tgsi_dump( stvp->tokens, 0 );
#endif
st->pipe->bind_vs_state(st->pipe, st->state.vs->data);
+#else
+ /* NEW */
+ st->dirty.st |= ST_NEW_LINKAGE;
+
+#endif
}
}
-
+#if 0
const struct st_tracked_state st_update_vs = {
.name = "st_update_vs",
.dirty = {
},
.update = update_vs
};
-
-
-
-
+#endif
p->OutputsWritten = (1 << FRAG_RESULT_COLR);
stfp = (struct st_fragment_program *) p;
- st_translate_fragment_shader(st, stfp);
+ st_translate_fragment_program(st, stfp, NULL,
+ stfp->tokens, ST_FP_MAX_TOKENS);
return stfp;
}
(1 << VERT_RESULT_HPOS));
stvp = (struct st_vertex_program *) p;
- st_translate_vertex_shader(st, stvp);
+ st_translate_vertex_program(st, stvp, NULL,
+ stvp->tokens, ST_FP_MAX_TOKENS);
assert(stvp->vs);
return stvp;
p->OutputsWritten = (1 << FRAG_RESULT_COLR);
stfp = (struct st_fragment_program *) p;
- st_translate_fragment_shader(st, stfp);
+ st_translate_fragment_program(st, stfp, NULL,
+ stfp->tokens, ST_FP_MAX_TOKENS);
return stfp;
}
(1 << VERT_RESULT_HPOS));
stvp = (struct st_vertex_program *) p;
- st_translate_vertex_shader(st, stvp);
+ st_translate_vertex_program(st, stvp, NULL,
+ stvp->tokens, ST_FP_MAX_TOKENS);
return stvp;
}
* color and texcoord attribs to use here.
*/
- slot = st->vertex_attrib_to_slot[VERT_RESULT_COL0];
+ slot = st->vertex_result_to_slot[VERT_RESULT_COL0];
if (slot)
color = v->data[slot];
else
color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
- slot = st->vertex_attrib_to_slot[VERT_RESULT_TEX0];
+ slot = st->vertex_result_to_slot[VERT_RESULT_TEX0];
if (slot)
texcoord = v->data[slot];
else
* Keith Whitwell <keith@tungstengraphics.com>
*/
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/program.h"
+#include "shader/programopt.h"
+
#include "st_context.h"
-#include "st_program.h"
-#include "glheader.h"
-#include "macros.h"
-#include "enums.h"
-#include "prog_instruction.h"
-#include "prog_parameter.h"
-#include "program.h"
-#include "programopt.h"
+#include "st_program.h"
+#include "st_atom_shader.h"
+
#include "tnl/tnl.h"
#include "pipe/tgsi/mesa/tgsi_mesa.h"
-/* Counter to track program string changes:
+/**
+ * Called via ctx->Driver.BindProgram() to bind an ARB vertex or
+ * fragment program.
*/
-static GLuint program_id = 0;
-
-
static void st_bind_program( GLcontext *ctx,
GLenum target,
struct gl_program *prog )
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
break;
}
+ st->dirty.st |= ST_NEW_LINKAGE;
}
+
+/**
+ * Called via ctx->Driver.UseProgram() to bind a linked GLSL program
+ * (vertex shader + fragment shader).
+ */
static void st_use_program( GLcontext *ctx,
GLuint program )
{
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+ st->dirty.st |= ST_NEW_LINKAGE;
}
GLenum target,
GLuint id )
{
-// struct st_context *st = st_context(ctx);
+ struct st_context *st = st_context(ctx);
switch (target) {
case GL_VERTEX_PROGRAM_ARB: {
struct st_vertex_program *prog = CALLOC_STRUCT(st_vertex_program);
- prog->id = program_id++;
- prog->dirty = 1;
+ prog->serialNo = 1;
#if defined(USE_X86_ASM) || defined(SLANG_X86)
x86_init_func( &prog->sse2_program );
case GL_FRAGMENT_PROGRAM_NV: {
struct st_fragment_program *prog = CALLOC_STRUCT(st_fragment_program);
- prog->id = program_id++;
- prog->dirty = 1;
+ prog->serialNo = 1;
#if defined(USE_X86_ASM) || defined(SLANG_X86)
x86_init_func( &prog->sse2_program );
default:
return _mesa_new_program(ctx, target, id);
}
+
+ st->dirty.st |= ST_NEW_LINKAGE;
}
+
static void st_delete_program( GLcontext *ctx,
struct gl_program *prog )
{
+ struct st_context *st = st_context(ctx);
+
switch( prog->Target ) {
- case GL_VERTEX_PROGRAM_ARB: {
+ case GL_VERTEX_PROGRAM_ARB:
+ {
+ struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
#if defined(USE_X86_ASM) || defined(SLANG_X86)
- struct st_vertex_program *p = (struct st_vertex_program *) prog;
-
- x86_release_func( &p->sse2_program );
+ x86_release_func( &stvp->sse2_program );
#endif
+ st_remove_vertex_program(st, stvp);
+ }
break;
- }
- case GL_FRAGMENT_PROGRAM_ARB: {
+ case GL_FRAGMENT_PROGRAM_ARB:
+ {
+ struct st_fragment_program *stfp
+ = (struct st_fragment_program *) prog;
#if defined(USE_X86_ASM) || defined(SLANG_X86)
- struct st_fragment_program *p = (struct st_fragment_program *) prog;
-
- x86_release_func( &p->sse2_program );
+ x86_release_func( &stfp->sse2_program );
#endif
+ st_remove_fragment_program(st, stfp);
+ }
break;
+ default:
+ assert(0); /* problem */
}
- }
+
_mesa_delete_program( ctx, prog );
}
struct st_context *st = st_context(ctx);
if (target == GL_FRAGMENT_PROGRAM_ARB) {
- struct st_fragment_program *p = (struct st_fragment_program *)prog;
+ struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
if (prog == &ctx->FragmentProgram._Current->Base)
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
- p->id = program_id++;
- p->param_state = p->Base.Base.Parameters->StateFlags;
+ stfp->serialNo++;
+
+ stfp->param_state = stfp->Base.Base.Parameters->StateFlags;
}
else if (target == GL_VERTEX_PROGRAM_ARB) {
- struct st_vertex_program *p = (struct st_vertex_program *)prog;
+ struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
if (prog == &ctx->VertexProgram._Current->Base)
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
- p->id = program_id++;
- p->param_state = p->Base.Base.Parameters->StateFlags;
+ stvp->serialNo++;
+
+ stvp->param_state = stvp->Base.Base.Parameters->StateFlags;
/* Also tell tnl about it:
*/
_tnl_program_string(ctx, target, prog);
}
+
+ st->dirty.st |= ST_NEW_LINKAGE;
}
setup_vertex_attribs(GLcontext *ctx)
{
struct pipe_context *pipe = ctx->st->pipe;
-#if 0
- const uint inputAttrs = ctx->st->state.vs->inputs_read;
- uint attr;
+ const struct cso_vertex_shader *vs = ctx->st->state.vs;
+ const struct st_vertex_program *stvp = ctx->st->vp;
+ uint slot;
/* all attributes come from the default attribute buffer */
{
pipe->set_vertex_buffer(pipe, 0, &vbuffer);
}
- for (attr = 0; attr < 16; attr++) {
+ for (slot = 0; slot < vs->state.num_inputs; slot++) {
struct pipe_vertex_element velement;
+ const GLuint attr = stvp->index_to_input[slot];
- if (inputAttrs & (1 << attr)) {
- velement.src_offset = attr * 4 * sizeof(GLfloat);
- velement.vertex_buffer_index = 0;
- velement.dst_offset = 0;
- velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
- pipe->set_vertex_element(pipe, attr, &velement);
- }
+ velement.src_offset = attr * 4 * sizeof(GLfloat);
+ velement.vertex_buffer_index = 0;
+ velement.dst_offset = 0;
+ velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ pipe->set_vertex_element(pipe, slot, &velement);
}
-#else
- assert(0);
-#endif
}
feedback.discard = 1;
feedback.num_attribs = 0;
+ /* feedback all results from vertex shader */
for (i = 0; i < vs->num_outputs; i++) {
- if (1/***(1 << i) & outputAttrs***/) {
- feedback.attrib[feedback.num_attribs] = i;
- feedback.size[feedback.num_attribs] = 4;
- feedback.num_attribs++;
- }
+ feedback.attrib[feedback.num_attribs] = i;
+ feedback.size[feedback.num_attribs] = 4;
+ feedback.num_attribs++;
}
pipe->set_feedback_state(pipe, &feedback);
static void
st_RasterPos(GLcontext *ctx, const GLfloat v[4])
{
- struct pipe_context *pipe = ctx->st->pipe;
+ const struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
float *buf_map;
struct pipe_feedback_buffer fb_buf;
- /** XXX TEMPORARILY DISABLE */
- return;
-
st_validate_state(ctx->st);
/* setup vertex buffers */
* Load the default attribute buffer with current attribs.
*/
{
- struct pipe_buffer_handle *buf = ctx->st->default_attrib_buffer;
+ struct pipe_buffer_handle *buf = st->default_attrib_buffer;
const unsigned size = sizeof(ctx->Current.Attrib);
const void *data = ctx->Current.Attrib;
/* colors, texcoords, etc */
PIPE_BUFFER_FLAG_READ);
/* extract values and update rasterpos state */
-#if 0 /* XXX update */
{
- const uint outputAttrs = ctx->st->state.vs->outputs_written;
+ const GLuint *outputMapping = st->vertex_result_to_slot;
const float *pos, *color0, *color1, *tex0;
float *buf = buf_map;
- assert(outputAttrs & (1 << TGSI_ATTRIB_POS));
+ assert(outputMapping[VERT_RESULT_HPOS] != ~0);
pos = buf;
buf += 4;
- if (outputAttrs & (1 << TGSI_ATTRIB_COLOR0)) {
+ if (outputMapping[VERT_RESULT_COL0] != ~0) {
color0 = buf;
buf += 4;
}
color0 = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
}
- if (outputAttrs & (1 << TGSI_ATTRIB_COLOR1)) {
+ if (outputMapping[VERT_RESULT_COL1] != ~0) {
color1 = buf;
buf += 4;
}
color1 = ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
}
+ if (outputMapping[VERT_RESULT_TEX0] != ~0) {
+ tex0 = buf;
+ buf += 4;
+ }
+ else {
+ tex0 = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+ }
+
update_rasterpos(ctx, pos, color0, color1, tex0);
}
-#endif
/* free vertex feedback buffer */
pipe->winsys->buffer_unmap(pipe->winsys, fb_buf.buffer);
pipe->winsys->buffer_reference(pipe->winsys, &fb_buf.buffer, NULL);
/* restore pipe state */
- pipe->set_feedback_state(pipe, &ctx->st->state.feedback);
+ pipe->set_feedback_state(pipe, &st->state.feedback);
}
#define ST_NEW_MESA 0x1 /* Mesa state has changed */
#define ST_NEW_FRAGMENT_PROGRAM 0x2
#define ST_NEW_VERTEX_PROGRAM 0x4
+#define ST_NEW_LINKAGE 0x8
+
struct st_state_flags {
GLuint mesa;
GLfloat polygon_offset_scale; /* ?? */
- /** Mapping from VERT_ATTRIB_x to post-transformed vertex slot */
- GLuint vertex_attrib_to_slot[VERT_RESULT_MAX];
+ /** Mapping from VERT_RESULT_x to post-transformed vertex slot */
+ const GLuint *vertex_result_to_slot;
struct st_vertex_program *vp; /**< Currently bound vertex program */
struct st_fragment_program *fp; /**< Currently bound fragment program */
{
struct gl_fragment_program Base;
GLboolean error; /* If program is malformed for any reason. */
- GLuint id; /**< String id, for tracking ProgramStringNotify changes. */
+
+ GLuint serialNo;
/** The program in TGSI format */
struct tgsi_token tokens[ST_FP_MAX_TOKENS];
- GLboolean dirty;
#if defined(USE_X86_ASM) || defined(SLANG_X86)
struct x86_function sse2_program;
{
struct gl_vertex_program Base; /**< The Mesa vertex program */
GLboolean error; /**< Set if program is malformed for any reason. */
- GLuint id; /**< String id, for tracking ProgramStringNotify changes. */
+
+ GLuint serialNo;
/** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */
GLuint input_to_index[MAX_VERTEX_PROGRAM_ATTRIBS];
/** The program in TGSI format */
struct tgsi_token tokens[ST_FP_MAX_TOKENS];
- GLboolean dirty;
#if defined(USE_X86_ASM) || defined(SLANG_X86)
struct x86_function sse2_program;
};
-extern void st_init_program_functions(struct dd_function_table *functions);
+extern void
+st_init_program_functions(struct dd_function_table *functions);
static inline struct st_fragment_program *
return (struct st_fragment_program *)fp;
}
+
static inline struct st_vertex_program *
st_vertex_program( struct gl_vertex_program *vp )
{
extern const struct cso_fragment_shader *
-st_translate_fragment_shader(struct st_context *st,
- struct st_fragment_program *fp);
+st_translate_fragment_program(struct st_context *st,
+ struct st_fragment_program *fp,
+ const GLuint inputMapping[],
+ struct tgsi_token *tokens,
+ GLuint maxTokens);
extern const struct cso_vertex_shader *
-st_translate_vertex_shader(struct st_context *st,
- struct st_vertex_program *vp);
-
+st_translate_vertex_program(struct st_context *st,
+ struct st_vertex_program *vp,
+ const GLuint vert_output_to_slot[],
+ struct tgsi_token *tokens,
+ GLuint maxTokens);
#endif