diff options
Diffstat (limited to 'src/mesa/shader')
44 files changed, 2679 insertions, 1221 deletions
diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c index 4d89d057c7..2e0fc3694a 100644 --- a/src/mesa/shader/arbprogparse.c +++ b/src/mesa/shader/arbprogparse.c @@ -53,23 +53,17 @@ having three separate program parameter arrays. #include "main/glheader.h" #include "main/imports.h" +#include "main/context.h" +#include "main/macros.h" +#include "main/mtypes.h" #include "shader/grammar/grammar_mesa.h" #include "arbprogparse.h" #include "program.h" #include "programopt.h" #include "prog_parameter.h" #include "prog_statevars.h" -#include "main/context.h" -#include "main/macros.h" -#include "main/mtypes.h" #include "prog_instruction.h" - -/* For ARB programs, use the NV instruction limits */ -#define MAX_INSTRUCTIONS MAX2(MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS, \ - MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) - - /** * This is basically a union of the vertex_program and fragment_program * structs that we can use to parse the program into @@ -985,6 +979,8 @@ parse_output_color_num (GLcontext * ctx, const GLubyte ** inst, /** + * Validate the index of a texture coordinate + * * \param coord The texture unit index * \return 0 on sucess, 1 on error */ @@ -994,8 +990,8 @@ parse_texcoord_num (GLcontext * ctx, const GLubyte ** inst, { GLint i = parse_integer (inst, Program); - if ((i < 0) || (i >= (int)ctx->Const.MaxTextureUnits)) { - program_error(ctx, Program->Position, "Invalid texture unit index"); + if ((i < 0) || (i >= (int)ctx->Const.MaxTextureCoordUnits)) { + program_error(ctx, Program->Position, "Invalid texture coordinate index"); return 1; } @@ -1003,6 +999,29 @@ parse_texcoord_num (GLcontext * ctx, const GLubyte ** inst, return 0; } + +/** + * Validate the index of a texture image unit + * + * \param coord The texture unit index + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_teximage_num (GLcontext * ctx, const GLubyte ** inst, + struct arb_program *Program, GLuint * coord) +{ + GLint i = parse_integer (inst, Program); + + if ((i < 0) || (i >= (int)ctx->Const.MaxTextureImageUnits)) { + program_error(ctx, Program->Position, "Invalid texture image index"); + return 1; + } + + *coord = (GLuint) i; + return 0; +} + + /** * \param coord The weight index * \return 0 on sucess, 1 on error @@ -3041,7 +3060,7 @@ parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst, return 1; /* texImageUnit */ - if (parse_texcoord_num (ctx, inst, Program, &texcoord)) + if (parse_teximage_num (ctx, inst, Program, &texcoord)) return 1; fp->TexSrcUnit = texcoord; @@ -3443,6 +3462,8 @@ parse_instructions(GLcontext * ctx, const GLubyte * inst, : ctx->Const.VertexProgram.MaxInstructions; GLint err = 0; + ASSERT(MAX_PROGRAM_INSTRUCTIONS >= maxInst); + Program->MajorVersion = (GLuint) * inst++; Program->MinorVersion = (GLuint) * inst++; @@ -3627,8 +3648,7 @@ enable_parser_extensions(GLcontext *ctx, grammar id) if (ctx->Extensions.NV_texture_rectangle && !enable_ext(ctx, id, "texture_rectangle")) return GL_FALSE; - if (ctx->Extensions.ARB_draw_buffers - && !enable_ext(ctx, id, "draw_buffers")) + if (!enable_ext(ctx, id, "draw_buffers")) return GL_FALSE; if (ctx->Extensions.MESA_texture_array && !enable_ext(ctx, id, "texture_array")) @@ -3796,7 +3816,7 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target, /* Initialize the arb_program struct */ program->Base.String = strz; - program->Base.Instructions = _mesa_alloc_instructions(MAX_INSTRUCTIONS); + program->Base.Instructions = _mesa_alloc_instructions(MAX_PROGRAM_INSTRUCTIONS); program->Base.NumInstructions = program->Base.NumTemporaries = program->Base.NumParameters = @@ -3841,12 +3861,12 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target, _mesa_free (parsed); - /* Reallocate the instruction array from size [MAX_INSTRUCTIONS] + /* Reallocate the instruction array from size [MAX_PROGRAM_INSTRUCTIONS] * to size [ap.Base.NumInstructions]. */ program->Base.Instructions = _mesa_realloc_instructions(program->Base.Instructions, - MAX_INSTRUCTIONS, + MAX_PROGRAM_INSTRUCTIONS, program->Base.NumInstructions); return !err; @@ -3899,6 +3919,9 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target, program->FogOption = ap.FogOption; program->UsesKill = ap.UsesKill; + if (program->FogOption) + program->Base.InputsRead |= FRAG_BIT_FOGC; + if (program->Base.Instructions) _mesa_free(program->Base.Instructions); program->Base.Instructions = ap.Base.Instructions; diff --git a/src/mesa/shader/arbprogram.c b/src/mesa/shader/arbprogram.c index beb5deea50..7831e0faf9 100644 --- a/src/mesa/shader/arbprogram.c +++ b/src/mesa/shader/arbprogram.c @@ -30,13 +30,13 @@ #include "main/glheader.h" -#include "arbprogram.h" -#include "arbprogparse.h" #include "main/context.h" #include "main/hash.h" #include "main/imports.h" #include "main/macros.h" #include "main/mtypes.h" +#include "arbprogram.h" +#include "arbprogparse.h" #include "program.h" @@ -335,10 +335,6 @@ _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: - if (!ctx->Extensions.ARB_vertex_buffer_object) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)"); - return; - } params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name; break; default: @@ -807,6 +803,7 @@ _mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index, { GET_CURRENT_CONTEXT(ctx); GLfloat floatParams[4]; + ASSIGN_4V(floatParams, 0.0F, 0.0F, 0.0F, 0.0F); _mesa_GetProgramLocalParameterfvARB(target, index, floatParams); if (ctx->ErrorValue == GL_NO_ERROR) { COPY_4V(params, floatParams); diff --git a/src/mesa/shader/descrip.mms b/src/mesa/shader/descrip.mms new file mode 100644 index 0000000000..19bafd4830 --- /dev/null +++ b/src/mesa/shader/descrip.mms @@ -0,0 +1,95 @@ +# Makefile for core library for VMS +# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl +# Last revision : 29 September 2008 +.first + define gl [---.include.gl] + define math [-.math] + define swrast [-.swrast] + define array_cache [-.array_cache] + define glapi [-.glapi] + define main [-.main] + define shader [-.shader] + +.include [---]mms-config. + +##### MACROS ##### + +VPATH = RCS + +INCDIR = [---.include],[.grammar],[-.main],[-.glapi],[.slang] +LIBDIR = [---.lib] +CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1,"__extension__=")/name=(as_is,short)/float=ieee/ieee=denorm + +SOURCES = \ + atifragshader.c \ + arbprogparse.c \ + arbprogram.c \ + nvfragparse.c \ + nvprogram.c \ + nvvertparse.c \ + program.c \ + programopt.c \ + prog_debug.c \ + prog_execute.c \ + prog_instruction.c \ + prog_parameter.c \ + prog_print.c \ + prog_cache.c \ + prog_statevars.c \ + shader_api.c prog_uniform.c + +OBJECTS = \ + atifragshader.obj,\ + arbprogparse.obj,\ + arbprogram.obj,\ + nvfragparse.obj,\ + nvprogram.obj,\ + nvvertparse.obj,\ + program.obj,\ + programopt.obj,\ + prog_debug.obj,\ + prog_execute.obj,\ + prog_instruction.obj,\ + prog_parameter.obj,\ + prog_print.obj,\ + prog_statevars.obj,\ + shader_api.obj,prog_uniform.obj,prog_cache.obj + +##### RULES ##### + +VERSION=Mesa V3.4 + +##### TARGETS ##### +all : + $(MMS)$(MMSQUALIFIERS) $(LIBDIR)$(GL_LIB) + set def [.slang] + $(MMS)$(MMSQUALIFIERS) + set def [-.grammar] + $(MMS)$(MMSQUALIFIERS) + set def [-] + +# Make the library +$(LIBDIR)$(GL_LIB) : $(OBJECTS) + @ library $(LIBDIR)$(GL_LIB) $(OBJECTS) + +clean : + purge + delete *.obj;* + +atifragshader.obj : atifragshader.c +arbprogparse.obj : arbprogparse.c +arbprogram.obj : arbprogram.c +nvfragparse.obj : nvfragparse.c +nvprogram.obj : nvprogram.c +nvvertparse.obj : nvvertparse.c +program.obj : program.c +programopt. obj : programopt.c +prog_debug.obj : prog_debug.c +prog_execute.obj : prog_execute.c +prog_instruction.obj : prog_instruction.c +prog_parameter.obj : prog_parameter.c +prog_print.obj : prog_print.c +prog_statevars.obj : prog_statevars.c +shader_api.obj : shader_api.c +prog_uniform.obj : prog_uniform.c +prog_cache.obj : prog_cache.c diff --git a/src/mesa/shader/grammar/grammar_crt.c b/src/mesa/shader/grammar/grammar_crt.c index bdf2da9b2e..d2c95d1c8e 100644 --- a/src/mesa/shader/grammar/grammar_crt.c +++ b/src/mesa/shader/grammar/grammar_crt.c @@ -10,17 +10,17 @@ void grammar_alloc_free (void *ptr) free (ptr); } -void *grammar_alloc_malloc (unsigned int size) +void *grammar_alloc_malloc (size_t size) { return malloc (size); } -void *grammar_alloc_realloc (void *ptr, unsigned int old_size, unsigned int size) +void *grammar_alloc_realloc (void *ptr, size_t old_size, size_t size) { return realloc (ptr, size); } -void *grammar_memory_copy (void *dst, const void * src, unsigned int size) +void *grammar_memory_copy (void *dst, const void * src, size_t size) { return memcpy (dst, src, size); } @@ -30,7 +30,7 @@ int grammar_string_compare (const byte *str1, const byte *str2) return strcmp ((const char *) str1, (const char *) str2); } -int grammar_string_compare_n (const byte *str1, const byte *str2, unsigned int n) +int grammar_string_compare_n (const byte *str1, const byte *str2, size_t n) { return strncmp ((const char *) str1, (const char *) str2, n); } @@ -40,7 +40,7 @@ byte *grammar_string_copy (byte *dst, const byte *src) return (byte *) strcpy ((char *) dst, (const char *) src); } -byte *grammar_string_copy_n (byte *dst, const byte *src, unsigned int n) +byte *grammar_string_copy_n (byte *dst, const byte *src, size_t n) { return (byte *) strncpy ((char *) dst, (const char *) src, n); } diff --git a/src/mesa/shader/grammar/sources b/src/mesa/shader/grammar/sources deleted file mode 100644 index a6bbfd3ffd..0000000000 --- a/src/mesa/shader/grammar/sources +++ /dev/null @@ -1,8 +0,0 @@ -MESA_SHADER_GRAMMAR_SOURCES = \ -grammar_mesa.c - -MESA_SHADER_GRAMMAR_HEADERS = \ -grammar.c \ -grammar.h \ -grammar_mesa.h \ -grammar_syn.h diff --git a/src/mesa/shader/nvfragparse.c b/src/mesa/shader/nvfragparse.c index a2a7a5f3f4..20e4781372 100644 --- a/src/mesa/shader/nvfragparse.c +++ b/src/mesa/shader/nvfragparse.c @@ -41,10 +41,10 @@ #include "main/context.h" #include "main/imports.h" #include "main/macros.h" +#include "program.h" #include "prog_parameter.h" #include "prog_instruction.h" #include "nvfragparse.h" -#include "program.h" #define INPUT_1V 1 diff --git a/src/mesa/shader/nvprogram.c b/src/mesa/shader/nvprogram.c index d656d4b28b..16116c4339 100644 --- a/src/mesa/shader/nvprogram.c +++ b/src/mesa/shader/nvprogram.c @@ -42,12 +42,12 @@ #include "main/hash.h" #include "main/imports.h" #include "main/macros.h" +#include "program.h" #include "prog_parameter.h" #include "prog_instruction.h" #include "nvfragparse.h" #include "nvvertparse.h" #include "nvprogram.h" -#include "program.h" @@ -469,10 +469,6 @@ _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: - if (!ctx->Extensions.ARB_vertex_buffer_object) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); - return; - } params[0] = ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name; break; default: diff --git a/src/mesa/shader/prog_execute.c b/src/mesa/shader/prog_execute.c index 65eee5f55b..a93733c085 100644 --- a/src/mesa/shader/prog_execute.c +++ b/src/mesa/shader/prog_execute.c @@ -43,7 +43,7 @@ #include "prog_instruction.h" #include "prog_parameter.h" #include "prog_print.h" -#include "shader/slang/slang_library_noise.h" +#include "prog_noise.h" /* debug predicate */ @@ -258,6 +258,37 @@ fetch_vector4(const struct prog_src_register *source, /** + * Fetch a 4-element uint vector from the given source register. + * Apply swizzling but not negation/abs. + */ +static void +fetch_vector4ui(const struct prog_src_register *source, + const struct gl_program_machine *machine, GLuint result[4]) +{ + const GLuint *src = (GLuint *) get_src_register_pointer(source, machine); + ASSERT(src); + + if (source->Swizzle == SWIZZLE_NOOP) { + /* no swizzling */ + COPY_4V(result, src); + } + else { + ASSERT(GET_SWZ(source->Swizzle, 0) <= 3); + ASSERT(GET_SWZ(source->Swizzle, 1) <= 3); + ASSERT(GET_SWZ(source->Swizzle, 2) <= 3); + ASSERT(GET_SWZ(source->Swizzle, 3) <= 3); + result[0] = src[GET_SWZ(source->Swizzle, 0)]; + result[1] = src[GET_SWZ(source->Swizzle, 1)]; + result[2] = src[GET_SWZ(source->Swizzle, 2)]; + result[3] = src[GET_SWZ(source->Swizzle, 3)]; + } + + /* Note: no NegateBase, Abs, NegateAbs here */ +} + + + +/** * Fetch the derivative with respect to X or Y for the given register. * XXX this currently only works for fragment program input attribs. */ @@ -267,7 +298,8 @@ fetch_vector4_deriv(GLcontext * ctx, const struct gl_program_machine *machine, char xOrY, GLfloat result[4]) { - if (source->File == PROGRAM_INPUT && source->Index < (GLint)machine->NumDeriv) { + if (source->File == PROGRAM_INPUT && + source->Index < (GLint) machine->NumDeriv) { const GLint col = machine->CurElement; const GLfloat w = machine->Attribs[FRAG_ATTRIB_WPOS][col][3]; const GLfloat invQ = 1.0f / w; @@ -514,6 +546,71 @@ store_vector4(const struct prog_instruction *inst, /** + * Store 4 uints into a register. Observe the set-condition-code flags. + */ +static void +store_vector4ui(const struct prog_instruction *inst, + struct gl_program_machine *machine, const GLuint value[4]) +{ + const struct prog_dst_register *dstReg = &(inst->DstReg); + GLuint writeMask = dstReg->WriteMask; + GLuint *dst = (GLuint *) get_dst_register_pointer(dstReg, machine); + + if (dstReg->CondMask != COND_TR) { + /* condition codes may turn off some writes */ + if (writeMask & WRITEMASK_X) { + if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 0)], + dstReg->CondMask)) + writeMask &= ~WRITEMASK_X; + } + if (writeMask & WRITEMASK_Y) { + if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 1)], + dstReg->CondMask)) + writeMask &= ~WRITEMASK_Y; + } + if (writeMask & WRITEMASK_Z) { + if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 2)], + dstReg->CondMask)) + writeMask &= ~WRITEMASK_Z; + } + if (writeMask & WRITEMASK_W) { + if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 3)], + dstReg->CondMask)) + writeMask &= ~WRITEMASK_W; + } + } + + if (writeMask & WRITEMASK_X) + dst[0] = value[0]; + if (writeMask & WRITEMASK_Y) + dst[1] = value[1]; + if (writeMask & WRITEMASK_Z) + dst[2] = value[2]; + if (writeMask & WRITEMASK_W) + dst[3] = value[3]; + + if (inst->CondUpdate) { + if (writeMask & WRITEMASK_X) + machine->CondCodes[0] = generate_cc(value[0]); + if (writeMask & WRITEMASK_Y) + machine->CondCodes[1] = generate_cc(value[1]); + if (writeMask & WRITEMASK_Z) + machine->CondCodes[2] = generate_cc(value[2]); + if (writeMask & WRITEMASK_W) + machine->CondCodes[3] = generate_cc(value[3]); +#if DEBUG_PROG + printf("CondCodes=(%s,%s,%s,%s) for:\n", + _mesa_condcode_string(machine->CondCodes[0]), + _mesa_condcode_string(machine->CondCodes[1]), + _mesa_condcode_string(machine->CondCodes[2]), + _mesa_condcode_string(machine->CondCodes[3])); +#endif + } +} + + + +/** * Execute the given vertex/fragment program. * * \param ctx rendering context @@ -592,11 +689,23 @@ _mesa_execute_program(GLcontext * ctx, } } break; + case OPCODE_AND: /* bitwise AND */ + { + GLuint a[4], b[4], result[4]; + fetch_vector4ui(&inst->SrcReg[0], machine, a); + fetch_vector4ui(&inst->SrcReg[1], machine, b); + result[0] = a[0] & b[0]; + result[1] = a[1] & b[1]; + result[2] = a[2] & b[2]; + result[3] = a[3] & b[3]; + store_vector4ui(inst, machine, result); + } + break; case OPCODE_ARL: { GLfloat t[4]; fetch_vector4(&inst->SrcReg[0], machine, t); - machine->AddressReg[0][0] = (GLint) FLOORF(t[0]); + machine->AddressReg[0][0] = IFLOOR(t[0]); } break; case OPCODE_BGNLOOP: @@ -670,6 +779,33 @@ _mesa_execute_program(GLcontext * ctx, store_vector4(inst, machine, result); } break; + case OPCODE_DP2: + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = result[1] = result[2] = result[3] = DOT2(a, b); + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("DP2 %g = (%g %g) . (%g %g)\n", + result[0], a[0], a[1], b[0], b[1]); + } + } + break; + case OPCODE_DP2A: + { + GLfloat a[4], b[4], c, result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + fetch_vector1(&inst->SrcReg[1], machine, &c); + result[0] = result[1] = result[2] = result[3] = DOT2(a, b) + c; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("DP2A %g = (%g %g) . (%g %g) + %g\n", + result[0], a[0], a[1], b[0], b[1], c); + } + } + break; case OPCODE_DP3: { GLfloat a[4], b[4], result[4]; @@ -702,8 +838,7 @@ _mesa_execute_program(GLcontext * ctx, GLfloat a[4], b[4], result[4]; fetch_vector4(&inst->SrcReg[0], machine, a); fetch_vector4(&inst->SrcReg[1], machine, b); - result[0] = result[1] = result[2] = result[3] = - a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + b[3]; + result[0] = result[1] = result[2] = result[3] = DOT3(a, b) + b[3]; store_vector4(inst, machine, result); } break; @@ -810,17 +945,6 @@ _mesa_execute_program(GLcontext * ctx, case OPCODE_ENDIF: /* nothing */ break; - case OPCODE_INT: /* float to int */ - { - GLfloat a[4], result[4]; - fetch_vector4(&inst->SrcReg[0], machine, a); - result[0] = (GLfloat) (GLint) a[0]; - result[1] = (GLfloat) (GLint) a[1]; - result[2] = (GLfloat) (GLint) a[2]; - result[3] = (GLfloat) (GLint) a[3]; - store_vector4(inst, machine, result); - } - break; case OPCODE_KIL_NV: /* NV_f_p only (conditional) */ if (eval_condition(machine, inst)) { return GL_FALSE; @@ -839,7 +963,10 @@ _mesa_execute_program(GLcontext * ctx, { GLfloat a[4], result[4]; fetch_vector1(&inst->SrcReg[0], machine, a); - result[0] = result[1] = result[2] = result[3] = LOG2(a[0]); + /* The fast LOG2 macro doesn't meet the precision requirements. + */ + result[0] = result[1] = result[2] = result[3] = + (log(a[0]) * 1.442695F); store_vector4(inst, machine, result); } break; @@ -898,7 +1025,11 @@ _mesa_execute_program(GLcontext * ctx, GLfloat mantissa = FREXPF(t[0], &exponent); q[0] = (GLfloat) (exponent - 1); q[1] = (GLfloat) (2.0 * mantissa); /* map [.5, 1) -> [1, 2) */ - q[2] = (GLfloat) (q[0] + LOG2(q[1])); + + /* The fast LOG2 macro doesn't meet the precision + * requirements. + */ + q[2] = (log(t[0]) * 1.442695F); } } else { @@ -1013,7 +1144,8 @@ _mesa_execute_program(GLcontext * ctx, fetch_vector1(&inst->SrcReg[0], machine, a); result[0] = result[1] = - result[2] = result[3] = _slang_library_noise1(a[0]); + result[2] = + result[3] = _mesa_noise1(a[0]); store_vector4(inst, machine, result); } break; @@ -1023,7 +1155,7 @@ _mesa_execute_program(GLcontext * ctx, fetch_vector4(&inst->SrcReg[0], machine, a); result[0] = result[1] = - result[2] = result[3] = _slang_library_noise2(a[0], a[1]); + result[2] = result[3] = _mesa_noise2(a[0], a[1]); store_vector4(inst, machine, result); } break; @@ -1034,7 +1166,7 @@ _mesa_execute_program(GLcontext * ctx, result[0] = result[1] = result[2] = - result[3] = _slang_library_noise3(a[0], a[1], a[2]); + result[3] = _mesa_noise3(a[0], a[1], a[2]); store_vector4(inst, machine, result); } break; @@ -1045,45 +1177,100 @@ _mesa_execute_program(GLcontext * ctx, result[0] = result[1] = result[2] = - result[3] = _slang_library_noise4(a[0], a[1], a[2], a[3]); + result[3] = _mesa_noise4(a[0], a[1], a[2], a[3]); store_vector4(inst, machine, result); } break; case OPCODE_NOP: break; - case OPCODE_PK2H: /* pack two 16-bit floats in one 32-bit float */ + case OPCODE_NOT: /* bitwise NOT */ + { + GLuint a[4], result[4]; + fetch_vector4ui(&inst->SrcReg[0], machine, a); + result[0] = ~a[0]; + result[1] = ~a[1]; + result[2] = ~a[2]; + result[3] = ~a[3]; + store_vector4ui(inst, machine, result); + } + break; + case OPCODE_NRM3: /* 3-component normalization */ + { + GLfloat a[4], result[4]; + GLfloat tmp; + fetch_vector4(&inst->SrcReg[0], machine, a); + tmp = a[0] * a[0] + a[1] * a[1] + a[2] * a[2]; + if (tmp != 0.0F) + tmp = INV_SQRTF(tmp); + result[0] = tmp * a[0]; + result[1] = tmp * a[1]; + result[2] = tmp * a[2]; + result[3] = 0.0; /* undefined, but prevent valgrind warnings */ + store_vector4(inst, machine, result); + } + break; + case OPCODE_NRM4: /* 4-component normalization */ { GLfloat a[4], result[4]; + GLfloat tmp; + fetch_vector4(&inst->SrcReg[0], machine, a); + tmp = a[0] * a[0] + a[1] * a[1] + a[2] * a[2] + a[3] * a[3]; + if (tmp != 0.0F) + tmp = INV_SQRTF(tmp); + result[0] = tmp * a[0]; + result[1] = tmp * a[1]; + result[2] = tmp * a[2]; + result[3] = tmp * a[3]; + store_vector4(inst, machine, result); + } + break; + case OPCODE_OR: /* bitwise OR */ + { + GLuint a[4], b[4], result[4]; + fetch_vector4ui(&inst->SrcReg[0], machine, a); + fetch_vector4ui(&inst->SrcReg[1], machine, b); + result[0] = a[0] | b[0]; + result[1] = a[1] | b[1]; + result[2] = a[2] | b[2]; + result[3] = a[3] | b[3]; + store_vector4ui(inst, machine, result); + } + break; + case OPCODE_PK2H: /* pack two 16-bit floats in one 32-bit float */ + { + GLfloat a[4]; + GLuint result[4]; GLhalfNV hx, hy; - GLuint *rawResult = (GLuint *) result; - GLuint twoHalves; fetch_vector4(&inst->SrcReg[0], machine, a); hx = _mesa_float_to_half(a[0]); hy = _mesa_float_to_half(a[1]); - twoHalves = hx | (hy << 16); - rawResult[0] = rawResult[1] = rawResult[2] = rawResult[3] - = twoHalves; - store_vector4(inst, machine, result); + result[0] = + result[1] = + result[2] = + result[3] = hx | (hy << 16); + store_vector4ui(inst, machine, result); } break; case OPCODE_PK2US: /* pack two GLushorts into one 32-bit float */ { - GLfloat a[4], result[4]; - GLuint usx, usy, *rawResult = (GLuint *) result; + GLfloat a[4]; + GLuint result[4], usx, usy; fetch_vector4(&inst->SrcReg[0], machine, a); a[0] = CLAMP(a[0], 0.0F, 1.0F); a[1] = CLAMP(a[1], 0.0F, 1.0F); usx = IROUND(a[0] * 65535.0F); usy = IROUND(a[1] * 65535.0F); - rawResult[0] = rawResult[1] = rawResult[2] = rawResult[3] - = usx | (usy << 16); - store_vector4(inst, machine, result); + result[0] = + result[1] = + result[2] = + result[3] = usx | (usy << 16); + store_vector4ui(inst, machine, result); } break; case OPCODE_PK4B: /* pack four GLbytes into one 32-bit float */ { - GLfloat a[4], result[4]; - GLuint ubx, uby, ubz, ubw, *rawResult = (GLuint *) result; + GLfloat a[4]; + GLuint result[4], ubx, uby, ubz, ubw; fetch_vector4(&inst->SrcReg[0], machine, a); a[0] = CLAMP(a[0], -128.0F / 127.0F, 1.0F); a[1] = CLAMP(a[1], -128.0F / 127.0F, 1.0F); @@ -1093,15 +1280,17 @@ _mesa_execute_program(GLcontext * ctx, uby = IROUND(127.0F * a[1] + 128.0F); ubz = IROUND(127.0F * a[2] + 128.0F); ubw = IROUND(127.0F * a[3] + 128.0F); - rawResult[0] = rawResult[1] = rawResult[2] = rawResult[3] - = ubx | (uby << 8) | (ubz << 16) | (ubw << 24); - store_vector4(inst, machine, result); + result[0] = + result[1] = + result[2] = + result[3] = ubx | (uby << 8) | (ubz << 16) | (ubw << 24); + store_vector4ui(inst, machine, result); } break; case OPCODE_PK4UB: /* pack four GLubytes into one 32-bit float */ { - GLfloat a[4], result[4]; - GLuint ubx, uby, ubz, ubw, *rawResult = (GLuint *) result; + GLfloat a[4]; + GLuint result[4], ubx, uby, ubz, ubw; fetch_vector4(&inst->SrcReg[0], machine, a); a[0] = CLAMP(a[0], 0.0F, 1.0F); a[1] = CLAMP(a[1], 0.0F, 1.0F); @@ -1111,9 +1300,11 @@ _mesa_execute_program(GLcontext * ctx, uby = IROUND(255.0F * a[1]); ubz = IROUND(255.0F * a[2]); ubw = IROUND(255.0F * a[3]); - rawResult[0] = rawResult[1] = rawResult[2] = rawResult[3] - = ubx | (uby << 8) | (ubz << 16) | (ubw << 24); - store_vector4(inst, machine, result); + result[0] = + result[1] = + result[2] = + result[3] = ubx | (uby << 8) | (ubz << 16) | (ubw << 24); + store_vector4ui(inst, machine, result); } break; case OPCODE_POW: @@ -1309,6 +1500,17 @@ _mesa_execute_program(GLcontext * ctx, } } break; + case OPCODE_SSG: /* set sign (-1, 0 or +1) */ + { + GLfloat a[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + result[0] = (GLfloat) ((a[0] > 0.0F) - (a[0] < 0.0F)); + result[1] = (GLfloat) ((a[1] > 0.0F) - (a[1] < 0.0F)); + result[2] = (GLfloat) ((a[2] > 0.0F) - (a[2] < 0.0F)); + result[3] = (GLfloat) ((a[3] > 0.0F) - (a[3] < 0.0F)); + store_vector4(inst, machine, result); + } + break; case OPCODE_STR: /* set true, operands ignored */ { static const GLfloat result[4] = { 1.0F, 1.0F, 1.0F, 1.0F }; @@ -1446,6 +1648,17 @@ _mesa_execute_program(GLcontext * ctx, store_vector4(inst, machine, color); } break; + case OPCODE_TRUNC: /* truncate toward zero */ + { + GLfloat a[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + result[0] = (GLfloat) (GLint) a[0]; + result[1] = (GLfloat) (GLint) a[1]; + result[2] = (GLfloat) (GLint) a[2]; + result[3] = (GLfloat) (GLint) a[3]; + store_vector4(inst, machine, result); + } + break; case OPCODE_UP2H: /* unpack two 16-bit floats */ { GLfloat a[4], result[4]; @@ -1496,6 +1709,18 @@ _mesa_execute_program(GLcontext * ctx, store_vector4(inst, machine, result); } break; + case OPCODE_XOR: /* bitwise XOR */ + { + GLuint a[4], b[4], result[4]; + fetch_vector4ui(&inst->SrcReg[0], machine, a); + fetch_vector4ui(&inst->SrcReg[1], machine, b); + result[0] = a[0] ^ b[0]; + result[1] = a[1] ^ b[1]; + result[2] = a[2] ^ b[2]; + result[3] = a[3] ^ b[3]; + store_vector4ui(inst, machine, result); + } + break; case OPCODE_XPD: /* cross product */ { GLfloat a[4], b[4], result[4]; diff --git a/src/mesa/shader/prog_instruction.c b/src/mesa/shader/prog_instruction.c index 1033496d97..4a6d0d670a 100644 --- a/src/mesa/shader/prog_instruction.c +++ b/src/mesa/shader/prog_instruction.c @@ -1,8 +1,9 @@ /* * Mesa 3-D graphics library - * Version: 6.5.3 + * Version: 7.3 * - * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2009 VMware, Inc. 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"), @@ -154,9 +155,10 @@ static const struct instruction_info InstInfo[MAX_OPCODE] = { { OPCODE_NOP, "NOP", 0, 0 }, { OPCODE_ABS, "ABS", 1, 1 }, { OPCODE_ADD, "ADD", 2, 1 }, + { OPCODE_AND, "AND", 2, 1 }, { OPCODE_ARA, "ARA", 1, 1 }, { OPCODE_ARL, "ARL", 1, 1 }, - { OPCODE_ARL_NV, "ARL", 1, 1 }, + { OPCODE_ARL_NV, "ARL_NV", 1, 1 }, { OPCODE_ARR, "ARL", 1, 1 }, { OPCODE_BGNLOOP,"BGNLOOP", 0, 0 }, { OPCODE_BGNSUB, "BGNSUB", 0, 0 }, @@ -168,6 +170,8 @@ static const struct instruction_info InstInfo[MAX_OPCODE] = { { OPCODE_COS, "COS", 1, 1 }, { OPCODE_DDX, "DDX", 1, 1 }, { OPCODE_DDY, "DDY", 1, 1 }, + { OPCODE_DP2, "DP2", 2, 1 }, + { OPCODE_DP2A, "DP2A", 3, 1 }, { OPCODE_DP3, "DP3", 2, 1 }, { OPCODE_DP4, "DP4", 2, 1 }, { OPCODE_DPH, "DPH", 2, 1 }, @@ -182,9 +186,8 @@ static const struct instruction_info InstInfo[MAX_OPCODE] = { { OPCODE_FLR, "FLR", 1, 1 }, { OPCODE_FRC, "FRC", 1, 1 }, { OPCODE_IF, "IF", 1, 0 }, - { OPCODE_INT, "INT", 1, 1 }, { OPCODE_KIL, "KIL", 1, 0 }, - { OPCODE_KIL_NV, "KIL", 0, 0 }, + { OPCODE_KIL_NV, "KIL_NV", 0, 0 }, { OPCODE_LG2, "LG2", 1, 1 }, { OPCODE_LIT, "LIT", 1, 1 }, { OPCODE_LOG, "LOG", 1, 1 }, @@ -198,6 +201,10 @@ static const struct instruction_info InstInfo[MAX_OPCODE] = { { OPCODE_NOISE2, "NOISE2", 1, 1 }, { OPCODE_NOISE3, "NOISE3", 1, 1 }, { OPCODE_NOISE4, "NOISE4", 1, 1 }, + { OPCODE_NOT, "NOT", 1, 1 }, + { OPCODE_NRM3, "NRM3", 1, 1 }, + { OPCODE_NRM4, "NRM4", 1, 1 }, + { OPCODE_OR, "OR", 2, 1 }, { OPCODE_PK2H, "PK2H", 1, 1 }, { OPCODE_PK2US, "PK2US", 1, 1 }, { OPCODE_PK4B, "PK4B", 1, 1 }, @@ -229,12 +236,14 @@ static const struct instruction_info InstInfo[MAX_OPCODE] = { { OPCODE_TXD, "TXD", 3, 1 }, { OPCODE_TXL, "TXL", 1, 1 }, { OPCODE_TXP, "TXP", 1, 1 }, - { OPCODE_TXP_NV, "TXP", 1, 1 }, + { OPCODE_TXP_NV, "TXP_NV", 1, 1 }, + { OPCODE_TRUNC, "TRUNC", 1, 1 }, { OPCODE_UP2H, "UP2H", 1, 1 }, { OPCODE_UP2US, "UP2US", 1, 1 }, { OPCODE_UP4B, "UP4B", 1, 1 }, { OPCODE_UP4UB, "UP4UB", 1, 1 }, { OPCODE_X2D, "X2D", 3, 1 }, + { OPCODE_XOR, "XOR", 2, 1 }, { OPCODE_XPD, "XPD", 2, 1 } }; diff --git a/src/mesa/shader/prog_instruction.h b/src/mesa/shader/prog_instruction.h index a8842c68c7..c649b3db5e 100644 --- a/src/mesa/shader/prog_instruction.h +++ b/src/mesa/shader/prog_instruction.h @@ -145,6 +145,7 @@ typedef enum prog_opcode { OPCODE_NOP = 0, /* X */ OPCODE_ABS, /* X X 1.1 X */ OPCODE_ADD, /* X X X X X */ + OPCODE_AND, /* */ OPCODE_ARA, /* 2 */ OPCODE_ARL, /* X X */ OPCODE_ARL_NV, /* 2 */ @@ -159,6 +160,8 @@ typedef enum prog_opcode { OPCODE_COS, /* X 2 X X */ OPCODE_DDX, /* X X */ OPCODE_DDY, /* X X */ + OPCODE_DP2, /* 2 */ + OPCODE_DP2A, /* 2 */ OPCODE_DP3, /* X X X X X */ OPCODE_DP4, /* X X X X X */ OPCODE_DPH, /* X X 1.1 */ @@ -173,7 +176,6 @@ typedef enum prog_opcode { OPCODE_FLR, /* X X 2 X X */ OPCODE_FRC, /* X X 2 X X */ OPCODE_IF, /* opt */ - OPCODE_INT, /* X */ OPCODE_KIL, /* X */ OPCODE_KIL_NV, /* X X */ OPCODE_LG2, /* X X 2 X X */ @@ -189,6 +191,10 @@ typedef enum prog_opcode { OPCODE_NOISE2, /* X */ OPCODE_NOISE3, /* X */ OPCODE_NOISE4, /* X */ + OPCODE_NOT, /* */ + OPCODE_NRM3, /* */ + OPCODE_NRM4, /* */ + OPCODE_OR, /* */ OPCODE_PK2H, /* X */ OPCODE_PK2US, /* X */ OPCODE_PK4B, /* X */ @@ -221,11 +227,13 @@ typedef enum prog_opcode { OPCODE_TXL, /* 3 2 X */ OPCODE_TXP, /* X X */ OPCODE_TXP_NV, /* 3 X */ + OPCODE_TRUNC, /* X */ OPCODE_UP2H, /* X */ OPCODE_UP2US, /* X */ OPCODE_UP4B, /* X */ OPCODE_UP4UB, /* X */ OPCODE_X2D, /* X */ + OPCODE_XOR, /* */ OPCODE_XPD, /* X X X */ MAX_OPCODE } gl_inst_opcode; @@ -410,7 +418,7 @@ struct prog_instruction */ GLint BranchTarget; -#if 0 +#if 01 /* XXX just use this for i965 driver for now! */ /** * For TEX instructions in shaders, the sampler to use for the * texture lookup. diff --git a/src/mesa/shader/prog_noise.c b/src/mesa/shader/prog_noise.c new file mode 100644 index 0000000000..1713ddb5f3 --- /dev/null +++ b/src/mesa/shader/prog_noise.c @@ -0,0 +1,638 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 Brian Paul 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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. + */ + +/* + * SimplexNoise1234 + * Copyright (c) 2003-2005, Stefan Gustavson + * + * Contact: stegu@itn.liu.se + */ + +/** + * \file + * \brief C implementation of Perlin Simplex Noise over 1, 2, 3 and 4 dims. + * \author Stefan Gustavson (stegu@itn.liu.se) + * + * + * This implementation is "Simplex Noise" as presented by + * Ken Perlin at a relatively obscure and not often cited course + * session "Real-Time Shading" at Siggraph 2001 (before real + * time shading actually took on), under the title "hardware noise". + * The 3D function is numerically equivalent to his Java reference + * code available in the PDF course notes, although I re-implemented + * it from scratch to get more readable code. The 1D, 2D and 4D cases + * were implemented from scratch by me from Ken Perlin's text. + * + * This file has no dependencies on any other file, not even its own + * header file. The header file is made for use by external code only. + */ + + +#include "main/imports.h" +#include "prog_noise.h" + +#define FASTFLOOR(x) ( ((x)>0) ? ((int)x) : (((int)x)-1) ) + +/* + * --------------------------------------------------------------------- + * Static data + */ + +/** + * Permutation table. This is just a random jumble of all numbers 0-255, + * repeated twice to avoid wrapping the index at 255 for each lookup. + * This needs to be exactly the same for all instances on all platforms, + * so it's easiest to just keep it as static explicit data. + * This also removes the need for any initialisation of this class. + * + * Note that making this an int[] instead of a char[] might make the + * code run faster on platforms with a high penalty for unaligned single + * byte addressing. Intel x86 is generally single-byte-friendly, but + * some other CPUs are faster with 4-aligned reads. + * However, a char[] is smaller, which avoids cache trashing, and that + * is probably the most important aspect on most architectures. + * This array is accessed a *lot* by the noise functions. + * A vector-valued noise over 3D accesses it 96 times, and a + * float-valued 4D noise 64 times. We want this to fit in the cache! + */ +unsigned char perm[512] = { 151, 160, 137, 91, 90, 15, + 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, + 99, 37, 240, 21, 10, 23, + 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, + 11, 32, 57, 177, 33, + 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, + 134, 139, 48, 27, 166, + 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, + 55, 46, 245, 40, 244, + 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, + 18, 169, 200, 196, + 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, + 226, 250, 124, 123, + 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, + 17, 182, 189, 28, 42, + 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, + 167, 43, 172, 9, + 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, + 218, 246, 97, 228, + 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, + 249, 14, 239, 107, + 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, + 127, 4, 150, 254, + 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, + 215, 61, 156, 180, + 151, 160, 137, 91, 90, 15, + 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, + 99, 37, 240, 21, 10, 23, + 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, + 11, 32, 57, 177, 33, + 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, + 134, 139, 48, 27, 166, + 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, + 55, 46, 245, 40, 244, + 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, + 18, 169, 200, 196, + 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, + 226, 250, 124, 123, + 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, + 17, 182, 189, 28, 42, + 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, + 167, 43, 172, 9, + 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, + 218, 246, 97, 228, + 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, + 249, 14, 239, 107, + 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, + 127, 4, 150, 254, + 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, + 215, 61, 156, 180 +}; + +/* + * --------------------------------------------------------------------- + */ + +/* + * Helper functions to compute gradients-dot-residualvectors (1D to 4D) + * Note that these generate gradients of more than unit length. To make + * a close match with the value range of classic Perlin noise, the final + * noise values need to be rescaled to fit nicely within [-1,1]. + * (The simplex noise functions as such also have different scaling.) + * Note also that these noise functions are the most practical and useful + * signed version of Perlin noise. To return values according to the + * RenderMan specification from the SL noise() and pnoise() functions, + * the noise values need to be scaled and offset to [0,1], like this: + * float SLnoise = (SimplexNoise1234::noise(x,y,z) + 1.0) * 0.5; + */ + +static float +grad1(int hash, float x) +{ + int h = hash & 15; + float grad = 1.0f + (h & 7); /* Gradient value 1.0, 2.0, ..., 8.0 */ + if (h & 8) + grad = -grad; /* Set a random sign for the gradient */ + return (grad * x); /* Multiply the gradient with the distance */ +} + +static float +grad2(int hash, float x, float y) +{ + int h = hash & 7; /* Convert low 3 bits of hash code */ + float u = h < 4 ? x : y; /* into 8 simple gradient directions, */ + float v = h < 4 ? y : x; /* and compute the dot product with (x,y). */ + return ((h & 1) ? -u : u) + ((h & 2) ? -2.0f * v : 2.0f * v); +} + +static float +grad3(int hash, float x, float y, float z) +{ + int h = hash & 15; /* Convert low 4 bits of hash code into 12 simple */ + float u = h < 8 ? x : y; /* gradient directions, and compute dot product. */ + float v = h < 4 ? y : h == 12 || h == 14 ? x : z; /* Fix repeats at h = 12 to 15 */ + return ((h & 1) ? -u : u) + ((h & 2) ? -v : v); +} + +static float +grad4(int hash, float x, float y, float z, float t) +{ + int h = hash & 31; /* Convert low 5 bits of hash code into 32 simple */ + float u = h < 24 ? x : y; /* gradient directions, and compute dot product. */ + float v = h < 16 ? y : z; + float w = h < 8 ? z : t; + return ((h & 1) ? -u : u) + ((h & 2) ? -v : v) + ((h & 4) ? -w : w); +} + +/** + * A lookup table to traverse the simplex around a given point in 4D. + * Details can be found where this table is used, in the 4D noise method. + * TODO: This should not be required, backport it from Bill's GLSL code! + */ +static unsigned char simplex[64][4] = { + {0, 1, 2, 3}, {0, 1, 3, 2}, {0, 0, 0, 0}, {0, 2, 3, 1}, + {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {1, 2, 3, 0}, + {0, 2, 1, 3}, {0, 0, 0, 0}, {0, 3, 1, 2}, {0, 3, 2, 1}, + {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {1, 3, 2, 0}, + {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, + {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, + {1, 2, 0, 3}, {0, 0, 0, 0}, {1, 3, 0, 2}, {0, 0, 0, 0}, + {0, 0, 0, 0}, {0, 0, 0, 0}, {2, 3, 0, 1}, {2, 3, 1, 0}, + {1, 0, 2, 3}, {1, 0, 3, 2}, {0, 0, 0, 0}, {0, 0, 0, 0}, + {0, 0, 0, 0}, {2, 0, 3, 1}, {0, 0, 0, 0}, {2, 1, 3, 0}, + {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, + {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, + {2, 0, 1, 3}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, + {3, 0, 1, 2}, {3, 0, 2, 1}, {0, 0, 0, 0}, {3, 1, 2, 0}, + {2, 1, 0, 3}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, + {3, 1, 0, 2}, {0, 0, 0, 0}, {3, 2, 0, 1}, {3, 2, 1, 0} +}; + + +/** 1D simplex noise */ +GLfloat +_mesa_noise1(GLfloat x) +{ + int i0 = FASTFLOOR(x); + int i1 = i0 + 1; + float x0 = x - i0; + float x1 = x0 - 1.0f; + float t1 = 1.0f - x1 * x1; + float n0, n1; + + float t0 = 1.0f - x0 * x0; +/* if(t0 < 0.0f) t0 = 0.0f; // this never happens for the 1D case */ + t0 *= t0; + n0 = t0 * t0 * grad1(perm[i0 & 0xff], x0); + +/* if(t1 < 0.0f) t1 = 0.0f; // this never happens for the 1D case */ + t1 *= t1; + n1 = t1 * t1 * grad1(perm[i1 & 0xff], x1); + /* The maximum value of this noise is 8*(3/4)^4 = 2.53125 */ + /* A factor of 0.395 would scale to fit exactly within [-1,1], but */ + /* we want to match PRMan's 1D noise, so we scale it down some more. */ + return 0.25f * (n0 + n1); +} + + +/** 2D simplex noise */ +GLfloat +_mesa_noise2(GLfloat x, GLfloat y) +{ +#define F2 0.366025403f /* F2 = 0.5*(sqrt(3.0)-1.0) */ +#define G2 0.211324865f /* G2 = (3.0-Math.sqrt(3.0))/6.0 */ + + float n0, n1, n2; /* Noise contributions from the three corners */ + + /* Skew the input space to determine which simplex cell we're in */ + float s = (x + y) * F2; /* Hairy factor for 2D */ + float xs = x + s; + float ys = y + s; + int i = FASTFLOOR(xs); + int j = FASTFLOOR(ys); + + float t = (float) (i + j) * G2; + float X0 = i - t; /* Unskew the cell origin back to (x,y) space */ + float Y0 = j - t; + float x0 = x - X0; /* The x,y distances from the cell origin */ + float y0 = y - Y0; + + float x1, y1, x2, y2; + int ii, jj; + float t0, t1, t2; + + /* For the 2D case, the simplex shape is an equilateral triangle. */ + /* Determine which simplex we are in. */ + int i1, j1; /* Offsets for second (middle) corner of simplex in (i,j) coords */ + if (x0 > y0) { + i1 = 1; + j1 = 0; + } /* lower triangle, XY order: (0,0)->(1,0)->(1,1) */ + else { + i1 = 0; + j1 = 1; + } /* upper triangle, YX order: (0,0)->(0,1)->(1,1) */ + + /* A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and */ + /* a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where */ + /* c = (3-sqrt(3))/6 */ + + x1 = x0 - i1 + G2; /* Offsets for middle corner in (x,y) unskewed coords */ + y1 = y0 - j1 + G2; + x2 = x0 - 1.0f + 2.0f * G2; /* Offsets for last corner in (x,y) unskewed coords */ + y2 = y0 - 1.0f + 2.0f * G2; + + /* Wrap the integer indices at 256, to avoid indexing perm[] out of bounds */ + ii = i % 256; + jj = j % 256; + + /* Calculate the contribution from the three corners */ + t0 = 0.5f - x0 * x0 - y0 * y0; + if (t0 < 0.0f) + n0 = 0.0f; + else { + t0 *= t0; + n0 = t0 * t0 * grad2(perm[ii + perm[jj]], x0, y0); + } + + t1 = 0.5f - x1 * x1 - y1 * y1; + if (t1 < 0.0f) + n1 = 0.0f; + else { + t1 *= t1; + n1 = t1 * t1 * grad2(perm[ii + i1 + perm[jj + j1]], x1, y1); + } + + t2 = 0.5f - x2 * x2 - y2 * y2; + if (t2 < 0.0f) + n2 = 0.0f; + else { + t2 *= t2; + n2 = t2 * t2 * grad2(perm[ii + 1 + perm[jj + 1]], x2, y2); + } + + /* Add contributions from each corner to get the final noise value. */ + /* The result is scaled to return values in the interval [-1,1]. */ + return 40.0f * (n0 + n1 + n2); /* TODO: The scale factor is preliminary! */ +} + + +/** 3D simplex noise */ +GLfloat +_mesa_noise3(GLfloat x, GLfloat y, GLfloat z) +{ +/* Simple skewing factors for the 3D case */ +#define F3 0.333333333f +#define G3 0.166666667f + + float n0, n1, n2, n3; /* Noise contributions from the four corners */ + + /* Skew the input space to determine which simplex cell we're in */ + float s = (x + y + z) * F3; /* Very nice and simple skew factor for 3D */ + float xs = x + s; + float ys = y + s; + float zs = z + s; + int i = FASTFLOOR(xs); + int j = FASTFLOOR(ys); + int k = FASTFLOOR(zs); + + float t = (float) (i + j + k) * G3; + float X0 = i - t; /* Unskew the cell origin back to (x,y,z) space */ + float Y0 = j - t; + float Z0 = k - t; + float x0 = x - X0; /* The x,y,z distances from the cell origin */ + float y0 = y - Y0; + float z0 = z - Z0; + + float x1, y1, z1, x2, y2, z2, x3, y3, z3; + int ii, jj, kk; + float t0, t1, t2, t3; + + /* For the 3D case, the simplex shape is a slightly irregular tetrahedron. */ + /* Determine which simplex we are in. */ + int i1, j1, k1; /* Offsets for second corner of simplex in (i,j,k) coords */ + int i2, j2, k2; /* Offsets for third corner of simplex in (i,j,k) coords */ + +/* This code would benefit from a backport from the GLSL version! */ + if (x0 >= y0) { + if (y0 >= z0) { + i1 = 1; + j1 = 0; + k1 = 0; + i2 = 1; + j2 = 1; + k2 = 0; + } /* X Y Z order */ + else if (x0 >= z0) { + i1 = 1; + j1 = 0; + k1 = 0; + i2 = 1; + j2 = 0; + k2 = 1; + } /* X Z Y order */ + else { + i1 = 0; + j1 = 0; + k1 = 1; + i2 = 1; + j2 = 0; + k2 = 1; + } /* Z X Y order */ + } + else { /* x0<y0 */ + if (y0 < z0) { + i1 = 0; + j1 = 0; + k1 = 1; + i2 = 0; + j2 = 1; + k2 = 1; + } /* Z Y X order */ + else if (x0 < z0) { + i1 = 0; + j1 = 1; + k1 = 0; + i2 = 0; + j2 = 1; + k2 = 1; + } /* Y Z X order */ + else { + i1 = 0; + j1 = 1; + k1 = 0; + i2 = 1; + j2 = 1; + k2 = 0; + } /* Y X Z order */ + } + + /* A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in + * (x,y,z), a step of (0,1,0) in (i,j,k) means a step of + * (-c,1-c,-c) in (x,y,z), and a step of (0,0,1) in (i,j,k) means a + * step of (-c,-c,1-c) in (x,y,z), where c = 1/6. + */ + + x1 = x0 - i1 + G3; /* Offsets for second corner in (x,y,z) coords */ + y1 = y0 - j1 + G3; + z1 = z0 - k1 + G3; + x2 = x0 - i2 + 2.0f * G3; /* Offsets for third corner in (x,y,z) coords */ + y2 = y0 - j2 + 2.0f * G3; + z2 = z0 - k2 + 2.0f * G3; + x3 = x0 - 1.0f + 3.0f * G3;/* Offsets for last corner in (x,y,z) coords */ + y3 = y0 - 1.0f + 3.0f * G3; + z3 = z0 - 1.0f + 3.0f * G3; + + /* Wrap the integer indices at 256 to avoid indexing perm[] out of bounds */ + ii = i % 256; + jj = j % 256; + kk = k % 256; + + /* Calculate the contribution from the four corners */ + t0 = 0.6f - x0 * x0 - y0 * y0 - z0 * z0; + if (t0 < 0.0f) + n0 = 0.0f; + else { + t0 *= t0; + n0 = t0 * t0 * grad3(perm[ii + perm[jj + perm[kk]]], x0, y0, z0); + } + + t1 = 0.6f - x1 * x1 - y1 * y1 - z1 * z1; + if (t1 < 0.0f) + n1 = 0.0f; + else { + t1 *= t1; + n1 = + t1 * t1 * grad3(perm[ii + i1 + perm[jj + j1 + perm[kk + k1]]], x1, + y1, z1); + } + + t2 = 0.6f - x2 * x2 - y2 * y2 - z2 * z2; + if (t2 < 0.0f) + n2 = 0.0f; + else { + t2 *= t2; + n2 = + t2 * t2 * grad3(perm[ii + i2 + perm[jj + j2 + perm[kk + k2]]], x2, + y2, z2); + } + + t3 = 0.6f - x3 * x3 - y3 * y3 - z3 * z3; + if (t3 < 0.0f) + n3 = 0.0f; + else { + t3 *= t3; + n3 = + t3 * t3 * grad3(perm[ii + 1 + perm[jj + 1 + perm[kk + 1]]], x3, y3, + z3); + } + + /* Add contributions from each corner to get the final noise value. + * The result is scaled to stay just inside [-1,1] + */ + return 32.0f * (n0 + n1 + n2 + n3); /* TODO: The scale factor is preliminary! */ +} + + +/** 4D simplex noise */ +GLfloat +_mesa_noise4(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + /* The skewing and unskewing factors are hairy again for the 4D case */ +#define F4 0.309016994f /* F4 = (Math.sqrt(5.0)-1.0)/4.0 */ +#define G4 0.138196601f /* G4 = (5.0-Math.sqrt(5.0))/20.0 */ + + float n0, n1, n2, n3, n4; /* Noise contributions from the five corners */ + + /* Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in */ + float s = (x + y + z + w) * F4; /* Factor for 4D skewing */ + float xs = x + s; + float ys = y + s; + float zs = z + s; + float ws = w + s; + int i = FASTFLOOR(xs); + int j = FASTFLOOR(ys); + int k = FASTFLOOR(zs); + int l = FASTFLOOR(ws); + + float t = (i + j + k + l) * G4; /* Factor for 4D unskewing */ + float X0 = i - t; /* Unskew the cell origin back to (x,y,z,w) space */ + float Y0 = j - t; + float Z0 = k - t; + float W0 = l - t; + + float x0 = x - X0; /* The x,y,z,w distances from the cell origin */ + float y0 = y - Y0; + float z0 = z - Z0; + float w0 = w - W0; + + /* For the 4D case, the simplex is a 4D shape I won't even try to describe. + * To find out which of the 24 possible simplices we're in, we need to + * determine the magnitude ordering of x0, y0, z0 and w0. + * The method below is a good way of finding the ordering of x,y,z,w and + * then find the correct traversal order for the simplex we're in. + * First, six pair-wise comparisons are performed between each possible pair + * of the four coordinates, and the results are used to add up binary bits + * for an integer index. + */ + int c1 = (x0 > y0) ? 32 : 0; + int c2 = (x0 > z0) ? 16 : 0; + int c3 = (y0 > z0) ? 8 : 0; + int c4 = (x0 > w0) ? 4 : 0; + int c5 = (y0 > w0) ? 2 : 0; + int c6 = (z0 > w0) ? 1 : 0; + int c = c1 + c2 + c3 + c4 + c5 + c6; + + int i1, j1, k1, l1; /* The integer offsets for the second simplex corner */ + int i2, j2, k2, l2; /* The integer offsets for the third simplex corner */ + int i3, j3, k3, l3; /* The integer offsets for the fourth simplex corner */ + + float x1, y1, z1, w1, x2, y2, z2, w2, x3, y3, z3, w3, x4, y4, z4, w4; + int ii, jj, kk, ll; + float t0, t1, t2, t3, t4; + + /* + * simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some + * order. Many values of c will never occur, since e.g. x>y>z>w + * makes x<z, y<w and x<w impossible. Only the 24 indices which + * have non-zero entries make any sense. We use a thresholding to + * set the coordinates in turn from the largest magnitude. The + * number 3 in the "simplex" array is at the position of the + * largest coordinate. + */ + i1 = simplex[c][0] >= 3 ? 1 : 0; + j1 = simplex[c][1] >= 3 ? 1 : 0; + k1 = simplex[c][2] >= 3 ? 1 : 0; + l1 = simplex[c][3] >= 3 ? 1 : 0; + /* The number 2 in the "simplex" array is at the second largest coordinate. */ + i2 = simplex[c][0] >= 2 ? 1 : 0; + j2 = simplex[c][1] >= 2 ? 1 : 0; + k2 = simplex[c][2] >= 2 ? 1 : 0; + l2 = simplex[c][3] >= 2 ? 1 : 0; + /* The number 1 in the "simplex" array is at the second smallest coordinate. */ + i3 = simplex[c][0] >= 1 ? 1 : 0; + j3 = simplex[c][1] >= 1 ? 1 : 0; + k3 = simplex[c][2] >= 1 ? 1 : 0; + l3 = simplex[c][3] >= 1 ? 1 : 0; + /* The fifth corner has all coordinate offsets = 1, so no need to look that up. */ + + x1 = x0 - i1 + G4; /* Offsets for second corner in (x,y,z,w) coords */ + y1 = y0 - j1 + G4; + z1 = z0 - k1 + G4; + w1 = w0 - l1 + G4; + x2 = x0 - i2 + 2.0f * G4; /* Offsets for third corner in (x,y,z,w) coords */ + y2 = y0 - j2 + 2.0f * G4; + z2 = z0 - k2 + 2.0f * G4; + w2 = w0 - l2 + 2.0f * G4; + x3 = x0 - i3 + 3.0f * G4; /* Offsets for fourth corner in (x,y,z,w) coords */ + y3 = y0 - j3 + 3.0f * G4; + z3 = z0 - k3 + 3.0f * G4; + w3 = w0 - l3 + 3.0f * G4; + x4 = x0 - 1.0f + 4.0f * G4; /* Offsets for last corner in (x,y,z,w) coords */ + y4 = y0 - 1.0f + 4.0f * G4; + z4 = z0 - 1.0f + 4.0f * G4; + w4 = w0 - 1.0f + 4.0f * G4; + + /* Wrap the integer indices at 256, to avoid indexing perm[] out of bounds */ + ii = i % 256; + jj = j % 256; + kk = k % 256; + ll = l % 256; + + /* Calculate the contribution from the five corners */ + t0 = 0.6f - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0; + if (t0 < 0.0f) + n0 = 0.0f; + else { + t0 *= t0; + n0 = + t0 * t0 * grad4(perm[ii + perm[jj + perm[kk + perm[ll]]]], x0, y0, + z0, w0); + } + + t1 = 0.6f - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1; + if (t1 < 0.0f) + n1 = 0.0f; + else { + t1 *= t1; + n1 = + t1 * t1 * + grad4(perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]], + x1, y1, z1, w1); + } + + t2 = 0.6f - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2; + if (t2 < 0.0f) + n2 = 0.0f; + else { + t2 *= t2; + n2 = + t2 * t2 * + grad4(perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]], + x2, y2, z2, w2); + } + + t3 = 0.6f - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3; + if (t3 < 0.0f) + n3 = 0.0f; + else { + t3 *= t3; + n3 = + t3 * t3 * + grad4(perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]], + x3, y3, z3, w3); + } + + t4 = 0.6f - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4; + if (t4 < 0.0f) + n4 = 0.0f; + else { + t4 *= t4; + n4 = + t4 * t4 * + grad4(perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]], x4, + y4, z4, w4); + } + + /* Sum up and scale the result to cover the range [-1,1] */ + return 27.0f * (n0 + n1 + n2 + n3 + n4); /* TODO: The scale factor is preliminary! */ +} diff --git a/src/mesa/shader/slang/slang_library_noise.h b/src/mesa/shader/prog_noise.h index da7367c1ce..c4779479f9 100644 --- a/src/mesa/shader/slang/slang_library_noise.h +++ b/src/mesa/shader/prog_noise.h @@ -22,21 +22,13 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#if !defined SLANG_LIBRARY_NOISE_H -#define SLANG_LIBRARY_NOISE_H +#ifndef PROG_NOISE +#define PROG_NOISE -#if defined __cplusplus -extern "C" { -#endif - -GLfloat _slang_library_noise1 (GLfloat); -GLfloat _slang_library_noise2 (GLfloat, GLfloat); -GLfloat _slang_library_noise3 (GLfloat, GLfloat, GLfloat); -GLfloat _slang_library_noise4 (GLfloat, GLfloat, GLfloat, GLfloat); - -#ifdef __cplusplus -} -#endif +extern GLfloat _mesa_noise1(GLfloat); +extern GLfloat _mesa_noise2(GLfloat, GLfloat); +extern GLfloat _mesa_noise3(GLfloat, GLfloat, GLfloat); +extern GLfloat _mesa_noise4(GLfloat, GLfloat, GLfloat, GLfloat); #endif diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c index 29b4d90a3e..516ea73301 100644 --- a/src/mesa/shader/prog_print.c +++ b/src/mesa/shader/prog_print.c @@ -3,6 +3,7 @@ * Version: 7.3 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. 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"), @@ -71,6 +72,8 @@ file_string(enum register_file f, gl_prog_print_mode mode) return "ADDR"; case PROGRAM_SAMPLER: return "SAMPLER"; + case PROGRAM_UNDEFINED: + return "UNDEFINED"; default: return "Unknown program file!"; } @@ -209,54 +212,52 @@ reg_string(enum register_file f, GLint index, gl_prog_print_mode mode, GLboolean relAddr, const struct gl_program *prog) { static char str[100]; + const char *addr = relAddr ? "ADDR+" : ""; str[0] = 0; switch (mode) { case PROG_PRINT_DEBUG: - if (relAddr) - sprintf(str, "%s[ADDR+%d]", file_string(f, mode), index); - else - sprintf(str, "%s[%d]", file_string(f, mode), index); + _mesa_sprintf(str, "%s[%s%d]", file_string(f, mode), addr, index); break; case PROG_PRINT_ARB: switch (f) { case PROGRAM_INPUT: - sprintf(str, "%s", arb_input_attrib_string(index, prog->Target)); + _mesa_sprintf(str, "%s", arb_input_attrib_string(index, prog->Target)); break; case PROGRAM_OUTPUT: - sprintf(str, "%s", arb_output_attrib_string(index, prog->Target)); + _mesa_sprintf(str, "%s", arb_output_attrib_string(index, prog->Target)); break; case PROGRAM_TEMPORARY: - sprintf(str, "temp%d", index); + _mesa_sprintf(str, "temp%d", index); break; case PROGRAM_ENV_PARAM: - sprintf(str, "program.env[%d]", index); + _mesa_sprintf(str, "program.env[%s%d]", addr, index); break; case PROGRAM_LOCAL_PARAM: - sprintf(str, "program.local[%d]", index); + _mesa_sprintf(str, "program.local[%s%d]", addr, index); break; case PROGRAM_VARYING: /* extension */ - sprintf(str, "varying[%d]", index); + _mesa_sprintf(str, "varying[%s%d]", addr, index); break; case PROGRAM_CONSTANT: /* extension */ - sprintf(str, "constant[%d]", index); + _mesa_sprintf(str, "constant[%s%d]", addr, index); break; case PROGRAM_UNIFORM: /* extension */ - sprintf(str, "uniform[%d]", index); + _mesa_sprintf(str, "uniform[%s%d]", addr, index); break; case PROGRAM_STATE_VAR: { struct gl_program_parameter *param = prog->Parameters->Parameters + index; char *state = _mesa_program_state_string(param->StateIndexes); - sprintf(str, state); + _mesa_sprintf(str, state); _mesa_free(state); } break; case PROGRAM_ADDRESS: - sprintf(str, "A%d", index); + _mesa_sprintf(str, "A%d", index); break; default: _mesa_problem(NULL, "bad file in reg_string()"); @@ -267,30 +268,30 @@ reg_string(enum register_file f, GLint index, gl_prog_print_mode mode, switch (f) { case PROGRAM_INPUT: if (prog->Target == GL_VERTEX_PROGRAM_ARB) - sprintf(str, "v[%d]", index); + _mesa_sprintf(str, "v[%d]", index); else - sprintf(str, "f[%d]", index); + _mesa_sprintf(str, "f[%d]", index); break; case PROGRAM_OUTPUT: - sprintf(str, "o[%d]", index); + _mesa_sprintf(str, "o[%d]", index); break; case PROGRAM_TEMPORARY: - sprintf(str, "R%d", index); + _mesa_sprintf(str, "R%d", index); break; case PROGRAM_ENV_PARAM: - sprintf(str, "c[%d]", index); + _mesa_sprintf(str, "c[%d]", index); break; case PROGRAM_VARYING: /* extension */ - sprintf(str, "varying[%d]", index); + _mesa_sprintf(str, "varying[%s%d]", addr, index); break; case PROGRAM_UNIFORM: /* extension */ - sprintf(str, "uniform[%d]", index); + _mesa_sprintf(str, "uniform[%s%d]", addr, index); break; case PROGRAM_CONSTANT: /* extension */ - sprintf(str, "constant[%d]", index); + _mesa_sprintf(str, "constant[%s%d]", addr, index); break; case PROGRAM_STATE_VAR: /* extension */ - sprintf(str, "state[%d]", index); + _mesa_sprintf(str, "state[%s%d]", addr, index); break; default: _mesa_problem(NULL, "bad file in reg_string()"); @@ -414,90 +415,98 @@ _mesa_condcode_string(GLuint condcode) static void -print_dst_reg(const struct prog_dst_register *dstReg, gl_prog_print_mode mode, - const struct gl_program *prog) +fprint_dst_reg(FILE * f, + const struct prog_dst_register *dstReg, + gl_prog_print_mode mode, + const struct gl_program *prog) { - _mesa_printf("%s%s", - reg_string((enum register_file) dstReg->File, - dstReg->Index, mode, dstReg->RelAddr, prog), - _mesa_writemask_string(dstReg->WriteMask)); + _mesa_fprintf(f, "%s%s", + reg_string((enum register_file) dstReg->File, + dstReg->Index, mode, dstReg->RelAddr, prog), + _mesa_writemask_string(dstReg->WriteMask)); if (dstReg->CondMask != COND_TR) { - _mesa_printf(" (%s.%s)", - _mesa_condcode_string(dstReg->CondMask), - _mesa_swizzle_string(dstReg->CondSwizzle, GL_FALSE, GL_FALSE)); + _mesa_fprintf(f, " (%s.%s)", + _mesa_condcode_string(dstReg->CondMask), + _mesa_swizzle_string(dstReg->CondSwizzle, + GL_FALSE, GL_FALSE)); } #if 0 - _mesa_printf("%s[%d]%s", + _mesa_fprintf(f, "%s[%d]%s", file_string((enum register_file) dstReg->File, mode), dstReg->Index, _mesa_writemask_string(dstReg->WriteMask)); #endif } + static void -print_src_reg(const struct prog_src_register *srcReg, gl_prog_print_mode mode, - const struct gl_program *prog) +fprint_src_reg(FILE *f, + const struct prog_src_register *srcReg, + gl_prog_print_mode mode, + const struct gl_program *prog) { - _mesa_printf("%s%s", - reg_string((enum register_file) srcReg->File, - srcReg->Index, mode, srcReg->RelAddr, prog), - _mesa_swizzle_string(srcReg->Swizzle, - srcReg->NegateBase, GL_FALSE)); + _mesa_fprintf(f, "%s%s", + reg_string((enum register_file) srcReg->File, + srcReg->Index, mode, srcReg->RelAddr, prog), + _mesa_swizzle_string(srcReg->Swizzle, + srcReg->NegateBase, GL_FALSE)); #if 0 - _mesa_printf("%s[%d]%s", - file_string((enum register_file) srcReg->File, mode), - srcReg->Index, - _mesa_swizzle_string(srcReg->Swizzle, - srcReg->NegateBase, GL_FALSE)); + _mesa_fprintf(f, "%s[%d]%s", + file_string((enum register_file) srcReg->File, mode), + srcReg->Index, + _mesa_swizzle_string(srcReg->Swizzle, + srcReg->NegateBase, GL_FALSE)); #endif } + static void -print_comment(const struct prog_instruction *inst) +fprint_comment(FILE *f, const struct prog_instruction *inst) { if (inst->Comment) - _mesa_printf("; # %s\n", inst->Comment); + _mesa_fprintf(f, "; # %s\n", inst->Comment); else - _mesa_printf(";\n"); + _mesa_fprintf(f, ";\n"); } static void -print_alu_instruction(const struct prog_instruction *inst, - const char *opcode_string, GLuint numRegs, - gl_prog_print_mode mode, - const struct gl_program *prog) +fprint_alu_instruction(FILE *f, + const struct prog_instruction *inst, + const char *opcode_string, GLuint numRegs, + gl_prog_print_mode mode, + const struct gl_program *prog) { GLuint j; - _mesa_printf("%s", opcode_string); + _mesa_fprintf(f, "%s", opcode_string); if (inst->CondUpdate) - _mesa_printf(".C"); + _mesa_fprintf(f, ".C"); /* frag prog only */ if (inst->SaturateMode == SATURATE_ZERO_ONE) - _mesa_printf("_SAT"); + _mesa_fprintf(f, "_SAT"); - _mesa_printf(" "); + _mesa_fprintf(f, " "); if (inst->DstReg.File != PROGRAM_UNDEFINED) { - print_dst_reg(&inst->DstReg, mode, prog); + fprint_dst_reg(f, &inst->DstReg, mode, prog); } else { - _mesa_printf(" ???"); + _mesa_fprintf(f, " ???"); } if (numRegs > 0) - _mesa_printf(", "); + _mesa_fprintf(f, ", "); for (j = 0; j < numRegs; j++) { - print_src_reg(inst->SrcReg + j, mode, prog); + fprint_src_reg(f, inst->SrcReg + j, mode, prog); if (j + 1 < numRegs) - _mesa_printf(", "); + _mesa_fprintf(f, ", "); } - print_comment(inst); + fprint_comment(f, inst); } @@ -505,23 +514,18 @@ void _mesa_print_alu_instruction(const struct prog_instruction *inst, const char *opcode_string, GLuint numRegs) { - print_alu_instruction(inst, opcode_string, numRegs, PROG_PRINT_DEBUG, NULL); -} - - -void -_mesa_print_instruction(const struct prog_instruction *inst) -{ - /* note: 4th param should be ignored for PROG_PRINT_DEBUG */ - _mesa_print_instruction_opt(inst, 0, PROG_PRINT_DEBUG, NULL); + fprint_alu_instruction(stdout, inst, opcode_string, + numRegs, PROG_PRINT_DEBUG, NULL); } /** * Print a single vertex/fragment program instruction. */ -GLint -_mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent, +static GLint +_mesa_fprint_instruction_opt(FILE *f, + const struct prog_instruction *inst, + GLint indent, gl_prog_print_mode mode, const struct gl_program *prog) { @@ -534,15 +538,15 @@ _mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent, indent -= 3; } for (i = 0; i < indent; i++) { - _mesa_printf(" "); + _mesa_fprintf(f, " "); } switch (inst->Opcode) { case OPCODE_PRINT: - _mesa_printf("PRINT '%s'", inst->Data); + _mesa_fprintf(f, "PRINT '%s'", inst->Data); if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { - _mesa_printf(", "); - _mesa_printf("%s[%d]%s", + _mesa_fprintf(f, ", "); + _mesa_fprintf(f, "%s[%d]%s", file_string((enum register_file) inst->SrcReg[0].File, mode), inst->SrcReg[0].Index, @@ -550,259 +554,295 @@ _mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent, inst->SrcReg[0].NegateBase, GL_FALSE)); } if (inst->Comment) - _mesa_printf(" # %s", inst->Comment); - print_comment(inst); + _mesa_fprintf(f, " # %s", inst->Comment); + fprint_comment(f, inst); break; case OPCODE_SWZ: - _mesa_printf("SWZ"); + _mesa_fprintf(f, "SWZ"); if (inst->SaturateMode == SATURATE_ZERO_ONE) - _mesa_printf("_SAT"); - _mesa_printf(" "); - print_dst_reg(&inst->DstReg, mode, prog); - _mesa_printf(", %s[%d], %s", + _mesa_fprintf(f, "_SAT"); + _mesa_fprintf(f, " "); + fprint_dst_reg(f, &inst->DstReg, mode, prog); + _mesa_fprintf(f, ", %s[%d], %s", file_string((enum register_file) inst->SrcReg[0].File, mode), inst->SrcReg[0].Index, _mesa_swizzle_string(inst->SrcReg[0].Swizzle, inst->SrcReg[0].NegateBase, GL_TRUE)); - print_comment(inst); + fprint_comment(f, inst); break; case OPCODE_TEX: case OPCODE_TXP: case OPCODE_TXL: case OPCODE_TXB: - _mesa_printf("%s", _mesa_opcode_string(inst->Opcode)); + _mesa_fprintf(f, "%s", _mesa_opcode_string(inst->Opcode)); if (inst->SaturateMode == SATURATE_ZERO_ONE) - _mesa_printf("_SAT"); - _mesa_printf(" "); - print_dst_reg(&inst->DstReg, mode, prog); - _mesa_printf(", "); - print_src_reg(&inst->SrcReg[0], mode, prog); - _mesa_printf(", texture[%d], ", inst->TexSrcUnit); + _mesa_fprintf(f, "_SAT"); + _mesa_fprintf(f, " "); + fprint_dst_reg(f, &inst->DstReg, mode, prog); + _mesa_fprintf(f, ", "); + fprint_src_reg(f, &inst->SrcReg[0], mode, prog); + _mesa_fprintf(f, ", texture[%d], ", inst->TexSrcUnit); switch (inst->TexSrcTarget) { - case TEXTURE_1D_INDEX: _mesa_printf("1D"); break; - case TEXTURE_2D_INDEX: _mesa_printf("2D"); break; - case TEXTURE_3D_INDEX: _mesa_printf("3D"); break; - case TEXTURE_CUBE_INDEX: _mesa_printf("CUBE"); break; - case TEXTURE_RECT_INDEX: _mesa_printf("RECT"); break; + case TEXTURE_1D_INDEX: _mesa_fprintf(f, "1D"); break; + case TEXTURE_2D_INDEX: _mesa_fprintf(f, "2D"); break; + case TEXTURE_3D_INDEX: _mesa_fprintf(f, "3D"); break; + case TEXTURE_CUBE_INDEX: _mesa_fprintf(f, "CUBE"); break; + case TEXTURE_RECT_INDEX: _mesa_fprintf(f, "RECT"); break; default: ; } - print_comment(inst); + fprint_comment(f, inst); break; case OPCODE_KIL: - _mesa_printf("%s", _mesa_opcode_string(inst->Opcode)); - _mesa_printf(" "); - print_src_reg(&inst->SrcReg[0], mode, prog); - print_comment(inst); + _mesa_fprintf(f, "%s", _mesa_opcode_string(inst->Opcode)); + _mesa_fprintf(f, " "); + fprint_src_reg(f, &inst->SrcReg[0], mode, prog); + fprint_comment(f, inst); break; case OPCODE_KIL_NV: - _mesa_printf("%s", _mesa_opcode_string(inst->Opcode)); - _mesa_printf(" "); - _mesa_printf("%s.%s", + _mesa_fprintf(f, "%s", _mesa_opcode_string(inst->Opcode)); + _mesa_fprintf(f, " "); + _mesa_fprintf(f, "%s.%s", _mesa_condcode_string(inst->DstReg.CondMask), _mesa_swizzle_string(inst->DstReg.CondSwizzle, GL_FALSE, GL_FALSE)); - print_comment(inst); + fprint_comment(f, inst); break; case OPCODE_ARL: - _mesa_printf("ARL "); - print_dst_reg(&inst->DstReg, mode, prog); - _mesa_printf(", "); - print_src_reg(&inst->SrcReg[0], mode, prog); - print_comment(inst); + _mesa_fprintf(f, "ARL "); + fprint_dst_reg(f, &inst->DstReg, mode, prog); + _mesa_fprintf(f, ", "); + fprint_src_reg(f, &inst->SrcReg[0], mode, prog); + fprint_comment(f, inst); break; case OPCODE_BRA: - _mesa_printf("BRA %d (%s%s)", + _mesa_fprintf(f, "BRA %d (%s%s)", inst->BranchTarget, _mesa_condcode_string(inst->DstReg.CondMask), _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE)); - print_comment(inst); + fprint_comment(f, inst); break; case OPCODE_IF: if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { /* Use ordinary register */ - _mesa_printf("IF "); - print_src_reg(&inst->SrcReg[0], mode, prog); - _mesa_printf("; "); + _mesa_fprintf(f, "IF "); + fprint_src_reg(f, &inst->SrcReg[0], mode, prog); + _mesa_fprintf(f, "; "); } else { /* Use cond codes */ - _mesa_printf("IF (%s%s);", + _mesa_fprintf(f, "IF (%s%s);", _mesa_condcode_string(inst->DstReg.CondMask), _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE)); } - _mesa_printf(" # (if false, goto %d)", inst->BranchTarget); - print_comment(inst); + _mesa_fprintf(f, " # (if false, goto %d)", inst->BranchTarget); + fprint_comment(f, inst); return indent + 3; case OPCODE_ELSE: - _mesa_printf("ELSE; # (goto %d)\n", inst->BranchTarget); + _mesa_fprintf(f, "ELSE; # (goto %d)\n", inst->BranchTarget); return indent + 3; case OPCODE_ENDIF: - _mesa_printf("ENDIF;\n"); + _mesa_fprintf(f, "ENDIF;\n"); break; case OPCODE_BGNLOOP: - _mesa_printf("BGNLOOP; # (end at %d)\n", inst->BranchTarget); + _mesa_fprintf(f, "BGNLOOP; # (end at %d)\n", inst->BranchTarget); return indent + 3; case OPCODE_ENDLOOP: - _mesa_printf("ENDLOOP; # (goto %d)\n", inst->BranchTarget); + _mesa_fprintf(f, "ENDLOOP; # (goto %d)\n", inst->BranchTarget); break; case OPCODE_BRK: case OPCODE_CONT: - _mesa_printf("%s (%s%s); # (goto %d)", + _mesa_fprintf(f, "%s (%s%s); # (goto %d)", _mesa_opcode_string(inst->Opcode), _mesa_condcode_string(inst->DstReg.CondMask), _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE), inst->BranchTarget); - print_comment(inst); + fprint_comment(f, inst); break; case OPCODE_BGNSUB: if (mode == PROG_PRINT_NV) { - _mesa_printf("%s:\n", inst->Comment); /* comment is label */ + _mesa_fprintf(f, "%s:\n", inst->Comment); /* comment is label */ return indent; } else { - _mesa_printf("BGNSUB"); - print_comment(inst); + _mesa_fprintf(f, "BGNSUB"); + fprint_comment(f, inst); return indent + 3; } case OPCODE_ENDSUB: if (mode == PROG_PRINT_DEBUG) { - _mesa_printf("ENDSUB"); - print_comment(inst); + _mesa_fprintf(f, "ENDSUB"); + fprint_comment(f, inst); } break; case OPCODE_CAL: if (mode == PROG_PRINT_NV) { - _mesa_printf("CAL %s; # (goto %d)\n", inst->Comment, inst->BranchTarget); + _mesa_fprintf(f, "CAL %s; # (goto %d)\n", inst->Comment, inst->BranchTarget); } else { - _mesa_printf("CAL %u", inst->BranchTarget); - print_comment(inst); + _mesa_fprintf(f, "CAL %u", inst->BranchTarget); + fprint_comment(f, inst); } break; case OPCODE_RET: - _mesa_printf("RET (%s%s)", + _mesa_fprintf(f, "RET (%s%s)", _mesa_condcode_string(inst->DstReg.CondMask), _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE)); - print_comment(inst); + fprint_comment(f, inst); break; case OPCODE_END: - _mesa_printf("END\n"); + _mesa_fprintf(f, "END\n"); break; case OPCODE_NOP: if (mode == PROG_PRINT_DEBUG) { - _mesa_printf("NOP"); - print_comment(inst); + _mesa_fprintf(f, "NOP"); + fprint_comment(f, inst); } else if (inst->Comment) { /* ARB/NV extensions don't have NOP instruction */ - _mesa_printf("# %s\n", inst->Comment); + _mesa_fprintf(f, "# %s\n", inst->Comment); } break; /* XXX may need other special-case instructions */ default: /* typical alu instruction */ - print_alu_instruction(inst, - _mesa_opcode_string(inst->Opcode), - _mesa_num_inst_src_regs(inst->Opcode), - mode, prog); + fprint_alu_instruction(f, inst, + _mesa_opcode_string(inst->Opcode), + _mesa_num_inst_src_regs(inst->Opcode), + mode, prog); break; } return indent; } -/** - * Print program to stdout, default options. - */ +GLint +_mesa_print_instruction_opt(const struct prog_instruction *inst, + GLint indent, + gl_prog_print_mode mode, + const struct gl_program *prog) +{ + return _mesa_fprint_instruction_opt(stdout, inst, indent, mode, prog); +} + + void -_mesa_print_program(const struct gl_program *prog) +_mesa_print_instruction(const struct prog_instruction *inst) { - _mesa_print_program_opt(prog, PROG_PRINT_DEBUG, GL_TRUE); + /* note: 4th param should be ignored for PROG_PRINT_DEBUG */ + _mesa_fprint_instruction_opt(stdout, inst, 0, PROG_PRINT_DEBUG, NULL); } + /** * Print program, with options. */ void -_mesa_print_program_opt(const struct gl_program *prog, - gl_prog_print_mode mode, - GLboolean lineNumbers) +_mesa_fprint_program_opt(FILE *f, + const struct gl_program *prog, + gl_prog_print_mode mode, + GLboolean lineNumbers) { GLuint i, indent = 0; switch (prog->Target) { case GL_VERTEX_PROGRAM_ARB: if (mode == PROG_PRINT_ARB) - _mesa_printf("!!ARBvp1.0\n"); + _mesa_fprintf(f, "!!ARBvp1.0\n"); else if (mode == PROG_PRINT_NV) - _mesa_printf("!!VP1.0\n"); + _mesa_fprintf(f, "!!VP1.0\n"); else - _mesa_printf("# Vertex Program/Shader\n"); + _mesa_fprintf(f, "# Vertex Program/Shader\n"); break; case GL_FRAGMENT_PROGRAM_ARB: case GL_FRAGMENT_PROGRAM_NV: if (mode == PROG_PRINT_ARB) - _mesa_printf("!!ARBfp1.0\n"); + _mesa_fprintf(f, "!!ARBfp1.0\n"); else if (mode == PROG_PRINT_NV) - _mesa_printf("!!FP1.0\n"); + _mesa_fprintf(f, "!!FP1.0\n"); else - _mesa_printf("# Fragment Program/Shader\n"); + _mesa_fprintf(f, "# Fragment Program/Shader\n"); break; } for (i = 0; i < prog->NumInstructions; i++) { if (lineNumbers) - _mesa_printf("%3d: ", i); - indent = _mesa_print_instruction_opt(prog->Instructions + i, + _mesa_fprintf(f, "%3d: ", i); + indent = _mesa_fprint_instruction_opt(f, prog->Instructions + i, indent, mode, prog); } } /** - * Print all of a program's parameters. + * Print program to stdout, default options. */ void -_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog) +_mesa_print_program(const struct gl_program *prog) +{ + _mesa_fprint_program_opt(stdout, prog, PROG_PRINT_DEBUG, GL_TRUE); +} + + +/** + * Print all of a program's parameters/fields to given file. + */ +static void +_mesa_fprint_program_parameters(FILE *f, + GLcontext *ctx, + const struct gl_program *prog) { GLuint i; - _mesa_printf("InputsRead: 0x%x\n", prog->InputsRead); - _mesa_printf("OutputsWritten: 0x%x\n", prog->OutputsWritten); - _mesa_printf("NumInstructions=%d\n", prog->NumInstructions); - _mesa_printf("NumTemporaries=%d\n", prog->NumTemporaries); - _mesa_printf("NumParameters=%d\n", prog->NumParameters); - _mesa_printf("NumAttributes=%d\n", prog->NumAttributes); - _mesa_printf("NumAddressRegs=%d\n", prog->NumAddressRegs); - _mesa_printf("Samplers=[ "); + _mesa_fprintf(f, "InputsRead: 0x%x\n", prog->InputsRead); + _mesa_fprintf(f, "OutputsWritten: 0x%x\n", prog->OutputsWritten); + _mesa_fprintf(f, "NumInstructions=%d\n", prog->NumInstructions); + _mesa_fprintf(f, "NumTemporaries=%d\n", prog->NumTemporaries); + _mesa_fprintf(f, "NumParameters=%d\n", prog->NumParameters); + _mesa_fprintf(f, "NumAttributes=%d\n", prog->NumAttributes); + _mesa_fprintf(f, "NumAddressRegs=%d\n", prog->NumAddressRegs); + _mesa_fprintf(f, "Samplers=[ "); for (i = 0; i < MAX_SAMPLERS; i++) { - _mesa_printf("%d ", prog->SamplerUnits[i]); + _mesa_fprintf(f, "%d ", prog->SamplerUnits[i]); } - _mesa_printf("]\n"); + _mesa_fprintf(f, "]\n"); _mesa_load_state_parameters(ctx, prog->Parameters); #if 0 - _mesa_printf("Local Params:\n"); + _mesa_fprintf(f, "Local Params:\n"); for (i = 0; i < MAX_PROGRAM_LOCAL_PARAMS; i++){ const GLfloat *p = prog->LocalParams[i]; - _mesa_printf("%2d: %f, %f, %f, %f\n", i, p[0], p[1], p[2], p[3]); + _mesa_fprintf(f, "%2d: %f, %f, %f, %f\n", i, p[0], p[1], p[2], p[3]); } #endif _mesa_print_parameter_list(prog->Parameters); } +/** + * Print all of a program's parameters/fields to stdout. + */ void -_mesa_print_parameter_list(const struct gl_program_parameter_list *list) +_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog) +{ + _mesa_fprint_program_parameters(stdout, ctx, prog); +} + + +/** + * Print a program parameter list to given file. + */ +static void +_mesa_fprint_parameter_list(FILE *f, + const struct gl_program_parameter_list *list) { const gl_prog_print_mode mode = PROG_PRINT_DEBUG; GLuint i; @@ -810,22 +850,77 @@ _mesa_print_parameter_list(const struct gl_program_parameter_list *list) if (!list) return; - _mesa_printf("param list %p\n", (void *) list); + _mesa_fprintf(f, "param list %p\n", (void *) list); for (i = 0; i < list->NumParameters; i++){ struct gl_program_parameter *param = list->Parameters + i; const GLfloat *v = list->ParameterValues[i]; - _mesa_printf("param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g}", + _mesa_fprintf(f, "param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g}", i, param->Size, file_string(list->Parameters[i].Type, mode), param->Name, v[0], v[1], v[2], v[3]); if (param->Flags & PROG_PARAM_BIT_CENTROID) - _mesa_printf(" Centroid"); + _mesa_fprintf(f, " Centroid"); if (param->Flags & PROG_PARAM_BIT_INVARIANT) - _mesa_printf(" Invariant"); + _mesa_fprintf(f, " Invariant"); if (param->Flags & PROG_PARAM_BIT_FLAT) - _mesa_printf(" Flat"); + _mesa_fprintf(f, " Flat"); if (param->Flags & PROG_PARAM_BIT_LINEAR) - _mesa_printf(" Linear"); - _mesa_printf("\n"); + _mesa_fprintf(f, " Linear"); + _mesa_fprintf(f, "\n"); } } + + +/** + * Print a program parameter list to stdout. + */ +void +_mesa_print_parameter_list(const struct gl_program_parameter_list *list) +{ + _mesa_fprint_parameter_list(stdout, list); +} + + +/** + * Write shader and associated info to a file. + */ +void +_mesa_write_shader_to_file(const struct gl_shader *shader) +{ + const char *type; + char filename[100]; + FILE *f; + + if (shader->Type == GL_FRAGMENT_SHADER) + type = "frag"; + else + type = "vert"; + + _mesa_snprintf(filename, strlen(filename), "shader_%u.%s", shader->Name, type); + f = fopen(filename, "w"); + if (!f) { + fprintf(stderr, "Unable to open %s for writing\n", filename); + return; + } + + fprintf(f, "/* Shader %u source */\n", shader->Name); + fputs(shader->Source, f); + fprintf(f, "\n"); + + fprintf(f, "/* Compile status: %s */\n", + shader->CompileStatus ? "ok" : "fail"); + if (!shader->CompileStatus) { + fprintf(f, "/* Log Info: */\n"); + fputs(shader->InfoLog, f); + } + else { + fprintf(f, "/* GPU code */\n"); + fprintf(f, "/*\n"); + _mesa_fprint_program_opt(f, shader->Program, PROG_PRINT_DEBUG, GL_TRUE); + fprintf(f, "*/\n"); + } + + fclose(f); +} + + diff --git a/src/mesa/shader/prog_print.h b/src/mesa/shader/prog_print.h index 3966909aed..d55661cebb 100644 --- a/src/mesa/shader/prog_print.h +++ b/src/mesa/shader/prog_print.h @@ -65,8 +65,9 @@ extern void _mesa_print_program(const struct gl_program *prog); extern void -_mesa_print_program_opt(const struct gl_program *prog, gl_prog_print_mode mode, - GLboolean lineNumbers); +_mesa_fprint_program_opt(FILE *f, + const struct gl_program *prog, gl_prog_print_mode mode, + GLboolean lineNumbers); extern void _mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog); @@ -75,4 +76,8 @@ extern void _mesa_print_parameter_list(const struct gl_program_parameter_list *list); +extern void +_mesa_write_shader_to_file(const struct gl_shader *shader); + + #endif /* PROG_PRINT_H */ diff --git a/src/mesa/shader/prog_statevars.c b/src/mesa/shader/prog_statevars.c index 9cc33fa2c1..e1db30b78f 100644 --- a/src/mesa/shader/prog_statevars.c +++ b/src/mesa/shader/prog_statevars.c @@ -131,7 +131,7 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], ADD_3V(value, p, eye_z); NORMALIZE_3FV(value); value[3] = 1.0; - } + } return; default: _mesa_problem(ctx, "Invalid light state in fetch_state"); @@ -235,11 +235,11 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], } } case STATE_TEXENV_COLOR: - { + { /* state[1] is the texture unit */ const GLuint unit = (GLuint) state[1]; COPY_4V(value, ctx->Texture.Unit[unit].EnvColor); - } + } return; case STATE_FOG_COLOR: COPY_4V(value, ctx->Fog.Color); @@ -369,7 +369,7 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], } } return; - + case STATE_VERTEX_PROGRAM: { /* state[1] = {STATE_ENV, STATE_LOCAL} */ @@ -475,7 +475,6 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], } - case STATE_PT_SCALE: value[0] = ctx->Pixel.RedScale; value[1] = ctx->Pixel.GreenScale; @@ -494,6 +493,19 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], case STATE_PCM_BIAS: COPY_4V(value, ctx->Pixel.PostColorMatrixBias); break; + case STATE_SHADOW_AMBIENT: + { + const int unit = (int) state[2]; + const struct gl_texture_object *texObj + = ctx->Texture.Unit[unit]._Current; + if (texObj) { + value[0] = + value[1] = + value[2] = + value[3] = texObj->CompareFailValue; + } + } + return; /* XXX: make sure new tokens added here are also handled in the * _mesa_program_state_flags() switch, below. @@ -578,6 +590,7 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]) return _NEW_MODELVIEW; case STATE_TEXRECT_SCALE: + case STATE_SHADOW_AMBIENT: return _NEW_TEXTURE; case STATE_FOG_PARAMS_OPTIMIZED: return _NEW_FOG; @@ -618,6 +631,9 @@ append(char *dst, const char *src) } +/** + * Convert token 'k' to a string, append it onto 'dst' string. + */ static void append_token(char *dst, gl_state_index k) { @@ -750,11 +766,30 @@ append_token(char *dst, gl_state_index k) case STATE_LOCAL: append(dst, "local"); break; + /* BEGIN internal state vars */ + case STATE_INTERNAL: + append(dst, "(internal)"); + break; case STATE_NORMAL_SCALE: append(dst, "normalScale"); break; - case STATE_INTERNAL: - append(dst, "(internal)"); + case STATE_TEXRECT_SCALE: + append(dst, "texrectScale"); + break; + case STATE_FOG_PARAMS_OPTIMIZED: + append(dst, "fogParamsOptimized"); + break; + case STATE_LIGHT_SPOT_DIR_NORMALIZED: + append(dst, "lightSpotDirNormalized"); + break; + case STATE_LIGHT_POSITION: + append(dst, "lightPosition"); + break; + case STATE_LIGHT_POSITION_NORMALIZED: + append(dst, "light.position.normalized"); + break; + case STATE_LIGHT_HALF_VECTOR: + append(dst, "lightHalfVector"); break; case STATE_PT_SCALE: append(dst, "PTscale"); @@ -768,8 +803,12 @@ append_token(char *dst, gl_state_index k) case STATE_PCM_BIAS: append(dst, "PCMbias"); break; + case STATE_SHADOW_AMBIENT: + append(dst, "CompareFailValue"); + break; default: - ; + /* probably STATE_INTERNAL_DRIVER+i (driver private state) */ + append(dst, "driverState"); } } @@ -802,16 +841,16 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) char tmp[30]; append(str, "state."); - append_token(str, (gl_state_index) state[0]); + append_token(str, state[0]); switch (state[0]) { case STATE_MATERIAL: append_face(str, state[1]); - append_token(str, (gl_state_index) state[2]); + append_token(str, state[2]); break; case STATE_LIGHT: append_index(str, state[1]); /* light number [i]. */ - append_token(str, (gl_state_index) state[2]); /* coefficients */ + append_token(str, state[2]); /* coefficients */ break; case STATE_LIGHTMODEL_AMBIENT: append(str, "lightmodel.ambient"); @@ -827,11 +866,11 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) case STATE_LIGHTPROD: append_index(str, state[1]); /* light number [i]. */ append_face(str, state[2]); - append_token(str, (gl_state_index) state[3]); + append_token(str, state[3]); break; case STATE_TEXGEN: append_index(str, state[1]); /* tex unit [i] */ - append_token(str, (gl_state_index) state[2]); /* plane coef */ + append_token(str, state[2]); /* plane coef */ break; case STATE_TEXENV_COLOR: append_index(str, state[1]); /* tex unit [i] */ @@ -853,11 +892,11 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) /* state[2] = first row to fetch */ /* state[3] = last row to fetch */ /* state[4] = transpose, inverse or invtrans */ - const gl_state_index mat = (gl_state_index) state[0]; + const gl_state_index mat = state[0]; const GLuint index = (GLuint) state[1]; const GLuint firstRow = (GLuint) state[2]; const GLuint lastRow = (GLuint) state[3]; - const gl_state_index modifier = (gl_state_index) state[4]; + const gl_state_index modifier = state[4]; if (index || mat == STATE_TEXTURE_MATRIX || mat == STATE_PROGRAM_MATRIX) @@ -885,10 +924,11 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) case STATE_VERTEX_PROGRAM: /* state[1] = {STATE_ENV, STATE_LOCAL} */ /* state[2] = parameter index */ - append_token(str, (gl_state_index) state[1]); + append_token(str, state[1]); append_index(str, state[2]); break; case STATE_INTERNAL: + append_token(str, state[1]); break; default: _mesa_problem(NULL, "Invalid state in _mesa_program_state_string"); @@ -918,10 +958,101 @@ _mesa_load_state_parameters(GLcontext *ctx, for (i = 0; i < paramList->NumParameters; i++) { if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) { - _mesa_fetch_state(ctx, + _mesa_fetch_state(ctx, (gl_state_index *) paramList->Parameters[i].StateIndexes, paramList->ParameterValues[i]); } } } + +/** + * Copy the 16 elements of a matrix into four consecutive program + * registers starting at 'pos'. + */ +static void +load_matrix(GLfloat registers[][4], GLuint pos, const GLfloat mat[16]) +{ + GLuint i; + for (i = 0; i < 4; i++) { + registers[pos + i][0] = mat[0 + i]; + registers[pos + i][1] = mat[4 + i]; + registers[pos + i][2] = mat[8 + i]; + registers[pos + i][3] = mat[12 + i]; + } +} + + +/** + * As above, but transpose the matrix. + */ +static void +load_transpose_matrix(GLfloat registers[][4], GLuint pos, + const GLfloat mat[16]) +{ + MEMCPY(registers[pos], mat, 16 * sizeof(GLfloat)); +} + + +/** + * Load current vertex program's parameter registers with tracked + * matrices (if NV program). This only needs to be done per + * glBegin/glEnd, not per-vertex. + */ +void +_mesa_load_tracked_matrices(GLcontext *ctx) +{ + GLuint i; + + for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) { + /* point 'mat' at source matrix */ + GLmatrix *mat; + if (ctx->VertexProgram.TrackMatrix[i] == GL_MODELVIEW) { + mat = ctx->ModelviewMatrixStack.Top; + } + else if (ctx->VertexProgram.TrackMatrix[i] == GL_PROJECTION) { + mat = ctx->ProjectionMatrixStack.Top; + } + else if (ctx->VertexProgram.TrackMatrix[i] == GL_TEXTURE) { + mat = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top; + } + else if (ctx->VertexProgram.TrackMatrix[i] == GL_COLOR) { + mat = ctx->ColorMatrixStack.Top; + } + else if (ctx->VertexProgram.TrackMatrix[i]==GL_MODELVIEW_PROJECTION_NV) { + /* XXX verify the combined matrix is up to date */ + mat = &ctx->_ModelProjectMatrix; + } + else if (ctx->VertexProgram.TrackMatrix[i] >= GL_MATRIX0_NV && + ctx->VertexProgram.TrackMatrix[i] <= GL_MATRIX7_NV) { + GLuint n = ctx->VertexProgram.TrackMatrix[i] - GL_MATRIX0_NV; + ASSERT(n < MAX_PROGRAM_MATRICES); + mat = ctx->ProgramMatrixStack[n].Top; + } + else { + /* no matrix is tracked, but we leave the register values as-is */ + assert(ctx->VertexProgram.TrackMatrix[i] == GL_NONE); + continue; + } + + /* load the matrix values into sequential registers */ + if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_IDENTITY_NV) { + load_matrix(ctx->VertexProgram.Parameters, i*4, mat->m); + } + else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_INVERSE_NV) { + _math_matrix_analyse(mat); /* update the inverse */ + ASSERT(!_math_matrix_is_dirty(mat)); + load_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv); + } + else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_TRANSPOSE_NV) { + load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->m); + } + else { + assert(ctx->VertexProgram.TrackMatrixTransform[i] + == GL_INVERSE_TRANSPOSE_NV); + _math_matrix_analyse(mat); /* update the inverse */ + ASSERT(!_math_matrix_is_dirty(mat)); + load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv); + } + } +} diff --git a/src/mesa/shader/prog_statevars.h b/src/mesa/shader/prog_statevars.h index 1f728c64e8..d5358a1d04 100644 --- a/src/mesa/shader/prog_statevars.h +++ b/src/mesa/shader/prog_statevars.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.5.2 + * Version: 7.1 * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2007 Brian Paul 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"), @@ -77,12 +77,12 @@ typedef enum gl_state_index_ { STATE_SPECULAR, STATE_EMISSION, STATE_SHININESS, - STATE_HALF_VECTOR, + STATE_HALF_VECTOR, - STATE_POSITION, - STATE_ATTENUATION, - STATE_SPOT_DIRECTION, - STATE_SPOT_CUTOFF, + STATE_POSITION, /**< xyzw = position */ + STATE_ATTENUATION, /**< xyz = attenuation, w = spot exponent */ + STATE_SPOT_DIRECTION, /**< xyz = direction, w = cos(cutoff) */ + STATE_SPOT_CUTOFF, /**< x = cutoff, yzw = undefined */ STATE_TEXGEN_EYE_S, STATE_TEXGEN_EYE_T, @@ -94,7 +94,7 @@ typedef enum gl_state_index_ { STATE_TEXGEN_OBJECT_Q, STATE_TEXENV_COLOR, - + STATE_DEPTH_RANGE, STATE_VERTEX_PROGRAM, @@ -116,6 +116,7 @@ typedef enum gl_state_index_ { STATE_PT_BIAS, /**< Pixel transfer RGBA bias */ STATE_PCM_SCALE, /**< Post color matrix RGBA scale */ STATE_PCM_BIAS, /**< Post color matrix RGBA bias */ + STATE_SHADOW_AMBIENT, /**< ARB_shadow_ambient fail value; token[2] is texture unit index */ STATE_INTERNAL_DRIVER /* first available state index for drivers (must be last) */ } gl_state_index; @@ -134,4 +135,8 @@ extern char * _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]); +extern void +_mesa_load_tracked_matrices(GLcontext *ctx); + + #endif /* PROG_STATEVARS_H */ diff --git a/src/mesa/shader/prog_uniform.c b/src/mesa/shader/prog_uniform.c index dc76be8e46..0642713148 100644 --- a/src/mesa/shader/prog_uniform.c +++ b/src/mesa/shader/prog_uniform.c @@ -142,8 +142,8 @@ _mesa_longest_uniform_name(const struct gl_uniform_list *list) GLint max = 0; GLuint i; for (i = 0; list && i < list->NumUniforms; i++) { - GLuint len = _mesa_strlen(list->Uniforms[i].Name); - if (len > (GLuint)max) + GLint len = (GLint)_mesa_strlen(list->Uniforms[i].Name); + if (len > max) max = len; } return max; diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c index 723c46ee8c..7a3b827352 100644 --- a/src/mesa/shader/program.c +++ b/src/mesa/shader/program.c @@ -121,6 +121,43 @@ _mesa_free_program_data(GLcontext *ctx) /** + * Update the default program objects in the given context to reference those + * specified in the shared state and release those referencing the old + * shared state. + */ +void +_mesa_update_default_objects_program(GLcontext *ctx) +{ +#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program + _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, + (struct gl_vertex_program *) + ctx->Shared->DefaultVertexProgram); + assert(ctx->VertexProgram.Current); +#endif + +#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program + _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, + (struct gl_fragment_program *) + ctx->Shared->DefaultFragmentProgram); + assert(ctx->FragmentProgram.Current); +#endif + + /* XXX probably move this stuff */ +#if FEATURE_ATI_fragment_shader + if (ctx->ATIFragmentShader.Current) { + ctx->ATIFragmentShader.Current->RefCount--; + if (ctx->ATIFragmentShader.Current->RefCount <= 0) { + _mesa_free(ctx->ATIFragmentShader.Current); + } + } + ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader; + assert(ctx->ATIFragmentShader.Current); + ctx->ATIFragmentShader.Current->RefCount++; +#endif +} + + +/** * Set the vertex/fragment program error state (position and error string). * This is generally called from within the parsers. */ @@ -211,7 +248,7 @@ struct gl_program * _mesa_init_fragment_program( GLcontext *ctx, struct gl_fragment_program *prog, GLenum target, GLuint id) { - if (prog) + if (prog) return _mesa_init_program_struct( ctx, &prog->Base, target, id ); else return NULL; @@ -225,7 +262,7 @@ struct gl_program * _mesa_init_vertex_program( GLcontext *ctx, struct gl_vertex_program *prog, GLenum target, GLuint id) { - if (prog) + if (prog) return _mesa_init_program_struct( ctx, &prog->Base, target, id ); else return NULL; @@ -238,7 +275,7 @@ _mesa_init_vertex_program( GLcontext *ctx, struct gl_vertex_program *prog, * ctx->Driver.NewProgram. May be overridden (ie. replaced) by a * device driver function to implement OO deriviation with additional * types not understood by this function. - * + * * \param ctx context * \param id program id/number * \param target program target/type @@ -247,19 +284,23 @@ _mesa_init_vertex_program( GLcontext *ctx, struct gl_vertex_program *prog, struct gl_program * _mesa_new_program(GLcontext *ctx, GLenum target, GLuint id) { + struct gl_program *prog; switch (target) { case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */ - return _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program), + prog = _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program), target, id ); + break; case GL_FRAGMENT_PROGRAM_NV: case GL_FRAGMENT_PROGRAM_ARB: - return _mesa_init_fragment_program(ctx, + prog =_mesa_init_fragment_program(ctx, CALLOC_STRUCT(gl_fragment_program), target, id ); + break; default: _mesa_problem(ctx, "bad target in _mesa_new_program"); - return NULL; + prog = NULL; } + return prog; } @@ -278,7 +319,7 @@ _mesa_delete_program(GLcontext *ctx, struct gl_program *prog) if (prog == &_mesa_DummyProgram) return; - + if (prog->String) _mesa_free(prog->String); @@ -331,7 +372,11 @@ _mesa_reference_program(GLcontext *ctx, assert(ptr); if (*ptr && prog) { /* sanity check */ - ASSERT((*ptr)->Target == prog->Target); + if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB) + ASSERT(prog->Target == GL_VERTEX_PROGRAM_ARB); + else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB) + ASSERT(prog->Target == GL_FRAGMENT_PROGRAM_ARB || + prog->Target == GL_FRAGMENT_PROGRAM_NV); } if (*ptr == prog) { return; /* no change */ @@ -341,15 +386,17 @@ _mesa_reference_program(GLcontext *ctx, /*_glthread_LOCK_MUTEX((*ptr)->Mutex);*/ #if 0 - printf("Program %p %u 0x%x Refcount-- to %d\n", - *ptr, (*ptr)->Id, (*ptr)->Target, (*ptr)->RefCount - 1); + printf("Program %p ID=%u Target=%s Refcount-- to %d\n", + *ptr, (*ptr)->Id, + ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : "FP"), + (*ptr)->RefCount - 1); #endif ASSERT((*ptr)->RefCount > 0); (*ptr)->RefCount--; deleteFlag = ((*ptr)->RefCount == 0); /*_glthread_UNLOCK_MUTEX((*ptr)->Mutex);*/ - + if (deleteFlag) { ASSERT(ctx); ctx->Driver.DeleteProgram(ctx, *ptr); @@ -363,8 +410,10 @@ _mesa_reference_program(GLcontext *ctx, /*_glthread_LOCK_MUTEX(prog->Mutex);*/ prog->RefCount++; #if 0 - printf("Program %p %u 0x%x Refcount++ to %d\n", - prog, prog->Id, prog->Target, prog->RefCount); + printf("Program %p ID=%u Target=%s Refcount++ to %d\n", + prog, prog->Id, + (prog->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : "FP"), + prog->RefCount); #endif /*_glthread_UNLOCK_MUTEX(prog->Mutex);*/ } @@ -402,6 +451,7 @@ _mesa_clone_program(GLcontext *ctx, const struct gl_program *prog) clone->InputsRead = prog->InputsRead; clone->OutputsWritten = prog->OutputsWritten; clone->SamplersUsed = prog->SamplersUsed; + clone->ShadowSamplers = prog->ShadowSamplers; memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed)); if (prog->Parameters) @@ -504,6 +554,52 @@ _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count) return GL_TRUE; } +/** + * Delete 'count' instructions at 'start' in the given program. + * Adjust branch targets accordingly. + */ +GLboolean +_mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count) +{ + const GLuint origLen = prog->NumInstructions; + const GLuint newLen = origLen - count; + struct prog_instruction *newInst; + GLuint i; + + /* adjust branches */ + for (i = 0; i < prog->NumInstructions; i++) { + struct prog_instruction *inst = prog->Instructions + i; + if (inst->BranchTarget > 0) { + if (inst->BranchTarget > start) { + inst->BranchTarget -= count; + } + } + } + + /* Alloc storage for new instructions */ + newInst = _mesa_alloc_instructions(newLen); + if (!newInst) { + return GL_FALSE; + } + + /* Copy 'start' instructions into new instruction buffer */ + _mesa_copy_instructions(newInst, prog->Instructions, start); + + /* Copy the remaining/tail instructions to new inst buffer */ + _mesa_copy_instructions(newInst + start, + prog->Instructions + start + count, + newLen - start); + + /* free old instructions */ + _mesa_free_instructions(prog->Instructions, origLen); + + /* install new instructions */ + prog->Instructions = newInst; + prog->NumInstructions = newLen; + + return GL_TRUE; +} + /** * Search instructions for registers that match (oldFile, oldIndex), diff --git a/src/mesa/shader/program.h b/src/mesa/shader/program.h index f8bd63233e..48176162c3 100644 --- a/src/mesa/shader/program.h +++ b/src/mesa/shader/program.h @@ -53,6 +53,9 @@ extern void _mesa_free_program_data(GLcontext *ctx); extern void +_mesa_update_default_objects_program(GLcontext *ctx); + +extern void _mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string); extern const GLubyte * @@ -60,13 +63,13 @@ _mesa_find_line_column(const GLubyte *string, const GLubyte *pos, GLint *line, GLint *col); -extern struct gl_program * -_mesa_init_vertex_program(GLcontext *ctx, - struct gl_vertex_program *prog, +extern struct gl_program * +_mesa_init_vertex_program(GLcontext *ctx, + struct gl_vertex_program *prog, GLenum target, GLuint id); -extern struct gl_program * -_mesa_init_fragment_program(GLcontext *ctx, +extern struct gl_program * +_mesa_init_fragment_program(GLcontext *ctx, struct gl_fragment_program *prog, GLenum target, GLuint id); @@ -108,6 +111,9 @@ _mesa_clone_program(GLcontext *ctx, const struct gl_program *prog); extern GLboolean _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count); +extern GLboolean +_mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count); + extern struct gl_program * _mesa_combine_programs(GLcontext *ctx, const struct gl_program *progA, diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index 2af97612f7..38f4cd03c4 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -39,15 +39,15 @@ #include "main/context.h" #include "main/hash.h" #include "main/macros.h" -#include "program.h" -#include "prog_parameter.h" -#include "prog_print.h" -#include "prog_statevars.h" -#include "prog_uniform.h" +#include "shader/program.h" +#include "shader/prog_parameter.h" +#include "shader/prog_print.h" +#include "shader/prog_statevars.h" +#include "shader/prog_uniform.h" #include "shader/shader_api.h" #include "shader/slang/slang_compile.h" #include "shader/slang/slang_link.h" - +#include "glapi/dispatch.h" #ifndef GL_PROGRAM_BINARY_LENGTH_OES @@ -370,6 +370,31 @@ _mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller) } +/** + * Return mask of GLSL_x flags by examining the MESA_GLSL env var. + */ +static GLbitfield +get_shader_flags(void) +{ + GLbitfield flags = 0x0; + const char *env = _mesa_getenv("MESA_GLSL"); + + if (env) { + if (_mesa_strstr(env, "dump")) + flags |= GLSL_DUMP; + if (_mesa_strstr(env, "log")) + flags |= GLSL_LOG; + if (_mesa_strstr(env, "nopt")) + flags |= GLSL_NO_OPT; + else if (_mesa_strstr(env, "opt")) + flags |= GLSL_OPT; + if (_mesa_strstr(env, "uniform")) + flags |= GLSL_UNIFORMS; + } + + return flags; +} + /** * Initialize context's shader state. @@ -381,8 +406,9 @@ _mesa_init_shader_state(GLcontext * ctx) * are generated by the GLSL compiler. */ ctx->Shader.EmitHighLevelInstructions = GL_TRUE; - ctx->Shader.EmitCondCodes = GL_FALSE;/*GL_TRUE;*/ /* XXX probably want GL_FALSE... */ + ctx->Shader.EmitCondCodes = GL_FALSE; ctx->Shader.EmitComments = GL_FALSE; + ctx->Shader.Flags = get_shader_flags(); } @@ -455,7 +481,13 @@ _mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader) n = shProg->NumShaders; for (i = 0; i < n; i++) { if (shProg->Shaders[i] == sh) { - /* already attached */ + /* The shader is already attched to this program. The + * GL_ARB_shader_objects spec says: + * + * "The error INVALID_OPERATION is generated by AttachObjectARB + * if <obj> is already attached to <containerObj>." + */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); return; } } @@ -517,7 +549,7 @@ _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index, { struct gl_shader_program *shProg; const GLint size = -1; /* unknown size */ - GLint i; + GLint i, oldIndex; GLenum datatype = GL_FLOAT_VEC4; shProg = _mesa_lookup_shader_program_err(ctx, program, @@ -540,6 +572,14 @@ _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index, return; } + if (shProg->LinkStatus) { + /* get current index/location for the attribute */ + oldIndex = _mesa_get_attrib_location(ctx, program, name); + } + else { + oldIndex = -1; + } + /* this will replace the current value if it's already in the list */ i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index); if (i < 0) { @@ -852,6 +892,7 @@ _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, { const struct gl_shader_program *shProg; const struct gl_program *prog; + const struct gl_program_parameter *param; GLint progPos; shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform"); @@ -877,14 +918,30 @@ _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, if (!prog || progPos < 0) return; /* should never happen */ - if (nameOut) - copy_string(nameOut, maxLength, length, - prog->Parameters->Parameters[progPos].Name); - if (size) - *size = prog->Parameters->Parameters[progPos].Size - / sizeof_glsl_type(prog->Parameters->Parameters[progPos].DataType); - if (type) - *type = prog->Parameters->Parameters[progPos].DataType; + ASSERT(progPos < prog->Parameters->NumParameters); + param = &prog->Parameters->Parameters[progPos]; + + if (nameOut) { + copy_string(nameOut, maxLength, length, param->Name); + } + + if (size) { + GLint typeSize = sizeof_glsl_type(param->DataType); + if (param->Size > typeSize) { + /* This is an array. + * Array elements are placed on vector[4] boundaries so they're + * a multiple of four floats. We round typeSize up to next multiple + * of four to get the right size below. + */ + typeSize = (typeSize + 3) & ~3; + } + /* Note that the returned size is in units of the <type>, not bytes */ + *size = param->Size / typeSize; + } + + if (type) { + *type = param->DataType; + } } @@ -911,24 +968,15 @@ _mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount, static GLuint _mesa_get_handle(GLcontext *ctx, GLenum pname) { -#if 0 - GET_CURRENT_CONTEXT(ctx); - - switch (pname) { - case GL_PROGRAM_OBJECT_ARB: - { - struct gl2_program_intf **pro = ctx->Shader.CurrentProgram; - - if (pro != NULL) - return (**pro)._container._generic. - GetName((struct gl2_generic_intf **) (pro)); - } - break; - default: + GLint handle = 0; + + if (pname == GL_PROGRAM_OBJECT_ARB) { + CALL_GetIntegerv(ctx->Exec, (GL_CURRENT_PROGRAM, &handle)); + } else { _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB"); } -#endif - return 0; + + return handle; } @@ -1137,24 +1185,30 @@ get_uniform_rows_cols(const struct gl_program_parameter *p, } -#define MAX_UNIFORM_ELEMENTS 16 - /** - * Helper for GetUniformfv(), GetUniformiv() - * Returns number of elements written to 'params' output. + * Helper for get_uniform[fi]v() functions. + * Given a shader program name and uniform location, return a pointer + * to the shader program and return the program parameter position. */ -static GLuint -get_uniformfv(GLcontext *ctx, GLuint program, GLint location, - GLfloat *params) +static void +lookup_uniform_parameter(GLcontext *ctx, GLuint program, GLint location, + struct gl_program **progOut, GLint *paramPosOut) { struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v"); - if (shProg) { - if (shProg->Uniforms && - location >= 0 && location < (GLint) shProg->Uniforms->NumUniforms) { - GLint progPos; - const struct gl_program *prog = NULL; + struct gl_program *prog = NULL; + GLint progPos = -1; + + /* if shProg is NULL, we'll have already recorded an error */ + if (shProg) { + if (!shProg->Uniforms || + location < 0 || + location >= (GLint) shProg->Uniforms->NumUniforms) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)"); + } + else { + /* OK, find the gl_program and program parameter location */ progPos = shProg->Uniforms->Uniforms[location].VertPos; if (progPos >= 0) { prog = &shProg->VertexProgram->Base; @@ -1165,33 +1219,11 @@ get_uniformfv(GLcontext *ctx, GLuint program, GLint location, prog = &shProg->FragmentProgram->Base; } } - - ASSERT(prog); - if (prog) { - const struct gl_program_parameter *p = - &prog->Parameters->Parameters[progPos]; - GLint rows, cols, i, j, k; - - /* See uniformiv() below */ - assert(p->Size <= MAX_UNIFORM_ELEMENTS); - - get_uniform_rows_cols(p, &rows, &cols); - - k = 0; - for (i = 0; i < rows; i++) { - for (j = 0; j < cols; j++ ) { - params[k++] = prog->Parameters->ParameterValues[progPos+i][j]; - } - } - - return p->Size; - } - } - else { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)"); } } - return 0; + + *progOut = prog; + *paramPosOut = progPos; } @@ -1202,23 +1234,54 @@ static void _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location, GLfloat *params) { - (void) get_uniformfv(ctx, program, location, params); + struct gl_program *prog; + GLint paramPos; + + lookup_uniform_parameter(ctx, program, location, &prog, ¶mPos); + + if (prog) { + const struct gl_program_parameter *p = + &prog->Parameters->Parameters[paramPos]; + GLint rows, cols, i, j, k; + + get_uniform_rows_cols(p, &rows, &cols); + + k = 0; + for (i = 0; i < rows; i++) { + for (j = 0; j < cols; j++ ) { + params[k++] = prog->Parameters->ParameterValues[paramPos+i][j]; + } + } + } } /** * Called via ctx->Driver.GetUniformiv(). + * \sa _mesa_get_uniformfv, only difference is a cast. */ static void _mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location, GLint *params) { - GLfloat fparams[MAX_UNIFORM_ELEMENTS]; - GLuint n = get_uniformfv(ctx, program, location, fparams); - GLuint i; - assert(n <= MAX_UNIFORM_ELEMENTS); - for (i = 0; i < n; i++) { - params[i] = (GLint) fparams[i]; + struct gl_program *prog; + GLint paramPos; + + lookup_uniform_parameter(ctx, program, location, &prog, ¶mPos); + + if (prog) { + const struct gl_program_parameter *p = + &prog->Parameters->Parameters[paramPos]; + GLint rows, cols, i, j, k; + + get_uniform_rows_cols(p, &rows, &cols); + + k = 0; + for (i = 0; i < rows; i++) { + for (j = 0; j < cols; j++ ) { + params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j]; + } + } } } @@ -1359,7 +1422,10 @@ _mesa_compile_shader(GLcontext *ctx, GLuint shaderObj) if (!sh) return; - sh->CompileStatus = _slang_compile(ctx, sh); + /* this call will set the sh->CompileStatus field to indicate if + * compilation was successful. + */ + (void) _slang_compile(ctx, sh); } @@ -1537,27 +1603,36 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, if (param->Type == PROGRAM_SAMPLER) { /* This controls which texture unit which is used by a sampler */ GLuint texUnit, sampler; + GLint i; /* data type for setting samplers must be int */ - if (type != GL_INT || count != 1) { + if (type != GL_INT) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(only glUniform1i can be used " "to set sampler uniforms)"); return; } - sampler = (GLuint) program->Parameters->ParameterValues[index][0]; - texUnit = ((GLuint *) values)[0]; + /* XXX arrays of samplers haven't been tested much, but it's not a + * common thing... + */ + for (i = 0; i < count; i++) { + sampler = (GLuint) program->Parameters->ParameterValues[index + i][0]; + texUnit = ((GLuint *) values)[i]; + + /* check that the sampler (tex unit index) is legal */ + if (texUnit >= ctx->Const.MaxTextureImageUnits) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glUniform1(invalid sampler/tex unit index)"); + return; + } - /* check that the sampler (tex unit index) is legal */ - if (texUnit >= ctx->Const.MaxTextureImageUnits) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glUniform1(invalid sampler/tex unit index)"); - return; + /* This maps a sampler to a texture unit: */ + if (sampler < MAX_SAMPLERS) { + program->SamplerUnits[sampler] = texUnit; + } } - /* This maps a sampler to a texture unit: */ - program->SamplerUnits[sampler] = texUnit; _mesa_update_shader_textures_used(program); FLUSH_VERTICES(ctx, _NEW_TEXTURE); @@ -1565,19 +1640,31 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, else { /* ordinary uniform variable */ GLsizei k, i; - GLint slots = (param->Size + 3) / 4; + const GLint slots = (param->Size + 3) / 4; + const GLint typeSize = sizeof_glsl_type(param->DataType); - if (count * elems > (GLint) param->Size) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)"); - return; + if (param->Size > typeSize) { + /* an array */ + /* we'll ignore extra data below */ + } + else { + /* non-array: count must be one */ + if (count != 1) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUniform(uniform is not an array)"); + return; + } } - - if (count > slots) - count = slots; for (k = 0; k < count; k++) { - GLfloat *uniformVal = - program->Parameters->ParameterValues[index + offset + k]; + GLfloat *uniformVal; + + if (offset + k > slots) { + /* Extra array data is ignored */ + break; + } + + uniformVal = program->Parameters->ParameterValues[index + offset + k]; if (is_integer_type(type)) { const GLint *iValues = ((const GLint *) values) + k * elems; for (i = 0; i < elems; i++) { @@ -1612,6 +1699,7 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; struct gl_uniform *uniform; GLint elems, offset; + GLenum basicType; if (!shProg || !shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)"); @@ -1621,6 +1709,11 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, if (location == -1) return; /* The standard specifies this as a no-op */ + if (location < -1) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)"); + return; + } + split_location_offset(&location, &offset); if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) { @@ -1635,19 +1728,35 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, switch (type) { case GL_FLOAT: + basicType = GL_FLOAT; + elems = 1; + break; case GL_INT: + basicType = GL_INT; elems = 1; break; case GL_FLOAT_VEC2: + basicType = GL_FLOAT; + elems = 2; + break; case GL_INT_VEC2: + basicType = GL_INT; elems = 2; break; case GL_FLOAT_VEC3: + basicType = GL_FLOAT; + elems = 3; + break; case GL_INT_VEC3: + basicType = GL_INT; elems = 3; break; case GL_FLOAT_VEC4: + basicType = GL_FLOAT; + elems = 4; + break; case GL_INT_VEC4: + basicType = GL_INT; elems = 4; break; default: @@ -1659,6 +1768,25 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, uniform = &shProg->Uniforms->Uniforms[location]; + if (ctx->Shader.Flags & GLSL_UNIFORMS) { + GLint i; + _mesa_printf("Mesa: set program %u uniform %s (loc %d) to: ", + shProg->Name, uniform->Name, location); + if (basicType == GL_INT) { + const GLint *v = (const GLint *) values; + for (i = 0; i < count * elems; i++) { + _mesa_printf("%d ", v[i]); + } + } + else { + const GLfloat *v = (const GLfloat *) values; + for (i = 0; i < count * elems; i++) { + _mesa_printf("%g ", v[i]); + } + } + _mesa_printf("\n"); + } + /* A uniform var may be used by both a vertex shader and a fragment * shader. We may need to update one or both shader's uniform here: */ @@ -1760,6 +1888,11 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows, if (location == -1) return; /* The standard specifies this as a no-op */ + if (location < -1) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)"); + return; + } + split_location_offset(&location, &offset); if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) { diff --git a/src/mesa/shader/slang/descrip.mms b/src/mesa/shader/slang/descrip.mms new file mode 100644 index 0000000000..6eefbcf5bd --- /dev/null +++ b/src/mesa/shader/slang/descrip.mms @@ -0,0 +1,68 @@ +# Makefile for core library for VMS +# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl +# Last revision : 3 October 2007 + +.first + define gl [----.include.gl] + define math [--.math] + define swrast [--.swrast] + define array_cache [--.array_cache] + define main [--.main] + define glapi [--.glapi] + define shader [--.shader] + +.include [----]mms-config. + +##### MACROS ##### + +VPATH = RCS + +INCDIR = [----.include],[--.main],[--.glapi],[-.slang],[-.grammar],[-] +LIBDIR = [----.lib] +CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm + +SOURCES = \ + slang_compile.c,slang_preprocess.c + +OBJECTS = slang_builtin.obj,slang_codegen.obj,slang_compile.obj,\ + slang_compile_function.obj,slang_compile_operation.obj,\ + slang_compile_struct.obj,slang_compile_variable.obj,slang_emit.obj,\ + slang_ir.obj,slang_label.obj,slang_library_noise.obj,slang_link.obj,\ + slang_log.obj,slang_mem.obj,slang_preprocess.obj,slang_print.obj,\ + slang_simplify.obj,slang_storage.obj,slang_typeinfo.obj,\ + slang_utility.obj,slang_vartable.obj + +##### RULES ##### + +VERSION=Mesa V3.4 + +##### TARGETS ##### +# Make the library +$(LIBDIR)$(GL_LIB) : $(OBJECTS) + @ library $(LIBDIR)$(GL_LIB) $(OBJECTS) + +clean : + purge + delete *.obj;* + +slang_builtin.obj : slang_builtin.c +slang_codegen.obj : slang_codegen.c +slang_compile.obj : slang_compile.c +slang_compile_function.obj : slang_compile_function.c +slang_compile_operation.obj : slang_compile_operation.c +slang_compile_struct.obj : slang_compile_struct.c +slang_compile_variable.obj : slang_compile_variable.c +slang_emit.obj : slang_emit.c +slang_ir.obj : slang_ir.c +slang_label.obj : slang_label.c +slang_library_noise.obj : slang_library_noise.c +slang_link.obj : slang_link.c +slang_log.obj : slang_log.c +slang_mem.obj : slang_mem.c +slang_preprocess.obj : slang_preprocess.c +slang_print.obj : slang_print.c +slang_simplify.obj : slang_simplify.c +slang_storage.obj : slang_storage.c +slang_typeinfo.obj : slang_typeinfo.c +slang_utility.obj : slang_utility.c +slang_vartable.obj : slang_vartable.c diff --git a/src/mesa/shader/slang/library/slang_pp_directives.syn b/src/mesa/shader/slang/library/slang_pp_directives.syn index d4a321034d..b51d168cc0 100755..100644 --- a/src/mesa/shader/slang/library/slang_pp_directives.syn +++ b/src/mesa/shader/slang/library/slang_pp_directives.syn @@ -79,6 +79,12 @@ .emtcode BEHAVIOR_WARN 3 .emtcode BEHAVIOR_DISABLE 4 +/* + * The PRAGMA_* symbols follow TOKEN_PRAGMA + */ +.emtcode PRAGMA_NO_PARAM 0 +.emtcode PRAGMA_PARAM 1 + source optional_directive .and .loop source_element .and '\0' .emit ESCAPE_TOKEN .emit TOKEN_END; @@ -153,6 +159,7 @@ directive dir_elif .emit TOKEN_ELIF .or dir_endif .emit TOKEN_ENDIF .or dir_ext .emit TOKEN_EXTENSION .or + dir_pragma .emit TOKEN_PRAGMA .or dir_line .emit TOKEN_LINE; dir_define @@ -187,6 +194,19 @@ dir_ext dir_line optional_space .and '#' .and optional_space .and "line" .and expression; +dir_pragma + optional_space .and '#' .and optional_space .and "pragma" .and symbol .and opt_pragma_param; + + +opt_pragma_param + pragma_param .or .true .emit PRAGMA_NO_PARAM; + +pragma_param + optional_space .and '(' .emit PRAGMA_PARAM .and optional_space .and symbol_no_space .and optional_space .and ')'; + +symbol_no_space + symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\0'; + symbol space .and symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\0'; diff --git a/src/mesa/shader/slang/library/slang_pp_directives_syn.h b/src/mesa/shader/slang/library/slang_pp_directives_syn.h index 35e7bc2761..430f8d8217 100644 --- a/src/mesa/shader/slang/library/slang_pp_directives_syn.h +++ b/src/mesa/shader/slang/library/slang_pp_directives_syn.h @@ -20,6 +20,8 @@ ".emtcode BEHAVIOR_ENABLE 2\n" ".emtcode BEHAVIOR_WARN 3\n" ".emtcode BEHAVIOR_DISABLE 4\n" +".emtcode PRAGMA_NO_PARAM 0\n" +".emtcode PRAGMA_PARAM 1\n" "source\n" " optional_directive .and .loop source_element .and '\\0' .emit ESCAPE_TOKEN .emit TOKEN_END;\n" "source_element\n" @@ -76,6 +78,7 @@ " dir_elif .emit TOKEN_ELIF .or\n" " dir_endif .emit TOKEN_ENDIF .or\n" " dir_ext .emit TOKEN_EXTENSION .or\n" +" dir_pragma .emit TOKEN_PRAGMA .or\n" " dir_line .emit TOKEN_LINE;\n" "dir_define\n" " optional_space .and '#' .and optional_space .and \"define\" .and symbol .and opt_parameters .and\n" @@ -99,6 +102,14 @@ " optional_space .and ':' .and optional_space .and extension_behavior;\n" "dir_line\n" " optional_space .and '#' .and optional_space .and \"line\" .and expression;\n" +"dir_pragma\n" +" optional_space .and '#' .and optional_space .and \"pragma\" .and symbol .and opt_pragma_param;\n" +"opt_pragma_param\n" +" pragma_param .or .true .emit PRAGMA_NO_PARAM;\n" +"pragma_param\n" +" optional_space .and '(' .emit PRAGMA_PARAM .and optional_space .and symbol_no_space .and optional_space .and ')';\n" +"symbol_no_space\n" +" symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\\0';\n" "symbol\n" " space .and symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\\0';\n" "opt_parameters\n" diff --git a/src/mesa/shader/slang/library/slang_pp_expression.syn b/src/mesa/shader/slang/library/slang_pp_expression.syn index bfdb220bf5..bfdb220bf5 100755..100644 --- a/src/mesa/shader/slang/library/slang_pp_expression.syn +++ b/src/mesa/shader/slang/library/slang_pp_expression.syn diff --git a/src/mesa/shader/slang/library/slang_shader.syn b/src/mesa/shader/slang/library/slang_shader.syn index 0ad4a1cba6..cc5c70a02f 100644 --- a/src/mesa/shader/slang/library/slang_shader.syn +++ b/src/mesa/shader/slang/library/slang_shader.syn @@ -1162,13 +1162,6 @@ compound_statement_3 lbrace .and statement_list .and rbrace; /* - * <statement_no_new_scope> ::= <compound_statement_no_new_scope> - * | <simple_statement> - */ -statement_no_new_scope - compound_statement_no_new_scope .or simple_statement; - -/* * <compound_statement_no_new_scope> ::= "{" "}" * | "{" <statement_list> "}" */ @@ -1181,6 +1174,7 @@ compound_statement_no_new_scope_2 compound_statement_no_new_scope_3 lbrace .and statement_list .and rbrace; + /* * <statement_list> ::= <statement> * | <statement_list> <statement> @@ -1242,8 +1236,7 @@ condition_3 /* * <iteration_statement> ::= "while" "(" <condition> ")" <statement> * | "do" <statement> "while" "(" <expression> ")" ";" - * | "for" "(" <for_init_statement> <for_rest_statement> ")" - * <statement_no_new_scope> + * | "for" "(" <for_init_statement> <for_rest_statement> ")" <statement> */ iteration_statement iteration_statement_1 .or iteration_statement_2 .or iteration_statement_3; @@ -1255,7 +1248,7 @@ iteration_statement_2 expression .and rparen .error RPAREN_EXPECTED .emit OP_END .and semicolon; iteration_statement_3 "for" .emit OP_FOR .and lparen .error LPAREN_EXPECTED .and for_init_statement .and - for_rest_statement .and rparen .error RPAREN_EXPECTED .and statement_no_new_scope; + for_rest_statement .and rparen .error RPAREN_EXPECTED .and statement; /* * <for_init_statement> ::= <expression_statement> diff --git a/src/mesa/shader/slang/library/slang_shader_syn.h b/src/mesa/shader/slang/library/slang_shader_syn.h index e1705dfe19..6a382970e1 100644 --- a/src/mesa/shader/slang/library/slang_shader_syn.h +++ b/src/mesa/shader/slang/library/slang_shader_syn.h @@ -566,8 +566,6 @@ " lbrace .and rbrace;\n" "compound_statement_3\n" " lbrace .and statement_list .and rbrace;\n" -"statement_no_new_scope\n" -" compound_statement_no_new_scope .or simple_statement;\n" "compound_statement_no_new_scope\n" " compound_statement_no_new_scope_1 .emit OP_BLOCK_BEGIN_NO_NEW_SCOPE .and .true .emit OP_END;\n" "compound_statement_no_new_scope_1\n" @@ -617,7 +615,7 @@ " expression .and rparen .error RPAREN_EXPECTED .emit OP_END .and semicolon;\n" "iteration_statement_3\n" " \"for\" .emit OP_FOR .and lparen .error LPAREN_EXPECTED .and for_init_statement .and\n" -" for_rest_statement .and rparen .error RPAREN_EXPECTED .and statement_no_new_scope;\n" +" for_rest_statement .and rparen .error RPAREN_EXPECTED .and statement;\n" "for_init_statement\n" " expression_statement .emit OP_EXPRESSION .or declaration_statement .emit OP_DECLARE;\n" "conditionopt\n" diff --git a/src/mesa/shader/slang/library/slang_version.syn b/src/mesa/shader/slang/library/slang_version.syn index aaf8bef342..aaf8bef342 100755..100644 --- a/src/mesa/shader/slang/library/slang_version.syn +++ b/src/mesa/shader/slang/library/slang_version.syn diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 712f5975dc..cfdb868d6c 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -57,6 +57,21 @@ #include "slang_print.h" +/** Max iterations to unroll */ +const GLuint MAX_FOR_LOOP_UNROLL_ITERATIONS = 32; + +/** Max for-loop body size (in slang operations) to unroll */ +const GLuint MAX_FOR_LOOP_UNROLL_BODY_SIZE = 50; + +/** Max for-loop body complexity to unroll. + * We'll compute complexity as the product of the number of iterations + * and the size of the body. So long-ish loops with very simple bodies + * can be unrolled, as well as short loops with larger bodies. + */ +const GLuint MAX_FOR_LOOP_UNROLL_COMPLEXITY = 256; + + + static slang_ir_node * _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper); @@ -398,7 +413,7 @@ _slang_input_index(const char *name, GLenum target, GLuint *swizzleOut) const struct input_info *inputs = (target == GL_VERTEX_PROGRAM_ARB) ? vertInputs : fragInputs; - ASSERT(MAX_TEXTURE_UNITS == 8); /* if this fails, fix vertInputs above */ + ASSERT(MAX_TEXTURE_COORD_UNITS == 8); /* if this fails, fix vertInputs above */ for (i = 0; inputs[i].Name; i++) { if (strcmp(inputs[i].Name, name) == 0) { @@ -476,6 +491,9 @@ static slang_asm_info AsmInfo[] = { { "vec4_multiply", IR_MUL, 1, 2 }, { "vec4_dot", IR_DOT4, 1, 2 }, { "vec3_dot", IR_DOT3, 1, 2 }, + { "vec2_dot", IR_DOT2, 1, 2 }, + { "vec3_nrm", IR_NRM3, 1, 1 }, + { "vec4_nrm", IR_NRM4, 1, 1 }, { "vec3_cross", IR_CROSS, 1, 2 }, { "vec4_lrp", IR_LRP, 1, 3 }, { "vec4_min", IR_MIN, 1, 2 }, @@ -1574,6 +1592,7 @@ swizzle_to_writemask(slang_assemble_ctx *A, GLuint swizzle, } +#if 0 /* not used, but don't remove just yet */ /** * Recursively traverse 'oper' to produce a swizzle mask in the event * of any vector subscripts and swizzle suffixes. @@ -1627,8 +1646,10 @@ resolve_swizzle(const slang_operation *oper) return SWIZZLE_XYZW; } } +#endif +#if 0 /** * Recursively descend through swizzle nodes to find the node's storage info. */ @@ -1640,7 +1661,7 @@ get_store(const slang_ir_node *n) } return n->Store; } - +#endif /** @@ -1713,6 +1734,7 @@ _slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper, } +#if 0 static void print_funcs(struct slang_function_scope_ *scope, const char *name) { @@ -1726,6 +1748,7 @@ print_funcs(struct slang_function_scope_ *scope, const char *name) if (scope->outer_scope) print_funcs(scope->outer_scope, name); } +#endif /** @@ -2443,40 +2466,259 @@ _slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper) /** - * Generate for-loop using high-level IR_LOOP instruction. + * Recursively count the number of operations rooted at 'oper'. + * This gives some kind of indication of the size/complexity of an operation. + */ +static GLuint +sizeof_operation(const slang_operation *oper) +{ + if (oper) { + GLuint count = 1; /* me */ + GLuint i; + for (i = 0; i < oper->num_children; i++) { + count += sizeof_operation(&oper->children[i]); + } + return count; + } + else { + return 0; + } +} + + +/** + * Determine if a for-loop can be unrolled. + * At this time, only a rather narrow class of for loops can be unrolled. + * See code for details. + * When a loop can't be unrolled because it's too large we'll emit a + * message to the log. + */ +static GLboolean +_slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) +{ + GLuint bodySize; + GLint start, end; + const char *varName; + slang_atom varId; + + assert(oper->type == SLANG_OPER_FOR); + assert(oper->num_children == 4); + + /* children[0] must be either "int i=constant" or "i=constant" */ + if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) { + slang_variable *var; + + if (oper->children[0].children[0].type != SLANG_OPER_VARIABLE_DECL) + return GL_FALSE; + + varId = oper->children[0].children[0].a_id; + + var = _slang_variable_locate(oper->children[0].children[0].locals, + varId, GL_TRUE); + if (!var) + return GL_FALSE; + if (!var->initializer) + return GL_FALSE; + if (var->initializer->type != SLANG_OPER_LITERAL_INT) + return GL_FALSE; + start = (GLint) var->initializer->literal[0]; + } + else if (oper->children[0].type == SLANG_OPER_EXPRESSION) { + if (oper->children[0].children[0].type != SLANG_OPER_ASSIGN) + return GL_FALSE; + if (oper->children[0].children[0].children[0].type != SLANG_OPER_IDENTIFIER) + return GL_FALSE; + if (oper->children[0].children[0].children[1].type != SLANG_OPER_LITERAL_INT) + return GL_FALSE; + + varId = oper->children[0].children[0].children[0].a_id; + + start = (GLint) oper->children[0].children[0].children[1].literal[0]; + } + else { + return GL_FALSE; + } + + /* children[1] must be "i<constant" */ + if (oper->children[1].type != SLANG_OPER_EXPRESSION) + return GL_FALSE; + if (oper->children[1].children[0].type != SLANG_OPER_LESS) + return GL_FALSE; + if (oper->children[1].children[0].children[0].type != SLANG_OPER_IDENTIFIER) + return GL_FALSE; + if (oper->children[1].children[0].children[1].type != SLANG_OPER_LITERAL_INT) + return GL_FALSE; + + end = (GLint) oper->children[1].children[0].children[1].literal[0]; + + /* children[2] must be "i++" or "++i" */ + if (oper->children[2].type != SLANG_OPER_POSTINCREMENT && + oper->children[2].type != SLANG_OPER_PREINCREMENT) + return GL_FALSE; + if (oper->children[2].children[0].type != SLANG_OPER_IDENTIFIER) + return GL_FALSE; + + /* make sure the same variable name is used in all places */ + if ((oper->children[1].children[0].children[0].a_id != varId) || + (oper->children[2].children[0].a_id != varId)) + return GL_FALSE; + + varName = (const char *) varId; + + /* children[3], the loop body, can't be too large */ + bodySize = sizeof_operation(&oper->children[3]); + if (bodySize > MAX_FOR_LOOP_UNROLL_BODY_SIZE) { + slang_info_log_print(A->log, + "Note: 'for (%s ... )' body is too large/complex" + " to unroll", + varName); + return GL_FALSE; + } + + if (start >= end) + return GL_FALSE; /* degenerate case */ + + if (end - start > MAX_FOR_LOOP_UNROLL_ITERATIONS) { + slang_info_log_print(A->log, + "Note: 'for (%s=%d; %s<%d; ++%s)' is too" + " many iterations to unroll", + varName, start, varName, end, varName); + return GL_FALSE; + } + + if ((end - start) * bodySize > MAX_FOR_LOOP_UNROLL_COMPLEXITY) { + slang_info_log_print(A->log, + "Note: 'for (%s=%d; %s<%d; ++%s)' will generate" + " too much code to unroll", + varName, start, varName, end, varName); + return GL_FALSE; + } + + return GL_TRUE; /* we can unroll the loop */ +} + + +/** + * Unroll a for-loop. + * First we determine the number of iterations to unroll. + * Then for each iteration: + * make a copy of the loop body + * replace instances of the loop variable with the current iteration value + * generate IR code for the body + * \return pointer to generated IR code or NULL if error, out of memory, etc. + */ +static slang_ir_node * +_slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) +{ + GLint start, end, iter; + slang_ir_node *n, *root = NULL; + slang_atom varId; + + if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) { + /* for (int i=0; ... */ + slang_variable *var; + + varId = oper->children[0].children[0].a_id; + var = _slang_variable_locate(oper->children[0].children[0].locals, + varId, GL_TRUE); + start = (GLint) var->initializer->literal[0]; + } + else { + /* for (i=0; ... */ + varId = oper->children[0].children[0].children[0].a_id; + start = (GLint) oper->children[0].children[0].children[1].literal[0]; + } + + end = (GLint) oper->children[1].children[0].children[1].literal[0]; + + for (iter = start; iter < end; iter++) { + slang_operation *body; + + /* make a copy of the loop body */ + body = slang_operation_new(1); + if (!body) + return NULL; + + if (!slang_operation_copy(body, &oper->children[3])) + return NULL; + + /* in body, replace instances of 'varId' with literal 'iter' */ + { + slang_variable *oldVar; + slang_operation *newOper; + + oldVar = _slang_variable_locate(oper->locals, varId, GL_TRUE); + if (!oldVar) { + /* undeclared loop variable */ + slang_operation_delete(body); + return NULL; + } + + newOper = slang_operation_new(1); + newOper->type = SLANG_OPER_LITERAL_INT; + newOper->literal_size = 1; + newOper->literal[0] = iter; + + /* replace instances of the loop variable with newOper */ + slang_substitute(A, body, 1, &oldVar, &newOper, GL_FALSE); + } + + /* do IR codegen for body */ + n = _slang_gen_operation(A, body); + root = new_seq(root, n); + + slang_operation_delete(body); + } + + return root; +} + + +/** + * Generate IR for a for-loop. Unrolling will be done when possible. */ static slang_ir_node * _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper) { - /* - * init code (child[0]) - * LOOP: - * BREAK if !expr (child[1]) - * body code (child[3]) - * tail code: - * incr code (child[2]) // XXX continue here - */ - slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body, *init, *incr; + GLboolean unroll = _slang_can_unroll_for_loop(A, oper); - init = _slang_gen_operation(A, &oper->children[0]); - loop = new_loop(NULL); + if (unroll) { + slang_ir_node *code = _slang_unroll_for_loop(A, oper); + if (code) + return code; + } - /* save old, push new loop */ - prevLoop = A->CurLoop; - A->CurLoop = loop; + /* conventional for-loop code generation */ + { + /* + * init code (child[0]) + * LOOP: + * BREAK if !expr (child[1]) + * body code (child[3]) + * tail code: + * incr code (child[2]) // XXX continue here + */ + slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body, *init, *incr; + init = _slang_gen_operation(A, &oper->children[0]); + loop = new_loop(NULL); - cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1]))); - breakIf = new_break_if_true(A->CurLoop, cond); - body = _slang_gen_operation(A, &oper->children[3]); - incr = _slang_gen_operation(A, &oper->children[2]); + /* save old, push new loop */ + prevLoop = A->CurLoop; + A->CurLoop = loop; - loop->Children[0] = new_seq(breakIf, body); - loop->Children[1] = incr; /* tail code */ + cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1]))); + breakIf = new_break_if_true(A->CurLoop, cond); + body = _slang_gen_operation(A, &oper->children[3]); + incr = _slang_gen_operation(A, &oper->children[2]); - /* pop loop, restore prev */ - A->CurLoop = prevLoop; + loop->Children[0] = new_seq(breakIf, body); + loop->Children[1] = incr; /* tail code */ + + /* pop loop, restore prev */ + A->CurLoop = prevLoop; - return new_seq(init, loop); + return new_seq(init, loop); + } } @@ -3093,6 +3335,7 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) } +#if 0 /** * Determine if the given operation/expression is const-valued. */ @@ -3116,6 +3359,7 @@ _slang_is_constant_expr(const slang_operation *oper) return GL_TRUE; } } +#endif /** @@ -3418,7 +3662,7 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper) if (lhs && rhs) { /* convert lhs swizzle into writemask */ const GLuint swizzle = root_swizzle(lhs->Store); - GLuint writemask, newSwizzle; + GLuint writemask, newSwizzle = 0x0; if (!swizzle_to_writemask(A, swizzle, &writemask, &newSwizzle)) { /* Non-simple writemask, need to swizzle right hand side in * order to put components into the right place. @@ -3560,8 +3804,16 @@ _slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper) index = (GLint) oper->children[1].literal[0]; if (oper->children[1].type != SLANG_OPER_LITERAL_INT || index >= (GLint) max) { +#if 0 slang_info_log_error(A->log, "Invalid array index for vector type"); + printf("type = %d\n", oper->children[1].type); + printf("index = %d, max = %d\n", index, max); + printf("array = %s\n", (char*)oper->children[0].a_id); + printf("index = %s\n", (char*)oper->children[1].a_id); return NULL; +#else + index = 0; +#endif } n = _slang_gen_operation(A, &oper->children[0]); @@ -3987,6 +4239,21 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) /** + * Check if the given type specifier is a rectangular texture sampler. + */ +static GLboolean +is_rect_sampler_spec(const slang_type_specifier *spec) +{ + while (spec->_array) { + spec = spec->_array; + } + return spec->type == SLANG_SPEC_SAMPLER2DRECT || + spec->type == SLANG_SPEC_SAMPLER2DRECTSHADOW; +} + + + +/** * Called by compiler when a global variable has been parsed/compiled. * Here we examine the variable's type to determine what kind of register * storage will be used. @@ -4009,10 +4276,14 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var, slang_ir_storage *store = NULL; int dbg = 0; const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier); - const GLint texIndex = sampler_to_texture_index(var->type.specifier.type); const GLint size = _slang_sizeof_type_specifier(&var->type.specifier); const GLint arrayLen = _slang_array_length(var); const GLint totalSize = _slang_array_size(size, arrayLen); + GLint texIndex = sampler_to_texture_index(var->type.specifier.type); + + /* check for sampler2D arrays */ + if (texIndex == -1 && var->type.specifier._array) + texIndex = sampler_to_texture_index(var->type.specifier._array->type); if (texIndex != -1) { /* This is a texture sampler variable... @@ -4026,15 +4297,32 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var, } #if FEATURE_es2_glsl /* XXX should use FEATURE_texture_rect */ /* disallow rect samplers */ - if (var->type.specifier.type == SLANG_SPEC_SAMPLER2DRECT || - var->type.specifier.type == SLANG_SPEC_SAMPLER2DRECTSHADOW) { + if (is_rect_sampler_spec(&var->type.specifier)) { slang_info_log_error(A->log, "invalid sampler type for '%s'", varName); return GL_FALSE; } +#else + (void) is_rect_sampler_spec; /* silence warning */ #endif { GLint sampNum = _mesa_add_sampler(prog->Parameters, varName, datatype); - store = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, texIndex); + store = _slang_new_ir_storage_sampler(sampNum, texIndex, totalSize); + + /* If we have a sampler array, then we need to allocate the + * additional samplers to ensure we don't allocate them elsewhere. + * We can't directly use _mesa_add_sampler() as that checks the + * varName and gets a match, so we call _mesa_add_parameter() + * directly and use the last sampler number from the call above. + */ + if (arrayLen > 0) { + GLint a = arrayLen - 1; + GLint i; + for (i = 0; i < a; i++) { + GLfloat value = (GLfloat)(i + sampNum + 1); + (void) _mesa_add_parameter(prog->Parameters, PROGRAM_SAMPLER, + varName, 1, datatype, &value, NULL, 0x0); + } + } } if (dbg) printf("SAMPLER "); } @@ -4218,7 +4506,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var, n = _slang_gen_var_decl(A, var, var->initializer); /* emit GPU instructions */ - success = _slang_emit_code(n, A->vartable, A->program, GL_FALSE, A->log); + success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_FALSE, A->log); _slang_free_ir_tree(n); } @@ -4328,7 +4616,7 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun) #endif /* Emit program instructions */ - success = _slang_emit_code(n, A->vartable, A->program, GL_TRUE, A->log); + success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_TRUE, A->log); _slang_free_ir_tree(n); /* free codegen context */ diff --git a/src/mesa/shader/slang/slang_codegen.h b/src/mesa/shader/slang/slang_codegen.h index 9489033d7b..f2daa034e4 100644 --- a/src/mesa/shader/slang/slang_codegen.h +++ b/src/mesa/shader/slang/slang_codegen.h @@ -36,6 +36,7 @@ typedef struct slang_assemble_ctx_ slang_atom_pool *atoms; slang_name_space space; struct gl_program *program; + struct gl_sl_pragmas *pragmas; slang_var_table *vartable; slang_info_log *log; struct slang_label_ *curFuncEndLabel; diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index b8044b1060..ab848579b7 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -144,6 +144,7 @@ typedef struct slang_output_ctx_ slang_function_scope *funs; slang_struct_scope *structs; struct gl_program *program; + struct gl_sl_pragmas *pragmas; slang_var_table *vartable; GLuint default_precision[TYPE_SPECIFIER_COUNT]; GLboolean allow_precision; @@ -1005,7 +1006,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, /* parse child statements, do not create new variable scope */ oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; while (*C->I != OP_END) - if (!parse_child_operation(C, O, oper, 1)) + if (!parse_child_operation(C, O, oper, GL_TRUE)) RETURN0; C->I++; break; @@ -1017,7 +1018,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, oper->type = SLANG_OPER_BLOCK_NEW_SCOPE; o.vars = oper->locals; while (*C->I != OP_END) - if (!parse_child_operation(C, &o, oper, 1)) + if (!parse_child_operation(C, &o, oper, GL_TRUE)) RETURN0; C->I++; } @@ -1074,7 +1075,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, if (oper->a_id == SLANG_ATOM_NULL) RETURN0; while (*C->I != OP_END) { - if (!parse_child_operation(C, O, oper, 0)) + if (!parse_child_operation(C, O, oper, GL_FALSE)) RETURN0; } C->I++; @@ -1090,21 +1091,21 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, break; case OP_RETURN: oper->type = SLANG_OPER_RETURN; - if (!parse_child_operation(C, O, oper, 0)) + if (!parse_child_operation(C, O, oper, GL_FALSE)) RETURN0; break; case OP_EXPRESSION: oper->type = SLANG_OPER_EXPRESSION; - if (!parse_child_operation(C, O, oper, 0)) + if (!parse_child_operation(C, O, oper, GL_FALSE)) RETURN0; break; case OP_IF: oper->type = SLANG_OPER_IF; - if (!parse_child_operation(C, O, oper, 0)) + if (!parse_child_operation(C, O, oper, GL_FALSE)) RETURN0; - if (!parse_child_operation(C, O, oper, 1)) + if (!parse_child_operation(C, O, oper, GL_TRUE)) RETURN0; - if (!parse_child_operation(C, O, oper, 1)) + if (!parse_child_operation(C, O, oper, GL_TRUE)) RETURN0; break; case OP_WHILE: @@ -1113,17 +1114,17 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, oper->type = SLANG_OPER_WHILE; o.vars = oper->locals; - if (!parse_child_operation(C, &o, oper, 1)) + if (!parse_child_operation(C, &o, oper, GL_TRUE)) RETURN0; - if (!parse_child_operation(C, &o, oper, 1)) + if (!parse_child_operation(C, &o, oper, GL_TRUE)) RETURN0; } break; case OP_DO: oper->type = SLANG_OPER_DO; - if (!parse_child_operation(C, O, oper, 1)) + if (!parse_child_operation(C, O, oper, GL_TRUE)) RETURN0; - if (!parse_child_operation(C, O, oper, 0)) + if (!parse_child_operation(C, O, oper, GL_FALSE)) RETURN0; break; case OP_FOR: @@ -1132,13 +1133,13 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, oper->type = SLANG_OPER_FOR; o.vars = oper->locals; - if (!parse_child_operation(C, &o, oper, 1)) + if (!parse_child_operation(C, &o, oper, GL_TRUE)) RETURN0; - if (!parse_child_operation(C, &o, oper, 1)) + if (!parse_child_operation(C, &o, oper, GL_TRUE)) RETURN0; - if (!parse_child_operation(C, &o, oper, 0)) + if (!parse_child_operation(C, &o, oper, GL_FALSE)) RETURN0; - if (!parse_child_operation(C, &o, oper, 1)) + if (!parse_child_operation(C, &o, oper, GL_TRUE)) RETURN0; } break; @@ -1429,7 +1430,7 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, C->I++; while (*C->I != OP_END) - if (!parse_child_operation(C, O, op, 0)) + if (!parse_child_operation(C, O, op, GL_FALSE)) RETURN0; C->I++; #if 0 @@ -1449,7 +1450,7 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, case OP_CALL: { GLboolean array_constructor = GL_FALSE; - GLint array_constructor_size; + GLint array_constructor_size = 0; op->type = SLANG_OPER_CALL; op->a_id = parse_identifier(C); @@ -1470,9 +1471,9 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, RETURN0; } else { + /* parse the array constructor size */ slang_operation array_size; array_constructor = GL_TRUE; - /* parse the array constructor size */ slang_operation_construct(&array_size); if (!parse_expression(C, O, &array_size)) { slang_operation_destruct(&array_size); @@ -1494,7 +1495,7 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, RETURN0; } while (*C->I != OP_END) - if (!parse_child_operation(C, O, op, 0)) + if (!parse_child_operation(C, O, op, GL_FALSE)) RETURN0; C->I++; @@ -2059,6 +2060,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O, A.space.structs = O->structs; A.space.vars = O->vars; A.program = O->program; + A.pragmas = O->pragmas; A.vartable = O->vartable; A.log = C->L; A.curFuncEndLabel = NULL; @@ -2349,6 +2351,7 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit, o.structs = &unit->structs; o.vars = &unit->vars; o.program = shader ? shader->Program : NULL; + o.pragmas = shader ? &shader->Pragmas : NULL; o.vartable = _slang_new_var_table(maxRegs); _slang_push_var_table(o.vartable); @@ -2417,6 +2420,7 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit, A.space.structs = o.structs; A.space.vars = o.vars; A.program = o.program; + A.pragmas = &shader->Pragmas; A.vartable = o.vartable; A.log = C->L; @@ -2474,7 +2478,9 @@ static GLboolean compile_with_grammar(grammar id, const char *source, slang_code_unit * unit, slang_unit_type type, slang_info_log * infolog, slang_code_unit * builtin, - struct gl_shader *shader) + struct gl_shader *shader, + const struct gl_extensions *extensions, + struct gl_sl_pragmas *pragmas) { byte *prod; GLuint size, start, version; @@ -2502,7 +2508,8 @@ compile_with_grammar(grammar id, const char *source, slang_code_unit * unit, /* Now preprocess the source string. */ slang_string_init(&preprocessed); - if (!_slang_preprocess_directives(&preprocessed, &source[start], infolog)) { + if (!_slang_preprocess_directives(&preprocessed, &source[start], + infolog, extensions, pragmas)) { slang_string_free(&preprocessed); slang_info_log_error(infolog, "failed to preprocess the source."); return GL_FALSE; @@ -2575,7 +2582,9 @@ static const byte slang_vertex_builtin_gc[] = { static GLboolean compile_object(grammar * id, const char *source, slang_code_object * object, slang_unit_type type, slang_info_log * infolog, - struct gl_shader *shader) + struct gl_shader *shader, + const struct gl_extensions *extensions, + struct gl_sl_pragmas *pragmas) { slang_code_unit *builtins = NULL; GLuint base_version = 110; @@ -2674,7 +2683,7 @@ compile_object(grammar * id, const char *source, slang_code_object * object, /* compile the actual shader - pass-in built-in library for external shader */ return compile_with_grammar(*id, source, &object->unit, type, infolog, - builtins, shader); + builtins, shader, extensions, pragmas); } @@ -2697,7 +2706,8 @@ compile_shader(GLcontext *ctx, slang_code_object * object, _slang_code_object_dtr(object); _slang_code_object_ctr(object); - success = compile_object(&id, shader->Source, object, type, infolog, shader); + success = compile_object(&id, shader->Source, object, type, infolog, shader, + &ctx->Extensions, &shader->Pragmas); if (id != 0) grammar_destroy(id); if (!success) @@ -2784,6 +2794,12 @@ _slang_compile(GLcontext *ctx, struct gl_shader *shader) _mesa_print_program(shader->Program); #endif + shader->CompileStatus = success; + + if (ctx->Shader.Flags & GLSL_LOG) { + _mesa_write_shader_to_file(shader); + } + return success; } diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 3a837c9c10..ac01462bd5 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -451,7 +451,7 @@ emit_arl_load(slang_emit_info *emitInfo, struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ARL); inst->SrcReg[0].File = file; inst->SrcReg[0].Index = index; - inst->SrcReg[0].Swizzle = swizzle; + inst->SrcReg[0].Swizzle = fix_swizzle(swizzle); inst->DstReg.File = PROGRAM_ADDRESS; inst->DstReg.Index = 0; inst->DstReg.WriteMask = WRITEMASK_X; @@ -717,6 +717,9 @@ instruction_annotation(gl_inst_opcode opcode, char *dstAnnot, case OPCODE_MUL: operator = "*"; break; + case OPCODE_DP2: + operator = "DP2"; + break; case OPCODE_DP3: operator = "DP3"; break; @@ -870,6 +873,7 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) if (n->Children[0]->Store->Size != n->Children[1]->Store->Size) { slang_info_log_error(emitInfo->log, "invalid operands to == or !="); + n->Store = NULL; return NULL; } @@ -899,6 +903,7 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) slang_ir_storage tempStore; if (!alloc_local_temp(emitInfo, &tempStore, 4)) { + n->Store = NULL; return NULL; /* out of temps */ } @@ -913,7 +918,7 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) } else { assert(size == 2); - dotOp = OPCODE_DP3; + dotOp = OPCODE_DP3; /* XXX use OPCODE_DP2 eventually */ swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y); } @@ -1268,6 +1273,20 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n) opcode = OPCODE_TXP; } + if (n->Children[0]->Opcode == IR_ELEMENT) { + /* array is the sampler (a uniform which'll indicate the texture unit) */ + assert(n->Children[0]->Children[0]->Store); + assert(n->Children[0]->Children[0]->Store->File == PROGRAM_SAMPLER); + + emit(emitInfo, n->Children[0]); + + n->Children[0]->Var = n->Children[0]->Children[0]->Var; + } else { + /* this is the sampler (a uniform which'll indicate the texture unit) */ + assert(n->Children[0]->Store); + assert(n->Children[0]->Store->File == PROGRAM_SAMPLER); + } + /* emit code for the texcoord operand */ (void) emit(emitInfo, n->Children[1]); @@ -1283,17 +1302,10 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n) NULL, NULL); - /* Child[0] is the sampler (a uniform which'll indicate the texture unit) */ - assert(n->Children[0]->Store); - assert(n->Children[0]->Store->File == PROGRAM_SAMPLER); - /* Store->Index is the sampler index */ + /* Store->Index is the uniform/sampler index */ assert(n->Children[0]->Store->Index >= 0); - /* Store->Size is the texture target */ - assert(n->Children[0]->Store->Size >= TEXTURE_1D_INDEX); - assert(n->Children[0]->Store->Size <= TEXTURE_RECT_INDEX); - - inst->TexSrcTarget = n->Children[0]->Store->Size; - inst->TexSrcUnit = n->Children[0]->Store->Index; /* i.e. uniform's index */ + inst->TexSrcUnit = n->Children[0]->Store->Index; + inst->TexSrcTarget = n->Children[0]->Store->TexTarget; /* mark the sampler as being used */ _mesa_use_uniform(emitInfo->prog->Parameters, @@ -1339,9 +1351,10 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n) if (n->Store->File == PROGRAM_SAMPLER) { /* no code generated for sampler assignments, - * just copy the sampler index at compile time. + * just copy the sampler index/target at compile time. */ n->Store->Index = n->Children[1]->Store->Index; + n->Store->TexTarget = n->Children[1]->Store->TexTarget; return NULL; } @@ -1802,6 +1815,25 @@ emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n) } +/** + * Return the size of a swizzle mask given that some swizzle components + * may be NIL/undefined. For example: + * swizzle_size(".zzxx") = 4 + * swizzle_size(".xy??") = 2 + * swizzle_size(".w???") = 1 + */ +static GLuint +swizzle_size(GLuint swizzle) +{ + GLuint i; + for (i = 0; i < 4; i++) { + if (GET_SWZ(swizzle, i) == SWIZZLE_NIL) + return i; + } + return 4; +} + + static struct prog_instruction * emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) { @@ -1809,14 +1841,24 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) inst = emit(emitInfo, n->Children[0]); -#if 0 - assert(n->Store->Parent); - /* Apply this node's swizzle to parent's storage */ - GLuint swizzle = n->Store->Swizzle; - _slang_copy_ir_storage(n->Store, n->Store->Parent); - n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle); - assert(!n->Store->Parent); -#endif + if (n->Children[0]->Opcode == IR_VAR || + n->Children[0]->Opcode == IR_SWIZZLE || + n->Children[0]->Opcode == IR_ELEMENT) { + /* We can resolve the swizzle now. Other swizzles will be resolved + * in storage_to_src_reg(). + */ + const GLuint swizzle = n->Store->Swizzle; + assert(n->Store->Parent); + /* new storage is parent storage with updated Swizzle + Size fields */ + _slang_copy_ir_storage(n->Store, n->Store->Parent); + /* Apply this node's swizzle to parent's storage */ + n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle); + /* Update size */ + n->Store->Size = swizzle_size(n->Store->Swizzle); + assert(!n->Store->Parent); + assert(n->Store->Index >= 0); + } + return inst; } @@ -2109,6 +2151,10 @@ emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n) /* mark var as used */ _mesa_use_uniform(emitInfo->prog->Parameters, (char *) n->Var->a_name); } + else if (n->Store->File == PROGRAM_INPUT) { + assert(n->Store->Index >= 0); + emitInfo->prog->InputsRead |= (1 << n->Store->Index); + } if (n->Store->Index < 0) { /* probably ran out of registers */ @@ -2192,12 +2238,15 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n) case IR_NOISE2: case IR_NOISE3: case IR_NOISE4: + case IR_NRM4: + case IR_NRM3: /* binary */ case IR_ADD: case IR_SUB: case IR_MUL: case IR_DOT4: case IR_DOT3: + case IR_DOT2: case IR_CROSS: case IR_MIN: case IR_MAX: @@ -2364,10 +2413,20 @@ _slang_resolve_subroutines(slang_emit_info *emitInfo) - +/** + * Convert the IR tree into GPU instructions. + * \param n root of IR tree + * \param vt variable table + * \param prog program to put GPU instructions into + * \param pragmas controls codegen options + * \param withEnd if true, emit END opcode at end + * \param log log for emitting errors/warnings/info + */ GLboolean _slang_emit_code(slang_ir_node *n, slang_var_table *vt, - struct gl_program *prog, GLboolean withEnd, + struct gl_program *prog, + const struct gl_sl_pragmas *pragmas, + GLboolean withEnd, slang_info_log *log) { GET_CURRENT_CONTEXT(ctx); @@ -2384,7 +2443,7 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt, emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions; emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes; - emitInfo.EmitComments = ctx->Shader.EmitComments; + emitInfo.EmitComments = ctx->Shader.EmitComments || pragmas->Debug; emitInfo.EmitBeginEndSub = GL_TRUE; if (!emitInfo.EmitCondCodes) { @@ -2400,7 +2459,9 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt, maxUniforms = ctx->Const.VertexProgram.MaxUniformComponents / 4; } if (prog->Parameters->NumParameters > maxUniforms) { - slang_info_log_error(log, "Constant/uniform register limit exceeded"); + slang_info_log_error(log, "Constant/uniform register limit exceeded " + "(max=%u vec4)", maxUniforms); + return GL_FALSE; } diff --git a/src/mesa/shader/slang/slang_emit.h b/src/mesa/shader/slang/slang_emit.h index 59fb2fa890..ab4c202d67 100644 --- a/src/mesa/shader/slang/slang_emit.h +++ b/src/mesa/shader/slang/slang_emit.h @@ -32,10 +32,6 @@ #include "main/mtypes.h" -extern void -slang_print_ir(const slang_ir_node *n, int indent); - - extern GLuint _slang_swizzle_swizzle(GLuint swz1, GLuint swz2); @@ -46,7 +42,9 @@ _slang_var_swizzle(GLint size, GLint comp); extern GLboolean _slang_emit_code(slang_ir_node *n, slang_var_table *vartable, - struct gl_program *prog, GLboolean withEnd, + struct gl_program *prog, + const struct gl_sl_pragmas *pragmas, + GLboolean withEnd, slang_info_log *log); diff --git a/src/mesa/shader/slang/slang_ir.c b/src/mesa/shader/slang/slang_ir.c index b459accb90..e4c6e0ea51 100644 --- a/src/mesa/shader/slang/slang_ir.c +++ b/src/mesa/shader/slang/slang_ir.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 7.1 * * Copyright (C) 2005-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. 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"), @@ -27,6 +27,7 @@ #include "main/context.h" #include "slang_ir.h" #include "slang_mem.h" +#include "shader/prog_instruction.h" #include "shader/prog_print.h" @@ -36,8 +37,11 @@ static const slang_ir_info IrInfo[] = { { IR_SUB, "IR_SUB", OPCODE_SUB, 4, 2 }, { IR_MUL, "IR_MUL", OPCODE_MUL, 4, 2 }, { IR_DIV, "IR_DIV", OPCODE_NOP, 0, 2 }, /* XXX broke */ - { IR_DOT4, "IR_DOT_4", OPCODE_DP4, 1, 2 }, - { IR_DOT3, "IR_DOT_3", OPCODE_DP3, 1, 2 }, + { IR_DOT4, "IR_DOT4", OPCODE_DP4, 1, 2 }, + { IR_DOT3, "IR_DOT3", OPCODE_DP3, 1, 2 }, + { IR_DOT2, "IR_DOT2", OPCODE_DP2, 1, 2 }, + { IR_NRM4, "IR_NRM4", OPCODE_NRM4, 1, 1 }, + { IR_NRM3, "IR_NRM3", OPCODE_NRM3, 1, 1 }, { IR_CROSS, "IR_CROSS", OPCODE_XPD, 3, 2 }, { IR_LRP, "IR_LRP", OPCODE_LRP, 4, 3 }, { IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 }, @@ -56,7 +60,7 @@ static const slang_ir_info IrInfo[] = { /* unary ops */ { IR_MOVE, "IR_MOVE", OPCODE_MOV, 4, 1 }, { IR_I_TO_F, "IR_I_TO_F", OPCODE_MOV, 4, 1 }, /* int[4] to float[4] */ - { IR_F_TO_I, "IR_F_TO_I", OPCODE_INT, 4, 1 }, /* 4 floats to 4 ints */ + { IR_F_TO_I, "IR_F_TO_I", OPCODE_TRUNC, 4, 1 }, { IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 }, { IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 }, { IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 }, @@ -212,6 +216,26 @@ _slang_new_ir_storage_indirect(enum register_file file, } +/** + * Allocate IR storage for a texture sampler. + * \param sampNum the sampler number/index + * \param texTarget one of TEXTURE_x_INDEX values + * \param size number of samplers (in case of sampler array) + */ +slang_ir_storage * +_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size) +{ + slang_ir_storage *st; + assert(texTarget < NUM_TEXTURE_TARGETS); + st = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, size); + if (st) { + st->TexTarget = texTarget; + } + return st; +} + + + /* XXX temporary function */ void _slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src) diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h index cc784d431b..644269d491 100644 --- a/src/mesa/shader/slang/slang_ir.h +++ b/src/mesa/shader/slang/slang_ir.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.5.3 * - * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. 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"), @@ -83,6 +83,9 @@ typedef enum IR_DIV, IR_DOT4, IR_DOT3, + IR_DOT2, + IR_NRM4, + IR_NRM3, IR_CROSS, /* vec3 cross product */ IR_LRP, IR_CLAMP, @@ -165,8 +168,8 @@ typedef enum struct slang_ir_storage_ { enum register_file File; /**< PROGRAM_TEMPORARY, PROGRAM_INPUT, etc */ - GLint Index; /**< -1 means unallocated */ - GLint Size; /**< number of floats */ + GLint Index; /**< -1 means unallocated */ + GLint Size; /**< number of floats or ints */ GLuint Swizzle; /**< Swizzle AND writemask info */ GLint RefCount; /**< Used during IR tree delete */ @@ -176,6 +179,7 @@ struct slang_ir_storage_ enum register_file IndirectFile; GLint IndirectIndex; GLuint IndirectSwizzle; + GLuint TexTarget; /**< If File==PROGRAM_SAMPLER, one of TEXTURE_x_INDEX */ /** If Parent is non-null, Index is relative to parent. * The other fields are ignored. @@ -251,6 +255,10 @@ _slang_new_ir_storage_indirect(enum register_file file, GLint indirectIndex, GLuint indirectSwizzle); +extern slang_ir_storage * +_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size); + + extern void _slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src); diff --git a/src/mesa/shader/slang/slang_library_noise.c b/src/mesa/shader/slang/slang_library_noise.c deleted file mode 100644 index 25a05657cc..0000000000 --- a/src/mesa/shader/slang/slang_library_noise.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 2006 Brian Paul 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, sublicense, - * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL 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. - */ - -/* - * SimplexNoise1234 - * Copyright (c) 2003-2005, Stefan Gustavson - * - * Contact: stegu@itn.liu.se - */ - -/** \file - \brief C implementation of Perlin Simplex Noise over 1,2,3, and 4 dimensions. - \author Stefan Gustavson (stegu@itn.liu.se) -*/ - -/* - * This implementation is "Simplex Noise" as presented by - * Ken Perlin at a relatively obscure and not often cited course - * session "Real-Time Shading" at Siggraph 2001 (before real - * time shading actually took on), under the title "hardware noise". - * The 3D function is numerically equivalent to his Java reference - * code available in the PDF course notes, although I re-implemented - * it from scratch to get more readable code. The 1D, 2D and 4D cases - * were implemented from scratch by me from Ken Perlin's text. - * - * This file has no dependencies on any other file, not even its own - * header file. The header file is made for use by external code only. - */ - - -#include "main/imports.h" -#include "slang_library_noise.h" - -#define FASTFLOOR(x) ( ((x)>0) ? ((int)x) : (((int)x)-1) ) - -/* - * --------------------------------------------------------------------- - * Static data - */ - -/* - * Permutation table. This is just a random jumble of all numbers 0-255, - * repeated twice to avoid wrapping the index at 255 for each lookup. - * This needs to be exactly the same for all instances on all platforms, - * so it's easiest to just keep it as static explicit data. - * This also removes the need for any initialisation of this class. - * - * Note that making this an int[] instead of a char[] might make the - * code run faster on platforms with a high penalty for unaligned single - * byte addressing. Intel x86 is generally single-byte-friendly, but - * some other CPUs are faster with 4-aligned reads. - * However, a char[] is smaller, which avoids cache trashing, and that - * is probably the most important aspect on most architectures. - * This array is accessed a *lot* by the noise functions. - * A vector-valued noise over 3D accesses it 96 times, and a - * float-valued 4D noise 64 times. We want this to fit in the cache! - */ -unsigned char perm[512] = {151,160,137,91,90,15, - 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, - 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, - 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, - 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, - 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, - 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, - 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, - 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, - 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, - 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, - 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, - 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, - 151,160,137,91,90,15, - 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, - 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, - 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, - 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, - 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, - 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, - 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, - 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, - 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, - 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, - 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, - 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 -}; - -/* - * --------------------------------------------------------------------- - */ - -/* - * Helper functions to compute gradients-dot-residualvectors (1D to 4D) - * Note that these generate gradients of more than unit length. To make - * a close match with the value range of classic Perlin noise, the final - * noise values need to be rescaled to fit nicely within [-1,1]. - * (The simplex noise functions as such also have different scaling.) - * Note also that these noise functions are the most practical and useful - * signed version of Perlin noise. To return values according to the - * RenderMan specification from the SL noise() and pnoise() functions, - * the noise values need to be scaled and offset to [0,1], like this: - * float SLnoise = (SimplexNoise1234::noise(x,y,z) + 1.0) * 0.5; - */ - -static float grad1( int hash, float x ) { - int h = hash & 15; - float grad = 1.0f + (h & 7); /* Gradient value 1.0, 2.0, ..., 8.0 */ - if (h&8) grad = -grad; /* Set a random sign for the gradient */ - return ( grad * x ); /* Multiply the gradient with the distance */ -} - -static float grad2( int hash, float x, float y ) { - int h = hash & 7; /* Convert low 3 bits of hash code */ - float u = h<4 ? x : y; /* into 8 simple gradient directions, */ - float v = h<4 ? y : x; /* and compute the dot product with (x,y). */ - return ((h&1)? -u : u) + ((h&2)? -2.0f*v : 2.0f*v); -} - -static float grad3( int hash, float x, float y , float z ) { - int h = hash & 15; /* Convert low 4 bits of hash code into 12 simple */ - float u = h<8 ? x : y; /* gradient directions, and compute dot product. */ - float v = h<4 ? y : h==12||h==14 ? x : z; /* Fix repeats at h = 12 to 15 */ - return ((h&1)? -u : u) + ((h&2)? -v : v); -} - -static float grad4( int hash, float x, float y, float z, float t ) { - int h = hash & 31; /* Convert low 5 bits of hash code into 32 simple */ - float u = h<24 ? x : y; /* gradient directions, and compute dot product. */ - float v = h<16 ? y : z; - float w = h<8 ? z : t; - return ((h&1)? -u : u) + ((h&2)? -v : v) + ((h&4)? -w : w); -} - - /* A lookup table to traverse the simplex around a given point in 4D. */ - /* Details can be found where this table is used, in the 4D noise method. */ - /* TODO: This should not be required, backport it from Bill's GLSL code! */ - static unsigned char simplex[64][4] = { - {0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0}, - {0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0}, - {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, - {1,2,0,3},{0,0,0,0},{1,3,0,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,3,0,1},{2,3,1,0}, - {1,0,2,3},{1,0,3,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,0,3,1},{0,0,0,0},{2,1,3,0}, - {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, - {2,0,1,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,0,1,2},{3,0,2,1},{0,0,0,0},{3,1,2,0}, - {2,1,0,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,1,0,2},{0,0,0,0},{3,2,0,1},{3,2,1,0}}; - -/* 1D simplex noise */ -GLfloat _slang_library_noise1 (GLfloat x) -{ - int i0 = FASTFLOOR(x); - int i1 = i0 + 1; - float x0 = x - i0; - float x1 = x0 - 1.0f; - float t1 = 1.0f - x1*x1; - float n0, n1; - - float t0 = 1.0f - x0*x0; -/* if(t0 < 0.0f) t0 = 0.0f; // this never happens for the 1D case */ - t0 *= t0; - n0 = t0 * t0 * grad1(perm[i0 & 0xff], x0); - -/* if(t1 < 0.0f) t1 = 0.0f; // this never happens for the 1D case */ - t1 *= t1; - n1 = t1 * t1 * grad1(perm[i1 & 0xff], x1); - /* The maximum value of this noise is 8*(3/4)^4 = 2.53125 */ - /* A factor of 0.395 would scale to fit exactly within [-1,1], but */ - /* we want to match PRMan's 1D noise, so we scale it down some more. */ - return 0.25f * (n0 + n1); -} - -/* 2D simplex noise */ -GLfloat _slang_library_noise2 (GLfloat x, GLfloat y) -{ -#define F2 0.366025403f /* F2 = 0.5*(sqrt(3.0)-1.0) */ -#define G2 0.211324865f /* G2 = (3.0-Math.sqrt(3.0))/6.0 */ - - float n0, n1, n2; /* Noise contributions from the three corners */ - - /* Skew the input space to determine which simplex cell we're in */ - float s = (x+y)*F2; /* Hairy factor for 2D */ - float xs = x + s; - float ys = y + s; - int i = FASTFLOOR(xs); - int j = FASTFLOOR(ys); - - float t = (float)(i+j)*G2; - float X0 = i-t; /* Unskew the cell origin back to (x,y) space */ - float Y0 = j-t; - float x0 = x-X0; /* The x,y distances from the cell origin */ - float y0 = y-Y0; - - float x1, y1, x2, y2; - int ii, jj; - float t0, t1, t2; - - /* For the 2D case, the simplex shape is an equilateral triangle. */ - /* Determine which simplex we are in. */ - int i1, j1; /* Offsets for second (middle) corner of simplex in (i,j) coords */ - if(x0>y0) {i1=1; j1=0;} /* lower triangle, XY order: (0,0)->(1,0)->(1,1) */ - else {i1=0; j1=1;} /* upper triangle, YX order: (0,0)->(0,1)->(1,1) */ - - /* A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and */ - /* a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where */ - /* c = (3-sqrt(3))/6 */ - - x1 = x0 - i1 + G2; /* Offsets for middle corner in (x,y) unskewed coords */ - y1 = y0 - j1 + G2; - x2 = x0 - 1.0f + 2.0f * G2; /* Offsets for last corner in (x,y) unskewed coords */ - y2 = y0 - 1.0f + 2.0f * G2; - - /* Wrap the integer indices at 256, to avoid indexing perm[] out of bounds */ - ii = i % 256; - jj = j % 256; - - /* Calculate the contribution from the three corners */ - t0 = 0.5f - x0*x0-y0*y0; - if(t0 < 0.0f) n0 = 0.0f; - else { - t0 *= t0; - n0 = t0 * t0 * grad2(perm[ii+perm[jj]], x0, y0); - } - - t1 = 0.5f - x1*x1-y1*y1; - if(t1 < 0.0f) n1 = 0.0f; - else { - t1 *= t1; - n1 = t1 * t1 * grad2(perm[ii+i1+perm[jj+j1]], x1, y1); - } - - t2 = 0.5f - x2*x2-y2*y2; - if(t2 < 0.0f) n2 = 0.0f; - else { - t2 *= t2; - n2 = t2 * t2 * grad2(perm[ii+1+perm[jj+1]], x2, y2); - } - - /* Add contributions from each corner to get the final noise value. */ - /* The result is scaled to return values in the interval [-1,1]. */ - return 40.0f * (n0 + n1 + n2); /* TODO: The scale factor is preliminary! */ -} - -/* 3D simplex noise */ -GLfloat _slang_library_noise3 (GLfloat x, GLfloat y, GLfloat z) -{ -/* Simple skewing factors for the 3D case */ -#define F3 0.333333333f -#define G3 0.166666667f - - float n0, n1, n2, n3; /* Noise contributions from the four corners */ - - /* Skew the input space to determine which simplex cell we're in */ - float s = (x+y+z)*F3; /* Very nice and simple skew factor for 3D */ - float xs = x+s; - float ys = y+s; - float zs = z+s; - int i = FASTFLOOR(xs); - int j = FASTFLOOR(ys); - int k = FASTFLOOR(zs); - - float t = (float)(i+j+k)*G3; - float X0 = i-t; /* Unskew the cell origin back to (x,y,z) space */ - float Y0 = j-t; - float Z0 = k-t; - float x0 = x-X0; /* The x,y,z distances from the cell origin */ - float y0 = y-Y0; - float z0 = z-Z0; - - float x1, y1, z1, x2, y2, z2, x3, y3, z3; - int ii, jj, kk; - float t0, t1, t2, t3; - - /* For the 3D case, the simplex shape is a slightly irregular tetrahedron. */ - /* Determine which simplex we are in. */ - int i1, j1, k1; /* Offsets for second corner of simplex in (i,j,k) coords */ - int i2, j2, k2; /* Offsets for third corner of simplex in (i,j,k) coords */ - -/* This code would benefit from a backport from the GLSL version! */ - if(x0>=y0) { - if(y0>=z0) - { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } /* X Y Z order */ - else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } /* X Z Y order */ - else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } /* Z X Y order */ - } - else { /* x0<y0 */ - if(y0<z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } /* Z Y X order */ - else if(x0<z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } /* Y Z X order */ - else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } /* Y X Z order */ - } - - /* A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), */ - /* a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and */ - /* a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where */ - /* c = 1/6. */ - - x1 = x0 - i1 + G3; /* Offsets for second corner in (x,y,z) coords */ - y1 = y0 - j1 + G3; - z1 = z0 - k1 + G3; - x2 = x0 - i2 + 2.0f*G3; /* Offsets for third corner in (x,y,z) coords */ - y2 = y0 - j2 + 2.0f*G3; - z2 = z0 - k2 + 2.0f*G3; - x3 = x0 - 1.0f + 3.0f*G3; /* Offsets for last corner in (x,y,z) coords */ - y3 = y0 - 1.0f + 3.0f*G3; - z3 = z0 - 1.0f + 3.0f*G3; - - /* Wrap the integer indices at 256, to avoid indexing perm[] out of bounds */ - ii = i % 256; - jj = j % 256; - kk = k % 256; - - /* Calculate the contribution from the four corners */ - t0 = 0.6f - x0*x0 - y0*y0 - z0*z0; - if(t0 < 0.0f) n0 = 0.0f; - else { - t0 *= t0; - n0 = t0 * t0 * grad3(perm[ii+perm[jj+perm[kk]]], x0, y0, z0); - } - - t1 = 0.6f - x1*x1 - y1*y1 - z1*z1; - if(t1 < 0.0f) n1 = 0.0f; - else { - t1 *= t1; - n1 = t1 * t1 * grad3(perm[ii+i1+perm[jj+j1+perm[kk+k1]]], x1, y1, z1); - } - - t2 = 0.6f - x2*x2 - y2*y2 - z2*z2; - if(t2 < 0.0f) n2 = 0.0f; - else { - t2 *= t2; - n2 = t2 * t2 * grad3(perm[ii+i2+perm[jj+j2+perm[kk+k2]]], x2, y2, z2); - } - - t3 = 0.6f - x3*x3 - y3*y3 - z3*z3; - if(t3<0.0f) n3 = 0.0f; - else { - t3 *= t3; - n3 = t3 * t3 * grad3(perm[ii+1+perm[jj+1+perm[kk+1]]], x3, y3, z3); - } - - /* Add contributions from each corner to get the final noise value. */ - /* The result is scaled to stay just inside [-1,1] */ - return 32.0f * (n0 + n1 + n2 + n3); /* TODO: The scale factor is preliminary! */ -} - -/* 4D simplex noise */ -GLfloat _slang_library_noise4 (GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - /* The skewing and unskewing factors are hairy again for the 4D case */ -#define F4 0.309016994f /* F4 = (Math.sqrt(5.0)-1.0)/4.0 */ -#define G4 0.138196601f /* G4 = (5.0-Math.sqrt(5.0))/20.0 */ - - float n0, n1, n2, n3, n4; /* Noise contributions from the five corners */ - - /* Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in */ - float s = (x + y + z + w) * F4; /* Factor for 4D skewing */ - float xs = x + s; - float ys = y + s; - float zs = z + s; - float ws = w + s; - int i = FASTFLOOR(xs); - int j = FASTFLOOR(ys); - int k = FASTFLOOR(zs); - int l = FASTFLOOR(ws); - - float t = (i + j + k + l) * G4; /* Factor for 4D unskewing */ - float X0 = i - t; /* Unskew the cell origin back to (x,y,z,w) space */ - float Y0 = j - t; - float Z0 = k - t; - float W0 = l - t; - - float x0 = x - X0; /* The x,y,z,w distances from the cell origin */ - float y0 = y - Y0; - float z0 = z - Z0; - float w0 = w - W0; - - /* For the 4D case, the simplex is a 4D shape I won't even try to describe. */ - /* To find out which of the 24 possible simplices we're in, we need to */ - /* determine the magnitude ordering of x0, y0, z0 and w0. */ - /* The method below is a good way of finding the ordering of x,y,z,w and */ - /* then find the correct traversal order for the simplex we're in. */ - /* First, six pair-wise comparisons are performed between each possible pair */ - /* of the four coordinates, and the results are used to add up binary bits */ - /* for an integer index. */ - int c1 = (x0 > y0) ? 32 : 0; - int c2 = (x0 > z0) ? 16 : 0; - int c3 = (y0 > z0) ? 8 : 0; - int c4 = (x0 > w0) ? 4 : 0; - int c5 = (y0 > w0) ? 2 : 0; - int c6 = (z0 > w0) ? 1 : 0; - int c = c1 + c2 + c3 + c4 + c5 + c6; - - int i1, j1, k1, l1; /* The integer offsets for the second simplex corner */ - int i2, j2, k2, l2; /* The integer offsets for the third simplex corner */ - int i3, j3, k3, l3; /* The integer offsets for the fourth simplex corner */ - - float x1, y1, z1, w1, x2, y2, z2, w2, x3, y3, z3, w3, x4, y4, z4, w4; - int ii, jj, kk, ll; - float t0, t1, t2, t3, t4; - - /* simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order. */ - /* Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w */ - /* impossible. Only the 24 indices which have non-zero entries make any sense. */ - /* We use a thresholding to set the coordinates in turn from the largest magnitude. */ - /* The number 3 in the "simplex" array is at the position of the largest coordinate. */ - i1 = simplex[c][0]>=3 ? 1 : 0; - j1 = simplex[c][1]>=3 ? 1 : 0; - k1 = simplex[c][2]>=3 ? 1 : 0; - l1 = simplex[c][3]>=3 ? 1 : 0; - /* The number 2 in the "simplex" array is at the second largest coordinate. */ - i2 = simplex[c][0]>=2 ? 1 : 0; - j2 = simplex[c][1]>=2 ? 1 : 0; - k2 = simplex[c][2]>=2 ? 1 : 0; - l2 = simplex[c][3]>=2 ? 1 : 0; - /* The number 1 in the "simplex" array is at the second smallest coordinate. */ - i3 = simplex[c][0]>=1 ? 1 : 0; - j3 = simplex[c][1]>=1 ? 1 : 0; - k3 = simplex[c][2]>=1 ? 1 : 0; - l3 = simplex[c][3]>=1 ? 1 : 0; - /* The fifth corner has all coordinate offsets = 1, so no need to look that up. */ - - x1 = x0 - i1 + G4; /* Offsets for second corner in (x,y,z,w) coords */ - y1 = y0 - j1 + G4; - z1 = z0 - k1 + G4; - w1 = w0 - l1 + G4; - x2 = x0 - i2 + 2.0f*G4; /* Offsets for third corner in (x,y,z,w) coords */ - y2 = y0 - j2 + 2.0f*G4; - z2 = z0 - k2 + 2.0f*G4; - w2 = w0 - l2 + 2.0f*G4; - x3 = x0 - i3 + 3.0f*G4; /* Offsets for fourth corner in (x,y,z,w) coords */ - y3 = y0 - j3 + 3.0f*G4; - z3 = z0 - k3 + 3.0f*G4; - w3 = w0 - l3 + 3.0f*G4; - x4 = x0 - 1.0f + 4.0f*G4; /* Offsets for last corner in (x,y,z,w) coords */ - y4 = y0 - 1.0f + 4.0f*G4; - z4 = z0 - 1.0f + 4.0f*G4; - w4 = w0 - 1.0f + 4.0f*G4; - - /* Wrap the integer indices at 256, to avoid indexing perm[] out of bounds */ - ii = i % 256; - jj = j % 256; - kk = k % 256; - ll = l % 256; - - /* Calculate the contribution from the five corners */ - t0 = 0.6f - x0*x0 - y0*y0 - z0*z0 - w0*w0; - if(t0 < 0.0f) n0 = 0.0f; - else { - t0 *= t0; - n0 = t0 * t0 * grad4(perm[ii+perm[jj+perm[kk+perm[ll]]]], x0, y0, z0, w0); - } - - t1 = 0.6f - x1*x1 - y1*y1 - z1*z1 - w1*w1; - if(t1 < 0.0f) n1 = 0.0f; - else { - t1 *= t1; - n1 = t1 * t1 * grad4(perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]], x1, y1, z1, w1); - } - - t2 = 0.6f - x2*x2 - y2*y2 - z2*z2 - w2*w2; - if(t2 < 0.0f) n2 = 0.0f; - else { - t2 *= t2; - n2 = t2 * t2 * grad4(perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]], x2, y2, z2, w2); - } - - t3 = 0.6f - x3*x3 - y3*y3 - z3*z3 - w3*w3; - if(t3 < 0.0f) n3 = 0.0f; - else { - t3 *= t3; - n3 = t3 * t3 * grad4(perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]], x3, y3, z3, w3); - } - - t4 = 0.6f - x4*x4 - y4*y4 - z4*z4 - w4*w4; - if(t4 < 0.0f) n4 = 0.0f; - else { - t4 *= t4; - n4 = t4 * t4 * grad4(perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]], x4, y4, z4, w4); - } - - /* Sum up and scale the result to cover the range [-1,1] */ - return 27.0f * (n0 + n1 + n2 + n3 + n4); /* TODO: The scale factor is preliminary! */ -} - diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index 108d11c7df..99f2cbdcc0 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -260,8 +260,8 @@ link_uniform_vars(GLcontext *ctx, GLuint newSampNum = *numSamplers; if (newSampNum >= ctx->Const.MaxTextureImageUnits) { char s[100]; - sprintf(s, "Too many texture samplers (%u, max is %u)", - newSampNum, ctx->Const.MaxTextureImageUnits); + _mesa_sprintf(s, "Too many texture samplers (%u, max is %u)", + newSampNum, ctx->Const.MaxTextureImageUnits); link_error(shProg, s); return GL_FALSE; } @@ -282,12 +282,14 @@ link_uniform_vars(GLcontext *ctx, for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = prog->Instructions + i; if (_mesa_is_tex_instruction(inst->Opcode)) { - /* + const GLint oldSampNum = inst->TexSrcUnit; + +#if 0 printf("====== remap sampler from %d to %d\n", - inst->Sampler, map[ inst->Sampler ]); - */ + inst->TexSrcUnit, samplerMap[ inst->TexSrcUnit ]); +#endif + /* here, texUnit is really samplerUnit */ - const GLint oldSampNum = inst->TexSrcUnit; if (oldSampNum < Elements(samplerMap)) { const GLuint newSampNum = samplerMap[oldSampNum]; inst->TexSrcUnit = newSampNum; @@ -316,7 +318,7 @@ _slang_resolve_attributes(struct gl_shader_program *shProg, { GLint attribMap[MAX_VERTEX_ATTRIBS]; GLuint i, j; - GLbitfield usedAttributes; + GLbitfield usedAttributes; /* generics only, not legacy attributes */ assert(origProg != linkedProg); assert(origProg->Target == GL_VERTEX_PROGRAM_ARB); @@ -340,6 +342,15 @@ _slang_resolve_attributes(struct gl_shader_program *shProg, usedAttributes |= (1 << attr); } + /* If gl_Vertex is used, that actually counts against the limit + * on generic vertex attributes. This avoids the ambiguity of + * whether glVertexAttrib4fv(0, v) sets legacy attribute 0 (vert pos) + * or generic attribute[0]. If gl_Vertex is used, we want the former. + */ + if (origProg->InputsRead & VERT_BIT_POS) { + usedAttributes |= 0x1; + } + /* initialize the generic attribute map entries to -1 */ for (i = 0; i < MAX_VERTEX_ATTRIBS; i++) { attribMap[i] = -1; @@ -382,7 +393,7 @@ _slang_resolve_attributes(struct gl_shader_program *shProg, * Start at 1 since generic attribute 0 always aliases * glVertex/position. */ - for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) { + for (attr = 0; attr < MAX_VERTEX_ATTRIBS; attr++) { if (((1 << attr) & usedAttributes) == 0) break; } @@ -491,7 +502,6 @@ _slang_update_inputs_outputs(struct gl_program *prog) maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1); } } - prog->NumAddressRegs = maxAddrReg; } @@ -645,6 +655,17 @@ _slang_link(GLcontext *ctx, } } + /* check that gl_FragColor and gl_FragData are not both written to */ + if (shProg->FragmentProgram) { + GLbitfield outputsWritten = shProg->FragmentProgram->Base.OutputsWritten; + if ((outputsWritten & ((1 << FRAG_RESULT_COLR))) && + (outputsWritten >= (1 << FRAG_RESULT_DATA0))) { + link_error(shProg, "Fragment program cannot write both gl_FragColor" + " and gl_FragData[].\n"); + return; + } + } + if (fragProg && shProg->FragmentProgram) { /* Compute initial program's TexturesUsed info */ @@ -653,12 +674,12 @@ _slang_link(GLcontext *ctx, /* notify driver that a new fragment program has been compiled/linked */ ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, &shProg->FragmentProgram->Base); - if (MESA_VERBOSE & VERBOSE_GLSL_DUMP) { - printf("Mesa original fragment program:\n"); + if (ctx->Shader.Flags & GLSL_DUMP) { + _mesa_printf("Mesa pre-link fragment program:\n"); _mesa_print_program(&fragProg->Base); _mesa_print_program_parameters(ctx, &fragProg->Base); - printf("Mesa post-link fragment program:\n"); + _mesa_printf("Mesa post-link fragment program:\n"); _mesa_print_program(&shProg->FragmentProgram->Base); _mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base); } @@ -671,20 +692,23 @@ _slang_link(GLcontext *ctx, /* notify driver that a new vertex program has been compiled/linked */ ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, &shProg->VertexProgram->Base); - if (MESA_VERBOSE & VERBOSE_GLSL_DUMP) { - printf("Mesa original vertex program:\n"); + if (ctx->Shader.Flags & GLSL_DUMP) { + _mesa_printf("Mesa pre-link vertex program:\n"); _mesa_print_program(&vertProg->Base); _mesa_print_program_parameters(ctx, &vertProg->Base); - printf("Mesa post-link vertex program:\n"); + _mesa_printf("Mesa post-link vertex program:\n"); _mesa_print_program(&shProg->VertexProgram->Base); _mesa_print_program_parameters(ctx, &shProg->VertexProgram->Base); } } - if (MESA_VERBOSE & VERBOSE_GLSL_DUMP) { - printf("Varying vars:\n"); + if (ctx->Shader.Flags & GLSL_DUMP) { + _mesa_printf("Varying vars:\n"); _mesa_print_parameter_list(shProg->Varying); + if (shProg->InfoLog) { + _mesa_printf("Info Log: %s\n", shProg->InfoLog); + } } shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram); diff --git a/src/mesa/shader/slang/slang_log.c b/src/mesa/shader/slang/slang_log.c index 25f696f67e..d7d2b4fbfd 100644 --- a/src/mesa/shader/slang/slang_log.c +++ b/src/mesa/shader/slang/slang_log.c @@ -1,8 +1,9 @@ /* * Mesa 3-D graphics library - * Version: 6.5.3 + * Version: 7.3 * * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. 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"), @@ -43,11 +44,7 @@ void slang_info_log_destruct(slang_info_log * log) { if (!log->dont_free_text) -#if 0 - slang_alloc_free(log->text); -#else _mesa_free(log->text); -#endif } static int @@ -64,18 +61,10 @@ slang_info_log_message(slang_info_log * log, const char *prefix, if (log->text != NULL) { GLuint old_len = slang_string_length(log->text); log->text = (char *) -#if 0 - slang_alloc_realloc(log->text, old_len + 1, old_len + size); -#else _mesa_realloc(log->text, old_len + 1, old_len + size); -#endif } else { -#if 0 - log->text = (char *) (slang_alloc_malloc(size)); -#else log->text = (char *) (_mesa_malloc(size)); -#endif if (log->text != NULL) log->text[0] = '\0'; } @@ -88,10 +77,6 @@ slang_info_log_message(slang_info_log * log, const char *prefix, slang_string_concat(log->text, msg); slang_string_concat(log->text, "\n"); - if (MESA_VERBOSE & VERBOSE_GLSL) { - _mesa_printf("Mesa: GLSL %s", log->text); - } - return 1; } diff --git a/src/mesa/shader/slang/slang_mem.c b/src/mesa/shader/slang/slang_mem.c index 21d6bfce88..9224578edb 100644 --- a/src/mesa/shader/slang/slang_mem.c +++ b/src/mesa/shader/slang/slang_mem.c @@ -184,6 +184,7 @@ _slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize) #else GET_CURRENT_CONTEXT(ctx); slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool; + (void) pool; if (newSize < oldSize) { return oldBuffer; @@ -235,6 +236,7 @@ _slang_free(void *addr) if (addr) { GET_CURRENT_CONTEXT(ctx); slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool; + (void) pool; ASSERT(is_valid_address(pool, addr)); } #endif diff --git a/src/mesa/shader/slang/slang_preprocess.c b/src/mesa/shader/slang/slang_preprocess.c index 7d971627f5..89aaa3a621 100644 --- a/src/mesa/shader/slang/slang_preprocess.c +++ b/src/mesa/shader/slang/slang_preprocess.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.5.2 * - * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. 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"), @@ -51,6 +51,9 @@ grammar_error_to_log (slang_info_log *log) GLint pos; grammar_get_last_error ((byte *) (buf), sizeof (buf), &pos); + if (buf[0] == 0) { + _mesa_snprintf(buf, sizeof(buf), "Preprocessor error"); + } slang_info_log_error (log, buf); } @@ -475,52 +478,112 @@ pp_cond_stack_reevaluate (pp_cond_stack *self) self->top->effective = self->top->current && self->top[1].effective; } -/* + +/** * Extension enables through #extension directive. * NOTE: Currently, only enable/disable state is stored. */ - typedef struct { - GLboolean MESA_shader_debug; /* GL_MESA_shader_debug enable */ - GLboolean ARB_texture_rectangle; /* GL_ARB_texture_rectangle enable */ + GLboolean ARB_draw_buffers; + GLboolean ARB_texture_rectangle; } pp_ext; -/* + +/** * Disable all extensions. Called at startup and on #extension all: disable. */ static GLvoid -pp_ext_disable_all (pp_ext *self) +pp_ext_disable_all(pp_ext *self) { - self->MESA_shader_debug = GL_FALSE; + _mesa_memset(self, 0, sizeof(self)); } + +/** + * Called during preprocessor initialization to set the initial enable/disable + * state of extensions. + */ static GLvoid -pp_ext_init (pp_ext *self) +pp_ext_init(pp_ext *self, const struct gl_extensions *extensions) { pp_ext_disable_all (self); - self->ARB_texture_rectangle = GL_TRUE; - /* Other initialization code goes here. */ + self->ARB_draw_buffers = GL_TRUE; + if (extensions->NV_texture_rectangle) + self->ARB_texture_rectangle = GL_TRUE; } +/** + * Called in response to #extension directives to enable/disable + * the named extension. + */ static GLboolean -pp_ext_set (pp_ext *self, const char *name, GLboolean enable) +pp_ext_set(pp_ext *self, const char *name, GLboolean enable) { - if (_mesa_strcmp (name, "MESA_shader_debug") == 0) - self->MESA_shader_debug = enable; + if (_mesa_strcmp (name, "GL_ARB_draw_buffers") == 0) + self->ARB_draw_buffers = enable; else if (_mesa_strcmp (name, "GL_ARB_texture_rectangle") == 0) self->ARB_texture_rectangle = enable; - /* Next extension name tests go here. */ else return GL_FALSE; return GL_TRUE; } -/* - * The state of preprocessor: current line, file and version number, list of all defined macros - * and the #if/#endif context. + +static void +pp_pragmas_init(struct gl_sl_pragmas *pragmas) +{ + pragmas->Optimize = GL_TRUE; + pragmas->Debug = GL_FALSE; +} + + +/** + * Called in response to #pragma. For example, "#pragma debug(on)" would + * call this function as pp_pragma("debug", "on"). + * \return GL_TRUE if pragma is valid, GL_FALSE if invalid */ +static GLboolean +pp_pragma(struct gl_sl_pragmas *pragmas, const char *pragma, const char *param) +{ +#if 0 + printf("#pragma %s %s\n", pragma, param); +#endif + if (_mesa_strcmp(pragma, "optimize") == 0) { + if (!param) + return GL_FALSE; /* missing required param */ + if (_mesa_strcmp(param, "on") == 0) { + pragmas->Optimize = GL_TRUE; + } + else if (_mesa_strcmp(param, "off") == 0) { + pragmas->Optimize = GL_FALSE; + } + else { + return GL_FALSE; /* invalid param */ + } + } + else if (_mesa_strcmp(pragma, "debug") == 0) { + if (!param) + return GL_FALSE; /* missing required param */ + if (_mesa_strcmp(param, "on") == 0) { + pragmas->Debug = GL_TRUE; + } + else if (_mesa_strcmp(param, "off") == 0) { + pragmas->Debug = GL_FALSE; + } + else { + return GL_FALSE; /* invalid param */ + } + } + /* all other pragmas are silently ignored */ + return GL_TRUE; +} + +/** + * The state of preprocessor: current line, file and version number, list + * of all defined macros and the #if/#endif context. + */ typedef struct { GLint line; @@ -533,7 +596,8 @@ typedef struct } pp_state; static GLvoid -pp_state_init (pp_state *self, slang_info_log *elog) +pp_state_init (pp_state *self, slang_info_log *elog, + const struct gl_extensions *extensions) { self->line = 0; self->file = 1; @@ -543,7 +607,7 @@ pp_state_init (pp_state *self, slang_info_log *elog) self->version = 110; #endif pp_symbols_init (&self->symbols); - pp_ext_init (&self->ext); + pp_ext_init (&self->ext, extensions); self->elog = elog; /* Initialize condition stack and create the global context. */ @@ -850,9 +914,16 @@ parse_if (slang_string *output, const byte *prod, GLuint *pi, GLint *result, pp_ #define BEHAVIOR_WARN 3 #define BEHAVIOR_DISABLE 4 +#define PRAGMA_NO_PARAM 0 +#define PRAGMA_PARAM 1 + + static GLboolean -preprocess_source (slang_string *output, const char *source, grammar pid, grammar eid, - slang_info_log *elog) +preprocess_source (slang_string *output, const char *source, + grammar pid, grammar eid, + slang_info_log *elog, + const struct gl_extensions *extensions, + struct gl_sl_pragmas *pragmas) { static const char *predefined[] = { "__FILE__", @@ -873,7 +944,8 @@ preprocess_source (slang_string *output, const char *source, grammar pid, gramma return GL_FALSE; } - pp_state_init (&state, elog); + pp_state_init (&state, elog, extensions); + pp_pragmas_init (pragmas); /* add the predefined symbols to the symbol table */ for (i = 0; predefined[i]; i++) { @@ -926,9 +998,11 @@ preprocess_source (slang_string *output, const char *source, grammar pid, gramma else { const char *id; GLuint idlen; + GLubyte token; i++; - switch (prod[i++]) { + token = prod[i++]; + switch (token) { case TOKEN_END: /* End of source string. @@ -1145,6 +1219,25 @@ preprocess_source (slang_string *output, const char *source, grammar pid, gramma } break; + case TOKEN_PRAGMA: + { + GLint have_param; + const char *pragma, *param; + + pragma = (const char *) (&prod[i]); + i += _mesa_strlen(pragma) + 1; + have_param = (prod[i++] == PRAGMA_PARAM); + if (have_param) { + param = (const char *) (&prod[i]); + i += _mesa_strlen(param) + 1; + } + else { + param = NULL; + } + pp_pragma(pragmas, pragma, param); + } + break; + case TOKEN_LINE: id = (const char *) (&prod[i]); i += _mesa_strlen (id) + 1; @@ -1196,8 +1289,21 @@ error: return GL_FALSE; } + +/** + * Run preprocessor on source code. + * \param extensions indicates which GL extensions are enabled + * \param output the post-process results + * \param input the input text + * \param elog log to record warnings, errors + * \return GL_TRUE for success, GL_FALSE for error + */ GLboolean -_slang_preprocess_directives (slang_string *output, const char *input, slang_info_log *elog) +_slang_preprocess_directives(slang_string *output, + const char *input, + slang_info_log *elog, + const struct gl_extensions *extensions, + struct gl_sl_pragmas *pragmas) { grammar pid, eid; GLboolean success; @@ -1213,7 +1319,7 @@ _slang_preprocess_directives (slang_string *output, const char *input, slang_inf grammar_destroy (pid); return GL_FALSE; } - success = preprocess_source (output, input, pid, eid, elog); + success = preprocess_source (output, input, pid, eid, elog, extensions, pragmas); grammar_destroy (eid); grammar_destroy (pid); return success; diff --git a/src/mesa/shader/slang/slang_preprocess.h b/src/mesa/shader/slang/slang_preprocess.h index d8eb12e4ff..f344820dae 100644 --- a/src/mesa/shader/slang/slang_preprocess.h +++ b/src/mesa/shader/slang/slang_preprocess.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.5.3 * - * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. 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"), @@ -33,8 +33,9 @@ extern GLboolean _slang_preprocess_version (const char *, GLuint *, GLuint *, slang_info_log *); extern GLboolean -_slang_preprocess_directives (slang_string *output, const char *input, - slang_info_log *); - +_slang_preprocess_directives(slang_string *output, const char *input, + slang_info_log *, + const struct gl_extensions *extensions, + struct gl_sl_pragmas *pragmas); #endif /* SLANG_PREPROCESS_H */ diff --git a/src/mesa/shader/slang/slang_typeinfo.c b/src/mesa/shader/slang/slang_typeinfo.c index a5bcde404f..1ef43f58c0 100644 --- a/src/mesa/shader/slang/slang_typeinfo.c +++ b/src/mesa/shader/slang/slang_typeinfo.c @@ -23,7 +23,7 @@ */ /** - * \file slang_assemble_typeinfo.c + * \file slang_typeinfo.c * slang type info * \author Michal Krol */ diff --git a/src/mesa/shader/slang/slang_vartable.c b/src/mesa/shader/slang/slang_vartable.c index de0c93957b..a4ebacc093 100644 --- a/src/mesa/shader/slang/slang_vartable.c +++ b/src/mesa/shader/slang/slang_vartable.c @@ -4,6 +4,7 @@ #include "shader/prog_print.h" #include "slang_compile.h" #include "slang_compile_variable.h" +#include "slang_emit.h" #include "slang_mem.h" #include "slang_vartable.h" #include "slang_ir.h" @@ -72,9 +73,8 @@ _slang_delete_var_table(slang_var_table *vt) /** - * Create new table, put at head, return ptr to it. - * XXX we should take a maxTemps parameter to indicate how many temporaries - * are available for the current shader/program target. + * Create new table on top of vartable stack. + * Used when we enter a {} block. */ void _slang_push_var_table(slang_var_table *vt) @@ -95,7 +95,8 @@ _slang_push_var_table(slang_var_table *vt) /** - * Destroy given table, return ptr to Parent + * Pop top entry from variable table. + * Used when we leave a {} block. */ void _slang_pop_var_table(slang_var_table *vt) @@ -125,10 +126,12 @@ _slang_pop_var_table(slang_var_table *vt) else comp = 0; - assert(store->Index >= 0); - for (j = 0; j < store->Size; j++) { - assert(t->Temps[store->Index * 4 + j + comp] == VAR); - t->Temps[store->Index * 4 + j + comp] = FREE; + /* store->Index may be -1 if we run out of registers */ + if (store->Index >= 0) { + for (j = 0; j < store->Size; j++) { + assert(t->Temps[store->Index * 4 + j + comp] == VAR); + t->Temps[store->Index * 4 + j + comp] = FREE; + } } store->Index = -1; } @@ -156,7 +159,7 @@ _slang_pop_var_table(slang_var_table *vt) /** - * Add a new variable to the given symbol table. + * Add a new variable to the given var/symbol table. */ void _slang_add_variable(slang_var_table *vt, slang_variable *v) @@ -214,6 +217,7 @@ alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp) for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) { GLuint found = 0; for (j = 0; j < (GLuint) size; j++) { + assert(i + j < 4 * MAX_PROGRAM_TEMPS); if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) { found++; } @@ -225,13 +229,17 @@ alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp) /* found block of size free regs */ if (size > 1) assert(i % 4 == 0); - for (j = 0; j < (GLuint) size; j++) + for (j = 0; j < (GLuint) size; j++) { + assert(i + j < 4 * MAX_PROGRAM_TEMPS); t->Temps[i + j] = isTemp ? TEMP : VAR; + } assert(i < MAX_PROGRAM_TEMPS * 4); t->ValSize[i] = size; return i; } } + + /* if we get here, we ran out of registers */ return -1; } @@ -259,21 +267,7 @@ _slang_alloc_var(slang_var_table *vt, slang_ir_storage *store) return GL_FALSE; store->Index = i / 4; - if (store->Size == 1) { - const GLuint comp = i % 4; - store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp); - } - else if (store->Size == 2) { - store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, - SWIZZLE_NIL, SWIZZLE_NIL); - } - else if (store->Size == 3) { - store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, - SWIZZLE_Z, SWIZZLE_NIL); - } - else { - store->Swizzle = SWIZZLE_NOOP; - } + store->Swizzle = _slang_var_swizzle(store->Size, i % 4); if (dbg) printf("Alloc var storage sz %d at %d.%s (level %d) store %p\n", @@ -301,20 +295,7 @@ _slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store) assert(store->Index < 0); store->Index = i / 4; - if (store->Size == 1) { - const GLuint comp = i % 4; - store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp); - } - else { - /* XXX improve swizzled for size=2/3, use for writemask... */ -#if 1 - if (store->Size == 2) { - store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, - SWIZZLE_NIL, SWIZZLE_NIL); - } -#endif - store->Swizzle = SWIZZLE_NOOP; - } + store->Swizzle = _slang_var_swizzle(store->Size, i % 4); if (dbg) printf("Alloc temp sz %d at %d.%s (level %d) store %p\n", store->Size, store->Index, diff --git a/src/mesa/shader/slang/sources b/src/mesa/shader/slang/sources deleted file mode 100644 index 00d617fa8a..0000000000 --- a/src/mesa/shader/slang/sources +++ /dev/null @@ -1,44 +0,0 @@ -MESA_SHADER_SLANG_SOURCES = \ -slang_analyse.c \ -slang_assemble_assignment.c \ -slang_assemble.c \ -slang_assemble_conditional.c \ -slang_assemble_constructor.c \ -slang_assemble_typeinfo.c \ -slang_compile.c \ -slang_compile_function.c \ -slang_compile_operation.c \ -slang_compile_struct.c \ -slang_compile_variable.c \ -slang_execute.c \ -slang_execute_x86.c \ -slang_export.c \ -slang_library_texsample.c \ -slang_library_noise.c \ -slang_link.c \ -slang_preprocess.c \ -slang_storage.c \ -slang_utility.c - -MESA_SHADER_SLANG_HEADERS = \ -slang_analyse.h \ -slang_assemble.h \ -slang_assemble_assignment.h \ -slang_assemble_conditional.h \ -slang_assemble_constructor.h \ -slang_assemble_typeinfo.h \ -slang_compile.h \ -slang_compile_function.h \ -slang_compile_operation.h \ -slang_compile_struct.h \ -slang_compile_variable.h \ -slang_execute.h \ -slang_export.h \ -slang_library_noise.h \ -slang_library_texsample.h \ -slang_link.h \ -slang_mesa.h \ -slang_preprocess.h \ -slang_storage.h \ -slang_utility.h \ -traverse_wrap.h diff --git a/src/mesa/shader/sources b/src/mesa/shader/sources deleted file mode 100644 index 2787187276..0000000000 --- a/src/mesa/shader/sources +++ /dev/null @@ -1,28 +0,0 @@ -# List of source files in this directory used for X.org xserver build -MESA_SHADER_SOURCES = \ -arbprogparse.c \ -arbprogram.c \ -atifragshader.c \ -nvfragparse.c \ -nvprogram.c \ -nvvertexec.c \ -nvvertparse.c \ -program.c \ -programopt.c \ -shaderobjects.c \ -shaderobjects_3dlabs.c - -MESA_SHADER_HEADERS = \ -arbprogparse.h \ -arbprogram.h \ -arbprogram_syn.h \ -atifragshader.h \ -nvfragparse.h \ -nvprogram.h \ -nvvertexec.h \ -nvvertparse.h \ -programopt.h \ -program.h \ -program_instruction.h \ -shaderobjects.h \ -shaderobjects_3dlabs.h |