const TType &rightType = right->getType();\r
const TType &resultType = node->getType();\r
\r
+ if(isSamplerRegister(result))\r
+ {\r
+ return false; // Don't traverse, the register index is determined statically\r
+ }\r
+\r
switch(node->getOp())\r
{\r
case EOpAssign:\r
return true;\r
}\r
\r
- bool OutputASM::isSamplerRegister(TIntermTyped *operand)\r
- {\r
- return operand && isSamplerRegister(operand->getType());\r
- }\r
-\r
- bool OutputASM::isSamplerRegister(const TType &type)\r
- {\r
- // A sampler register's qualifiers can be:\r
- // - EvqUniform: The sampler uniform is used as is in the code (default case).\r
- // - EvqTemporary: The sampler is indexed. It's still a sampler register.\r
- // - EvqIn (and other similar types): The sampler has been passed as a function argument. At this point,\r
- // the sampler has been copied and is no longer a sampler register.\r
- return IsSampler(type.getBasicType()) && (type.getQualifier() == EvqUniform || type.getQualifier() == EvqTemporary);\r
- }\r
-\r
Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2, TIntermNode *src3, TIntermNode *src4)\r
{\r
return emit(op, dst, 0, src0, 0, src1, 0, src2, 0, src3, 0, src4, 0);\r
Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, int dstIndex, TIntermNode *src0, int index0, TIntermNode *src1, int index1,\r
TIntermNode *src2, int index2, TIntermNode *src3, int index3, TIntermNode *src4, int index4)\r
{\r
- if(isSamplerRegister(dst))\r
- {\r
- op = sw::Shader::OPCODE_NULL; // Can't assign to a sampler, but this is hit when indexing sampler arrays\r
- }\r
-\r
Instruction *instruction = new Instruction(op);\r
\r
if(dst)\r
{\r
parameter.index = registerIndex(arg) + argumentInfo.clampedIndex;\r
\r
- if(isSamplerRegister(arg))\r
- {\r
- TIntermBinary *binary = argument->getAsBinaryNode();\r
-\r
- if(binary)\r
- {\r
- TIntermTyped *left = binary->getLeft();\r
- TIntermTyped *right = binary->getRight();\r
-\r
- switch(binary->getOp())\r
- {\r
- case EOpIndexDirect:\r
- parameter.index += right->getAsConstantUnion()->getIConst(0);\r
- break;\r
- case EOpIndexIndirect:\r
- if(left->getArraySize() > 1)\r
- {\r
- parameter.rel.type = registerType(binary->getRight());\r
- parameter.rel.index = registerIndex(binary->getRight());\r
- parameter.rel.scale = 1;\r
- parameter.rel.deterministic = true;\r
- }\r
- break;\r
- case EOpIndexDirectStruct:\r
- case EOpIndexDirectInterfaceBlock:\r
- parameter.index += right->getAsConstantUnion()->getIConst(0);\r
- break;\r
- default:\r
- UNREACHABLE(binary->getOp());\r
- }\r
- }\r
- }\r
- else if(parameter.bufferIndex != -1)\r
+ if(parameter.bufferIndex != -1)\r
{\r
int stride = (argumentInfo.typedMemberInfo.matrixStride > 0) ? argumentInfo.typedMemberInfo.matrixStride : argumentInfo.typedMemberInfo.arrayStride;\r
parameter.index = argumentInfo.typedMemberInfo.offset + argumentInfo.clampedIndex * stride;\r
\r
int OutputASM::samplerRegister(TIntermTyped *sampler)\r
{\r
- ASSERT(IsSampler(sampler->getType().getBasicType()));\r
+ const TType &type = sampler->getType();\r
+ ASSERT(IsSampler(type.getBasicType()) || type.isStruct()); // Structures can contain samplers\r
+\r
TIntermSymbol *symbol = sampler->getAsSymbolNode();\r
TIntermBinary *binary = sampler->getAsBinaryNode();\r
\r
- if(symbol)\r
+ if(symbol && type.getQualifier() == EvqUniform)\r
{\r
return samplerRegister(symbol);\r
}\r
else if(binary)\r
{\r
- ASSERT(binary->getOp() == EOpIndexDirect || binary->getOp() == EOpIndexIndirect ||\r
- binary->getOp() == EOpIndexDirectStruct || binary->getOp() == EOpIndexDirectInterfaceBlock);\r
+ TIntermTyped *left = binary->getLeft();\r
+ TIntermTyped *right = binary->getRight();\r
+ const TType &leftType = left->getType();\r
+ int index = right->getAsConstantUnion() ? right->getAsConstantUnion()->getIConst(0) : 0;\r
+\r
+ switch(binary->getOp())\r
+ {\r
+ case EOpIndexDirect:\r
+ ASSERT(left->isArray());\r
+ return samplerRegister(left) + index * leftType.elementRegisterCount();\r
+ case EOpIndexDirectStruct:\r
+ {\r
+ ASSERT(leftType.isStruct());\r
+ const TFieldList &fields = leftType.getStruct()->fields();\r
+ int fieldOffset = 0;\r
+\r
+ for(int i = 0; i < index; i++)\r
+ {\r
+ fieldOffset += fields[i]->type()->totalRegisterCount();\r
+ }\r
\r
- return samplerRegister(binary->getLeft()); // Index added later\r
+ return samplerRegister(left) + fieldOffset;\r
+ }\r
+ case EOpIndexDirectInterfaceBlock: // Interface blocks can't contain samplers\r
+ case EOpIndexIndirect: // Indirect indexing produces a temporary, not a sampler register\r
+ default:\r
+ UNREACHABLE(binary->getOp());\r
+ return 0;\r
+ }\r
}\r
- else UNREACHABLE(0);\r
\r
- return 0;\r
+ UNREACHABLE(0);\r
+ return 0; // Not a sampler register\r
}\r
\r
int OutputASM::samplerRegister(TIntermSymbol *sampler)\r
{\r
const TType &type = sampler->getType();\r
- ASSERT(IsSampler(type.getBasicType()) || type.getStruct()); // Structures can contain samplers\r
+ ASSERT(IsSampler(type.getBasicType()) || type.isStruct()); // Structures can contain samplers\r
\r
int index = lookup(samplers, sampler);\r
\r
return index;\r
}\r
\r
+ bool OutputASM::isSamplerRegister(TIntermTyped *operand)\r
+ {\r
+ return operand && IsSampler(operand->getBasicType()) && samplerRegister(operand) >= 0;\r
+ }\r
+\r
int OutputASM::lookup(VariableArray &list, TIntermTyped *variable)\r
{\r
for(unsigned int i = 0; i < list.size(); i++)\r
int fieldRegisterIndex = encoder ? shaderObject->activeUniformBlocks[blockId].registerIndex + BlockLayoutEncoder::getBlockRegister(blockInfo) : registerIndex;\r
activeUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(),\r
fieldRegisterIndex, blockId, blockInfo));\r
- if(isSamplerRegister(type))\r
+ if(IsSampler(type.getBasicType()))\r
{\r
for(int i = 0; i < type.totalRegisterCount(); i++)\r
{\r