OSDN Git Service

Fix indexing of samplers in structures.
authorNicolas Capens <capn@google.com>
Tue, 26 Apr 2016 05:10:24 +0000 (01:10 -0400)
committerNicolas Capens <capn@google.com>
Thu, 28 Apr 2016 14:27:05 +0000 (14:27 +0000)
Change-Id: I0bde678865902d549d4260bf8f6c1a368a46f4d4
Reviewed-on: https://swiftshader-review.googlesource.com/5191
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
src/OpenGL/compiler/OutputASM.cpp
src/OpenGL/compiler/OutputASM.h

index cc4bd45..88a8780 100644 (file)
@@ -495,6 +495,11 @@ namespace glsl
                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
@@ -1758,21 +1763,6 @@ namespace glsl
                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
@@ -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,\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
@@ -2172,39 +2157,7 @@ namespace glsl
                        {\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
@@ -2884,30 +2837,57 @@ namespace glsl
 \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
@@ -2925,6 +2905,11 @@ namespace glsl
                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
@@ -3110,7 +3095,7 @@ namespace glsl
                        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
index 2329cf5..854c262 100644 (file)
@@ -286,6 +286,7 @@ namespace glsl
                int fragmentOutputRegister(TIntermTyped *fragmentOutput);\r
                int samplerRegister(TIntermTyped *sampler);\r
                int samplerRegister(TIntermSymbol *sampler);\r
+               bool isSamplerRegister(TIntermTyped *operand);\r
 \r
                typedef std::vector<TIntermTyped*> VariableArray;\r
 \r
@@ -302,8 +303,6 @@ namespace glsl
                static int dim(TIntermNode *v);\r
                static int dim2(TIntermNode *m);\r
                static unsigned int loopCount(TIntermLoop *node);\r
-               static bool isSamplerRegister(TIntermTyped *operand);\r
-               static bool isSamplerRegister(const TType &type);\r
 \r
                Shader *const shaderObject;\r
                sw::Shader *shader;\r