GLSL sampler variables indicate which texture unit to use for TEX instructions.
Previously, this was baked into the fragment/vertex program and couldn't be
readily changed once set.
Now, SamplerUnits[] array indicates which texture unit is to be used for
each sampler variable. These values are set with glUniform1i().
This is extra state that must be passed to the fragment/vertex program
executor at runtime.
#define MAX_PROGRAM_ADDRESS_REGS 2
#define MAX_UNIFORMS 128
#define MAX_VARYING 8
+#define MAX_SAMPLERS 8
/*@}*/
/** For GL_ARB_vertex_shader */
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 */
/** 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;
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
+ uint sampler_units[PIPE_MAX_SAMPLERS];
struct pipe_mipmap_tree *texture[PIPE_MAX_SAMPLERS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_ATTRIB_MAX];
failover->hw->set_polygon_stipple( failover->hw, stipple );
}
+static void
+failover_set_sampler_units( struct pipe_context *pipe,
+ uint num_samplers, const uint *units )
+{
+ struct failover_context *failover = failover_context(pipe);
+ uint i;
+
+ for (i = 0; i < num_samplers; i++)
+ failover->sampler_units[i] = units[i];
+ failover->dirty |= FO_NEW_SAMPLER;
+ failover->hw->set_sampler_units(failover->hw, num_samplers, units);
+}
+
static void *
failover_create_rasterizer_state(struct pipe_context *pipe,
const struct pipe_rasterizer_state *templ)
failover->pipe.set_clear_color_state = failover_set_clear_color_state;
failover->pipe.set_framebuffer_state = failover_set_framebuffer_state;
failover->pipe.set_polygon_stipple = failover_set_polygon_stipple;
+ failover->pipe.set_sampler_units = failover_set_sampler_units;
failover->pipe.set_scissor_state = failover_set_scissor_state;
failover->pipe.set_texture_state = failover_set_texture_state;
failover->pipe.set_viewport_state = failover_set_viewport_state;
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
+ uint sampler_units[PIPE_MAX_SAMPLERS];
struct pipe_mipmap_tree *texture[PIPE_MAX_SAMPLERS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_ATTRIB_MAX];
{
}
+static void i915_set_sampler_units(struct pipe_context *pipe,
+ uint numSamplers, const uint *units)
+{
+ struct i915_context *i915 = i915_context(pipe);
+ uint i;
+ for (i = 0; i < numSamplers; i++)
+ i915->sampler_units[i] = units[i];
+}
+
static void * i915_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
i915->pipe.set_feedback_buffer = i915_set_feedback_buffer;
i915->pipe.set_polygon_stipple = i915_set_polygon_stipple;
+ i915->pipe.set_sampler_units = i915_set_sampler_units;
i915->pipe.set_scissor_state = i915_set_scissor_state;
i915->pipe.set_texture_state = i915_set_texture_state;
i915->pipe.set_viewport_state = i915_set_viewport_state;
void (*set_polygon_stipple)( struct pipe_context *,
const struct pipe_poly_stipple * );
+ void (*set_sampler_units)( struct pipe_context *,
+ uint num_samplers, const uint *units );
+
void (*set_scissor_state)( struct pipe_context *,
const struct pipe_scissor_state * );
softpipe->pipe.set_feedback_state = softpipe_set_feedback_state;
softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state;
softpipe->pipe.set_polygon_stipple = softpipe_set_polygon_stipple;
+ softpipe->pipe.set_sampler_units = softpipe_set_sampler_units;
softpipe->pipe.set_scissor_state = softpipe_set_scissor_state;
softpipe->pipe.set_texture_state = softpipe_set_texture_state;
softpipe->pipe.set_viewport_state = softpipe_set_viewport_state;
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_ATTRIB_MAX];
struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX];
+ uint sampler_units[PIPE_MAX_SAMPLERS];
unsigned dirty;
/*
/* Consts does not require 16 byte alignment. */
machine->Consts = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT];
+ machine->SamplerUnits = softpipe->sampler_units;
machine->InterpCoefs = quad->coef;
machine->Inputs[0].xyzw[0].f[0] = fx;
void softpipe_set_polygon_stipple( struct pipe_context *,
const struct pipe_poly_stipple * );
+void softpipe_set_sampler_units( struct pipe_context *,
+ uint numSamplers, const uint *units );
+
void softpipe_set_scissor_state( struct pipe_context *,
const struct pipe_scissor_state * );
softpipe->dirty |= SP_NEW_TEXTURE;
}
+
+
+void
+softpipe_set_sampler_units(struct pipe_context *pipe,
+ uint num_samplers, const uint *units )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+ uint i;
+ for (i = 0; i < num_samplers; i++)
+ softpipe->sampler_units[i] = units[i];
+ softpipe->dirty |= SP_NEW_SAMPLER;
+}
+
+
const struct tgsi_full_instruction *inst,
boolean biasLod)
{
- const uint unit = inst->FullSrcRegisters[1].SrcRegister.Index;
+ const uint sampler = inst->FullSrcRegisters[1].SrcRegister.Index;
+ const uint unit = mach->SamplerUnits[sampler];
union tgsi_exec_channel r[8];
uint chan_index;
float lodBias;
+ // printf("Sampler %u unit %u\n", sampler, unit);
+
switch (inst->InstructionExtTexture.Texture) {
case TGSI_TEXTURE_1D:
struct tgsi_exec_vector *Temps;
struct tgsi_exec_vector *Addrs;
+ uint *SamplerUnits;
struct tgsi_sampler *Samplers;
float Imms[TGSI_EXEC_NUM_IMMEDIATES][4];
* The rest of the time, just use zero (until we get a more
* sophisticated way of computing lambda).
*/
+ const GLuint unit = machine->Samplers[inst->TexSrcUnit];
GLfloat coord[4], color[4], lambda;
#if 0
if (inst->SrcReg[0].File == PROGRAM_INPUT &&
- inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0 + inst->TexSrcUnit)
- lambda = span->array->lambda[inst->TexSrcUnit][column];
+ inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0 + unit)
+ lambda = span->array->lambda[unit][column];
else
#endif
lambda = 0.0;
fetch_vector4(&inst->SrcReg[0], machine, coord);
- machine->FetchTexelLod(ctx, coord, lambda, inst->TexSrcUnit,
- color);
+ machine->FetchTexelLod(ctx, coord, lambda, unit, color);
if (DEBUG_PROG) {
printf("TEX (%g, %g, %g, %g) = texture[%d][%g, %g, %g, %g], "
"lod %f\n",
color[0], color[1], color[2], color[3],
- inst->TexSrcUnit,
+ unit,
coord[0], coord[1], coord[2], coord[3], lambda);
}
store_vector4(inst, machine, color);
case OPCODE_TXP: /* GL_ARB_fragment_program only */
/* Texture lookup w/ projective divide */
{
+ const GLuint unit = machine->Samplers[inst->TexSrcUnit];
GLfloat texcoord[4], color[4], lambda;
#if 0
if (inst->SrcReg[0].File == PROGRAM_INPUT &&
inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0 + inst->TexSrcUnit)
- lambda = span->array->lambda[inst->TexSrcUnit][column];
+ lambda = span->array->lambda[unit][column];
else
#endif
lambda = 0.0;
texcoord[1] /= texcoord[3];
texcoord[2] /= texcoord[3];
}
- machine->FetchTexelLod(ctx, texcoord, lambda,
- inst->TexSrcUnit, color);
+ machine->FetchTexelLod(ctx, texcoord, lambda, unit, color);
store_vector4(inst, machine, color);
}
break;
GLuint CondCodes[4]; /**< COND_* value for x/y/z/w */
GLint AddressReg[MAX_PROGRAM_ADDRESS_REGS][4];
+ GLuint *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[] */
}
+GLboolean
+_mesa_is_tex_instruction(gl_inst_opcode opcode)
+{
+ return (opcode == OPCODE_TEX ||
+ opcode == OPCODE_TXB ||
+ opcode == OPCODE_TXD ||
+ opcode == OPCODE_TXL ||
+ opcode == OPCODE_TXP);
+}
+
+
/**
* Return string name for given program opcode.
*/
*/
GLint BranchTarget;
+#if 0
/**
* For TEX instructions in shaders, the sampler to use for the
* texture lookup.
*/
GLint Sampler;
+#endif
const char *Comment;
};
extern GLuint
_mesa_num_inst_dst_regs(gl_inst_opcode opcode);
+extern GLboolean
+_mesa_is_tex_instruction(gl_inst_opcode opcode);
+
extern const char *
_mesa_opcode_string(gl_inst_opcode opcode);
* 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;
}
}
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,
void
_mesa_print_program_parameters(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("NumParameters=%d\n", prog->NumParameters);
_mesa_printf("NumAttributes=%d\n", prog->NumAttributes);
_mesa_printf("NumAddressRegs=%d\n", prog->NumAddressRegs);
+ _mesa_printf("Samplers=[ ");
+ for (i = 0; i < MAX_SAMPLERS; i++) {
+ _mesa_printf("%d ", prog->SamplerUnits[i]);
+ }
+ _mesa_printf("]\n");
_mesa_load_state_parameters(ctx, prog->Parameters);
{
(void) ctx;
if (prog) {
+ GLuint i;
_mesa_bzero(prog, sizeof(*prog));
prog->Id = id;
prog->Target = target;
prog->Resident = GL_TRUE;
prog->RefCount = 1;
prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB;
+
+ /* default mapping from samplers to texture units */
+ for (i = 0; i < MAX_SAMPLERS; i++)
+ prog->SamplerUnits[i] = i;
}
return prog;
}
+
+/**
+ * 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);
+ }
+ }
+}
+
+
/**
* Called via ctx->Driver.Uniform().
*/
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- /*
- * 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;
return;
}
- 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];
- }
+ if (shProg->Uniforms->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;
}
- else {
- const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
- for (i = 0; i < elems; i++) {
- uniformVal[i] = fValues[i];
- }
+
+ sampler = (GLuint) shProg->Uniforms->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;
}
- }
- 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);
+ if (shProg->VertexProgram) {
+ shProg->VertexProgram->Base.SamplerUnits[sampler] = texUnit;
+ update_textures_used(&shProg->VertexProgram->Base);
+ }
+ if (shProg->FragmentProgram) {
+ shProg->FragmentProgram->Base.SamplerUnits[sampler] = texUnit;
+ update_textures_used(&shProg->FragmentProgram->Base);
+ }
+
+
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
}
+ else {
+ /* ordinary uniform variable */
+ 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];
+ }
+ }
+ }
+ }
}
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)
*/
+#if 0
GLint samplerUniform
= _mesa_add_sampler(prog->Parameters, varName, datatype);
- store = _slang_new_ir_storage(PROGRAM_SAMPLER, samplerUniform, texIndex);
+#elif 0
+ GLint samplerUniform
+ = _mesa_add_sampler(prog->Samplers, varName, datatype);
+ (void) _mesa_add_sampler(prog->Parameters, varName, datatype); /* dummy entry */
+#else
+ const GLint sampNum = A->numSamplers++;
+ _mesa_add_sampler(prog->Parameters, varName, datatype, sampNum);
+#endif
+ store = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, texIndex);
if (dbg) printf("SAMPLER ");
}
else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
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;
}
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;
}
A.program = O->program;
A.vartable = O->vartable;
A.log = C->L;
+ A.numSamplers = 0;
_slang_codegen_function(&A, *parsed_func_ret);
}
shader->Programs[0]->Parameters = _mesa_new_parameter_list();
shader->Programs[0]->Varying = _mesa_new_parameter_list();
shader->Programs[0]->Attributes = _mesa_new_parameter_list();
+#if 0
+ shader->Programs[0]->Samplers = _mesa_new_parameter_list();
+#endif
}
slang_info_log_construct(&info_log);
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;
}
}
+static GLuint shProg_NumSamplers = 0; /** XXX temporary */
+
+
static GLboolean
link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
{
GLuint *map, i;
+ GLuint samplerMap[MAX_SAMPLERS];
#if 0
printf("================ pre link uniforms ===============\n");
/* sanity check */
assert(is_uniform(p->Type));
+ /* See if this uniform is already in the linked program's list */
if (p->Name) {
+ /* this is a named uniform */
j = _mesa_lookup_parameter_index(shProg->Uniforms, -1, p->Name);
}
else {
+ /* this is an unnamed constant */
/*GLuint swizzle;*/
ASSERT(p->Type == PROGRAM_CONSTANT);
if (_mesa_lookup_parameter_constant(shProg->Uniforms, pVals,
}
if (j >= 0) {
- /* already in list, check size XXX check this */
+ /* already in linked program's list */
+ /* check size XXX check this */
#if 0
assert(p->Size == shProg->Uniforms->Parameters[j].Size);
#endif
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);
+ {
+ GLuint sampNum = shProg_NumSamplers++;
+ GLuint oldSampNum;
+ j = _mesa_add_sampler(shProg->Uniforms, p->Name,
+ p->DataType, sampNum);
+ oldSampNum = (GLuint) prog->Parameters->ParameterValues[i][0];
+ assert(oldSampNum < MAX_SAMPLERS);
+ samplerMap[oldSampNum] = sampNum;
+ }
break;
default:
_mesa_problem(NULL, "bad parameter type in link_uniform_vars()");
/* OK, now scan the program/shader instructions looking for uniform 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 (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);
}
}
-/**
- * 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)
const struct gl_fragment_program *fragProg;
GLuint i;
+ shProg_NumSamplers = 0; /** XXX temporary */
+
_mesa_clear_shader_program_data(ctx, shProg);
shProg->Uniforms = _mesa_new_parameter_list();
shProg->FragmentProgram->Base.Parameters = shProg->Uniforms;
}
- if (shProg->VertexProgram) {
- _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
- }
- if (shProg->FragmentProgram) {
- _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
- }
-
if (shProg->VertexProgram) {
if (!_slang_resolve_attributes(shProg, &shProg->VertexProgram->Base)) {
/*goto cleanup;*/
_mesa_print_program(&fragProg->Base);
_mesa_print_program_parameters(ctx, &fragProg->Base);
#endif
-#if 0
+#if 01
printf("************** linked fragment prog\n");
_mesa_print_program(&shProg->FragmentProgram->Base);
_mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base);
_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);
struct slang_label_ *curFuncEndLabel;
struct slang_ir_node_ *CurLoop;
struct slang_function_ *CurFunction;
+ GLuint numSamplers;
} slang_assemble_ctx;
}
+static struct gl_fragment_program *
+current_fragment_program(GLcontext *ctx)
+{
+ struct gl_fragment_program *f;
+
+ if (ctx->Shader.CurrentProgram &&
+ ctx->Shader.CurrentProgram->LinkStatus &&
+ ctx->Shader.CurrentProgram->FragmentProgram) {
+ f = ctx->Shader.CurrentProgram->FragmentProgram;
+ }
+ else {
+ f = ctx->FragmentProgram._Current;
+ assert(f);
+ }
+ return f;
+}
+
static void
update_samplers(struct st_context *st)
st->pipe->bind_sampler_state(st->pipe, u, cso->data);
}
}
+
+
+ /* mapping from sampler vars to texture units */
+ {
+ struct gl_fragment_program *fprog = current_fragment_program(st->ctx);
+ const GLubyte *samplerUnits = fprog->Base.SamplerUnits;
+ uint sample_units[PIPE_MAX_SAMPLERS];
+ uint s;
+ for (s = 0; s < PIPE_MAX_SAMPLERS; s++) {
+ sample_units[s] = fprog->Base.SamplerUnits[s];
+ }
+
+ st->pipe->set_sampler_units(st->pipe, PIPE_MAX_SAMPLERS, sample_units);
+ }
}
const struct st_tracked_state st_update_sampler = {
.name = "st_update_sampler",
.dirty = {
- .mesa = _NEW_TEXTURE,
+ .mesa = _NEW_TEXTURE | _NEW_PROGRAM,
.st = 0,
},
.update = update_samplers
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 */