OSDN Git Service

gl_VertexID implementation
[android-x86/external-swiftshader.git] / src / OpenGL / compiler / OutputASM.cpp
index 9c467ab..2c8222e 100644 (file)
@@ -24,6 +24,8 @@
 #include <GLES2/gl2ext.h>
 #include <GLES3/gl3.h>
 
+#include <stdlib.h>
+
 namespace glsl
 {
        // Integer to TString conversion
@@ -1223,7 +1225,7 @@ namespace glsl
                                                if(argument->getQualifier() == EvqOut ||
                                                   argument->getQualifier() == EvqInOut)
                                                {
-                                                       copy(out, argument);
+                                                       assignLvalue(out, argument);
                                                }
                                        }
                                }
@@ -1236,25 +1238,12 @@ namespace glsl
 
                                        if(textureFunction.proj)
                                        {
-                                               TIntermConstantUnion* constant = arg[1]->getAsConstantUnion();
-                                               if(constant)
-                                               {
-                                                       float projFactor = 1.0f / constant->getFConst(t->getNominalSize() - 1);
-                                                       Constant projCoord(constant->getFConst(0) * projFactor,
-                                                                          constant->getFConst(1) * projFactor,
-                                                                          constant->getFConst(2) * projFactor,
-                                                                          0.0f);
-                                                       emit(sw::Shader::OPCODE_MOV, &coord, &projCoord);
-                                               }
-                                               else
-                                               {
-                                                       Instruction *rcp = emit(sw::Shader::OPCODE_RCPX, &coord, arg[1]);
-                                                       rcp->src[0].swizzle = 0x55 * (t->getNominalSize() - 1);
-                                                       rcp->dst.mask = 0x7;
+                                               Instruction *rcp = emit(sw::Shader::OPCODE_RCPX, &coord, arg[1]);
+                                               rcp->src[0].swizzle = 0x55 * (t->getNominalSize() - 1);
+                                               rcp->dst.mask = 0x7;
 
-                                                       Instruction *mul = emit(sw::Shader::OPCODE_MUL, &coord, arg[1], &coord);
-                                                       mul->dst.mask = 0x7;
-                                               }
+                                               Instruction *mul = emit(sw::Shader::OPCODE_MUL, &coord, arg[1], &coord);
+                                               mul->dst.mask = 0x7;
                                        }
                                        else
                                        {
@@ -1297,10 +1286,13 @@ namespace glsl
                                                {
                                                        if(argumentCount == 3 || (textureFunction.offset && argumentCount == 4))
                                                        {
+                                                               Instruction *lod = emit(sw::Shader::OPCODE_MOV, &coord, arg[2]);
+                                                               lod->dst.mask = 0x8;
+
                                                                TIntermNode *offset = textureFunction.offset ? arg[3] : nullptr;
 
                                                                emit(textureFunction.offset ? sw::Shader::OPCODE_TEXELFETCHOFFSET : sw::Shader::OPCODE_TEXELFETCH,
-                                                                    result, arg[1], arg[0], arg[2], offset);
+                                                                    result, &coord, arg[0], offset);
                                                        }
                                                        else UNREACHABLE(argumentCount);
                                                }
@@ -1347,17 +1339,20 @@ namespace glsl
                        if(visit == PostVisit)
                        {
                                int component = 0;
-
+                               int arrayMaxIndex = result->isArray() ? result->getArraySize() - 1 : 0;
+                               int arrayComponents = result->getType().getElementSize();
                                for(size_t i = 0; i < argumentCount; i++)
                                {
                                        TIntermTyped *argi = arg[i]->getAsTyped();
                                        int size = argi->getNominalSize();
+                                       int arrayIndex = std::min(component / arrayComponents, arrayMaxIndex);
+                                       int swizzle = component - (arrayIndex * arrayComponents);
 
                                        if(!argi->isMatrix())
                                        {
-                                               Instruction *mov = emitCast(result, argi);
-                                               mov->dst.mask = (0xF << component) & 0xF;
-                                               mov->src[0].swizzle = readSwizzle(argi, size) << (component * 2);
+                                               Instruction *mov = emitCast(result, arrayIndex, argi, 0);
+                                               mov->dst.mask = (0xF << swizzle) & 0xF;
+                                               mov->src[0].swizzle = readSwizzle(argi, size) << (swizzle * 2);
 
                                                component += size;
                                        }
@@ -1367,9 +1362,9 @@ namespace glsl
 
                                                while(component < resultType.getNominalSize())
                                                {
-                                                       Instruction *mov = emitCast(result, 0, argi, column);
-                                                       mov->dst.mask = (0xF << component) & 0xF;
-                                                       mov->src[0].swizzle = readSwizzle(argi, size) << (component * 2);
+                                                       Instruction *mov = emitCast(result, arrayIndex, argi, column);
+                                                       mov->dst.mask = (0xF << swizzle) & 0xF;
+                                                       mov->src[0].swizzle = readSwizzle(argi, size) << (swizzle * 2);
 
                                                        column++;
                                                        component += size;
@@ -1405,22 +1400,28 @@ namespace glsl
                                }
                                else if(arg0->isMatrix())
                                {
-                                       const int inCols = arg0->getNominalSize();
-                                       const int inRows = arg0->getSecondarySize();
+                                       int arraySize = result->isArray() ? result->getArraySize() : 1;
 
-                                       for(int i = 0; i < outCols; i++)
+                                       for(int n = 0; n < arraySize; n++)
                                        {
-                                               if(i >= inCols || outRows > inRows)
-                                               {
-                                                       // Initialize to identity matrix
-                                                       Constant col((i == 0 ? 1.0f : 0.0f), (i == 1 ? 1.0f : 0.0f), (i == 2 ? 1.0f : 0.0f), (i == 3 ? 1.0f : 0.0f));
-                                                       emitCast(result, i, &col, 0);
-                                               }
+                                               TIntermTyped *argi = arg[n]->getAsTyped();
+                                               const int inCols = argi->getNominalSize();
+                                               const int inRows = argi->getSecondarySize();
 
-                                               if(i < inCols)
+                                               for(int i = 0; i < outCols; i++)
                                                {
-                                                       Instruction *mov = emitCast(result, i, arg0, i);
-                                                       mov->dst.mask = 0xF >> (4 - inRows);
+                                                       if(i >= inCols || outRows > inRows)
+                                                       {
+                                                               // Initialize to identity matrix
+                                                               Constant col((i == 0 ? 1.0f : 0.0f), (i == 1 ? 1.0f : 0.0f), (i == 2 ? 1.0f : 0.0f), (i == 3 ? 1.0f : 0.0f));
+                                                               emitCast(result, i + n * outCols, &col, 0);
+                                                       }
+
+                                                       if(i < inCols)
+                                                       {
+                                                               Instruction *mov = emitCast(result, i + n * outCols, argi, i);
+                                                               mov->dst.mask = 0xF >> (4 - inRows);
+                                                       }
                                                }
                                        }
                                }
@@ -1509,8 +1510,8 @@ namespace glsl
                        if(visit == PostVisit)
                        {
                                TIntermTyped *arg0 = arg[0]->getAsTyped();
-                               TIntermTyped *arg1 = arg[1]->getAsTyped();
-                               ASSERT((arg0->getNominalSize() == arg1->getNominalSize()) && (arg0->getSecondarySize() == arg1->getSecondarySize()));
+                               ASSERT((arg0->getNominalSize() == arg[1]->getAsTyped()->getNominalSize()) &&
+                                      (arg0->getSecondarySize() == arg[1]->getAsTyped()->getSecondarySize()));
 
                                int size = arg0->getNominalSize();
                                for(int i = 0; i < size; i++)
@@ -2170,8 +2171,7 @@ namespace glsl
 
                                if(memberType.getBasicType() == EbtBool)
                                {
-                                       int arraySize = (memberType.isArray() ? memberType.getArraySize() : 1);
-                                       ASSERT(argumentInfo.clampedIndex < arraySize);
+                                       ASSERT(argumentInfo.clampedIndex < (memberType.isArray() ? memberType.getArraySize() : 1)); // index < arraySize
 
                                        // Convert the packed bool, which is currently an int, to a true bool
                                        Instruction *instruction = new Instruction(sw::Shader::OPCODE_I2B);
@@ -2190,9 +2190,8 @@ namespace glsl
                                {
                                        int numCols = memberType.getNominalSize();
                                        int numRows = memberType.getSecondarySize();
-                                       int arraySize = (memberType.isArray() ? memberType.getArraySize() : 1);
 
-                                       ASSERT(argumentInfo.clampedIndex < (numCols * arraySize));
+                                       ASSERT(argumentInfo.clampedIndex < (numCols * (memberType.isArray() ? memberType.getArraySize() : 1))); // index < cols * arraySize
 
                                        unsigned int dstIndex = registerIndex(&unpackedUniform);
                                        unsigned int srcSwizzle = (argumentInfo.clampedIndex % numCols) * 0x55;
@@ -2458,7 +2457,7 @@ namespace glsl
 
                                        dst.type = registerType(left);
                                        dst.index += fieldOffset;
-                                       dst.mask = writeMask(right);
+                                       dst.mask = writeMask(result);
 
                                        return 0xE4;
                                }
@@ -2555,6 +2554,7 @@ namespace glsl
                case EvqPosition:            return sw::Shader::PARAMETER_OUTPUT;
                case EvqPointSize:           return sw::Shader::PARAMETER_OUTPUT;
                case EvqInstanceID:          return sw::Shader::PARAMETER_MISCTYPE;
+               case EvqVertexID:            return sw::Shader::PARAMETER_MISCTYPE;
                case EvqFragCoord:           return sw::Shader::PARAMETER_MISCTYPE;
                case EvqFrontFacing:         return sw::Shader::PARAMETER_MISCTYPE;
                case EvqPointCoord:          return sw::Shader::PARAMETER_INPUT;
@@ -2607,9 +2607,10 @@ namespace glsl
                case EvqConstReadOnly:       return temporaryRegister(operand);
                case EvqPosition:            return varyingRegister(operand);
                case EvqPointSize:           return varyingRegister(operand);
-               case EvqInstanceID:          vertexShader->instanceIdDeclared = true; return 0;
-               case EvqFragCoord:           pixelShader->vPosDeclared = true;  return 0;
-               case EvqFrontFacing:         pixelShader->vFaceDeclared = true; return 1;
+               case EvqInstanceID:          vertexShader->declareInstanceId(); return sw::Shader::InstanceIDIndex;
+               case EvqVertexID:            vertexShader->declareVertexId(); return sw::Shader::VertexIDIndex;
+               case EvqFragCoord:           pixelShader->declareVPos();  return sw::Shader::VPosIndex;
+               case EvqFrontFacing:         pixelShader->declareVFace(); return sw::Shader::VFaceIndex;
                case EvqPointCoord:          return varyingRegister(operand);
                case EvqFragColor:           return 0;
                case EvqFragData:            return fragmentOutputRegister(operand);
@@ -2774,10 +2775,7 @@ namespace glsl
                                if(varying->getQualifier() == EvqPointCoord)
                                {
                                        ASSERT(varying->isRegister());
-                                       if(componentCount >= 1) pixelShader->semantic[var][0] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var);
-                                       if(componentCount >= 2) pixelShader->semantic[var][1] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var);
-                                       if(componentCount >= 3) pixelShader->semantic[var][2] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var);
-                                       if(componentCount >= 4) pixelShader->semantic[var][3] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var);
+                                       pixelShader->setInput(var, componentCount, sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var));
                                }
                                else
                                {
@@ -2785,10 +2783,7 @@ namespace glsl
                                        {
                                                bool flat = hasFlatQualifier(varying);
 
-                                               if(componentCount >= 1) pixelShader->semantic[var + i][0] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i, flat);
-                                               if(componentCount >= 2) pixelShader->semantic[var + i][1] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i, flat);
-                                               if(componentCount >= 3) pixelShader->semantic[var + i][2] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i, flat);
-                                               if(componentCount >= 4) pixelShader->semantic[var + i][3] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i, flat);
+                                               pixelShader->setInput(var + i, componentCount, sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i, flat));
                                        }
                                }
                        }
@@ -2803,20 +2798,12 @@ namespace glsl
                                if(varying->getQualifier() == EvqPosition)
                                {
                                        ASSERT(varying->isRegister());
-                                       vertexShader->output[var][0] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0);
-                                       vertexShader->output[var][1] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0);
-                                       vertexShader->output[var][2] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0);
-                                       vertexShader->output[var][3] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0);
-                                       vertexShader->positionRegister = var;
+                                       vertexShader->setPositionRegister(var);
                                }
                                else if(varying->getQualifier() == EvqPointSize)
                                {
                                        ASSERT(varying->isRegister());
-                                       vertexShader->output[var][0] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0);
-                                       vertexShader->output[var][1] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0);
-                                       vertexShader->output[var][2] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0);
-                                       vertexShader->output[var][3] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0);
-                                       vertexShader->pointSizeRegister = var;
+                                       vertexShader->setPointSizeRegister(var);
                                }
                                else
                                {
@@ -2914,12 +2901,25 @@ namespace glsl
                                index = allocate(attributes, attribute);
                                const TType &type = attribute->getType();
                                int registerCount = attribute->totalRegisterCount();
+                               sw::VertexShader::AttribType attribType = sw::VertexShader::ATTRIBTYPE_FLOAT;
+                               switch(type.getBasicType())
+                               {
+                               case EbtInt:
+                                       attribType = sw::VertexShader::ATTRIBTYPE_INT;
+                                       break;
+                               case EbtUInt:
+                                       attribType = sw::VertexShader::ATTRIBTYPE_UINT;
+                                       break;
+                               case EbtFloat:
+                               default:
+                                       break;
+                               }
 
                                if(vertexShader && (index + registerCount) <= sw::MAX_VERTEX_INPUTS)
                                {
                                        for(int i = 0; i < registerCount; i++)
                                        {
-                                               vertexShader->input[index + i] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, index + i);
+                                               vertexShader->setInput(index + i, sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, index + i, false), attribType);
                                        }
                                }
 
@@ -2946,9 +2946,19 @@ namespace glsl
                TIntermSymbol *symbol = sampler->getAsSymbolNode();
                TIntermBinary *binary = sampler->getAsBinaryNode();
 
-               if(symbol && type.getQualifier() == EvqUniform)
+               if(symbol)
                {
-                       return samplerRegister(symbol);
+                       switch(type.getQualifier())
+                       {
+                       case EvqUniform:
+                               return samplerRegister(symbol);
+                       case EvqIn:
+                       case EvqConstReadOnly:
+                               // Function arguments are not (uniform) sampler registers
+                               return -1;
+                       default:
+                               UNREACHABLE(type.getQualifier());
+                       }
                }
                else if(binary)
                {
@@ -2994,7 +3004,7 @@ namespace glsl
                }
 
                UNREACHABLE(0);
-               return -1;   // Not a sampler register
+               return -1;   // Not a (uniform) sampler register
        }
 
        int OutputASM::samplerRegister(TIntermSymbol *sampler)
@@ -3509,11 +3519,11 @@ namespace glsl
                                TIntermSequence &sequence = init->getSequence();
                                TIntermTyped *variable = sequence[0]->getAsTyped();
 
-                               if(variable && variable->getQualifier() == EvqTemporary)
+                               if(variable && variable->getQualifier() == EvqTemporary && variable->getBasicType() == EbtInt)
                                {
                                        TIntermBinary *assign = variable->getAsBinaryNode();
 
-                                       if(assign->getOp() == EOpInitialize)
+                                       if(assign && assign->getOp() == EOpInitialize)
                                        {
                                                TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
                                                TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
@@ -3600,14 +3610,32 @@ namespace glsl
                                comparator = EOpLessThan;
                                limit += 1;
                        }
+                       else if(comparator == EOpGreaterThanEqual)
+                       {
+                               comparator = EOpLessThan;
+                               limit -= 1;
+                               std::swap(initial, limit);
+                               increment = -increment;
+                       }
+                       else if(comparator == EOpGreaterThan)
+                       {
+                               comparator = EOpLessThan;
+                               std::swap(initial, limit);
+                               increment = -increment;
+                       }
 
                        if(comparator == EOpLessThan)
                        {
-                               int iterations = (limit - initial) / increment;
+                               if(!(initial < limit))   // Never loops
+                               {
+                                       return 0;
+                               }
+
+                               int iterations = (limit - initial + abs(increment) - 1) / increment;   // Ceiling division
 
-                               if(iterations <= 0)
+                               if(iterations < 0)
                                {
-                                       iterations = 0;
+                                       return ~0u;
                                }
 
                                return iterations;