-// 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"
}
}
- Shader::Opcode Shader::OPCODE_NRM(int i)
+ Shader::Opcode Shader::OPCODE_NRM(int i)
{
switch(i)
{
predicate = false;
predicateNot = false;
predicateSwizzle = 0xE4;
-
+
coissue = false;
samplerType = SAMPLER_UNKNOWN;
usage = USAGE_POSITION;
token++;
size--;
}
-
+
token++;
size--;
}
predicateNot = (Modifier)((*token & 0x0F000000) >> 24) == MODIFIER_NOT;
predicateSwizzle = (unsigned char)((*token & 0x00FF0000) >> 16);
-
+
token++;
size--;
}
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";
{
instructionString += " " + dst.string(shaderType, version) +
dst.relativeString() +
- dst.maskString();
+ dst.maskString();
}
for(int i = 0; i < 4; i++)
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();
}
}
{
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 "";
src[i].rel.type = PARAMETER_VOID;
src[i].rel.swizzle = 0x00;
src[i].rel.scale = 1;
-
+
switch(opcode)
{
case OPCODE_DEF:
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";
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);
}
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
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 "";
{
return opcode == OPCODE_IF || opcode == OPCODE_IFC;
}
-
+
bool Shader::Instruction::isCall() const
{
return opcode == OPCODE_CALL || opcode == OPCODE_CALLNZ;
token += 1 + tokenCount;
}
}
-
+
int Shader::size(unsigned long opcode) const
{
return size(opcode, version);
ASSERT(false);
}
- static const char size[] =
+ static const signed char size[] =
{
0, // NOP = 0
2, // MOV
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());
{
containsLeave = true;
}
-
+
if(instruction[i]->isBreak())
{
containsBreak = true;
int breakDepth = 0;
int continueDepth = 0;
bool leaveReturn = false;
+ unsigned int functionBegin = 0;
for(unsigned int i = 0; i < instruction.size(); i++)
{
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--;
}
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--;
}
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)
{