summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/shader')
-rw-r--r--src/mesa/shader/arbprogparse.c5
-rw-r--r--src/mesa/shader/prog_execute.c35
-rw-r--r--src/mesa/shader/program.c60
-rw-r--r--src/mesa/shader/program.h2
-rw-r--r--src/mesa/shader/slang/slang_link.c8
-rw-r--r--src/mesa/shader/slang/slang_preprocess.c94
6 files changed, 191 insertions, 13 deletions
diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c
index a90ce95a639..7e166830fd5 100644
--- a/src/mesa/shader/arbprogparse.c
+++ b/src/mesa/shader/arbprogparse.c
@@ -1022,7 +1022,10 @@ parse_teximage_num (GLcontext * ctx, const GLubyte ** inst,
GLint i = parse_integer (inst, Program);
if ((i < 0) || (i >= (int)ctx->Const.MaxTextureImageUnits)) {
- program_error(ctx, Program->Position, "Invalid texture image index");
+ char s[100];
+ _mesa_snprintf(s, sizeof(s), "Invalid texture image index %d (%u is max)",
+ i, ctx->Const.MaxTextureImageUnits);
+ program_error(ctx, Program->Position, s);
return 1;
}
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/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/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c
index 5ea89d2ff3e..f6032d1e9ad 100644
--- a/src/mesa/shader/slang/slang_link.c
+++ b/src/mesa/shader/slang/slang_link.c
@@ -843,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);
diff --git a/src/mesa/shader/slang/slang_preprocess.c b/src/mesa/shader/slang/slang_preprocess.c
index ff913ad8838..e9a24cc009a 100644
--- a/src/mesa/shader/slang/slang_preprocess.c
+++ b/src/mesa/shader/slang/slang_preprocess.c
@@ -1035,11 +1035,11 @@ preprocess_source (slang_string *output, const char *source,
/* Parse optional macro parameters. */
while (prod[i++] != PARAM_END) {
- if (state.cond.top->effective) {
- pp_symbol *param;
+ pp_symbol *param;
- id = (const char *) (&prod[i]);
- idlen = _mesa_strlen (id);
+ id = (const char *) (&prod[i]);
+ idlen = _mesa_strlen (id);
+ if (state.cond.top->effective) {
pp_annotate (output, "%s, ", id);
param = pp_symbols_push (&symbol->parameters);
if (param == NULL)
@@ -1053,8 +1053,23 @@ preprocess_source (slang_string *output, const char *source,
id = (const char *) (&prod[i]);
idlen = _mesa_strlen (id);
if (state.cond.top->effective) {
+ slang_string replacement;
+ expand_state es;
+
pp_annotate (output, ") %s", id);
- slang_string_pushs (&symbol->replacement, id, idlen);
+
+ slang_string_init(&replacement);
+ slang_string_pushs(&replacement, id, idlen);
+
+ /* Expand macro replacement. */
+ es.output = &symbol->replacement;
+ es.input = slang_string_cstr(&replacement);
+ es.state = &state;
+ if (!expand(&es, &state.symbols)) {
+ slang_string_free(&replacement);
+ goto error;
+ }
+ slang_string_free(&replacement);
}
i += idlen + 1;
}
@@ -1286,6 +1301,45 @@ error:
/**
+ * Remove the continuation characters from the input string.
+ * This is the very first step in preprocessing and is effective
+ * even inside comment blocks.
+ * If there is a whitespace between a backslash and a newline,
+ * this is not considered as a line continuation.
+ * \return GL_TRUE for success, GL_FALSE otherwise.
+ */
+static GLboolean
+_slang_preprocess_backslashes(slang_string *output,
+ const char *input)
+{
+ while (*input) {
+ if (input[0] == '\\') {
+ /* If a newline follows, eat the backslash and the newline. */
+ if (input[1] == '\r') {
+ if (input[2] == '\n') {
+ input += 3;
+ } else {
+ input += 2;
+ }
+ } else if (input[1] == '\n') {
+ if (input[2] == '\r') {
+ input += 3;
+ } else {
+ input += 2;
+ }
+ } else {
+ /* Leave the backslash alone. */
+ slang_string_pushc(output, *input++);
+ }
+ } else {
+ slang_string_pushc(output, *input++);
+ }
+ }
+ return GL_TRUE;
+}
+
+
+/**
* Run preprocessor on source code.
* \param extensions indicates which GL extensions are enabled
* \param output the post-process results
@@ -1304,6 +1358,7 @@ _slang_preprocess_directives(slang_string *output,
{
grammar pid, eid;
GLboolean success;
+ slang_string without_backslashes;
pid = grammar_load_from_text ((const byte *) (slang_pp_directives_syn));
if (pid == 0) {
@@ -1316,9 +1371,36 @@ _slang_preprocess_directives(slang_string *output,
grammar_destroy (pid);
return GL_FALSE;
}
- success = preprocess_source (output, input, pid, eid, elog, extensions, pragmas);
+
+ slang_string_init(&without_backslashes);
+ success = _slang_preprocess_backslashes(&without_backslashes, input);
+
+ if (0) {
+ _mesa_printf("Pre-processed shader:\n");
+ _mesa_printf("%s", slang_string_cstr(&without_backslashes));
+ _mesa_printf("----------------------\n");
+ }
+
+ if (success) {
+ success = preprocess_source(output,
+ slang_string_cstr(&without_backslashes),
+ pid,
+ eid,
+ elog,
+ extensions,
+ pragmas);
+ }
+
+ slang_string_free(&without_backslashes);
grammar_destroy (eid);
grammar_destroy (pid);
+
+ if (0) {
+ _mesa_printf("Post-processed shader:\n");
+ _mesa_printf("%s", slang_string_cstr(output));
+ _mesa_printf("----------------------\n");
+ }
+
return success;
}