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:
@@ -188,6 +188,7 @@
|
||||
#define MAX_PROGRAM_ADDRESS_REGS 2
|
||||
#define MAX_UNIFORMS 128
|
||||
#define MAX_VARYING 8
|
||||
#define MAX_SAMPLERS 8
|
||||
/*@}*/
|
||||
|
||||
/** For GL_NV_vertex_program */
|
||||
|
@@ -1863,6 +1863,7 @@ enum register_file
|
||||
/** Vertex and fragment instructions */
|
||||
struct prog_instruction;
|
||||
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 OutputsWritten; /**< Bitmask of which output regs are written to */
|
||||
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. */
|
||||
|
||||
/** Named parameters, constants, etc. from program text */
|
||||
@@ -1894,6 +1896,11 @@ struct gl_program
|
||||
/** Vertex program user-defined 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 */
|
||||
/*@{*/
|
||||
GLuint NumInstructions;
|
||||
@@ -2086,7 +2093,7 @@ struct gl_query_state
|
||||
|
||||
|
||||
/**
|
||||
* A GLSL shader object.
|
||||
* A GLSL vertex or fragment shader object.
|
||||
*/
|
||||
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
|
||||
{
|
||||
@@ -2119,7 +2127,7 @@ struct gl_shader_program
|
||||
/* post-link info: */
|
||||
struct gl_vertex_program *VertexProgram; /**< Linked vertex program */
|
||||
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 *Attributes; /**< Vertex attributes */
|
||||
GLboolean LinkStatus; /**< GL_LINK_STATUS */
|
||||
|
@@ -310,6 +310,8 @@ fetch_texel(GLcontext *ctx,
|
||||
const GLfloat texcoord[4], GLfloat lodBias,
|
||||
GLfloat color[4])
|
||||
{
|
||||
const GLuint unit = machine->Samplers[inst->TexSrcUnit];
|
||||
|
||||
/* Note: we only have the right derivatives for fragment input attribs.
|
||||
*/
|
||||
if (machine->NumDeriv > 0 &&
|
||||
@@ -320,12 +322,10 @@ fetch_texel(GLcontext *ctx,
|
||||
machine->FetchTexelDeriv(ctx, texcoord,
|
||||
machine->DerivX[attr],
|
||||
machine->DerivY[attr],
|
||||
lodBias,
|
||||
inst->TexSrcUnit, color);
|
||||
lodBias, unit, color);
|
||||
}
|
||||
else {
|
||||
machine->FetchTexelLod(ctx, texcoord, lodBias,
|
||||
inst->TexSrcUnit, color);
|
||||
machine->FetchTexelLod(ctx, texcoord, lodBias, unit, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -63,6 +63,8 @@ struct gl_program_machine
|
||||
GLuint CondCodes[4]; /**< COND_* value for x/y/z/w */
|
||||
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 StackDepth; /**< Index/ptr to top of CallStack[] */
|
||||
|
||||
|
@@ -413,12 +413,13 @@ struct prog_instruction
|
||||
*/
|
||||
GLint BranchTarget;
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* For TEX instructions in shaders, the sampler to use for the
|
||||
* texture lookup.
|
||||
*/
|
||||
GLint Sampler;
|
||||
|
||||
#endif
|
||||
const char *Comment;
|
||||
};
|
||||
|
||||
|
@@ -282,22 +282,25 @@ _mesa_add_uniform(struct gl_program_parameter_list *paramList,
|
||||
* Add a sampler to the parameter list.
|
||||
* \param name uniform's name
|
||||
* \param datatype GL_SAMPLER_2D, GL_SAMPLER_2D_RECT_ARB, etc.
|
||||
* \param index the sampler number (as seen in TEX instructions)
|
||||
*/
|
||||
GLint
|
||||
_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);
|
||||
if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_SAMPLER) {
|
||||
ASSERT(paramList->Parameters[i].Size == 1);
|
||||
ASSERT(paramList->Parameters[i].DataType == datatype);
|
||||
ASSERT(paramList->ParameterValues[i][0] == index);
|
||||
/* already in list */
|
||||
return i;
|
||||
}
|
||||
else {
|
||||
GLfloat indexf = index;
|
||||
const GLint size = 1; /* a sampler is basically a texture unit number */
|
||||
i = _mesa_add_parameter(paramList, PROGRAM_SAMPLER, name,
|
||||
size, datatype, NULL, NULL);
|
||||
size, datatype, &indexf, NULL);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@@ -114,7 +114,7 @@ _mesa_add_uniform(struct gl_program_parameter_list *paramList,
|
||||
|
||||
extern GLint
|
||||
_mesa_add_sampler(struct gl_program_parameter_list *paramList,
|
||||
const char *name, GLenum datatype);
|
||||
const char *name, GLenum datatype, GLuint index);
|
||||
|
||||
extern GLint
|
||||
_mesa_add_varying(struct gl_program_parameter_list *paramList,
|
||||
|
@@ -43,6 +43,7 @@
|
||||
#include "prog_parameter.h"
|
||||
#include "prog_print.h"
|
||||
#include "prog_statevars.h"
|
||||
#include "prog_uniform.h"
|
||||
#include "shader/shader_api.h"
|
||||
#include "shader/slang/slang_compile.h"
|
||||
#include "shader/slang/slang_link.h"
|
||||
@@ -75,23 +76,23 @@ _mesa_clear_shader_program_data(GLcontext *ctx,
|
||||
struct gl_shader_program *shProg)
|
||||
{
|
||||
if (shProg->VertexProgram) {
|
||||
if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) {
|
||||
/* to prevent a double-free in the next call */
|
||||
shProg->VertexProgram->Base.Parameters = NULL;
|
||||
}
|
||||
/* Set ptr to NULL since the param list is shared with the
|
||||
* original/unlinked program.
|
||||
*/
|
||||
shProg->VertexProgram->Base.Parameters = NULL;
|
||||
_mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
|
||||
}
|
||||
|
||||
if (shProg->FragmentProgram) {
|
||||
if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) {
|
||||
/* to prevent a double-free in the next call */
|
||||
shProg->FragmentProgram->Base.Parameters = NULL;
|
||||
}
|
||||
/* Set ptr to NULL since the param list is shared with the
|
||||
* original/unlinked program.
|
||||
*/
|
||||
shProg->FragmentProgram->Base.Parameters = NULL;
|
||||
_mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
|
||||
}
|
||||
|
||||
if (shProg->Uniforms) {
|
||||
_mesa_free_parameter_list(shProg->Uniforms);
|
||||
_mesa_free_uniform_list(shProg->Uniforms);
|
||||
shProg->Uniforms = NULL;
|
||||
}
|
||||
|
||||
@@ -680,9 +681,9 @@ _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
|
||||
shProg->Attributes->Parameters[index].Name);
|
||||
sz = shProg->Attributes->Parameters[index].Size;
|
||||
if (size)
|
||||
*size = 1; /* attributes may not be arrays */
|
||||
if (type && sz > 0 && sz <= 4) /* XXX this is a temporary hack */
|
||||
*type = vec_types[sz - 1];
|
||||
*size = sz;
|
||||
if (type)
|
||||
*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
|
||||
= _mesa_lookup_shader_program(ctx, program);
|
||||
GLuint ind, j;
|
||||
const struct gl_program *prog;
|
||||
GLint progPos;
|
||||
|
||||
if (!shProg) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
|
||||
if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
|
||||
return;
|
||||
}
|
||||
|
||||
ind = 0;
|
||||
for (j = 0; j < shProg->Uniforms->NumParameters; j++) {
|
||||
if (shProg->Uniforms->Parameters[j].Type == PROGRAM_UNIFORM ||
|
||||
shProg->Uniforms->Parameters[j].Type == PROGRAM_SAMPLER) {
|
||||
if (ind == index) {
|
||||
GLuint uSize = shProg->Uniforms->Parameters[j].Size;
|
||||
GLenum uType = shProg->Uniforms->Parameters[j].DataType;
|
||||
/* found it */
|
||||
copy_string(nameOut, maxLength, length,
|
||||
shProg->Uniforms->Parameters[j].Name);
|
||||
if (size) {
|
||||
/* convert from floats to 'type' (eg: sizeof(mat4x4)=1) */
|
||||
*size = uSize / sizeof_glsl_type(uType);
|
||||
}
|
||||
if (type)
|
||||
*type = uType;
|
||||
return;
|
||||
}
|
||||
ind++;
|
||||
progPos = shProg->Uniforms->Uniforms[index].VertPos;
|
||||
if (progPos >= 0) {
|
||||
prog = &shProg->VertexProgram->Base;
|
||||
}
|
||||
else {
|
||||
progPos = shProg->Uniforms->Uniforms[index].FragPos;
|
||||
if (progPos >= 0) {
|
||||
prog = &shProg->FragmentProgram->Base;
|
||||
}
|
||||
}
|
||||
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(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;
|
||||
|
||||
if (type)
|
||||
*type = prog->Parameters->Parameters[progPos].DataType;
|
||||
}
|
||||
|
||||
|
||||
@@ -848,14 +849,10 @@ _mesa_get_programiv(GLcontext *ctx, GLuint program,
|
||||
PROGRAM_INPUT) + 1;
|
||||
break;
|
||||
case GL_ACTIVE_UNIFORMS:
|
||||
*params
|
||||
= _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_UNIFORM)
|
||||
+ _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_SAMPLER);
|
||||
*params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
|
||||
break;
|
||||
case GL_ACTIVE_UNIFORM_MAX_LENGTH:
|
||||
*params = MAX2(
|
||||
_mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_UNIFORM),
|
||||
_mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_SAMPLER));
|
||||
*params = _mesa_longest_uniform_name(shProg->Uniforms);
|
||||
if (*params > 0)
|
||||
(*params)++; /* add one for terminating zero */
|
||||
break;
|
||||
@@ -952,42 +949,24 @@ _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
|
||||
struct gl_shader_program *shProg
|
||||
= _mesa_lookup_shader_program(ctx, program);
|
||||
if (shProg) {
|
||||
GLint i;
|
||||
if (location >= 0 && location < shProg->Uniforms->NumParameters) {
|
||||
GLuint uSize;
|
||||
GLenum uType;
|
||||
GLint rows = 0;
|
||||
uType = shProg->Uniforms->Parameters[location].DataType;
|
||||
uSize = sizeof_glsl_type(uType);
|
||||
/* 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 (location < shProg->Uniforms->NumUniforms) {
|
||||
GLint progPos, i;
|
||||
const struct gl_program *prog;
|
||||
|
||||
progPos = shProg->Uniforms->Uniforms[location].VertPos;
|
||||
if (progPos >= 0) {
|
||||
prog = &shProg->VertexProgram->Base;
|
||||
}
|
||||
if (rows != 0) {
|
||||
GLint r, c;
|
||||
for (c = 0, i = 0; c * 4 < uSize; c++)
|
||||
for (r = 0; r < rows; r++, i++)
|
||||
params[i] = shProg->Uniforms->ParameterValues[location + c][r];
|
||||
}
|
||||
else
|
||||
for (i = 0; i < uSize; i++) {
|
||||
params[i] = shProg->Uniforms->ParameterValues[location][i];
|
||||
else {
|
||||
progPos = shProg->Uniforms->Uniforms[location].FragPos;
|
||||
if (progPos >= 0) {
|
||||
prog = &shProg->FragmentProgram->Base;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < prog->Parameters->Parameters[progPos].Size; i++) {
|
||||
params[i] = prog->Parameters->ParameterValues[progPos][i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
|
||||
@@ -1007,23 +986,10 @@ _mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
|
||||
{
|
||||
struct gl_shader_program *shProg
|
||||
= _mesa_lookup_shader_program(ctx, program);
|
||||
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;
|
||||
if (!shProg)
|
||||
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().
|
||||
*/
|
||||
@@ -1142,9 +1202,7 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
|
||||
const GLvoid *values, GLenum type)
|
||||
{
|
||||
struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
|
||||
GLint elems, i, k;
|
||||
GLenum uType;
|
||||
GLsizei maxCount;
|
||||
GLint elems;
|
||||
|
||||
if (!shProg || !shProg->LinkStatus) {
|
||||
_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)
|
||||
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 >= (GLint) shProg->Uniforms->NumParameters) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
|
||||
if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
|
||||
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) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
|
||||
return;
|
||||
@@ -1212,69 +1244,56 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
|
||||
return;
|
||||
}
|
||||
|
||||
/* OpenGL requires types to match exactly, except that one can convert
|
||||
* float or int array to boolean array.
|
||||
*/
|
||||
switch (uType)
|
||||
{
|
||||
case GL_BOOL:
|
||||
case GL_BOOL_VEC2:
|
||||
case GL_BOOL_VEC3:
|
||||
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;
|
||||
}
|
||||
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
|
||||
|
||||
/* XXX if this is a base type, then count must equal 1. However, we
|
||||
* don't have enough information from the compiler to distinguish a
|
||||
* base type from a 1-element array of that type. The standard allows
|
||||
* count to overrun an array, in which case the overflow is ignored.
|
||||
/* 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:
|
||||
*/
|
||||
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];
|
||||
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];
|
||||
}
|
||||
}
|
||||
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->VertexProgram) {
|
||||
GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
|
||||
if (loc >= 0) {
|
||||
set_program_uniform(ctx, &shProg->VertexProgram->Base,
|
||||
loc, type, count, elems, values);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if (shProg->FragmentProgram) {
|
||||
GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
|
||||
if (loc >= 0) {
|
||||
set_program_uniform(ctx, &shProg->FragmentProgram->Base,
|
||||
loc, type, count, elems, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
|
||||
GLuint location, GLuint rows, GLuint cols,
|
||||
GLboolean transpose, const GLfloat *values)
|
||||
{
|
||||
/*
|
||||
* Note: the _columns_ of a matrix are stored in program registers, not
|
||||
* 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 {
|
||||
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[col * rows + row];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1287,62 +1306,42 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
|
||||
GLenum matrixType, GLint location, GLsizei count,
|
||||
GLboolean transpose, const GLfloat *values)
|
||||
{
|
||||
GLsizei maxCount, i;
|
||||
struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
|
||||
|
||||
if (!shProg || !shProg->LinkStatus) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"glUniformMatrix(program not linked)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (location == -1)
|
||||
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 >= (GLint) shProg->Uniforms->NumParameters) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
|
||||
|
||||
if (location < 0 || location >= shProg->Uniforms->NumUniforms) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
|
||||
return;
|
||||
}
|
||||
if (values == NULL) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
|
||||
return;
|
||||
}
|
||||
if (count < 0) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(count < 0)");
|
||||
return;
|
||||
}
|
||||
|
||||
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
|
||||
|
||||
/*
|
||||
* Note: the _columns_ of a matrix are stored in program registers, not
|
||||
* the rows.
|
||||
*/
|
||||
/* XXXX need to test 3x3 and 2x2 matrices... */
|
||||
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->VertexProgram) {
|
||||
GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
|
||||
if (loc >= 0) {
|
||||
set_program_uniform_matrix(ctx, &shProg->VertexProgram->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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
location += cols;
|
||||
values += rows * cols;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
if (texIndex != -1) {
|
||||
/* Texture sampler:
|
||||
/* This is a texture sampler variable...
|
||||
* 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)
|
||||
*/
|
||||
GLint samplerUniform
|
||||
= _mesa_add_sampler(prog->Parameters, varName, datatype);
|
||||
store = _slang_new_ir_storage(PROGRAM_SAMPLER, samplerUniform, texIndex);
|
||||
const GLint sampNum = A->numSamplers++;
|
||||
_mesa_add_sampler(prog->Parameters, varName, datatype, sampNum);
|
||||
store = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, texIndex);
|
||||
if (dbg) printf("SAMPLER ");
|
||||
}
|
||||
else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
|
||||
|
@@ -31,6 +31,8 @@
|
||||
#include "main/imports.h"
|
||||
#include "main/context.h"
|
||||
#include "shader/program.h"
|
||||
#include "shader/programopt.h"
|
||||
#include "shader/prog_print.h"
|
||||
#include "shader/prog_parameter.h"
|
||||
#include "shader/grammar/grammar_mesa.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.vartable = O->vartable;
|
||||
A.curFuncEndLabel = NULL;
|
||||
A.numSamplers = 0;
|
||||
if (!_slang_codegen_global_variable(&A, var, C->type))
|
||||
return 0;
|
||||
}
|
||||
@@ -1640,6 +1643,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
|
||||
A.space.funcs = O->funs;
|
||||
A.space.structs = O->structs;
|
||||
A.space.vars = O->vars;
|
||||
A.numSamplers = 0;
|
||||
if (!initialize_global(&A, var))
|
||||
return 0;
|
||||
}
|
||||
@@ -1773,6 +1777,7 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
|
||||
A.program = O->program;
|
||||
A.vartable = O->vartable;
|
||||
A.log = C->L;
|
||||
A.numSamplers = 0;
|
||||
|
||||
_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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@@ -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_RECT_INDEX);
|
||||
|
||||
inst->Sampler = n->Children[0]->Store->Index; /* i.e. uniform's index */
|
||||
inst->TexSrcTarget = n->Children[0]->Store->Size;
|
||||
#if 0
|
||||
inst->TexSrcUnit = 27; /* Dummy value; the TexSrcUnit will be computed at
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
@@ -37,12 +37,17 @@
|
||||
#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 "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
|
||||
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 ||
|
||||
file == PROGRAM_STATE_VAR ||
|
||||
file == PROGRAM_NAMED_PARAM ||
|
||||
file == PROGRAM_CONSTANT ||
|
||||
file == PROGRAM_SAMPLER ||
|
||||
file == PROGRAM_UNIFORM);
|
||||
}
|
||||
GLuint samplerMap[MAX_SAMPLERS];
|
||||
GLuint i;
|
||||
|
||||
|
||||
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 */
|
||||
for (i = 0; i < prog->Parameters->NumParameters; i++) {
|
||||
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));
|
||||
/*
|
||||
* 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->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 (p->Type == PROGRAM_UNIFORM ||
|
||||
p->Type == PROGRAM_SAMPLER) {
|
||||
_mesa_append_uniform(shProg->Uniforms, p->Name, prog->Target, i);
|
||||
}
|
||||
|
||||
if (j >= 0) {
|
||||
/* already in list, check size XXX check this */
|
||||
#if 0
|
||||
assert(p->Size == shProg->Uniforms->Parameters[j].Size);
|
||||
#endif
|
||||
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)++;
|
||||
}
|
||||
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;
|
||||
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,
|
||||
/* OK, now scan the program/shader instructions looking for sampler vars,
|
||||
* replacing the old index with the new index.
|
||||
*/
|
||||
prog->SamplersUsed = 0x0;
|
||||
for (i = 0; i < prog->NumInstructions; i++) {
|
||||
struct prog_instruction *inst = prog->Instructions + i;
|
||||
GLuint j;
|
||||
|
||||
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) {
|
||||
if (_mesa_is_tex_instruction(inst->Opcode)) {
|
||||
/*
|
||||
printf("====== remap sampler from %d to %d\n",
|
||||
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,10 +254,8 @@ _slang_resolve_attributes(struct gl_shader_program *shProg,
|
||||
* glVertex/position.
|
||||
*/
|
||||
for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) {
|
||||
if (((1 << attr) & usedAttributes) == 0) {
|
||||
usedAttributes |= (1 << attr);
|
||||
if (((1 << attr) & usedAttributes) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (attr == MAX_VERTEX_ATTRIBS) {
|
||||
/* too many! XXX record error log */
|
||||
@@ -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 */
|
||||
static struct gl_vertex_program *
|
||||
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
|
||||
* agree between the vertex and fragment stages. They're treated as
|
||||
* vertex program output attribs and as fragment program input attribs.
|
||||
* 3. Uniform vars (including state references, constants, etc) from the
|
||||
* vertex and fragment shaders are merged into one group. Recall that
|
||||
* GLSL uniforms are shared by all linked shaders.
|
||||
* 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.
|
||||
* 3. The vertex and fragment programs are cloned and modified to update
|
||||
* src/dst register references so they use the new, linked varying
|
||||
* storage locations.
|
||||
*/
|
||||
void
|
||||
_slang_link(GLcontext *ctx,
|
||||
@@ -490,11 +380,12 @@ _slang_link(GLcontext *ctx,
|
||||
{
|
||||
const struct gl_vertex_program *vertProg;
|
||||
const struct gl_fragment_program *fragProg;
|
||||
GLuint numSamplers = 0;
|
||||
GLuint i;
|
||||
|
||||
_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();
|
||||
|
||||
/**
|
||||
@@ -531,33 +422,30 @@ _slang_link(GLcontext *ctx,
|
||||
_mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
|
||||
}
|
||||
|
||||
/* link varying vars */
|
||||
if (shProg->VertexProgram)
|
||||
link_varying_vars(shProg, &shProg->VertexProgram->Base);
|
||||
if (shProg->FragmentProgram)
|
||||
link_varying_vars(shProg, &shProg->FragmentProgram->Base);
|
||||
|
||||
/* link uniform vars */
|
||||
if (shProg->VertexProgram)
|
||||
link_uniform_vars(shProg, &shProg->VertexProgram->Base);
|
||||
link_uniform_vars(shProg, &shProg->VertexProgram->Base, &numSamplers);
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
/*_mesa_print_uniforms(shProg->Uniforms);*/
|
||||
|
||||
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) {
|
||||
_slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
|
||||
/* see comment just above */
|
||||
shProg->FragmentProgram->Base.Parameters = fragProg->Base.Parameters;
|
||||
}
|
||||
|
||||
if (shProg->VertexProgram) {
|
||||
|
@@ -32,10 +32,6 @@ extern void
|
||||
_slang_link(GLcontext *ctx, GLhandleARB h,
|
||||
struct gl_shader_program *shProg);
|
||||
|
||||
extern void
|
||||
_slang_resolve_samplers(struct gl_shader_program *shProg,
|
||||
struct gl_program *prog);
|
||||
|
||||
extern void
|
||||
_slang_remap_attribute(struct gl_program *prog, GLuint oldAttrib,
|
||||
GLuint newAttrib);
|
||||
|
@@ -65,6 +65,7 @@ typedef struct slang_assemble_ctx_
|
||||
struct slang_label_ *curFuncEndLabel;
|
||||
struct slang_ir_node_ *CurLoop;
|
||||
struct slang_function_ *CurFunction;
|
||||
GLuint numSamplers;
|
||||
} slang_assemble_ctx;
|
||||
|
||||
|
||||
|
@@ -165,6 +165,7 @@ SHADER_SOURCES = \
|
||||
shader/prog_parameter.c \
|
||||
shader/prog_print.c \
|
||||
shader/prog_statevars.c \
|
||||
shader/prog_uniform.c \
|
||||
shader/programopt.c \
|
||||
shader/shader_api.c \
|
||||
|
||||
|
@@ -33,11 +33,12 @@
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a texel.
|
||||
* Fetch a texel with given lod.
|
||||
* Called via machine->FetchTexelLod()
|
||||
*/
|
||||
static void
|
||||
fetch_texel( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
|
||||
GLuint unit, GLfloat color[4] )
|
||||
fetch_texel_lod( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
|
||||
GLuint unit, GLfloat color[4] )
|
||||
{
|
||||
GLchan rgba[4];
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
@@ -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
|
||||
* of detail in the mipmap.
|
||||
* Called via machine->FetchTexelDeriv()
|
||||
*/
|
||||
static void
|
||||
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->NumDeriv = FRAG_ATTRIB_MAX;
|
||||
|
||||
machine->Samplers = program->Base.SamplerUnits;
|
||||
|
||||
/* if running a GLSL program (not ARB_fragment_program) */
|
||||
if (ctx->Shader.CurrentProgram) {
|
||||
/* 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 */
|
||||
machine->StackDepth = 0;
|
||||
|
||||
machine->FetchTexelLod = fetch_texel;
|
||||
machine->FetchTexelLod = fetch_texel_lod;
|
||||
machine->FetchTexelDeriv = fetch_texel_deriv;
|
||||
}
|
||||
|
||||
|
@@ -1401,7 +1401,6 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
|
||||
* Write to renderbuffers
|
||||
*/
|
||||
{
|
||||
const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
|
||||
const GLuint numBuffers = fb->_NumColorDrawBuffers;
|
||||
const GLboolean multiFragOutputs = numBuffers > 1;
|
||||
GLuint buf;
|
||||
|
Reference in New Issue
Block a user