Commit 398e046e authored by Brian Paul's avatar Brian Paul

glsl: handle indirectly indexed input registers in linker

For example, if the fragment shader reads gl_TexCoord[i] with a
dynamic index we need to set all the InputsRead bits for all
texcoords.  We were already doing this for shader outputs.
Refactored the later code so inputs and outputs are handled with
similar code.

Fixes a swrast failure with piglit's glsl-texcoord-array.shader_test
parent e57689c6
......@@ -590,6 +590,108 @@ _slang_count_temporaries(struct gl_program *prog)
}
/**
* If an input attribute is indexed with relative addressing we have
* to compute a gl_program::InputsRead bitmask which reflects the fact
* that any input may be referenced by array element. Ex: gl_TexCoord[i].
* This function computes the bitmask of potentially read inputs.
*/
static GLbitfield
get_inputs_read_mask(GLenum target, GLuint index, GLboolean relAddr)
{
GLbitfield mask;
mask = 1 << index;
if (relAddr) {
if (target == GL_VERTEX_PROGRAM_ARB) {
switch (index) {
case VERT_ATTRIB_TEX0:
mask = ((1U << (VERT_ATTRIB_TEX7 + 1)) - 1)
- ((1U << VERT_ATTRIB_TEX0) - 1);
break;
case VERT_ATTRIB_GENERIC0:
/* different code to avoid uint overflow */
mask = ~0x0U - ((1U << VERT_ATTRIB_GENERIC0) - 1);
break;
default:
; /* a non-array input attribute */
}
}
else if (target == GL_FRAGMENT_PROGRAM_ARB) {
switch (index) {
case FRAG_ATTRIB_TEX0:
mask = ((1U << (FRAG_ATTRIB_TEX7 + 1)) - 1)
- ((1U << FRAG_ATTRIB_TEX0) - 1);
break;
case FRAG_ATTRIB_VAR0:
mask = ((1U << (FRAG_ATTRIB_VAR0 + MAX_VARYING)) - 1)
- ((1U << FRAG_ATTRIB_VAR0) - 1);
break;
default:
; /* a non-array input attribute */
}
}
else {
assert(0 && "bad program target");
}
}
else {
}
return mask;
}
/**
* If an output attribute is indexed with relative addressing we have
* to compute a gl_program::OutputsWritten bitmask which reflects the fact
* that any output may be referenced by array element. Ex: gl_TexCoord[i].
* This function computes the bitmask of potentially written outputs.
*/
static GLbitfield64
get_outputs_written_mask(GLenum target, GLuint index, GLboolean relAddr)
{
GLbitfield64 mask;
mask = BITFIELD64_BIT(index);
if (relAddr) {
if (target == GL_VERTEX_PROGRAM_ARB) {
switch (index) {
case VERT_RESULT_TEX0:
mask = BITFIELD64_RANGE(VERT_RESULT_TEX0,
(VERT_RESULT_TEX0
+ MAX_TEXTURE_COORD_UNITS - 1));
break;
case VERT_RESULT_VAR0:
mask = BITFIELD64_RANGE(VERT_RESULT_VAR0,
(VERT_RESULT_VAR0 + MAX_VARYING - 1));
break;
default:
; /* a non-array output attribute */
}
}
else if (target == GL_FRAGMENT_PROGRAM_ARB) {
switch (index) {
case FRAG_RESULT_DATA0:
mask = BITFIELD64_RANGE(FRAG_RESULT_DATA0,
(FRAG_RESULT_DATA0
+ MAX_DRAW_BUFFERS - 1));
break;
default:
; /* a non-array output attribute */
}
}
else {
assert(0 && "bad program target");
}
}
return mask;
}
/**
* Scan program instructions to update the program's InputsRead and
* OutputsWritten fields.
......@@ -608,7 +710,9 @@ _slang_update_inputs_outputs(struct gl_program *prog)
const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
for (j = 0; j < numSrc; j++) {
if (inst->SrcReg[j].File == PROGRAM_INPUT) {
prog->InputsRead |= 1 << inst->SrcReg[j].Index;
prog->InputsRead |= get_inputs_read_mask(prog->Target,
inst->SrcReg[j].Index,
inst->SrcReg[j].RelAddr);
}
else if (inst->SrcReg[j].File == PROGRAM_ADDRESS) {
maxAddrReg = MAX2(maxAddrReg, (GLuint) (inst->SrcReg[j].Index + 1));
......@@ -616,34 +720,9 @@ _slang_update_inputs_outputs(struct gl_program *prog)
}
if (inst->DstReg.File == PROGRAM_OUTPUT) {
prog->OutputsWritten |= BITFIELD64_BIT(inst->DstReg.Index);
if (inst->DstReg.RelAddr) {
/* If the output attribute is indexed with relative addressing
* we know that it must be a varying or texcoord such as
* gl_TexCoord[i] = v; In this case, mark all the texcoords
* or varying outputs as being written. It's not an error if
* a vertex shader writes varying vars that aren't used by the
* fragment shader. But it is an error for a fragment shader
* to use varyings that are not written by the vertex shader.
*/
if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
if (inst->DstReg.Index == VERT_RESULT_TEX0) {
/* mark all texcoord outputs as written */
const GLbitfield64 mask =
BITFIELD64_RANGE(VERT_RESULT_TEX0,
(VERT_RESULT_TEX0
+ MAX_TEXTURE_COORD_UNITS - 1));
prog->OutputsWritten |= mask;
}
else if (inst->DstReg.Index == VERT_RESULT_VAR0) {
/* mark all generic varying outputs as written */
const GLbitfield64 mask =
BITFIELD64_RANGE(VERT_RESULT_VAR0,
(VERT_RESULT_VAR0 + MAX_VARYING - 1));
prog->OutputsWritten |= mask;
}
}
}
prog->OutputsWritten |= get_outputs_written_mask(prog->Target,
inst->DstReg.Index,
inst->DstReg.RelAddr);
}
else if (inst->DstReg.File == PROGRAM_ADDRESS) {
maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment