Updated GLSL uniform/sampler handling from gallium-0.1 branch

Previously, the shader linker combined the uniforms used by the vertex and
fragment shaders into a combined set of uniforms.  This made the implementation
of glUniform*() simple, but was rather inefficient otherwise.  Now each shader
gets its own set of uniforms (no more modelview matrix showing up in the
fragment shader uniforms, for example).

cherry-picked by hand from gallium-0.1 branch
This commit is contained in:
Brian Paul
2008-05-14 16:09:46 -06:00
parent c807c1a23f
commit ade508312c
17 changed files with 341 additions and 416 deletions

View File

@@ -188,6 +188,7 @@
#define MAX_PROGRAM_ADDRESS_REGS 2 #define MAX_PROGRAM_ADDRESS_REGS 2
#define MAX_UNIFORMS 128 #define MAX_UNIFORMS 128
#define MAX_VARYING 8 #define MAX_VARYING 8
#define MAX_SAMPLERS 8
/*@}*/ /*@}*/
/** For GL_NV_vertex_program */ /** For GL_NV_vertex_program */

View File

@@ -1863,6 +1863,7 @@ enum register_file
/** Vertex and fragment instructions */ /** Vertex and fragment instructions */
struct prog_instruction; struct prog_instruction;
struct gl_program_parameter_list; struct gl_program_parameter_list;
struct gl_uniform_list;
/** /**
@@ -1882,6 +1883,7 @@ struct gl_program
GLbitfield InputsRead; /**< Bitmask of which input regs are read */ GLbitfield InputsRead; /**< Bitmask of which input regs are read */
GLbitfield OutputsWritten; /**< Bitmask of which output regs are written to */ GLbitfield OutputsWritten; /**< Bitmask of which output regs are written to */
GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS]; /**< TEXTURE_x_BIT bitmask */ GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS]; /**< TEXTURE_x_BIT bitmask */
GLbitfield SamplersUsed; /**< Bitfield of which samplers are used */
GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */ GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */
/** Named parameters, constants, etc. from program text */ /** Named parameters, constants, etc. from program text */
@@ -1894,6 +1896,11 @@ struct gl_program
/** Vertex program user-defined attributes */ /** Vertex program user-defined attributes */
struct gl_program_parameter_list *Attributes; struct gl_program_parameter_list *Attributes;
/** Map from sampler unit to texture unit (set by glUniform1i()) */
GLubyte SamplerUnits[MAX_SAMPLERS];
/** Which texture target is being sampled (TEXTURE_1D/2D/3D/etc_INDEX) */
GLubyte SamplerTargets[MAX_SAMPLERS];
/** Logical counts */ /** Logical counts */
/*@{*/ /*@{*/
GLuint NumInstructions; GLuint NumInstructions;
@@ -2086,7 +2093,7 @@ struct gl_query_state
/** /**
* A GLSL shader object. * A GLSL vertex or fragment shader object.
*/ */
struct gl_shader struct gl_shader
{ {
@@ -2104,7 +2111,8 @@ struct gl_shader
/** /**
* A GLSL program object. Basically a linked collection of "shaders". * A GLSL program object.
* Basically a linked collection of vertex and fragment shaders.
*/ */
struct gl_shader_program struct gl_shader_program
{ {
@@ -2119,7 +2127,7 @@ struct gl_shader_program
/* post-link info: */ /* post-link info: */
struct gl_vertex_program *VertexProgram; /**< Linked vertex program */ struct gl_vertex_program *VertexProgram; /**< Linked vertex program */
struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */ struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */
struct gl_program_parameter_list *Uniforms; /**< Plus constants, etc */ struct gl_uniform_list *Uniforms;
struct gl_program_parameter_list *Varying; struct gl_program_parameter_list *Varying;
struct gl_program_parameter_list *Attributes; /**< Vertex attributes */ struct gl_program_parameter_list *Attributes; /**< Vertex attributes */
GLboolean LinkStatus; /**< GL_LINK_STATUS */ GLboolean LinkStatus; /**< GL_LINK_STATUS */

View File

@@ -310,6 +310,8 @@ fetch_texel(GLcontext *ctx,
const GLfloat texcoord[4], GLfloat lodBias, const GLfloat texcoord[4], GLfloat lodBias,
GLfloat color[4]) GLfloat color[4])
{ {
const GLuint unit = machine->Samplers[inst->TexSrcUnit];
/* Note: we only have the right derivatives for fragment input attribs. /* Note: we only have the right derivatives for fragment input attribs.
*/ */
if (machine->NumDeriv > 0 && if (machine->NumDeriv > 0 &&
@@ -320,12 +322,10 @@ fetch_texel(GLcontext *ctx,
machine->FetchTexelDeriv(ctx, texcoord, machine->FetchTexelDeriv(ctx, texcoord,
machine->DerivX[attr], machine->DerivX[attr],
machine->DerivY[attr], machine->DerivY[attr],
lodBias, lodBias, unit, color);
inst->TexSrcUnit, color);
} }
else { else {
machine->FetchTexelLod(ctx, texcoord, lodBias, machine->FetchTexelLod(ctx, texcoord, lodBias, unit, color);
inst->TexSrcUnit, color);
} }
} }

View File

@@ -63,6 +63,8 @@ struct gl_program_machine
GLuint CondCodes[4]; /**< COND_* value for x/y/z/w */ GLuint CondCodes[4]; /**< COND_* value for x/y/z/w */
GLint AddressReg[MAX_PROGRAM_ADDRESS_REGS][4]; GLint AddressReg[MAX_PROGRAM_ADDRESS_REGS][4];
const GLubyte *Samplers; /** Array mapping sampler var to tex unit */
GLuint CallStack[MAX_PROGRAM_CALL_DEPTH]; /**< For CAL/RET instructions */ GLuint CallStack[MAX_PROGRAM_CALL_DEPTH]; /**< For CAL/RET instructions */
GLuint StackDepth; /**< Index/ptr to top of CallStack[] */ GLuint StackDepth; /**< Index/ptr to top of CallStack[] */

View File

@@ -413,12 +413,13 @@ struct prog_instruction
*/ */
GLint BranchTarget; GLint BranchTarget;
#if 0
/** /**
* For TEX instructions in shaders, the sampler to use for the * For TEX instructions in shaders, the sampler to use for the
* texture lookup. * texture lookup.
*/ */
GLint Sampler; GLint Sampler;
#endif
const char *Comment; const char *Comment;
}; };

View File

@@ -282,22 +282,25 @@ _mesa_add_uniform(struct gl_program_parameter_list *paramList,
* Add a sampler to the parameter list. * Add a sampler to the parameter list.
* \param name uniform's name * \param name uniform's name
* \param datatype GL_SAMPLER_2D, GL_SAMPLER_2D_RECT_ARB, etc. * \param datatype GL_SAMPLER_2D, GL_SAMPLER_2D_RECT_ARB, etc.
* \param index the sampler number (as seen in TEX instructions)
*/ */
GLint GLint
_mesa_add_sampler(struct gl_program_parameter_list *paramList, _mesa_add_sampler(struct gl_program_parameter_list *paramList,
const char *name, GLenum datatype) const char *name, GLenum datatype, GLuint index)
{ {
GLint i = _mesa_lookup_parameter_index(paramList, -1, name); GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_SAMPLER) { if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_SAMPLER) {
ASSERT(paramList->Parameters[i].Size == 1); ASSERT(paramList->Parameters[i].Size == 1);
ASSERT(paramList->Parameters[i].DataType == datatype); ASSERT(paramList->Parameters[i].DataType == datatype);
ASSERT(paramList->ParameterValues[i][0] == index);
/* already in list */ /* already in list */
return i; return i;
} }
else { else {
GLfloat indexf = index;
const GLint size = 1; /* a sampler is basically a texture unit number */ const GLint size = 1; /* a sampler is basically a texture unit number */
i = _mesa_add_parameter(paramList, PROGRAM_SAMPLER, name, i = _mesa_add_parameter(paramList, PROGRAM_SAMPLER, name,
size, datatype, NULL, NULL); size, datatype, &indexf, NULL);
return i; return i;
} }
} }

View File

@@ -114,7 +114,7 @@ _mesa_add_uniform(struct gl_program_parameter_list *paramList,
extern GLint extern GLint
_mesa_add_sampler(struct gl_program_parameter_list *paramList, _mesa_add_sampler(struct gl_program_parameter_list *paramList,
const char *name, GLenum datatype); const char *name, GLenum datatype, GLuint index);
extern GLint extern GLint
_mesa_add_varying(struct gl_program_parameter_list *paramList, _mesa_add_varying(struct gl_program_parameter_list *paramList,

View File

@@ -43,6 +43,7 @@
#include "prog_parameter.h" #include "prog_parameter.h"
#include "prog_print.h" #include "prog_print.h"
#include "prog_statevars.h" #include "prog_statevars.h"
#include "prog_uniform.h"
#include "shader/shader_api.h" #include "shader/shader_api.h"
#include "shader/slang/slang_compile.h" #include "shader/slang/slang_compile.h"
#include "shader/slang/slang_link.h" #include "shader/slang/slang_link.h"
@@ -75,23 +76,23 @@ _mesa_clear_shader_program_data(GLcontext *ctx,
struct gl_shader_program *shProg) struct gl_shader_program *shProg)
{ {
if (shProg->VertexProgram) { if (shProg->VertexProgram) {
if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) { /* Set ptr to NULL since the param list is shared with the
/* to prevent a double-free in the next call */ * original/unlinked program.
*/
shProg->VertexProgram->Base.Parameters = NULL; shProg->VertexProgram->Base.Parameters = NULL;
}
_mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL); _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
} }
if (shProg->FragmentProgram) { if (shProg->FragmentProgram) {
if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) { /* Set ptr to NULL since the param list is shared with the
/* to prevent a double-free in the next call */ * original/unlinked program.
*/
shProg->FragmentProgram->Base.Parameters = NULL; shProg->FragmentProgram->Base.Parameters = NULL;
}
_mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL); _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
} }
if (shProg->Uniforms) { if (shProg->Uniforms) {
_mesa_free_parameter_list(shProg->Uniforms); _mesa_free_uniform_list(shProg->Uniforms);
shProg->Uniforms = NULL; shProg->Uniforms = NULL;
} }
@@ -680,9 +681,9 @@ _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
shProg->Attributes->Parameters[index].Name); shProg->Attributes->Parameters[index].Name);
sz = shProg->Attributes->Parameters[index].Size; sz = shProg->Attributes->Parameters[index].Size;
if (size) if (size)
*size = 1; /* attributes may not be arrays */ *size = sz;
if (type && sz > 0 && sz <= 4) /* XXX this is a temporary hack */ if (type)
*type = vec_types[sz - 1]; *type = vec_types[sz]; /* XXX this is a temporary hack */
} }
@@ -696,41 +697,41 @@ _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
{ {
struct gl_shader_program *shProg struct gl_shader_program *shProg
= _mesa_lookup_shader_program(ctx, program); = _mesa_lookup_shader_program(ctx, program);
GLuint ind, j; const struct gl_program *prog;
GLint progPos;
if (!shProg) { if (!shProg) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform"); _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
return; return;
} }
if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) { if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
return; return;
} }
ind = 0; progPos = shProg->Uniforms->Uniforms[index].VertPos;
for (j = 0; j < shProg->Uniforms->NumParameters; j++) { if (progPos >= 0) {
if (shProg->Uniforms->Parameters[j].Type == PROGRAM_UNIFORM || prog = &shProg->VertexProgram->Base;
shProg->Uniforms->Parameters[j].Type == PROGRAM_SAMPLER) { }
if (ind == index) { else {
GLuint uSize = shProg->Uniforms->Parameters[j].Size; progPos = shProg->Uniforms->Uniforms[index].FragPos;
GLenum uType = shProg->Uniforms->Parameters[j].DataType; if (progPos >= 0) {
/* found it */ prog = &shProg->FragmentProgram->Base;
}
}
if (!prog || progPos < 0)
return; /* should never happen */
if (nameOut)
copy_string(nameOut, maxLength, length, copy_string(nameOut, maxLength, length,
shProg->Uniforms->Parameters[j].Name); prog->Parameters->Parameters[progPos].Name);
if (size) { if (size)
/* convert from floats to 'type' (eg: sizeof(mat4x4)=1) */ *size = prog->Parameters->Parameters[progPos].Size;
*size = uSize / sizeof_glsl_type(uType);
}
if (type)
*type = uType;
return;
}
ind++;
}
}
_mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); if (type)
*type = prog->Parameters->Parameters[progPos].DataType;
} }
@@ -848,14 +849,10 @@ _mesa_get_programiv(GLcontext *ctx, GLuint program,
PROGRAM_INPUT) + 1; PROGRAM_INPUT) + 1;
break; break;
case GL_ACTIVE_UNIFORMS: case GL_ACTIVE_UNIFORMS:
*params *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
= _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_UNIFORM)
+ _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_SAMPLER);
break; break;
case GL_ACTIVE_UNIFORM_MAX_LENGTH: case GL_ACTIVE_UNIFORM_MAX_LENGTH:
*params = MAX2( *params = _mesa_longest_uniform_name(shProg->Uniforms);
_mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_UNIFORM),
_mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_SAMPLER));
if (*params > 0) if (*params > 0)
(*params)++; /* add one for terminating zero */ (*params)++; /* add one for terminating zero */
break; break;
@@ -952,41 +949,23 @@ _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
struct gl_shader_program *shProg struct gl_shader_program *shProg
= _mesa_lookup_shader_program(ctx, program); = _mesa_lookup_shader_program(ctx, program);
if (shProg) { if (shProg) {
GLint i; if (location < shProg->Uniforms->NumUniforms) {
if (location >= 0 && location < shProg->Uniforms->NumParameters) { GLint progPos, i;
GLuint uSize; const struct gl_program *prog;
GLenum uType;
GLint rows = 0; progPos = shProg->Uniforms->Uniforms[location].VertPos;
uType = shProg->Uniforms->Parameters[location].DataType; if (progPos >= 0) {
uSize = sizeof_glsl_type(uType); prog = &shProg->VertexProgram->Base;
/* Matrix types need special handling, because they span several
* parameters, and may also not be fully packed.
*/
switch (shProg->Uniforms->Parameters[location].DataType) {
case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3x2:
case GL_FLOAT_MAT4x2:
rows = 2;
break;
case GL_FLOAT_MAT2x3:
case GL_FLOAT_MAT3:
case GL_FLOAT_MAT4x3:
rows = 3;
break;
case GL_FLOAT_MAT2x4:
case GL_FLOAT_MAT3x4:
case GL_FLOAT_MAT4:
rows = 4;
} }
if (rows != 0) { else {
GLint r, c; progPos = shProg->Uniforms->Uniforms[location].FragPos;
for (c = 0, i = 0; c * 4 < uSize; c++) if (progPos >= 0) {
for (r = 0; r < rows; r++, i++) prog = &shProg->FragmentProgram->Base;
params[i] = shProg->Uniforms->ParameterValues[location + c][r];
} }
else }
for (i = 0; i < uSize; i++) {
params[i] = shProg->Uniforms->ParameterValues[location][i]; for (i = 0; i < prog->Parameters->Parameters[progPos].Size; i++) {
params[i] = prog->Parameters->ParameterValues[progPos][i];
} }
} }
else { else {
@@ -1007,23 +986,10 @@ _mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
{ {
struct gl_shader_program *shProg struct gl_shader_program *shProg
= _mesa_lookup_shader_program(ctx, program); = _mesa_lookup_shader_program(ctx, program);
if (shProg) { if (!shProg)
GLuint loc;
for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
const struct gl_program_parameter *u
= shProg->Uniforms->Parameters + loc;
/* XXX this is a temporary simplification / short-cut.
* We need to handle things like "e.c[0].b" as seen in the
* GLSL orange book, page 189.
*/
if ((u->Type == PROGRAM_UNIFORM ||
u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
return loc;
}
}
}
return -1; return -1;
return _mesa_lookup_uniform(shProg->Uniforms, name);
} }
@@ -1134,6 +1100,100 @@ _mesa_use_program(GLcontext *ctx, GLuint program)
} }
/**
* Update the vertex and fragment program's TexturesUsed arrays.
*/
static void
update_textures_used(struct gl_program *prog)
{
GLuint s;
memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
for (s = 0; s < MAX_SAMPLERS; s++) {
if (prog->SamplersUsed & (1 << s)) {
GLuint u = prog->SamplerUnits[s];
GLuint t = prog->SamplerTargets[s];
assert(u < MAX_TEXTURE_IMAGE_UNITS);
prog->TexturesUsed[u] |= (1 << t);
}
}
}
/**
* Set the value of a program's uniform variable.
* \param program the program whose uniform to update
* \param location the location/index of the uniform
* \param type the datatype of the uniform
* \param count the number of uniforms to set
* \param elems number of elements per uniform
* \param values the new values
*/
static void
set_program_uniform(GLcontext *ctx, struct gl_program *program, GLint location,
GLenum type, GLint count, GLint elems, const void *values)
{
if (program->Parameters->Parameters[location].Type == PROGRAM_SAMPLER) {
/* This controls which texture unit which is used by a sampler */
GLuint texUnit, sampler;
/* data type for setting samplers must be int */
if (type != GL_INT || count != 1) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUniform(only glUniform1i can be used "
"to set sampler uniforms)");
return;
}
sampler = (GLuint) program->Parameters->ParameterValues[location][0];
texUnit = ((GLuint *) values)[0];
/* 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: */
program->SamplerUnits[sampler] = texUnit;
update_textures_used(program);
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
}
else {
/* ordinary uniform variable */
GLint k, i;
if (count * elems > program->Parameters->Parameters[location].Size) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
return;
}
for (k = 0; k < count; k++) {
GLfloat *uniformVal = program->Parameters->ParameterValues[location + k];
if (type == GL_INT ||
type == GL_INT_VEC2 ||
type == GL_INT_VEC3 ||
type == GL_INT_VEC4) {
const GLint *iValues = ((const GLint *) values) + k * elems;
for (i = 0; i < elems; i++) {
uniformVal[i] = (GLfloat) iValues[i];
}
}
else {
const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
for (i = 0; i < elems; i++) {
uniformVal[i] = fValues[i];
}
}
}
}
}
/** /**
* Called via ctx->Driver.Uniform(). * Called via ctx->Driver.Uniform().
*/ */
@@ -1142,9 +1202,7 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
const GLvoid *values, GLenum type) const GLvoid *values, GLenum type)
{ {
struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
GLint elems, i, k; GLint elems;
GLenum uType;
GLsizei maxCount;
if (!shProg || !shProg->LinkStatus) { if (!shProg || !shProg->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)"); _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
@@ -1154,37 +1212,11 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
if (location == -1) if (location == -1)
return; /* The standard specifies this as a no-op */ return; /* The standard specifies this as a no-op */
/* The spec says this is GL_INVALID_OPERATION, although it seems like it if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
* ought to be GL_INVALID_VALUE _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
*/
if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
return; return;
} }
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
uType = shProg->Uniforms->Parameters[location].DataType;
/*
* If we're setting a sampler, we must use glUniformi1()!
*/
if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
GLint unit;
if (type != GL_INT || count != 1) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUniform(only glUniform1i can be used "
"to set sampler uniforms)");
return;
}
/* check that the sampler (tex unit index) is legal */
unit = ((GLint *) values)[0];
if (unit >= ctx->Const.MaxTextureImageUnits) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glUniform1(invalid sampler/tex unit index)");
return;
}
}
if (count < 0) { if (count < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)"); _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
return; return;
@@ -1212,69 +1244,56 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
return; return;
} }
/* OpenGL requires types to match exactly, except that one can convert FLUSH_VERTICES(ctx, _NEW_PROGRAM);
* float or int array to boolean array.
/* 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:
*/ */
switch (uType) if (shProg->VertexProgram) {
{ GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
case GL_BOOL: if (loc >= 0) {
case GL_BOOL_VEC2: set_program_uniform(ctx, &shProg->VertexProgram->Base,
case GL_BOOL_VEC3: loc, type, count, elems, values);
case GL_BOOL_VEC4:
if (elems != sizeof_glsl_type(uType)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count mismatch)");
} }
break;
case PROGRAM_SAMPLER:
break;
default:
if (shProg->Uniforms->Parameters[location].Type != PROGRAM_SAMPLER
&& uType != type) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
}
break;
} }
/* XXX if this is a base type, then count must equal 1. However, we if (shProg->FragmentProgram) {
* don't have enough information from the compiler to distinguish a GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
* base type from a 1-element array of that type. The standard allows if (loc >= 0) {
* count to overrun an array, in which case the overflow is ignored. set_program_uniform(ctx, &shProg->FragmentProgram->Base,
*/ loc, type, count, elems, values);
maxCount = shProg->Uniforms->Parameters[location].Size / elems; }
if (count > maxCount) count = maxCount; }
}
for (k = 0; k < count; k++) {
GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k]; static void
if (type == GL_INT || set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
type == GL_INT_VEC2 || GLuint location, GLuint rows, GLuint cols,
type == GL_INT_VEC3 || GLboolean transpose, const GLfloat *values)
type == GL_INT_VEC4) { {
const GLint *iValues = ((const GLint *) values) + k * elems; /*
for (i = 0; i < elems; i++) { * Note: the _columns_ of a matrix are stored in program registers, not
uniformVal[i] = (GLfloat) iValues[i]; * the rows.
*/
/* XXXX need to test 3x3 and 2x2 matrices... */
if (transpose) {
GLuint row, col;
for (col = 0; col < cols; col++) {
GLfloat *v = program->Parameters->ParameterValues[location + col];
for (row = 0; row < rows; row++) {
v[row] = values[row * cols + col];
}
} }
} }
else { else {
const GLfloat *fValues = ((const GLfloat *) values) + k * elems; GLuint row, col;
for (i = 0; i < elems; i++) { for (col = 0; col < cols; col++) {
uniformVal[i] = fValues[i]; GLfloat *v = program->Parameters->ParameterValues[location + col];
for (row = 0; row < rows; row++) {
v[row] = values[col * rows + row];
} }
} }
if (uType == GL_BOOL ||
uType == GL_BOOL_VEC2 ||
uType == GL_BOOL_VEC3 ||
uType == GL_BOOL_VEC4) {
for (i = 0; i < elems; i++)
uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
}
}
if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
if (shProg->VertexProgram)
_slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
if (shProg->FragmentProgram)
_slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
} }
} }
@@ -1287,62 +1306,42 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
GLenum matrixType, GLint location, GLsizei count, GLenum matrixType, GLint location, GLsizei count,
GLboolean transpose, const GLfloat *values) GLboolean transpose, const GLfloat *values)
{ {
GLsizei maxCount, i;
struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
if (!shProg || !shProg->LinkStatus) { if (!shProg || !shProg->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION, _mesa_error(ctx, GL_INVALID_OPERATION,
"glUniformMatrix(program not linked)"); "glUniformMatrix(program not linked)");
return; return;
} }
if (location == -1) if (location == -1)
return; /* The standard specifies this as a no-op */ return; /* The standard specifies this as a no-op */
/* The spec says this is GL_INVALID_OPERATION, although it seems like it
* ought to be GL_INVALID_VALUE if (location < 0 || location >= shProg->Uniforms->NumUniforms) {
*/ _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
return; return;
} }
if (values == NULL) { if (values == NULL) {
_mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix"); _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
return; return;
} }
if (count < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(count < 0)");
return;
}
FLUSH_VERTICES(ctx, _NEW_PROGRAM); FLUSH_VERTICES(ctx, _NEW_PROGRAM);
/* if (shProg->VertexProgram) {
* Note: the _columns_ of a matrix are stored in program registers, not GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
* the rows. if (loc >= 0) {
*/ set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
/* XXXX need to test 3x3 and 2x2 matrices... */ loc, rows, cols, transpose, values);
maxCount = shProg->Uniforms->Parameters[location].Size / (4 * cols);
if (count > maxCount)
count = maxCount;
for (i = 0; i < count; i++) {
if (transpose) {
GLuint row, col;
for (col = 0; col < cols; col++) {
GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
for (row = 0; row < rows; row++) {
v[row] = values[row * cols + col];
} }
} }
if (shProg->FragmentProgram) {
GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
if (loc >= 0) {
set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
loc, rows, cols, transpose, values);
} }
else {
GLuint row, col;
for (col = 0; col < cols; col++) {
GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
for (row = 0; row < rows; row++) {
v[row] = values[col * rows + row];
}
}
}
location += cols;
values += rows * cols;
} }
} }

View File

@@ -2836,14 +2836,14 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
const GLint texIndex = sampler_to_texture_index(var->type.specifier.type); const GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
if (texIndex != -1) { if (texIndex != -1) {
/* Texture sampler: /* This is a texture sampler variable...
* store->File = PROGRAM_SAMPLER * store->File = PROGRAM_SAMPLER
* store->Index = sampler uniform location * store->Index = sampler number (0..7, typically)
* store->Size = texture type index (1D, 2D, 3D, cube, etc) * store->Size = texture type index (1D, 2D, 3D, cube, etc)
*/ */
GLint samplerUniform const GLint sampNum = A->numSamplers++;
= _mesa_add_sampler(prog->Parameters, varName, datatype); _mesa_add_sampler(prog->Parameters, varName, datatype, sampNum);
store = _slang_new_ir_storage(PROGRAM_SAMPLER, samplerUniform, texIndex); store = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, texIndex);
if (dbg) printf("SAMPLER "); if (dbg) printf("SAMPLER ");
} }
else if (var->type.qualifier == SLANG_QUAL_UNIFORM) { else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {

View File

@@ -31,6 +31,8 @@
#include "main/imports.h" #include "main/imports.h"
#include "main/context.h" #include "main/context.h"
#include "shader/program.h" #include "shader/program.h"
#include "shader/programopt.h"
#include "shader/prog_print.h"
#include "shader/prog_parameter.h" #include "shader/prog_parameter.h"
#include "shader/grammar/grammar_mesa.h" #include "shader/grammar/grammar_mesa.h"
#include "slang_codegen.h" #include "slang_codegen.h"
@@ -1618,6 +1620,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
A.program = O->program; A.program = O->program;
A.vartable = O->vartable; A.vartable = O->vartable;
A.curFuncEndLabel = NULL; A.curFuncEndLabel = NULL;
A.numSamplers = 0;
if (!_slang_codegen_global_variable(&A, var, C->type)) if (!_slang_codegen_global_variable(&A, var, C->type))
return 0; return 0;
} }
@@ -1640,6 +1643,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
A.space.funcs = O->funs; A.space.funcs = O->funs;
A.space.structs = O->structs; A.space.structs = O->structs;
A.space.vars = O->vars; A.space.vars = O->vars;
A.numSamplers = 0;
if (!initialize_global(&A, var)) if (!initialize_global(&A, var))
return 0; return 0;
} }
@@ -1773,6 +1777,7 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
A.program = O->program; A.program = O->program;
A.vartable = O->vartable; A.vartable = O->vartable;
A.log = C->L; A.log = C->L;
A.numSamplers = 0;
_slang_codegen_function(&A, *parsed_func_ret); _slang_codegen_function(&A, *parsed_func_ret);
} }
@@ -2180,6 +2185,19 @@ _slang_compile(GLcontext *ctx, struct gl_shader *shader)
_slang_delete_mempool((slang_mempool *) ctx->Shader.MemPool); _slang_delete_mempool((slang_mempool *) ctx->Shader.MemPool);
ctx->Shader.MemPool = NULL; ctx->Shader.MemPool = NULL;
if (shader->Type == GL_VERTEX_SHADER) {
/* remove any reads of varying (output) registers */
#if 0
printf("Pre-remove output reads:\n");
_mesa_print_program(shader->Programs[0]);
#endif
_mesa_remove_varying_reads(shader->Programs[0]);
#if 0
printf("Post-remove output reads:\n");
_mesa_print_program(shader->Programs[0]);
#endif
}
return success; return success;
} }

View File

@@ -922,11 +922,15 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n)
assert(n->Children[0]->Store->Size >= TEXTURE_1D_INDEX); assert(n->Children[0]->Store->Size >= TEXTURE_1D_INDEX);
assert(n->Children[0]->Store->Size <= TEXTURE_RECT_INDEX); assert(n->Children[0]->Store->Size <= TEXTURE_RECT_INDEX);
inst->Sampler = n->Children[0]->Store->Index; /* i.e. uniform's index */
inst->TexSrcTarget = n->Children[0]->Store->Size; inst->TexSrcTarget = n->Children[0]->Store->Size;
#if 0
inst->TexSrcUnit = 27; /* Dummy value; the TexSrcUnit will be computed at inst->TexSrcUnit = 27; /* Dummy value; the TexSrcUnit will be computed at
* link time, using the sampler uniform's value. * link time, using the sampler uniform's value.
*/ */
inst->Sampler = n->Children[0]->Store->Index; /* i.e. uniform's index */
#else
inst->TexSrcUnit = n->Children[0]->Store->Index; /* i.e. uniform's index */
#endif
return inst; return inst;
} }

View File

@@ -37,12 +37,17 @@
#include "shader/prog_parameter.h" #include "shader/prog_parameter.h"
#include "shader/prog_print.h" #include "shader/prog_print.h"
#include "shader/prog_statevars.h" #include "shader/prog_statevars.h"
#include "shader/prog_uniform.h"
#include "shader/shader_api.h" #include "shader/shader_api.h"
#include "slang_link.h" #include "slang_link.h"
/**
* Linking varying vars involves rearranging varying vars so that the
* vertex program's output varyings matches the order of the fragment
* program's input varyings.
*/
static GLboolean static GLboolean
link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog) link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
{ {
@@ -132,145 +137,65 @@ link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
} }
static GLboolean /**
is_uniform(GLuint file) * Build the shProg->Uniforms list.
* This is basically a list/index of all uniforms found in either/both of
* the vertex and fragment shaders.
*/
static void
link_uniform_vars(struct gl_shader_program *shProg,
struct gl_program *prog,
GLuint *numSamplers)
{ {
return (file == PROGRAM_ENV_PARAM || GLuint samplerMap[MAX_SAMPLERS];
file == PROGRAM_STATE_VAR ||
file == PROGRAM_NAMED_PARAM ||
file == PROGRAM_CONSTANT ||
file == PROGRAM_SAMPLER ||
file == PROGRAM_UNIFORM);
}
static GLboolean
link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
{
GLuint *map, i;
#if 0
printf("================ pre link uniforms ===============\n");
_mesa_print_parameter_list(shProg->Uniforms);
#endif
map = (GLuint *) malloc(prog->Parameters->NumParameters * sizeof(GLuint));
if (!map)
return GL_FALSE;
for (i = 0; i < prog->Parameters->NumParameters; /* incr below*/) {
/* see if this uniform is in the linked uniform list */
const struct gl_program_parameter *p = prog->Parameters->Parameters + i;
const GLfloat *pVals = prog->Parameters->ParameterValues[i];
GLint j;
GLint size;
/* sanity check */
assert(is_uniform(p->Type));
if (p->Name) {
j = _mesa_lookup_parameter_index(shProg->Uniforms, -1, p->Name);
}
else {
/*GLuint swizzle;*/
ASSERT(p->Type == PROGRAM_CONSTANT);
if (_mesa_lookup_parameter_constant(shProg->Uniforms, pVals,
p->Size, &j, NULL)) {
assert(j >= 0);
}
else {
j = -1;
}
}
if (j >= 0) {
/* already in list, check size XXX check this */
#if 0
assert(p->Size == shProg->Uniforms->Parameters[j].Size);
#endif
}
else {
/* not already in linked list */
switch (p->Type) {
case PROGRAM_ENV_PARAM:
j = _mesa_add_named_parameter(shProg->Uniforms, p->Name, pVals);
break;
case PROGRAM_CONSTANT:
j = _mesa_add_named_constant(shProg->Uniforms, p->Name, pVals, p->Size);
break;
case PROGRAM_STATE_VAR:
j = _mesa_add_state_reference(shProg->Uniforms, p->StateIndexes);
break;
case PROGRAM_UNIFORM:
j = _mesa_add_uniform(shProg->Uniforms, p->Name, p->Size, p->DataType);
break;
case PROGRAM_SAMPLER:
j = _mesa_add_sampler(shProg->Uniforms, p->Name, p->DataType);
break;
default:
_mesa_problem(NULL, "bad parameter type in link_uniform_vars()");
return GL_FALSE;
}
}
ASSERT(j >= 0);
size = p->Size;
while (size > 0) {
map[i] = j;
i++;
j++;
size -= 4;
}
}
#if 0
printf("================ post link uniforms ===============\n");
_mesa_print_parameter_list(shProg->Uniforms);
#endif
#if 0
{
GLuint i; GLuint i;
for (i = 0; i < prog->Parameters->NumParameters; i++) {
printf("map[%d] = %d\n", i, map[i]);
}
_mesa_print_parameter_list(shProg->Uniforms);
}
#endif
/* OK, now scan the program/shader instructions looking for uniform vars, for (i = 0; i < prog->Parameters->NumParameters; i++) {
const struct gl_program_parameter *p = prog->Parameters->Parameters + i;
/*
* XXX FIX NEEDED HERE
* We should also be adding a uniform if p->Type == PROGRAM_STATE_VAR.
* For example, modelview matrix, light pos, etc.
* Also, we need to update the state-var name-generator code to
* generate GLSL-style names, like "gl_LightSource[0].position".
* Furthermore, we'll need to fix the state-var's size/datatype info.
*/
if (p->Type == PROGRAM_UNIFORM ||
p->Type == PROGRAM_SAMPLER) {
_mesa_append_uniform(shProg->Uniforms, p->Name, prog->Target, i);
}
if (p->Type == PROGRAM_SAMPLER) {
/* Allocate a new sampler index */
GLuint sampNum = *numSamplers;
GLuint oldSampNum = (GLuint) prog->Parameters->ParameterValues[i][0];
assert(oldSampNum < MAX_SAMPLERS);
samplerMap[oldSampNum] = sampNum;
(*numSamplers)++;
}
}
/* OK, now scan the program/shader instructions looking for sampler vars,
* replacing the old index with the new index. * replacing the old index with the new index.
*/ */
prog->SamplersUsed = 0x0;
for (i = 0; i < prog->NumInstructions; i++) { for (i = 0; i < prog->NumInstructions; i++) {
struct prog_instruction *inst = prog->Instructions + i; struct prog_instruction *inst = prog->Instructions + i;
GLuint j; if (_mesa_is_tex_instruction(inst->Opcode)) {
if (is_uniform(inst->DstReg.File)) {
inst->DstReg.Index = map[ inst->DstReg.Index ];
}
for (j = 0; j < 3; j++) {
if (is_uniform(inst->SrcReg[j].File)) {
inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ];
}
}
if (inst->Opcode == OPCODE_TEX ||
inst->Opcode == OPCODE_TXB ||
inst->Opcode == OPCODE_TXP) {
/* /*
printf("====== remap sampler from %d to %d\n", printf("====== remap sampler from %d to %d\n",
inst->Sampler, map[ inst->Sampler ]); inst->Sampler, map[ inst->Sampler ]);
*/ */
inst->Sampler = map[ inst->Sampler ]; /* here, texUnit is really samplerUnit */
inst->TexSrcUnit = samplerMap[inst->TexSrcUnit];
prog->SamplerTargets[inst->TexSrcUnit] = inst->TexSrcTarget;
prog->SamplersUsed |= (1 << inst->TexSrcUnit);
} }
} }
free(map);
return GL_TRUE;
} }
@@ -329,11 +254,9 @@ _slang_resolve_attributes(struct gl_shader_program *shProg,
* glVertex/position. * glVertex/position.
*/ */
for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) { for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) {
if (((1 << attr) & usedAttributes) == 0) { if (((1 << attr) & usedAttributes) == 0)
usedAttributes |= (1 << attr);
break; break;
} }
}
if (attr == MAX_VERTEX_ATTRIBS) { if (attr == MAX_VERTEX_ATTRIBS) {
/* too many! XXX record error log */ /* too many! XXX record error log */
return GL_FALSE; return GL_FALSE;
@@ -406,36 +329,6 @@ _slang_remap_attribute(struct gl_program *prog, GLuint oldAttrib, GLuint newAttr
/**
* Scan program for texture instructions, lookup sampler/uniform's value
* to determine which texture unit to use.
* Also, update the program's TexturesUsed[] array.
*/
void
_slang_resolve_samplers(struct gl_shader_program *shProg,
struct gl_program *prog)
{
GLuint i;
for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
prog->TexturesUsed[i] = 0;
for (i = 0; i < prog->NumInstructions; i++) {
struct prog_instruction *inst = prog->Instructions + i;
if (inst->Opcode == OPCODE_TEX ||
inst->Opcode == OPCODE_TXB ||
inst->Opcode == OPCODE_TXP) {
GLint sampleUnit = (GLint) shProg->Uniforms->ParameterValues[inst->Sampler][0];
assert(sampleUnit < MAX_TEXTURE_IMAGE_UNITS);
inst->TexSrcUnit = sampleUnit;
prog->TexturesUsed[inst->TexSrcUnit] |= (1 << inst->TexSrcTarget);
}
}
}
/** cast wrapper */ /** cast wrapper */
static struct gl_vertex_program * static struct gl_vertex_program *
vertex_program(struct gl_program *prog) vertex_program(struct gl_program *prog)
@@ -476,12 +369,9 @@ link_error(struct gl_shader_program *shProg, const char *msg)
* 2. Varying vars in the two shaders are combined so their locations * 2. Varying vars in the two shaders are combined so their locations
* agree between the vertex and fragment stages. They're treated as * agree between the vertex and fragment stages. They're treated as
* vertex program output attribs and as fragment program input attribs. * vertex program output attribs and as fragment program input attribs.
* 3. Uniform vars (including state references, constants, etc) from the * 3. The vertex and fragment programs are cloned and modified to update
* vertex and fragment shaders are merged into one group. Recall that * src/dst register references so they use the new, linked varying
* GLSL uniforms are shared by all linked shaders. * storage locations.
* 4. The vertex and fragment programs are cloned and modified to update
* src/dst register references so they use the new, linked uniform/
* varying storage locations.
*/ */
void void
_slang_link(GLcontext *ctx, _slang_link(GLcontext *ctx,
@@ -490,11 +380,12 @@ _slang_link(GLcontext *ctx,
{ {
const struct gl_vertex_program *vertProg; const struct gl_vertex_program *vertProg;
const struct gl_fragment_program *fragProg; const struct gl_fragment_program *fragProg;
GLuint numSamplers = 0;
GLuint i; GLuint i;
_mesa_clear_shader_program_data(ctx, shProg); _mesa_clear_shader_program_data(ctx, shProg);
shProg->Uniforms = _mesa_new_parameter_list(); shProg->Uniforms = _mesa_new_uniform_list();
shProg->Varying = _mesa_new_parameter_list(); shProg->Varying = _mesa_new_parameter_list();
/** /**
@@ -531,33 +422,30 @@ _slang_link(GLcontext *ctx,
_mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL); _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
} }
/* link varying vars */
if (shProg->VertexProgram) if (shProg->VertexProgram)
link_varying_vars(shProg, &shProg->VertexProgram->Base); link_varying_vars(shProg, &shProg->VertexProgram->Base);
if (shProg->FragmentProgram) if (shProg->FragmentProgram)
link_varying_vars(shProg, &shProg->FragmentProgram->Base); link_varying_vars(shProg, &shProg->FragmentProgram->Base);
/* link uniform vars */
if (shProg->VertexProgram) if (shProg->VertexProgram)
link_uniform_vars(shProg, &shProg->VertexProgram->Base); link_uniform_vars(shProg, &shProg->VertexProgram->Base, &numSamplers);
if (shProg->FragmentProgram) if (shProg->FragmentProgram)
link_uniform_vars(shProg, &shProg->FragmentProgram->Base); link_uniform_vars(shProg, &shProg->FragmentProgram->Base, &numSamplers);
/* The vertex and fragment programs share a common set of uniforms now */ /*_mesa_print_uniforms(shProg->Uniforms);*/
if (shProg->VertexProgram) {
_mesa_free_parameter_list(shProg->VertexProgram->Base.Parameters);
shProg->VertexProgram->Base.Parameters = shProg->Uniforms;
assert(shProg->Uniforms);
}
if (shProg->FragmentProgram) {
_mesa_free_parameter_list(shProg->FragmentProgram->Base.Parameters);
shProg->FragmentProgram->Base.Parameters = shProg->Uniforms;
assert(shProg->Uniforms);
}
if (shProg->VertexProgram) { if (shProg->VertexProgram) {
_slang_resolve_samplers(shProg, &shProg->VertexProgram->Base); /* Rather than cloning the parameter list here, just share it.
* We need to be careful _mesa_clear_shader_program_data() in
* to avoid double-freeing.
*/
shProg->VertexProgram->Base.Parameters = vertProg->Base.Parameters;
} }
if (shProg->FragmentProgram) { if (shProg->FragmentProgram) {
_slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base); /* see comment just above */
shProg->FragmentProgram->Base.Parameters = fragProg->Base.Parameters;
} }
if (shProg->VertexProgram) { if (shProg->VertexProgram) {

View File

@@ -32,10 +32,6 @@ extern void
_slang_link(GLcontext *ctx, GLhandleARB h, _slang_link(GLcontext *ctx, GLhandleARB h,
struct gl_shader_program *shProg); struct gl_shader_program *shProg);
extern void
_slang_resolve_samplers(struct gl_shader_program *shProg,
struct gl_program *prog);
extern void extern void
_slang_remap_attribute(struct gl_program *prog, GLuint oldAttrib, _slang_remap_attribute(struct gl_program *prog, GLuint oldAttrib,
GLuint newAttrib); GLuint newAttrib);

View File

@@ -65,6 +65,7 @@ typedef struct slang_assemble_ctx_
struct slang_label_ *curFuncEndLabel; struct slang_label_ *curFuncEndLabel;
struct slang_ir_node_ *CurLoop; struct slang_ir_node_ *CurLoop;
struct slang_function_ *CurFunction; struct slang_function_ *CurFunction;
GLuint numSamplers;
} slang_assemble_ctx; } slang_assemble_ctx;

View File

@@ -165,6 +165,7 @@ SHADER_SOURCES = \
shader/prog_parameter.c \ shader/prog_parameter.c \
shader/prog_print.c \ shader/prog_print.c \
shader/prog_statevars.c \ shader/prog_statevars.c \
shader/prog_uniform.c \
shader/programopt.c \ shader/programopt.c \
shader/shader_api.c \ shader/shader_api.c \

View File

@@ -33,10 +33,11 @@
/** /**
* Fetch a texel. * Fetch a texel with given lod.
* Called via machine->FetchTexelLod()
*/ */
static void static void
fetch_texel( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda, fetch_texel_lod( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
GLuint unit, GLfloat color[4] ) GLuint unit, GLfloat color[4] )
{ {
GLchan rgba[4]; GLchan rgba[4];
@@ -58,6 +59,7 @@ fetch_texel( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
/** /**
* Fetch a texel with the given partial derivatives to compute a level * Fetch a texel with the given partial derivatives to compute a level
* of detail in the mipmap. * of detail in the mipmap.
* Called via machine->FetchTexelDeriv()
*/ */
static void static void
fetch_texel_deriv( GLcontext *ctx, const GLfloat texcoord[4], fetch_texel_deriv( GLcontext *ctx, const GLfloat texcoord[4],
@@ -117,6 +119,8 @@ init_machine(GLcontext *ctx, struct gl_program_machine *machine,
machine->DerivY = (GLfloat (*)[4]) span->attrStepY; machine->DerivY = (GLfloat (*)[4]) span->attrStepY;
machine->NumDeriv = FRAG_ATTRIB_MAX; machine->NumDeriv = FRAG_ATTRIB_MAX;
machine->Samplers = program->Base.SamplerUnits;
/* if running a GLSL program (not ARB_fragment_program) */ /* if running a GLSL program (not ARB_fragment_program) */
if (ctx->Shader.CurrentProgram) { if (ctx->Shader.CurrentProgram) {
/* Store front/back facing value in register FOGC.Y */ /* Store front/back facing value in register FOGC.Y */
@@ -134,7 +138,7 @@ init_machine(GLcontext *ctx, struct gl_program_machine *machine,
/* init call stack */ /* init call stack */
machine->StackDepth = 0; machine->StackDepth = 0;
machine->FetchTexelLod = fetch_texel; machine->FetchTexelLod = fetch_texel_lod;
machine->FetchTexelDeriv = fetch_texel_deriv; machine->FetchTexelDeriv = fetch_texel_deriv;
} }

View File

@@ -1401,7 +1401,6 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
* Write to renderbuffers * Write to renderbuffers
*/ */
{ {
const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
const GLuint numBuffers = fb->_NumColorDrawBuffers; const GLuint numBuffers = fb->_NumColorDrawBuffers;
const GLboolean multiFragOutputs = numBuffers > 1; const GLboolean multiFragOutputs = numBuffers > 1;
GLuint buf; GLuint buf;