Commit 5c26c290 by Nicolas Capens

Fix indexing of samplers in structures.

Change-Id: I0bde678865902d549d4260bf8f6c1a368a46f4d4 Reviewed-on: https://swiftshader-review.googlesource.com/5191Tested-by: 's avatarNicolas Capens <capn@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 197226a0
...@@ -495,6 +495,11 @@ namespace glsl ...@@ -495,6 +495,11 @@ namespace glsl
const TType &rightType = right->getType(); const TType &rightType = right->getType();
const TType &resultType = node->getType(); const TType &resultType = node->getType();
if(isSamplerRegister(result))
{
return false; // Don't traverse, the register index is determined statically
}
switch(node->getOp()) switch(node->getOp())
{ {
case EOpAssign: case EOpAssign:
...@@ -1758,21 +1763,6 @@ namespace glsl ...@@ -1758,21 +1763,6 @@ namespace glsl
return true; return true;
} }
bool OutputASM::isSamplerRegister(TIntermTyped *operand)
{
return operand && isSamplerRegister(operand->getType());
}
bool OutputASM::isSamplerRegister(const TType &type)
{
// A sampler register's qualifiers can be:
// - EvqUniform: The sampler uniform is used as is in the code (default case).
// - EvqTemporary: The sampler is indexed. It's still a sampler register.
// - EvqIn (and other similar types): The sampler has been passed as a function argument. At this point,
// the sampler has been copied and is no longer a sampler register.
return IsSampler(type.getBasicType()) && (type.getQualifier() == EvqUniform || type.getQualifier() == EvqTemporary);
}
Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2, TIntermNode *src3, TIntermNode *src4) Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2, TIntermNode *src3, TIntermNode *src4)
{ {
return emit(op, dst, 0, src0, 0, src1, 0, src2, 0, src3, 0, src4, 0); return emit(op, dst, 0, src0, 0, src1, 0, src2, 0, src3, 0, src4, 0);
...@@ -1781,11 +1771,6 @@ namespace glsl ...@@ -1781,11 +1771,6 @@ namespace glsl
Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, int dstIndex, TIntermNode *src0, int index0, TIntermNode *src1, int index1, Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, int dstIndex, TIntermNode *src0, int index0, TIntermNode *src1, int index1,
TIntermNode *src2, int index2, TIntermNode *src3, int index3, TIntermNode *src4, int index4) TIntermNode *src2, int index2, TIntermNode *src3, int index3, TIntermNode *src4, int index4)
{ {
if(isSamplerRegister(dst))
{
op = sw::Shader::OPCODE_NULL; // Can't assign to a sampler, but this is hit when indexing sampler arrays
}
Instruction *instruction = new Instruction(op); Instruction *instruction = new Instruction(op);
if(dst) if(dst)
...@@ -2172,39 +2157,7 @@ namespace glsl ...@@ -2172,39 +2157,7 @@ namespace glsl
{ {
parameter.index = registerIndex(arg) + argumentInfo.clampedIndex; parameter.index = registerIndex(arg) + argumentInfo.clampedIndex;
if(isSamplerRegister(arg)) if(parameter.bufferIndex != -1)
{
TIntermBinary *binary = argument->getAsBinaryNode();
if(binary)
{
TIntermTyped *left = binary->getLeft();
TIntermTyped *right = binary->getRight();
switch(binary->getOp())
{
case EOpIndexDirect:
parameter.index += right->getAsConstantUnion()->getIConst(0);
break;
case EOpIndexIndirect:
if(left->getArraySize() > 1)
{
parameter.rel.type = registerType(binary->getRight());
parameter.rel.index = registerIndex(binary->getRight());
parameter.rel.scale = 1;
parameter.rel.deterministic = true;
}
break;
case EOpIndexDirectStruct:
case EOpIndexDirectInterfaceBlock:
parameter.index += right->getAsConstantUnion()->getIConst(0);
break;
default:
UNREACHABLE(binary->getOp());
}
}
}
else if(parameter.bufferIndex != -1)
{ {
int stride = (argumentInfo.typedMemberInfo.matrixStride > 0) ? argumentInfo.typedMemberInfo.matrixStride : argumentInfo.typedMemberInfo.arrayStride; int stride = (argumentInfo.typedMemberInfo.matrixStride > 0) ? argumentInfo.typedMemberInfo.matrixStride : argumentInfo.typedMemberInfo.arrayStride;
parameter.index = argumentInfo.typedMemberInfo.offset + argumentInfo.clampedIndex * stride; parameter.index = argumentInfo.typedMemberInfo.offset + argumentInfo.clampedIndex * stride;
...@@ -2884,30 +2837,57 @@ namespace glsl ...@@ -2884,30 +2837,57 @@ namespace glsl
int OutputASM::samplerRegister(TIntermTyped *sampler) int OutputASM::samplerRegister(TIntermTyped *sampler)
{ {
ASSERT(IsSampler(sampler->getType().getBasicType())); const TType &type = sampler->getType();
ASSERT(IsSampler(type.getBasicType()) || type.isStruct()); // Structures can contain samplers
TIntermSymbol *symbol = sampler->getAsSymbolNode(); TIntermSymbol *symbol = sampler->getAsSymbolNode();
TIntermBinary *binary = sampler->getAsBinaryNode(); TIntermBinary *binary = sampler->getAsBinaryNode();
if(symbol) if(symbol && type.getQualifier() == EvqUniform)
{ {
return samplerRegister(symbol); return samplerRegister(symbol);
} }
else if(binary) else if(binary)
{ {
ASSERT(binary->getOp() == EOpIndexDirect || binary->getOp() == EOpIndexIndirect || TIntermTyped *left = binary->getLeft();
binary->getOp() == EOpIndexDirectStruct || binary->getOp() == EOpIndexDirectInterfaceBlock); TIntermTyped *right = binary->getRight();
const TType &leftType = left->getType();
int index = right->getAsConstantUnion() ? right->getAsConstantUnion()->getIConst(0) : 0;
switch(binary->getOp())
{
case EOpIndexDirect:
ASSERT(left->isArray());
return samplerRegister(left) + index * leftType.elementRegisterCount();
case EOpIndexDirectStruct:
{
ASSERT(leftType.isStruct());
const TFieldList &fields = leftType.getStruct()->fields();
int fieldOffset = 0;
return samplerRegister(binary->getLeft()); // Index added later for(int i = 0; i < index; i++)
{
fieldOffset += fields[i]->type()->totalRegisterCount();
} }
else UNREACHABLE(0);
return samplerRegister(left) + fieldOffset;
}
case EOpIndexDirectInterfaceBlock: // Interface blocks can't contain samplers
case EOpIndexIndirect: // Indirect indexing produces a temporary, not a sampler register
default:
UNREACHABLE(binary->getOp());
return 0; return 0;
} }
}
UNREACHABLE(0);
return 0; // Not a sampler register
}
int OutputASM::samplerRegister(TIntermSymbol *sampler) int OutputASM::samplerRegister(TIntermSymbol *sampler)
{ {
const TType &type = sampler->getType(); const TType &type = sampler->getType();
ASSERT(IsSampler(type.getBasicType()) || type.getStruct()); // Structures can contain samplers ASSERT(IsSampler(type.getBasicType()) || type.isStruct()); // Structures can contain samplers
int index = lookup(samplers, sampler); int index = lookup(samplers, sampler);
...@@ -2925,6 +2905,11 @@ namespace glsl ...@@ -2925,6 +2905,11 @@ namespace glsl
return index; return index;
} }
bool OutputASM::isSamplerRegister(TIntermTyped *operand)
{
return operand && IsSampler(operand->getBasicType()) && samplerRegister(operand) >= 0;
}
int OutputASM::lookup(VariableArray &list, TIntermTyped *variable) int OutputASM::lookup(VariableArray &list, TIntermTyped *variable)
{ {
for(unsigned int i = 0; i < list.size(); i++) for(unsigned int i = 0; i < list.size(); i++)
...@@ -3110,7 +3095,7 @@ namespace glsl ...@@ -3110,7 +3095,7 @@ namespace glsl
int fieldRegisterIndex = encoder ? shaderObject->activeUniformBlocks[blockId].registerIndex + BlockLayoutEncoder::getBlockRegister(blockInfo) : registerIndex; int fieldRegisterIndex = encoder ? shaderObject->activeUniformBlocks[blockId].registerIndex + BlockLayoutEncoder::getBlockRegister(blockInfo) : registerIndex;
activeUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(), activeUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(),
fieldRegisterIndex, blockId, blockInfo)); fieldRegisterIndex, blockId, blockInfo));
if(isSamplerRegister(type)) if(IsSampler(type.getBasicType()))
{ {
for(int i = 0; i < type.totalRegisterCount(); i++) for(int i = 0; i < type.totalRegisterCount(); i++)
{ {
......
...@@ -286,6 +286,7 @@ namespace glsl ...@@ -286,6 +286,7 @@ namespace glsl
int fragmentOutputRegister(TIntermTyped *fragmentOutput); int fragmentOutputRegister(TIntermTyped *fragmentOutput);
int samplerRegister(TIntermTyped *sampler); int samplerRegister(TIntermTyped *sampler);
int samplerRegister(TIntermSymbol *sampler); int samplerRegister(TIntermSymbol *sampler);
bool isSamplerRegister(TIntermTyped *operand);
typedef std::vector<TIntermTyped*> VariableArray; typedef std::vector<TIntermTyped*> VariableArray;
...@@ -302,8 +303,6 @@ namespace glsl ...@@ -302,8 +303,6 @@ namespace glsl
static int dim(TIntermNode *v); static int dim(TIntermNode *v);
static int dim2(TIntermNode *m); static int dim2(TIntermNode *m);
static unsigned int loopCount(TIntermLoop *node); static unsigned int loopCount(TIntermLoop *node);
static bool isSamplerRegister(TIntermTyped *operand);
static bool isSamplerRegister(const TType &type);
Shader *const shaderObject; Shader *const shaderObject;
sw::Shader *shader; sw::Shader *shader;
......
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