Commit 0530b456 by Nicolas Capens Committed by Nicolas Capens

Refactor lvalue() to return the root node.

This will enable reusing it to determine the root node of rvalues as well. The only functional change is that struct indexing no longer overrides the register type. This is of no effect here since lvalue intermediates already inherited their type from the root node, but for rvalues the intermediates are considered temporary registers, while instead the root's type should be used. Change-Id: I2dbd1b0f8886c3f111a2ed3ef7fe4e9a5b480085 Reviewed-on: https://swiftshader-review.googlesource.com/13930Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 84249fde
......@@ -614,7 +614,7 @@ namespace glsl
if(left->totalRegisterCount() > 1)
{
sw::Shader::SourceParameter relativeRegister;
argument(relativeRegister, right);
source(relativeRegister, right);
mov->src[0].rel.type = relativeRegister.type;
mov->src[0].rel.index = relativeRegister.index;
......@@ -1887,9 +1887,7 @@ namespace glsl
if(dst)
{
instruction->dst.type = registerType(dst);
instruction->dst.index = registerIndex(dst) + dstIndex;
instruction->dst.mask = writeMask(dst);
destination(instruction->dst, dst, dstIndex);
}
if(src0)
......@@ -1898,11 +1896,11 @@ namespace glsl
instruction->dst.partialPrecision = src && (src->getPrecision() <= EbpLow);
}
argument(instruction->src[0], src0, index0);
argument(instruction->src[1], src1, index1);
argument(instruction->src[2], src2, index2);
argument(instruction->src[3], src3, index3);
argument(instruction->src[4], src4, index4);
source(instruction->src[0], src0, index0);
source(instruction->src[1], src1, index1);
source(instruction->src[2], src2, index2);
source(instruction->src[3], src3, index3);
source(instruction->src[4], src4, index4);
shader->append(instruction);
......@@ -2176,7 +2174,7 @@ namespace glsl
return argumentInfo;
}
void OutputASM::argument(sw::Shader::SourceParameter &parameter, TIntermNode *argument, int index)
void OutputASM::source(sw::Shader::SourceParameter &parameter, TIntermNode *argument, int index)
{
if(argument)
{
......@@ -2286,6 +2284,13 @@ namespace glsl
}
}
void OutputASM::destination(sw::Shader::DestinationParameter &parameter, TIntermTyped *arg, int index)
{
parameter.type = registerType(arg);
parameter.index = registerIndex(arg) + index;
parameter.mask = writeMask(arg);
}
void OutputASM::copy(TIntermTyped *dst, TIntermNode *src, int offset)
{
for(int index = 0; index < dst->totalRegisterCount(); index++)
......@@ -2328,8 +2333,8 @@ namespace glsl
insert->src[0].type = insert->dst.type;
insert->src[0].index = insert->dst.index;
insert->src[0].rel = insert->dst.rel;
argument(insert->src[1], src);
argument(insert->src[2], binary->getRight());
source(insert->src[1], src);
source(insert->src[2], binary->getRight());
shader->append(insert);
}
......@@ -2340,7 +2345,7 @@ namespace glsl
Temporary address(this);
int swizzle = lvalue(mov1->dst, address, dst);
argument(mov1->src[0], src);
source(mov1->src[0], src);
mov1->src[0].swizzle = swizzleSwizzle(mov1->src[0].swizzle, swizzle);
shader->append(mov1);
......@@ -2353,7 +2358,7 @@ namespace glsl
mov->dst.index += offset;
mov->dst.mask = writeMask(dst, offset);
argument(mov->src[0], src, offset);
source(mov->src[0], src, offset);
shader->append(mov);
}
......@@ -2362,6 +2367,20 @@ namespace glsl
int OutputASM::lvalue(sw::Shader::DestinationParameter &dst, Temporary &address, TIntermTyped *node)
{
TIntermTyped *root = nullptr;
unsigned int offset = 0;
unsigned char mask = 0xF;
int swizzle = lvalue(root, offset, dst.rel, mask, address, node);
dst.type = registerType(root);
dst.index = registerIndex(root) + offset;
dst.mask = mask;
return swizzle;
}
int OutputASM::lvalue(TIntermTyped *&root, unsigned int &offset, sw::Shader::Relative &rel, unsigned char &mask, Temporary &address, TIntermTyped *node)
{
TIntermTyped *result = node;
TIntermBinary *binary = node->getAsBinaryNode();
TIntermSymbol *symbol = node->getAsSymbolNode();
......@@ -2371,7 +2390,7 @@ namespace glsl
TIntermTyped *left = binary->getLeft();
TIntermTyped *right = binary->getRight();
int leftSwizzle = lvalue(dst, address, left); // Resolve the l-value of the left side
int leftSwizzle = lvalue(root, offset, rel, mask, address, left); // Resolve the l-value of the left side
switch(binary->getOp())
{
......@@ -2381,22 +2400,22 @@ namespace glsl
if(left->isRegister())
{
int leftMask = dst.mask;
int leftMask = mask;
dst.mask = 1;
while((leftMask & dst.mask) == 0)
mask = 1;
while((leftMask & mask) == 0)
{
dst.mask = dst.mask << 1;
mask = mask << 1;
}
int element = swizzleElement(leftSwizzle, rightIndex);
dst.mask = 1 << element;
mask = 1 << element;
return element;
}
else if(left->isArray() || left->isMatrix())
{
dst.index += rightIndex * result->totalRegisterCount();
offset += rightIndex * result->totalRegisterCount();
return 0xE4;
}
else UNREACHABLE(0);
......@@ -2414,42 +2433,42 @@ namespace glsl
{
int scale = result->totalRegisterCount();
if(dst.rel.type == sw::Shader::PARAMETER_VOID) // Use the index register as the relative address directly
if(rel.type == sw::Shader::PARAMETER_VOID) // Use the index register as the relative address directly
{
if(left->totalRegisterCount() > 1)
{
sw::Shader::SourceParameter relativeRegister;
argument(relativeRegister, right);
source(relativeRegister, right);
dst.rel.index = relativeRegister.index;
dst.rel.type = relativeRegister.type;
dst.rel.scale = scale;
dst.rel.deterministic = !(vertexShader && left->getQualifier() == EvqUniform);
rel.index = relativeRegister.index;
rel.type = relativeRegister.type;
rel.scale = scale;
rel.deterministic = !(vertexShader && left->getQualifier() == EvqUniform);
}
}
else if(dst.rel.index != registerIndex(&address)) // Move the previous index register to the address register
else if(rel.index != registerIndex(&address)) // Move the previous index register to the address register
{
if(scale == 1)
{
Constant oldScale((int)dst.rel.scale);
Constant oldScale((int)rel.scale);
Instruction *mad = emit(sw::Shader::OPCODE_IMAD, &address, &address, &oldScale, right);
mad->src[0].index = dst.rel.index;
mad->src[0].type = dst.rel.type;
mad->src[0].index = rel.index;
mad->src[0].type = rel.type;
}
else
{
Constant oldScale((int)dst.rel.scale);
Constant oldScale((int)rel.scale);
Instruction *mul = emit(sw::Shader::OPCODE_IMUL, &address, &address, &oldScale);
mul->src[0].index = dst.rel.index;
mul->src[0].type = dst.rel.type;
mul->src[0].index = rel.index;
mul->src[0].type = rel.type;
Constant newScale(scale);
emit(sw::Shader::OPCODE_IMAD, &address, right, &newScale, &address);
}
dst.rel.type = sw::Shader::PARAMETER_TEMP;
dst.rel.index = registerIndex(&address);
dst.rel.scale = 1;
rel.type = sw::Shader::PARAMETER_TEMP;
rel.index = registerIndex(&address);
rel.scale = 1;
}
else // Just add the new index to the address register
{
......@@ -2481,9 +2500,8 @@ namespace glsl
fieldOffset += fields[i]->type()->totalRegisterCount();
}
dst.type = registerType(left);
dst.index += fieldOffset;
dst.mask = writeMask(result);
offset += fieldOffset;
mask = writeMask(result);
return 0xE4;
}
......@@ -2492,7 +2510,7 @@ namespace glsl
{
ASSERT(left->isRegister());
int leftMask = dst.mask;
int leftMask = mask;
int swizzle = 0;
int rightMask = 0;
......@@ -2508,7 +2526,7 @@ namespace glsl
swizzle = swizzle | swizzleElement(leftSwizzle, i) << (element * 2);
}
dst.mask = leftMask & rightMask;
mask = leftMask & rightMask;
return swizzle;
}
......@@ -2520,9 +2538,20 @@ namespace glsl
}
else if(symbol)
{
dst.type = registerType(symbol);
dst.index = registerIndex(symbol);
dst.mask = writeMask(symbol);
root = symbol;
offset = 0;
mask = writeMask(symbol);
return 0xE4;
}
else
{
node->traverse(this);
root = node;
offset = 0;
mask = writeMask(node);
return 0xE4;
}
......@@ -2537,10 +2566,10 @@ namespace glsl
}
const TQualifier qualifier = operand->getQualifier();
if((EvqFragColor == qualifier) || (EvqFragData == qualifier))
if((qualifier == EvqFragColor) || (qualifier == EvqFragData))
{
if(((EvqFragData == qualifier) && (EvqFragColor == outputQualifier)) ||
((EvqFragColor == qualifier) && (EvqFragData == outputQualifier)))
if(((qualifier == EvqFragData) && (outputQualifier == EvqFragColor)) ||
((qualifier == EvqFragColor) && (outputQualifier == EvqFragData)))
{
mContext.error(operand->getLine(), "static assignment to both gl_FragData and gl_FragColor", "");
}
......
......@@ -251,14 +251,14 @@ namespace glsl
void emitShader(Scope scope);
// Visit AST nodes and output their code to the body stream
virtual void visitSymbol(TIntermSymbol*);
virtual bool visitBinary(Visit visit, TIntermBinary*);
virtual bool visitUnary(Visit visit, TIntermUnary*);
virtual bool visitSelection(Visit visit, TIntermSelection*);
virtual bool visitAggregate(Visit visit, TIntermAggregate*);
virtual bool visitLoop(Visit visit, TIntermLoop*);
virtual bool visitBranch(Visit visit, TIntermBranch*);
virtual bool visitSwitch(Visit, TIntermSwitch*);
void visitSymbol(TIntermSymbol*) override;
bool visitBinary(Visit visit, TIntermBinary*) override;
bool visitUnary(Visit visit, TIntermUnary*) override;
bool visitSelection(Visit visit, TIntermSelection*) override;
bool visitAggregate(Visit visit, TIntermAggregate*) override;
bool visitLoop(Visit visit, TIntermLoop*) override;
bool visitBranch(Visit visit, TIntermBranch*) override;
bool visitSwitch(Visit, TIntermSwitch*) override;
sw::Shader::Opcode getOpcode(sw::Shader::Opcode op, TIntermTyped *in) const;
Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0, TIntermNode *src3 = 0, TIntermNode *src4 = 0);
......@@ -270,10 +270,12 @@ namespace glsl
void emitAssign(sw::Shader::Opcode op, TIntermTyped *result, TIntermTyped *lhs, TIntermTyped *src0, TIntermTyped *src1 = 0);
void emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index = 0);
void emitDeterminant(TIntermTyped *result, TIntermTyped *arg, int size, int col = -1, int row = -1, int outCol = 0, int outRow = 0);
void argument(sw::Shader::SourceParameter &parameter, TIntermNode *argument, int index = 0);
void source(sw::Shader::SourceParameter &parameter, TIntermNode *argument, int index = 0);
void destination(sw::Shader::DestinationParameter &parameter, TIntermTyped *argument, int index = 0);
void copy(TIntermTyped *dst, TIntermNode *src, int offset = 0);
void assignLvalue(TIntermTyped *dst, TIntermTyped *src);
int lvalue(sw::Shader::DestinationParameter &dst, Temporary &address, TIntermTyped *node);
int lvalue(TIntermTyped *&root, unsigned int &offset, sw::Shader::Relative &rel, unsigned char &mask, Temporary &address, TIntermTyped *node);
sw::Shader::ParameterType registerType(TIntermTyped *operand);
bool hasFlatQualifier(TIntermTyped *operand);
unsigned int registerIndex(TIntermTyped *operand);
......
......@@ -396,6 +396,15 @@ namespace sw
ANALYSIS_LEAVE = 0x00000008,
};
struct Relative
{
ParameterType type : 8;
unsigned int index;
unsigned int swizzle : 8;
unsigned int scale;
bool deterministic; // Equal accross shader instances run in lockstep (e.g. unrollable loop couters)
};
struct Parameter
{
union
......@@ -404,14 +413,7 @@ namespace sw
{
unsigned int index; // For registers types
struct
{
ParameterType type : 8;
unsigned int index;
unsigned int swizzle : 8;
unsigned int scale;
bool deterministic; // Equal accross shader instances run in lockstep (e.g. unrollable loop couters)
} rel;
Relative rel;
};
float value[4]; // For float constants
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment