#include <GLES2/gl2ext.h>
#include <GLES3/gl3.h>
+#include <stdlib.h>
+
namespace glsl
{
// Integer to TString conversion
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
{
{
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);
}
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;
}
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;
}
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);
+ }
}
}
}
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++)
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);
{
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;
dst.type = registerType(left);
dst.index += fieldOffset;
- dst.mask = writeMask(right);
+ dst.mask = writeMask(result);
return 0xE4;
}
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;
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);
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
{
{
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));
}
}
}
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
{
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);
}
}
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)
{
}
UNREACHABLE(0);
- return -1; // Not a sampler register
+ return -1; // Not a (uniform) sampler register
}
int OutputASM::samplerRegister(TIntermSymbol *sampler)
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();
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;