Commit 6e8ec338 by Nicolas Capens Committed by Nicolas Capens

Fix deterministic loops within conditional blocks, again.

Deterministic loops use the first scalar of the SIMD register used as the loop index, for addressing arrays. This means that operations on the index register should not be masked (i.e. it should be treated as a scalar). Previously we were still masking it based on conditional statements, and we didn't disable the masking altogether for the loop initialization and initial test. A new shader assembly instruction 'SCALAR' was added for doing this. Previously this was conflated with the 'TEST' instruction, which should independently disable/restore the 'continue' mask. Bug swiftshader:93 Bug b/118009174 Change-Id: I4add1a6d74231f463217e57adfabdc81faf489ae Reviewed-on: https://swiftshader-review.googlesource.com/c/22348Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com>
parent dc2966a1
...@@ -1859,6 +1859,11 @@ namespace glsl ...@@ -1859,6 +1859,11 @@ namespace glsl
if(loop.isDeterministic()) if(loop.isDeterministic())
{ {
deterministicVariables.insert(loop.index->getId()); deterministicVariables.insert(loop.index->getId());
if(!unroll)
{
emit(sw::Shader::OPCODE_SCALAR); // Unrolled loops don't have an ENDWHILE to disable scalar mode.
}
} }
if(node->getType() == ELoopDoWhile) if(node->getType() == ELoopDoWhile)
...@@ -1926,6 +1931,11 @@ namespace glsl ...@@ -1926,6 +1931,11 @@ namespace glsl
emit(sw::Shader::OPCODE_TEST); emit(sw::Shader::OPCODE_TEST);
if(loop.isDeterministic())
{
emit(sw::Shader::OPCODE_SCALAR);
}
if(expression) if(expression)
{ {
expression->traverse(this); expression->traverse(this);
......
...@@ -310,6 +310,7 @@ namespace sw ...@@ -310,6 +310,7 @@ namespace sw
case Shader::OPCODE_BREAKP: BREAKP(src0); break; case Shader::OPCODE_BREAKP: BREAKP(src0); break;
case Shader::OPCODE_CONTINUE: CONTINUE(); break; case Shader::OPCODE_CONTINUE: CONTINUE(); break;
case Shader::OPCODE_TEST: TEST(); break; case Shader::OPCODE_TEST: TEST(); break;
case Shader::OPCODE_SCALAR: SCALAR(); break;
case Shader::OPCODE_CALL: CALL(dst.label, dst.callSite); break; case Shader::OPCODE_CALL: CALL(dst.label, dst.callSite); break;
case Shader::OPCODE_CALLNZ: CALLNZ(dst.label, dst.callSite, src0); break; case Shader::OPCODE_CALLNZ: CALLNZ(dst.label, dst.callSite, src0); break;
case Shader::OPCODE_ELSE: ELSE(); break; case Shader::OPCODE_ELSE: ELSE(); break;
...@@ -832,6 +833,11 @@ namespace sw ...@@ -832,6 +833,11 @@ namespace sw
Int4 PixelProgram::enableMask(const Shader::Instruction *instruction) Int4 PixelProgram::enableMask(const Shader::Instruction *instruction)
{ {
if(scalar)
{
return Int4(0xFFFFFFFF);
}
Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF); Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
if(shader->containsBreakInstruction() && instruction->analysisBreak) if(shader->containsBreakInstruction() && instruction->analysisBreak)
...@@ -1396,6 +1402,11 @@ namespace sw ...@@ -1396,6 +1402,11 @@ namespace sw
restoreContinue.pop_back(); restoreContinue.pop_back();
} }
void PixelProgram::SCALAR()
{
scalar = true;
}
void PixelProgram::CALL(int labelIndex, int callSiteIndex) void PixelProgram::CALL(int labelIndex, int callSiteIndex)
{ {
if(!labelBlock[labelIndex]) if(!labelBlock[labelIndex])
...@@ -1572,6 +1583,7 @@ namespace sw ...@@ -1572,6 +1583,7 @@ namespace sw
Nucleus::setInsertBlock(endBlock); Nucleus::setInsertBlock(endBlock);
enableIndex--; enableIndex--;
scalar = false;
} }
void PixelProgram::ENDSWITCH() void PixelProgram::ENDSWITCH()
...@@ -1777,6 +1789,7 @@ namespace sw ...@@ -1777,6 +1789,7 @@ namespace sw
Nucleus::setInsertBlock(loopBlock); Nucleus::setInsertBlock(loopBlock);
loopRepDepth++; loopRepDepth++;
scalar = false;
} }
void PixelProgram::SWITCH() void PixelProgram::SWITCH()
......
...@@ -24,14 +24,14 @@ namespace sw ...@@ -24,14 +24,14 @@ namespace sw
{ {
public: public:
PixelProgram(const PixelProcessor::State &state, const PixelShader *shader) : PixelProgram(const PixelProcessor::State &state, const PixelShader *shader) :
PixelRoutine(state, shader), r(shader->indirectAddressableTemporaries), PixelRoutine(state, shader), r(shader->indirectAddressableTemporaries)
loopDepth(-1), ifDepth(0), loopRepDepth(0), currentLabel(-1)
{ {
for(int i = 0; i < 2048; ++i) for(int i = 0; i < 2048; ++i)
{ {
labelBlock[i] = 0; labelBlock[i] = 0;
} }
loopDepth = -1;
enableStack[0] = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); enableStack[0] = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
if(shader->containsBreakInstruction()) if(shader->containsBreakInstruction())
...@@ -129,6 +129,7 @@ namespace sw ...@@ -129,6 +129,7 @@ namespace sw
void BREAK(Int4 &condition); void BREAK(Int4 &condition);
void CONTINUE(); void CONTINUE();
void TEST(); void TEST();
void SCALAR();
void CALL(int labelIndex, int callSiteIndex); void CALL(int labelIndex, int callSiteIndex);
void CALLNZ(int labelIndex, int callSiteIndex, const Src &src); void CALLNZ(int labelIndex, int callSiteIndex, const Src &src);
void CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister); void CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister);
...@@ -152,9 +153,10 @@ namespace sw ...@@ -152,9 +153,10 @@ namespace sw
void RET(); void RET();
void LEAVE(); void LEAVE();
int ifDepth; int ifDepth = 0;
int loopRepDepth; int loopRepDepth = 0;
int currentLabel; int currentLabel = -1;
bool scalar = false;
BasicBlock *ifFalseBlock[24 + 24]; BasicBlock *ifFalseBlock[24 + 24];
BasicBlock *loopRepTestBlock[4]; BasicBlock *loopRepTestBlock[4];
......
...@@ -244,9 +244,10 @@ namespace sw ...@@ -244,9 +244,10 @@ namespace sw
OPCODE_INSERT, OPCODE_INSERT,
OPCODE_DISCARD, OPCODE_DISCARD,
OPCODE_FWIDTH, OPCODE_FWIDTH,
OPCODE_LEAVE, // Return before the end of the function OPCODE_LEAVE, // Return before the end of the function
OPCODE_CONTINUE, OPCODE_CONTINUE,
OPCODE_TEST, // Marks the end of the code that can be skipped by 'continue' OPCODE_TEST, // Marks the end of the code that can be skipped by 'continue'
OPCODE_SCALAR, // Marks the start of code not subject to SIMD lane masking. Ends at WHILE and ENDWHILE.
OPCODE_SWITCH, OPCODE_SWITCH,
OPCODE_ENDSWITCH, OPCODE_ENDSWITCH,
......
...@@ -26,10 +26,6 @@ namespace sw ...@@ -26,10 +26,6 @@ namespace sw
VertexProgram::VertexProgram(const VertexProcessor::State &state, const VertexShader *shader) VertexProgram::VertexProgram(const VertexProcessor::State &state, const VertexShader *shader)
: VertexRoutine(state, shader), shader(shader), r(shader->indirectAddressableTemporaries) : VertexRoutine(state, shader), shader(shader), r(shader->indirectAddressableTemporaries)
{ {
ifDepth = 0;
loopRepDepth = 0;
currentLabel = -1;
for(int i = 0; i < 2048; i++) for(int i = 0; i < 2048; i++)
{ {
labelBlock[i] = 0; labelBlock[i] = 0;
...@@ -295,6 +291,7 @@ namespace sw ...@@ -295,6 +291,7 @@ namespace sw
case Shader::OPCODE_BREAKP: BREAKP(src0); break; case Shader::OPCODE_BREAKP: BREAKP(src0); break;
case Shader::OPCODE_CONTINUE: CONTINUE(); break; case Shader::OPCODE_CONTINUE: CONTINUE(); break;
case Shader::OPCODE_TEST: TEST(); break; case Shader::OPCODE_TEST: TEST(); break;
case Shader::OPCODE_SCALAR: SCALAR(); break;
case Shader::OPCODE_CALL: CALL(dst.label, dst.callSite); break; case Shader::OPCODE_CALL: CALL(dst.label, dst.callSite); break;
case Shader::OPCODE_CALLNZ: CALLNZ(dst.label, dst.callSite, src0); break; case Shader::OPCODE_CALLNZ: CALLNZ(dst.label, dst.callSite, src0); break;
case Shader::OPCODE_ELSE: ELSE(); break; case Shader::OPCODE_ELSE: ELSE(); break;
...@@ -977,6 +974,11 @@ namespace sw ...@@ -977,6 +974,11 @@ namespace sw
Int4 VertexProgram::enableMask(const Shader::Instruction *instruction) Int4 VertexProgram::enableMask(const Shader::Instruction *instruction)
{ {
if(scalar)
{
return Int4(0xFFFFFFFF);
}
Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF); Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
if(shader->containsBreakInstruction() && instruction->analysisBreak) if(shader->containsBreakInstruction() && instruction->analysisBreak)
...@@ -1108,6 +1110,11 @@ namespace sw ...@@ -1108,6 +1110,11 @@ namespace sw
restoreContinue.pop_back(); restoreContinue.pop_back();
} }
void VertexProgram::SCALAR()
{
scalar = true;
}
void VertexProgram::CALL(int labelIndex, int callSiteIndex) void VertexProgram::CALL(int labelIndex, int callSiteIndex)
{ {
if(!labelBlock[labelIndex]) if(!labelBlock[labelIndex])
...@@ -1284,6 +1291,7 @@ namespace sw ...@@ -1284,6 +1291,7 @@ namespace sw
Nucleus::setInsertBlock(endBlock); Nucleus::setInsertBlock(endBlock);
enableIndex--; enableIndex--;
scalar = false;
} }
void VertexProgram::ENDSWITCH() void VertexProgram::ENDSWITCH()
...@@ -1490,6 +1498,7 @@ namespace sw ...@@ -1490,6 +1498,7 @@ namespace sw
Nucleus::setInsertBlock(loopBlock); Nucleus::setInsertBlock(loopBlock);
loopRepDepth++; loopRepDepth++;
scalar = false;
} }
void VertexProgram::SWITCH() void VertexProgram::SWITCH()
......
...@@ -86,6 +86,7 @@ namespace sw ...@@ -86,6 +86,7 @@ namespace sw
void BREAK(Int4 &condition); void BREAK(Int4 &condition);
void CONTINUE(); void CONTINUE();
void TEST(); void TEST();
void SCALAR();
void CALL(int labelIndex, int callSiteIndex); void CALL(int labelIndex, int callSiteIndex);
void CALLNZ(int labelIndex, int callSiteIndex, const Src &src); void CALLNZ(int labelIndex, int callSiteIndex, const Src &src);
void CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister); void CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister);
...@@ -121,9 +122,10 @@ namespace sw ...@@ -121,9 +122,10 @@ namespace sw
Vector4f sampleTexture(const Src &s, Vector4f &uvwq, Float4 &lod, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function); Vector4f sampleTexture(const Src &s, Vector4f &uvwq, Float4 &lod, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function);
Vector4f sampleTexture(int sampler, Vector4f &uvwq, Float4 &lod, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function); Vector4f sampleTexture(int sampler, Vector4f &uvwq, Float4 &lod, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function);
int ifDepth; int ifDepth = 0;
int loopRepDepth; int loopRepDepth = 0;
int currentLabel; int currentLabel = -1;
bool scalar = false;
BasicBlock *ifFalseBlock[24 + 24]; BasicBlock *ifFalseBlock[24 + 24];
BasicBlock *loopRepTestBlock[4]; BasicBlock *loopRepTestBlock[4];
......
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