OSDN Git Service

gl_VertexID implementation
[android-x86/external-swiftshader.git] / src / Shader / Shader.cpp
index 5cc9242..ff1482e 100644 (file)
@@ -1,13 +1,16 @@
-// SwiftShader Software Renderer
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
 //
-// Copyright(c) 2005-2013 TransGaming Inc.
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
 //
-// All rights reserved. No part of this software may be copied, distributed, transmitted,
-// transcribed, stored in a retrieval system, translated into any human or computer
-// language by any means, or disclosed to third parties without the explicit written
-// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
-// or implied, including but not limited to any patent rights, are granted to you.
+//    http://www.apache.org/licenses/LICENSE-2.0
 //
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 #include "Shader.hpp"
 
@@ -61,7 +64,7 @@ namespace sw
                }
        }
 
-       Shader::Opcode Shader::OPCODE_NRM(int i)        
+       Shader::Opcode Shader::OPCODE_NRM(int i)
        {
                switch(i)
                {
@@ -116,7 +119,7 @@ namespace sw
                predicate = false;
                predicateNot = false;
                predicateSwizzle = 0xE4;
-               
+
                coissue = false;
                samplerType = SAMPLER_UNKNOWN;
                usage = USAGE_POSITION;
@@ -159,7 +162,7 @@ namespace sw
                                        token++;
                                        size--;
                                }
-                               
+
                                token++;
                                size--;
                        }
@@ -170,7 +173,7 @@ namespace sw
 
                                predicateNot = (Modifier)((*token & 0x0F000000) >> 24) == MODIFIER_NOT;
                                predicateSwizzle = (unsigned char)((*token & 0x00FF0000) >> 16);
-                               
+
                                token++;
                                size--;
                        }
@@ -198,11 +201,11 @@ namespace sw
        std::string Shader::Instruction::string(ShaderType shaderType, unsigned short version) const
        {
                std::string instructionString;
-               
+
                if(opcode != OPCODE_DCL)
                {
                        instructionString += coissue ? "+ " : "";
-                       
+
                        if(predicate)
                        {
                                instructionString += predicateNot ? "(!p0" : "(p0";
@@ -216,7 +219,7 @@ namespace sw
                        {
                                instructionString += " " + dst.string(shaderType, version) +
                                                           dst.relativeString() +
-                                                          dst.maskString(); 
+                                                          dst.maskString();
                        }
 
                        for(int i = 0; i < 4; i++)
@@ -226,8 +229,8 @@ namespace sw
                                        instructionString += (dst.type != PARAMETER_VOID || i > 0) ? ", " : " ";
                                        instructionString += src[i].preModifierString() +
                                                                                 src[i].string(shaderType, version) +
-                                                                                src[i].relativeString() + 
-                                                                                src[i].postModifierString() + 
+                                                                                src[i].relativeString() +
+                                                                                src[i].postModifierString() +
                                                                                 src[i].swizzleString();
                                }
                        }
@@ -348,10 +351,10 @@ namespace sw
                {
                case 0:         return "";
                case 1:         return "_x2";
-               case 2:         return "_x4"; 
+               case 2:         return "_x4";
                case 3:         return "_x8";
                case -1:        return "_d2";
-               case -2:        return "_d4"; 
+               case -2:        return "_d4";
                case -3:        return "_d8";
                default:
                        return "";
@@ -627,7 +630,7 @@ namespace sw
                src[i].rel.type = PARAMETER_VOID;
                src[i].rel.swizzle = 0x00;
                src[i].rel.scale = 1;
-               
+
                switch(opcode)
                {
                case OPCODE_DEF:
@@ -821,7 +824,9 @@ namespace sw
                case OPCODE_POWX:                       return "powx";
                case OPCODE_CRS:                        return "crs";
                case OPCODE_SGN:                        return "sgn";
+               case OPCODE_ISGN:                       return "isgn";
                case OPCODE_ABS:                        return "abs";
+               case OPCODE_IABS:                       return "iabs";
                case OPCODE_NRM2:                       return "nrm2";
                case OPCODE_NRM3:                       return "nrm3";
                case OPCODE_NRM4:                       return "nrm4";
@@ -966,6 +971,8 @@ namespace sw
                case OPCODE_LEAVE:          return "leave";
                case OPCODE_CONTINUE:       return "continue";
                case OPCODE_TEST:           return "test";
+               case OPCODE_SWITCH:         return "switch";
+               case OPCODE_ENDSWITCH:      return "endswitch";
                default:
                        ASSERT(false);
                }
@@ -1011,7 +1018,7 @@ namespace sw
                else if(type != PARAMETER_RASTOUT && !(type == PARAMETER_ADDR && shaderType == SHADER_VERTEX) && type != PARAMETER_LOOP && type != PARAMETER_PREDICATE && type != PARAMETER_MISCTYPE)
                {
                        buffer << index;
-                       
+
                        return typeString(shaderType, version) + buffer.str();
                }
                else
@@ -1052,9 +1059,14 @@ namespace sw
                case PARAMETER_LOOP:                    return "aL";
        //      case PARAMETER_TEMPFLOAT16:             return "";
                case PARAMETER_MISCTYPE:
-                       if(index == 0)                          return "vPos";
-                       else if(index == 1)                     return "vFace";
-                       else                                            ASSERT(false);
+                       switch(index)
+                       {
+                       case VPosIndex:                         return "vPos";
+                       case VFaceIndex:                        return "vFace";
+                       case InstanceIDIndex:           return "iID";
+                       case VertexIDIndex:                     return "vID";
+                       default: ASSERT(false);
+                       }
                case PARAMETER_LABEL:                   return "l";
                case PARAMETER_PREDICATE:               return "p0";
                case PARAMETER_FLOAT4LITERAL:   return "";
@@ -1072,7 +1084,7 @@ namespace sw
        {
                return opcode == OPCODE_IF || opcode == OPCODE_IFC;
        }
-       
+
        bool Shader::Instruction::isCall() const
        {
                return opcode == OPCODE_CALL || opcode == OPCODE_CALLNZ;
@@ -1153,7 +1165,7 @@ namespace sw
                        token += 1 + tokenCount;
                }
        }
-       
+
        int Shader::size(unsigned long opcode) const
        {
                return size(opcode, version);
@@ -1166,7 +1178,7 @@ namespace sw
                        ASSERT(false);
                }
 
-               static const char size[] =
+               static const signed char size[] =
                {
                        0,   // NOP = 0
                        2,   // MOV
@@ -1450,7 +1462,7 @@ namespace sw
                usedSamplers |= 1 << i;
        }
 
-       const Shader::Instruction *Shader::getInstruction(unsigned int i) const
+       const Shader::Instruction *Shader::getInstruction(size_t i) const
        {
                ASSERT(i < instruction.size());
 
@@ -1626,7 +1638,7 @@ namespace sw
                                {
                                        containsLeave = true;
                                }
-                               
+
                                if(instruction[i]->isBreak())
                                {
                                        containsBreak = true;
@@ -1650,6 +1662,7 @@ namespace sw
                int breakDepth = 0;
                int continueDepth = 0;
                bool leaveReturn = false;
+               unsigned int functionBegin = 0;
 
                for(unsigned int i = 0; i < instruction.size(); i++)
                {
@@ -1681,11 +1694,11 @@ namespace sw
 
                        if(breakDepth > 0)
                        {
-                               if(instruction[i]->isLoop())   // Nested loop, don't make the end of it disable the break execution mask
+                               if(instruction[i]->isLoop() || instruction[i]->opcode == OPCODE_SWITCH)   // Nested loop or switch, don't make the end of it disable the break execution mask
                                {
                                        breakDepth++;
                                }
-                               else if(instruction[i]->isEndLoop())
+                               else if(instruction[i]->isEndLoop() || instruction[i]->opcode == OPCODE_ENDSWITCH)
                                {
                                        breakDepth--;
                                }
@@ -1706,11 +1719,11 @@ namespace sw
 
                        if(continueDepth > 0)
                        {
-                               if(instruction[i]->isLoop())   // Nested loop, don't make the end of it disable the break execution mask
+                               if(instruction[i]->isLoop() || instruction[i]->opcode == OPCODE_SWITCH)   // Nested loop or switch, don't make the end of it disable the break execution mask
                                {
                                        continueDepth++;
                                }
-                               else if(instruction[i]->isEndLoop())
+                               else if(instruction[i]->isEndLoop() || instruction[i]->opcode == OPCODE_ENDSWITCH)
                                {
                                        continueDepth--;
                                }
@@ -1727,11 +1740,29 @@ namespace sw
                        if(instruction[i]->opcode == OPCODE_LEAVE)
                        {
                                leaveReturn = true;
+
+                               // Mark loop body instructions prior to the return statement
+                               for(unsigned int l = functionBegin; l < i; l++)
+                               {
+                                       if(instruction[l]->isLoop())
+                                       {
+                                               for(unsigned int r = l + 1; r < i; r++)
+                                               {
+                                                       instruction[r]->analysisLeave = true;
+                                               }
+
+                                               break;
+                                       }
+                               }
                        }
                        else if(instruction[i]->opcode == OPCODE_RET)   // End of the function
                        {
                                leaveReturn = false;
                        }
+                       else if(instruction[i]->opcode == OPCODE_LABEL)
+                       {
+                               functionBegin = i;
+                       }
 
                        if(leaveReturn)
                        {