summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/shader')
-rw-r--r--src/mesa/shader/arbprogparse.c115
-rw-r--r--src/mesa/shader/arbprogram.c42
-rw-r--r--src/mesa/shader/nvprogram.c31
-rw-r--r--src/mesa/shader/prog_execute.c35
-rw-r--r--src/mesa/shader/prog_instruction.c7
-rw-r--r--src/mesa/shader/prog_instruction.h9
-rw-r--r--src/mesa/shader/prog_optimize.c66
-rw-r--r--src/mesa/shader/prog_optimize.h12
-rw-r--r--src/mesa/shader/prog_print.c17
-rw-r--r--src/mesa/shader/prog_print.h7
-rw-r--r--src/mesa/shader/program.c60
-rw-r--r--src/mesa/shader/program.h2
-rw-r--r--src/mesa/shader/shader_api.c10
-rw-r--r--src/mesa/shader/slang/slang_link.c12
14 files changed, 327 insertions, 98 deletions
diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c
index 8607940dc1b..0f530ebb8a5 100644
--- a/src/mesa/shader/arbprogparse.c
+++ b/src/mesa/shader/arbprogparse.c
@@ -563,6 +563,7 @@ struct var_cache
* we take up with our state tokens or constants. Note that
* this is _not_ the same as the number of param registers
* we eventually use */
+ GLuint swizzle; /**< swizzle to access this variable */
struct var_cache *next;
};
@@ -581,6 +582,7 @@ var_cache_create (struct var_cache **va)
(**va).param_binding_begin = ~0;
(**va).param_binding_length = ~0;
(**va).alias_binding = NULL;
+ (**va).swizzle = SWIZZLE_XYZW;
(**va).next = NULL;
}
}
@@ -872,15 +874,16 @@ parse_signed_float (const GLubyte ** inst, struct arb_program *Program)
* This picks out a constant value from the parsed array. The constant vector is r
* returned in the *values array, which should be of length 4.
*
- * \param values - The 4 component vector with the constant value in it
+ * \param values - return the vector constant values.
+ * \param size - returns the number elements in valuesOut [1..4]
*/
static GLvoid
-parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Program,
- GLboolean use)
+parse_constant(const GLubyte ** inst, GLfloat *values, GLint *size,
+ struct arb_program *Program,
+ GLboolean use)
{
GLuint components, i;
-
switch (*(*inst)++) {
case CONSTANT_SCALAR:
if (use == GL_TRUE) {
@@ -893,7 +896,7 @@ parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Prog
values[1] =
values[2] = values[3] = parse_signed_float (inst, Program);
}
-
+ *size = 1;
break;
case CONSTANT_VECTOR:
values[0] = values[1] = values[2] = 0;
@@ -902,7 +905,12 @@ parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Prog
for (i = 0; i < components; i++) {
values[i] = parse_signed_float (inst, Program);
}
+ *size = 4;
break;
+ default:
+ _mesa_problem(NULL, "unexpected case in parse_constant()");
+ values[0] = 0.0F;
+ *size = 0;
}
}
@@ -945,7 +953,7 @@ parse_generic_attrib_num(GLcontext *ctx, const GLubyte ** inst,
{
GLint i = parse_integer(inst, Program);
- if ((i < 0) || (i >= MAX_VERTEX_PROGRAM_ATTRIBS))
+ if ((i < 0) || (i >= MAX_VERTEX_GENERIC_ATTRIBS))
{
program_error(ctx, Program->Position,
"Invalid generic vertex attribute index");
@@ -1505,10 +1513,10 @@ generic_attrib_check(struct var_cache *vc_head)
{
int a;
struct var_cache *curr;
- GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
- genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
+ GLboolean explicitAttrib[MAX_VERTEX_GENERIC_ATTRIBS],
+ genericAttrib[MAX_VERTEX_GENERIC_ATTRIBS];
- for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
+ for (a=0; a<MAX_VERTEX_GENERIC_ATTRIBS; a++) {
explicitAttrib[a] = GL_FALSE;
genericAttrib[a] = GL_FALSE;
}
@@ -1519,11 +1527,11 @@ generic_attrib_check(struct var_cache *vc_head)
if (curr->attrib_is_generic) {
GLuint attr = (curr->attrib_binding == 0)
? 0 : (curr->attrib_binding - VERT_ATTRIB_GENERIC0);
- assert(attr < MAX_VERTEX_PROGRAM_ATTRIBS);
+ assert(attr < MAX_VERTEX_GENERIC_ATTRIBS);
genericAttrib[attr] = GL_TRUE;
}
else {
- assert(curr->attrib_binding < MAX_VERTEX_PROGRAM_ATTRIBS);
+ assert(curr->attrib_binding < MAX_VERTEX_GENERIC_ATTRIBS);
explicitAttrib[ curr->attrib_binding ] = GL_TRUE;
}
}
@@ -1531,7 +1539,7 @@ generic_attrib_check(struct var_cache *vc_head)
curr = curr->next;
}
- for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
+ for (a=0; a<MAX_VERTEX_GENERIC_ATTRIBS; a++) {
if ((explicitAttrib[a]) && (genericAttrib[a]))
return 1;
}
@@ -1819,7 +1827,6 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
GLint idx;
GLuint err = 0;
gl_state_index state_tokens[STATE_LENGTH] = {0, 0, 0, 0, 0};
- GLfloat const_values[4];
GLubyte token = *(*inst)++;
@@ -1911,18 +1918,31 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
case PARAM_CONSTANT:
/* parsing something like {1.0, 2.0, 3.0, 4.0} */
- parse_constant (inst, const_values, Program, use);
- idx = _mesa_add_named_constant(Program->Base.Parameters,
- (char *) param_var->name,
- const_values, 4);
- if (param_var->param_binding_begin == ~0U)
- param_var->param_binding_begin = idx;
- param_var->param_binding_type = PROGRAM_STATE_VAR;
- /* Note: when we reference this parameter in an instruction later,
- * we'll check if it's really a constant/immediate and set the
- * instruction register type appropriately.
- */
- param_var->param_binding_length++;
+ {
+ GLfloat const_values[4];
+ GLint size;
+ parse_constant(inst, const_values, &size, Program, use);
+ if (param_var->name[0] == ' ') {
+ /* this is an unnamed constant */
+ idx = _mesa_add_unnamed_constant(Program->Base.Parameters,
+ const_values, size,
+ &param_var->swizzle);
+ }
+ else {
+ /* named parameter/constant */
+ idx = _mesa_add_named_constant(Program->Base.Parameters,
+ (char *) param_var->name,
+ const_values, size);
+ }
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_type = PROGRAM_STATE_VAR;
+ /* Note: when we reference this parameter in an instruction later,
+ * we'll check if it's really a constant/immediate and set the
+ * instruction register type appropriately.
+ */
+ param_var->param_binding_length++;
+ }
break;
default:
@@ -2432,6 +2452,9 @@ parse_swizzle_mask(const GLubyte ** inst, GLubyte *swizzle, GLint len)
return;
}
}
+
+ if (len == 1)
+ swizzle[1] = swizzle[2] = swizzle[3] = swizzle[0];
}
@@ -2486,7 +2509,7 @@ static GLuint
parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
struct var_cache **vc_head,
struct arb_program *Program,
- gl_register_file * File, GLint * Index,
+ gl_register_file * File, GLint * Index, GLuint *swizzle,
GLboolean *IsRelOffset )
{
struct var_cache *src;
@@ -2495,6 +2518,8 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
*IsRelOffset = 0;
+ *swizzle = SWIZZLE_XYZW; /* default */
+
/* And the binding for the src */
switch (*(*inst)++) {
case REGISTER_ATTRIB:
@@ -2550,6 +2575,7 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
}
*Index = src->param_binding_begin + offset;
+ *swizzle = src->swizzle;
break;
case ARRAY_INDEX_RELATIVE:
@@ -2572,6 +2598,7 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
/* And store it properly */
*Index = src->param_binding_begin + rel_off;
*IsRelOffset = 1;
+ *swizzle = src->swizzle;
}
break;
}
@@ -2583,6 +2610,7 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
*File = (gl_register_file) src->param_binding_type;
*Index = src->param_binding_begin;
+ *swizzle = src->swizzle;
break;
}
break;
@@ -2651,6 +2679,21 @@ parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
}
+static GLuint
+swizzle_swizzle(GLuint baseSwizzle, const GLubyte swizzle[4])
+{
+ GLuint i, swz, s[4];
+ for (i = 0; i < 4; i++) {
+ GLuint c = swizzle[i];
+ if (c <= SWIZZLE_W)
+ s[i] = GET_SWZ(baseSwizzle, c);
+ else
+ s[i] = c;
+ }
+ swz = MAKE_SWIZZLE4(s[0], s[1], s[2], s[3]);
+ return swz;
+}
+
/**
* Parse vertex/fragment program vector source register.
*/
@@ -2665,12 +2708,14 @@ parse_vector_src_reg(GLcontext *ctx, const GLubyte **inst,
GLubyte negateMask;
GLubyte swizzle[4];
GLboolean isRelOffset;
+ GLuint baseSwizzle;
/* Grab the sign */
negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
/* And the src reg */
- if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
+ if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &baseSwizzle,
+ &isRelOffset))
return 1;
/* finally, the swizzle */
@@ -2678,7 +2723,7 @@ parse_vector_src_reg(GLcontext *ctx, const GLubyte **inst,
reg->File = file;
reg->Index = index;
- reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
+ reg->Swizzle = swizzle_swizzle(baseSwizzle, swizzle);
reg->Negate = negateMask;
reg->RelAddr = isRelOffset;
return 0;
@@ -2699,12 +2744,14 @@ parse_scalar_src_reg(GLcontext *ctx, const GLubyte **inst,
GLubyte negateMask;
GLubyte swizzle[4];
GLboolean isRelOffset;
+ GLuint baseSwizzle;
/* Grab the sign */
negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
/* And the src reg */
- if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
+ if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &baseSwizzle,
+ &isRelOffset))
return 1;
/* finally, the swizzle */
@@ -2712,7 +2759,7 @@ parse_scalar_src_reg(GLcontext *ctx, const GLubyte **inst,
reg->File = file;
reg->Index = index;
- reg->Swizzle = (swizzle[0] << 0);
+ reg->Swizzle = swizzle_swizzle(baseSwizzle, swizzle);
reg->Negate = negateMask;
reg->RelAddr = isRelOffset;
return 0;
@@ -3023,8 +3070,10 @@ parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst,
GLubyte negateMask;
gl_register_file file;
GLint index;
+ GLuint baseSwizzle;
- if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &rel))
+ if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index,
+ &baseSwizzle, &rel))
return 1;
parse_extended_swizzle_mask(inst, swizzle, &negateMask);
fp->SrcReg[0].File = file;
@@ -3364,11 +3413,13 @@ parse_vp_instruction (GLcontext * ctx, const GLubyte ** inst,
GLboolean relAddr;
gl_register_file file;
GLint index;
+ GLuint baseSwizzle;
if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
return 1;
- if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr))
+ if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index,
+ &baseSwizzle, &relAddr))
return 1;
parse_extended_swizzle_mask (inst, swizzle, &negateMask);
vp->SrcReg[0].File = file;
diff --git a/src/mesa/shader/arbprogram.c b/src/mesa/shader/arbprogram.c
index 981565ab8f1..39136efadac 100644
--- a/src/mesa/shader/arbprogram.c
+++ b/src/mesa/shader/arbprogram.c
@@ -74,8 +74,6 @@ _mesa_BindProgram(GLenum target, GLuint id)
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-
/* Error-check target and get curProg */
if ((target == GL_VERTEX_PROGRAM_ARB) && /* == GL_VERTEX_PROGRAM_NV */
(ctx->Extensions.NV_vertex_program ||
@@ -132,6 +130,9 @@ _mesa_BindProgram(GLenum target, GLuint id)
return;
}
+ /* signal new program (and its new constants) */
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+
/* bind newProg */
if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */
_mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
@@ -253,6 +254,8 @@ _mesa_EnableVertexAttribArrayARB(GLuint index)
return;
}
+ ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
+
FLUSH_VERTICES(ctx, _NEW_ARRAY);
ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_TRUE;
ctx->Array.ArrayObj->_Enabled |= _NEW_ARRAY_ATTRIB(index);
@@ -272,6 +275,8 @@ _mesa_DisableVertexAttribArrayARB(GLuint index)
return;
}
+ ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
+
FLUSH_VERTICES(ctx, _NEW_ARRAY);
ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_FALSE;
ctx->Array.ArrayObj->_Enabled &= ~_NEW_ARRAY_ATTRIB(index);
@@ -298,32 +303,41 @@ _mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
}
+/**
+ * Return info for a generic vertex attribute array (no alias with
+ * legacy vertex attributes (pos, normal, color, etc)).
+ */
void GLAPIENTRY
_mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
{
+ const struct gl_client_array *array;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- if (index >= MAX_VERTEX_PROGRAM_ATTRIBS) {
+ if (index >= MAX_VERTEX_GENERIC_ATTRIBS) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribfvARB(index)");
return;
}
+ ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
+
+ array = &ctx->Array.ArrayObj->VertexAttrib[index];
+
switch (pname) {
case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Enabled;
+ params[0] = (GLfloat) array->Enabled;
break;
case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Size;
+ params[0] = (GLfloat) array->Size;
break;
case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Stride;
+ params[0] = (GLfloat) array->Stride;
break;
case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Type;
+ params[0] = (GLfloat) array->Type;
break;
case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Normalized;
+ params[0] = array->Normalized;
break;
case GL_CURRENT_VERTEX_ATTRIB_ARB:
if (index == 0) {
@@ -335,7 +349,7 @@ _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
COPY_4V(params, ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]);
break;
case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name;
+ params[0] = (GLfloat) array->BufferObj->Name;
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
@@ -379,6 +393,8 @@ _mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
return;
}
+ ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
+
*pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
}
@@ -489,7 +505,7 @@ _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
if (target == GL_FRAGMENT_PROGRAM_ARB
&& ctx->Extensions.ARB_fragment_program) {
@@ -537,7 +553,7 @@ _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
GLfloat * dest;
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
if (count <= 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
@@ -631,7 +647,7 @@ _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
struct gl_program *prog;
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
if ((target == GL_FRAGMENT_PROGRAM_NV
&& ctx->Extensions.NV_fragment_program) ||
@@ -685,7 +701,7 @@ _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
GLint i;
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
if (count <= 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
diff --git a/src/mesa/shader/nvprogram.c b/src/mesa/shader/nvprogram.c
index 5142c2a4a59..d6469b17bea 100644
--- a/src/mesa/shader/nvprogram.c
+++ b/src/mesa/shader/nvprogram.c
@@ -354,6 +354,7 @@ _mesa_GetTrackMatrixivNV(GLenum target, GLuint address,
void GLAPIENTRY
_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
{
+ const struct gl_client_array *array;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -362,15 +363,17 @@ _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
return;
}
+ array = &ctx->Array.ArrayObj->VertexAttrib[index];
+
switch (pname) {
case GL_ATTRIB_ARRAY_SIZE_NV:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Size;
+ params[0] = array->Size;
break;
case GL_ATTRIB_ARRAY_STRIDE_NV:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Stride;
+ params[0] = array->Stride;
break;
case GL_ATTRIB_ARRAY_TYPE_NV:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Type;
+ params[0] = array->Type;
break;
case GL_CURRENT_ATTRIB_NV:
if (index == 0) {
@@ -395,6 +398,7 @@ _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
void GLAPIENTRY
_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
{
+ const struct gl_client_array *array;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -403,15 +407,17 @@ _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
return;
}
+ array = &ctx->Array.ArrayObj->VertexAttrib[index];
+
switch (pname) {
case GL_ATTRIB_ARRAY_SIZE_NV:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Size;
+ params[0] = (GLfloat) array->Size;
break;
case GL_ATTRIB_ARRAY_STRIDE_NV:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Stride;
+ params[0] = (GLfloat) array->Stride;
break;
case GL_ATTRIB_ARRAY_TYPE_NV:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Type;
+ params[0] = (GLfloat) array->Type;
break;
case GL_CURRENT_ATTRIB_NV:
if (index == 0) {
@@ -436,6 +442,7 @@ _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
void GLAPIENTRY
_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
{
+ const struct gl_client_array *array;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -444,15 +451,17 @@ _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
return;
}
+ array = &ctx->Array.ArrayObj->VertexAttrib[index];
+
switch (pname) {
case GL_ATTRIB_ARRAY_SIZE_NV:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Size;
+ params[0] = array->Size;
break;
case GL_ATTRIB_ARRAY_STRIDE_NV:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Stride;
+ params[0] = array->Stride;
break;
case GL_ATTRIB_ARRAY_TYPE_NV:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Type;
+ params[0] = array->Type;
break;
case GL_CURRENT_ATTRIB_NV:
if (index == 0) {
@@ -467,7 +476,7 @@ _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
params[3] = (GLint) ctx->Current.Attrib[index][3];
break;
case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name;
+ params[0] = array->BufferObj->Name;
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
@@ -706,7 +715,7 @@ _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
prog = _mesa_lookup_program(ctx, id);
if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
diff --git a/src/mesa/shader/prog_execute.c b/src/mesa/shader/prog_execute.c
index 68a59350a13..f4beb9a78b6 100644
--- a/src/mesa/shader/prog_execute.c
+++ b/src/mesa/shader/prog_execute.c
@@ -225,6 +225,13 @@ fetch_vector4(const struct prog_src_register *source,
result[2] = -result[2];
result[3] = -result[3];
}
+
+#ifdef NAN_CHECK
+ assert(!IS_INF_OR_NAN(result[0]));
+ assert(!IS_INF_OR_NAN(result[0]));
+ assert(!IS_INF_OR_NAN(result[0]));
+ assert(!IS_INF_OR_NAN(result[0]));
+#endif
}
@@ -479,6 +486,13 @@ store_vector4(const struct prog_instruction *inst,
}
}
+#ifdef NAN_CHECK
+ assert(!IS_INF_OR_NAN(value[0]));
+ assert(!IS_INF_OR_NAN(value[0]));
+ assert(!IS_INF_OR_NAN(value[0]));
+ assert(!IS_INF_OR_NAN(value[0]));
+#endif
+
if (writeMask & WRITEMASK_X)
dst[0] = value[0];
if (writeMask & WRITEMASK_Y)
@@ -832,10 +846,14 @@ _mesa_execute_program(GLcontext * ctx,
break;
case OPCODE_EX2: /* Exponential base 2 */
{
- GLfloat a[4], result[4];
+ GLfloat a[4], result[4], val;
fetch_vector1(&inst->SrcReg[0], machine, a);
- result[0] = result[1] = result[2] = result[3] =
- (GLfloat) _mesa_pow(2.0, a[0]);
+ val = (GLfloat) _mesa_pow(2.0, a[0]);
+ /*
+ if (IS_INF_OR_NAN(val))
+ val = 1.0e10;
+ */
+ result[0] = result[1] = result[2] = result[3] = val;
store_vector4(inst, machine, result);
}
break;
@@ -911,12 +929,17 @@ _mesa_execute_program(GLcontext * ctx,
break;
case OPCODE_LG2: /* log base 2 */
{
- GLfloat a[4], result[4];
+ GLfloat a[4], result[4], val;
fetch_vector1(&inst->SrcReg[0], machine, a);
/* The fast LOG2 macro doesn't meet the precision requirements.
*/
- result[0] = result[1] = result[2] = result[3] =
- (log(a[0]) * 1.442695F);
+ if (a[0] == 0.0F) {
+ val = 0.0F;
+ }
+ else {
+ val = log(a[0]) * 1.442695F;
+ }
+ result[0] = result[1] = result[2] = result[3] = val;
store_vector4(inst, machine, result);
}
break;
diff --git a/src/mesa/shader/prog_instruction.c b/src/mesa/shader/prog_instruction.c
index ae3a003feed..44c961927a3 100644
--- a/src/mesa/shader/prog_instruction.c
+++ b/src/mesa/shader/prog_instruction.c
@@ -343,7 +343,10 @@ _mesa_opcode_string(gl_inst_opcode opcode)
{
if (opcode < MAX_OPCODE)
return InstInfo[opcode].Name;
- else
- return "OP?";
+ else {
+ static char s[20];
+ _mesa_snprintf(s, sizeof(s), "OP%u", opcode);
+ return s;
+ }
}
diff --git a/src/mesa/shader/prog_instruction.h b/src/mesa/shader/prog_instruction.h
index 40ad998f79d..39a221eeaba 100644
--- a/src/mesa/shader/prog_instruction.h
+++ b/src/mesa/shader/prog_instruction.h
@@ -133,6 +133,7 @@
#define NEGATE_Y 0x2
#define NEGATE_Z 0x4
#define NEGATE_W 0x8
+#define NEGATE_XYZ 0x7
#define NEGATE_XYZW 0xf
#define NEGATE_NONE 0x0
/*@}*/
@@ -303,11 +304,11 @@ struct prog_dst_register
* Condition code swizzle value.
*/
GLuint CondSwizzle:12;
-
+
/**
* Selects the condition code register to use for conditional destination
* update masking. In NV_fragmnet_program or NV_vertex_program2 mode, only
- * condition code register 0 is available. In NV_vertex_program3 mode,
+ * condition code register 0 is available. In NV_vertex_program3 mode,
* condition code registers 0 and 1 are available.
*/
GLuint CondSrc:1;
@@ -359,7 +360,7 @@ struct prog_instruction
* NV_fragment_program, NV_fragment_program_option, NV_vertex_program3.
*/
GLuint SaturateMode:2;
-
+
/**
* Per-instruction selectable precision: FLOAT32, FLOAT16, FIXED12.
*
@@ -374,7 +375,7 @@ struct prog_instruction
/*@{*/
/** Source texture unit. */
GLuint TexSrcUnit:5;
-
+
/** Source texture target, one of TEXTURE_{1D,2D,3D,CUBE,RECT}_INDEX */
GLuint TexSrcTarget:3;
diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c
index 6ba2e76ff96..be903106a08 100644
--- a/src/mesa/shader/prog_optimize.c
+++ b/src/mesa/shader/prog_optimize.c
@@ -547,15 +547,13 @@ update_interval(GLint intBegin[], GLint intEnd[], GLuint index, GLuint ic)
/**
- * Find the live intervals for each temporary register in the program.
- * For register R, the interval [A,B] indicates that R is referenced
- * from instruction A through instruction B.
- * Special consideration is needed for loops and subroutines.
- * \return GL_TRUE if success, GL_FALSE if we cannot proceed for some reason
+ * Find first/last instruction that references each temporary register.
*/
-static GLboolean
-find_live_intervals(struct gl_program *prog,
- struct interval_list *liveIntervals)
+GLboolean
+_mesa_find_temp_intervals(const struct prog_instruction *instructions,
+ GLuint numInstructions,
+ GLint intBegin[MAX_PROGRAM_TEMPS],
+ GLint intEnd[MAX_PROGRAM_TEMPS])
{
struct loop_info
{
@@ -563,26 +561,15 @@ find_live_intervals(struct gl_program *prog,
};
struct loop_info loopStack[MAX_LOOP_NESTING];
GLuint loopStackDepth = 0;
- GLint intBegin[MAX_PROGRAM_TEMPS], intEnd[MAX_PROGRAM_TEMPS];
GLuint i;
- /*
- * Note: we'll return GL_FALSE below if we find relative indexing
- * into the TEMP register file. We can't handle that yet.
- * We also give up on subroutines for now.
- */
-
- if (dbg) {
- _mesa_printf("Optimize: Begin find intervals\n");
- }
-
for (i = 0; i < MAX_PROGRAM_TEMPS; i++){
intBegin[i] = intEnd[i] = -1;
}
/* Scan instructions looking for temporary registers */
- for (i = 0; i < prog->NumInstructions; i++) {
- const struct prog_instruction *inst = prog->Instructions + i;
+ for (i = 0; i < numInstructions; i++) {
+ const struct prog_instruction *inst = instructions + i;
if (inst->Opcode == OPCODE_BGNLOOP) {
loopStack[loopStackDepth].Start = i;
loopStack[loopStackDepth].End = inst->BranchTarget;
@@ -595,7 +582,7 @@ find_live_intervals(struct gl_program *prog,
return GL_FALSE;
}
else {
- const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ const GLuint numSrc = 3;/*_mesa_num_inst_src_regs(inst->Opcode);*/
GLuint j;
for (j = 0; j < numSrc; j++) {
if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
@@ -624,6 +611,39 @@ find_live_intervals(struct gl_program *prog,
}
}
+ return GL_TRUE;
+}
+
+
+/**
+ * Find the live intervals for each temporary register in the program.
+ * For register R, the interval [A,B] indicates that R is referenced
+ * from instruction A through instruction B.
+ * Special consideration is needed for loops and subroutines.
+ * \return GL_TRUE if success, GL_FALSE if we cannot proceed for some reason
+ */
+static GLboolean
+find_live_intervals(struct gl_program *prog,
+ struct interval_list *liveIntervals)
+{
+ GLint intBegin[MAX_PROGRAM_TEMPS], intEnd[MAX_PROGRAM_TEMPS];
+ GLuint i;
+
+ /*
+ * Note: we'll return GL_FALSE below if we find relative indexing
+ * into the TEMP register file. We can't handle that yet.
+ * We also give up on subroutines for now.
+ */
+
+ if (dbg) {
+ _mesa_printf("Optimize: Begin find intervals\n");
+ }
+
+ /* build intermediate arrays */
+ if (!_mesa_find_temp_intervals(prog->Instructions, prog->NumInstructions,
+ intBegin, intEnd))
+ return GL_FALSE;
+
/* Build live intervals list from intermediate arrays */
liveIntervals->Num = 0;
for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
@@ -792,8 +812,6 @@ _mesa_reallocate_registers(struct gl_program *prog)
}
-
-
/**
* Apply optimizations to the given program to eliminate unnecessary
* instructions, temp regs, etc.
diff --git a/src/mesa/shader/prog_optimize.h b/src/mesa/shader/prog_optimize.h
index d102cfd9fc1..43894a27237 100644
--- a/src/mesa/shader/prog_optimize.h
+++ b/src/mesa/shader/prog_optimize.h
@@ -25,7 +25,19 @@
#ifndef PROG_OPT_H
#define PROG_OPT_H
+
+#include "main/config.h"
+
+
struct gl_program;
+struct prog_instruction;
+
+
+extern GLboolean
+_mesa_find_temp_intervals(const struct prog_instruction *instructions,
+ GLuint numInstructions,
+ GLint intBegin[MAX_PROGRAM_TEMPS],
+ GLint intEnd[MAX_PROGRAM_TEMPS]);
extern void
_mesa_optimize_program(GLcontext *ctx, struct gl_program *program);
diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c
index 9967f2978de..cef0288a9c9 100644
--- a/src/mesa/shader/prog_print.c
+++ b/src/mesa/shader/prog_print.c
@@ -75,7 +75,11 @@ file_string(gl_register_file f, gl_prog_print_mode mode)
case PROGRAM_UNDEFINED:
return "UNDEFINED";
default:
- return "Unknown program file!";
+ {
+ static char s[20];
+ _mesa_snprintf(s, sizeof(s), "FILE%u", f);
+ return s;
+ }
}
}
@@ -537,7 +541,7 @@ _mesa_print_alu_instruction(const struct prog_instruction *inst,
/**
* Print a single vertex/fragment program instruction.
*/
-static GLint
+GLint
_mesa_fprint_instruction_opt(FILE *f,
const struct prog_instruction *inst,
GLint indent,
@@ -736,7 +740,10 @@ _mesa_fprint_instruction_opt(FILE *f,
mode, prog);
}
else {
- _mesa_fprintf(f, "Other opcode %d\n", inst->Opcode);
+ fprint_alu_instruction(f, inst,
+ _mesa_opcode_string(inst->Opcode),
+ 3/*_mesa_num_inst_src_regs(inst->Opcode)*/,
+ mode, prog);
}
break;
}
@@ -941,6 +948,10 @@ _mesa_write_shader_to_file(const struct gl_shader *shader)
fprintf(f, "/*\n");
_mesa_fprint_program_opt(f, shader->Program, PROG_PRINT_DEBUG, GL_TRUE);
fprintf(f, "*/\n");
+ fprintf(f, "/* Parameters / constants */\n");
+ fprintf(f, "/*\n");
+ _mesa_fprint_parameter_list(f, shader->Program->Parameters);
+ fprintf(f, "*/\n");
}
fclose(f);
diff --git a/src/mesa/shader/prog_print.h b/src/mesa/shader/prog_print.h
index d55661cebb8..3da3e767cd0 100644
--- a/src/mesa/shader/prog_print.h
+++ b/src/mesa/shader/prog_print.h
@@ -57,6 +57,13 @@ extern void
_mesa_print_instruction(const struct prog_instruction *inst);
extern GLint
+_mesa_fprint_instruction_opt(FILE *f,
+ const struct prog_instruction *inst,
+ GLint indent,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog);
+
+extern GLint
_mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent,
gl_prog_print_mode mode,
const struct gl_program *prog);
diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c
index d270bf9e1c3..4623ff60de6 100644
--- a/src/mesa/shader/program.c
+++ b/src/mesa/shader/program.c
@@ -820,3 +820,63 @@ _mesa_find_free_register(const struct gl_program *prog, GLuint regFile)
return -1;
}
+
+
+
+/**
+ * "Post-process" a GPU program. This is intended to be used for debugging.
+ * Example actions include no-op'ing instructions or changing instruction
+ * behaviour.
+ */
+void
+_mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog)
+{
+ static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 };
+ GLuint i;
+ GLuint whiteSwizzle;
+ GLint whiteIndex = _mesa_add_unnamed_constant(prog->Parameters,
+ white, 4, &whiteSwizzle);
+
+ (void) whiteIndex;
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
+
+ (void) n;
+
+ if (_mesa_is_tex_instruction(inst->Opcode)) {
+#if 0
+ /* replace TEX/TXP/TXB with MOV */
+ inst->Opcode = OPCODE_MOV;
+ inst->DstReg.WriteMask = WRITEMASK_XYZW;
+ inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
+ inst->SrcReg[0].Negate = NEGATE_NONE;
+#endif
+
+#if 0
+ /* disable shadow texture mode */
+ inst->TexShadow = 0;
+#endif
+ }
+
+ if (inst->Opcode == OPCODE_TXP) {
+#if 0
+ inst->Opcode = OPCODE_MOV;
+ inst->DstReg.WriteMask = WRITEMASK_XYZW;
+ inst->SrcReg[0].File = PROGRAM_CONSTANT;
+ inst->SrcReg[0].Index = whiteIndex;
+ inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
+ inst->SrcReg[0].Negate = NEGATE_NONE;
+#endif
+#if 0
+ inst->TexShadow = 0;
+#endif
+#if 0
+ inst->Opcode = OPCODE_TEX;
+ inst->TexShadow = 0;
+#endif
+ }
+
+ }
+}
diff --git a/src/mesa/shader/program.h b/src/mesa/shader/program.h
index 48176162c35..56a4191f578 100644
--- a/src/mesa/shader/program.h
+++ b/src/mesa/shader/program.h
@@ -122,6 +122,8 @@ _mesa_combine_programs(GLcontext *ctx,
extern GLint
_mesa_find_free_register(const struct gl_program *prog, GLuint regFile);
+extern void
+_mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog);
#endif /* PROGRAM_H */
diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c
index cf9f8b92224..648fbc186bb 100644
--- a/src/mesa/shader/shader_api.c
+++ b/src/mesa/shader/shader_api.c
@@ -1488,7 +1488,7 @@ _mesa_use_program(GLcontext *ctx, GLuint program)
return;
}
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
if (program) {
shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
@@ -1510,6 +1510,10 @@ _mesa_use_program(GLcontext *ctx, GLuint program)
shProg->Shaders[i]->Name,
shProg->Shaders[i]->Type);
}
+ if (shProg->VertexProgram)
+ printf(" vert prog %u\n", shProg->VertexProgram->Base.Id);
+ if (shProg->FragmentProgram)
+ printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id);
}
}
else {
@@ -1790,7 +1794,7 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
return;
}
- FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
uniform = &shProg->Uniforms->Uniforms[location];
@@ -1930,7 +1934,7 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
return;
}
- FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
uniform = &shProg->Uniforms->Uniforms[location];
diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c
index 387659ff300..f6032d1e9ad 100644
--- a/src/mesa/shader/slang/slang_link.c
+++ b/src/mesa/shader/slang/slang_link.c
@@ -717,6 +717,8 @@ _slang_link(GLcontext *ctx,
struct gl_vertex_program *linked_vprog =
vertex_program(_mesa_clone_program(ctx, &vertProg->Base));
shProg->VertexProgram = linked_vprog; /* refcount OK */
+ /* vertex program ID not significant; just set Id for debugging purposes */
+ shProg->VertexProgram->Base.Id = shProg->Name;
ASSERT(shProg->VertexProgram->Base.RefCount == 1);
}
@@ -725,6 +727,8 @@ _slang_link(GLcontext *ctx,
struct gl_fragment_program *linked_fprog =
fragment_program(_mesa_clone_program(ctx, &fragProg->Base));
shProg->FragmentProgram = linked_fprog; /* refcount OK */
+ /* vertex program ID not significant; just set Id for debugging purposes */
+ shProg->FragmentProgram->Base.Id = shProg->Name;
ASSERT(shProg->FragmentProgram->Base.RefCount == 1);
}
@@ -839,6 +843,14 @@ _slang_link(GLcontext *ctx,
}
}
+ /* Debug: */
+ if (0) {
+ if (shProg->VertexProgram)
+ _mesa_postprocess_program(ctx, &shProg->VertexProgram->Base);
+ if (shProg->FragmentProgram)
+ _mesa_postprocess_program(ctx, &shProg->FragmentProgram->Base);
+ }
+
if (ctx->Shader.Flags & GLSL_DUMP) {
_mesa_printf("Varying vars:\n");
_mesa_print_parameter_list(shProg->Varying);