Perform texture coordinate projection at shader assembly level.
Change-Id: Ia94eb950d8d3ec4562f9f2e57d8d7ba27a41d16c
Reviewed-on: https://swiftshader-review.googlesource.com/5044
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index eec58d9..15bb374 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -1223,63 +1223,42 @@
else
{
const TextureFunction textureFunction(node->getName());
+ TIntermTyped *t = arg[1]->getAsTyped();
+
+ Temporary coord(this);
+
+ if(textureFunction.proj)
+ {
+ 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;
+ }
+ else
+ {
+ emit(sw::Shader::OPCODE_MOV, &coord, arg[1]);
+ }
+
switch(textureFunction.method)
{
case TextureFunction::IMPLICIT:
{
- TIntermTyped *t = arg[1]->getAsTyped();
-
TIntermNode* offset = textureFunction.offset ? arg[2] : 0;
if(argumentCount == 2 || (textureFunction.offset && argumentCount == 3))
{
Instruction *tex = emit(textureFunction.offset ? sw::Shader::OPCODE_TEXOFFSET : sw::Shader::OPCODE_TEX,
- result, arg[1], arg[0], offset);
- if(textureFunction.proj)
- {
- tex->project = true;
-
- switch(t->getNominalSize())
- {
- case 2: tex->src[0].swizzle = 0x54; break; // xyyy
- case 3: tex->src[0].swizzle = 0xA4; break; // xyzz
- case 4: break; // xyzw
- default:
- UNREACHABLE(t->getNominalSize());
- break;
- }
- }
+ result, &coord, arg[0], offset);
}
else if(argumentCount == 3 || (textureFunction.offset && argumentCount == 4)) // bias
{
- Temporary proj(this);
- if(textureFunction.proj)
- {
- Instruction *div = emit(sw::Shader::OPCODE_DIV, &proj, arg[1], arg[1]);
- div->dst.mask = 0x3;
-
- switch(t->getNominalSize())
- {
- case 2:
- case 3:
- case 4:
- div->src[1].swizzle = 0x55 * (t->getNominalSize() - 1);
- break;
- default:
- UNREACHABLE(t->getNominalSize());
- break;
- }
- }
- else
- {
- emit(sw::Shader::OPCODE_MOV, &proj, arg[1]);
- }
-
- Instruction *bias = emit(sw::Shader::OPCODE_MOV, &proj, arg[textureFunction.offset ? 3 : 2]);
+ Instruction *bias = emit(sw::Shader::OPCODE_MOV, &coord, arg[textureFunction.offset ? 3 : 2]);
bias->dst.mask = 0x8;
Instruction *tex = emit(textureFunction.offset ? sw::Shader::OPCODE_TEXOFFSET : sw::Shader::OPCODE_TEX,
- result, &proj, arg[0], offset); // FIXME: Implement an efficient TEXLDB instruction
+ result, &coord, arg[0], offset); // FIXME: Implement an efficient TEXLDB instruction
tex->bias = true;
}
else UNREACHABLE(argumentCount);
@@ -1287,45 +1266,18 @@
break;
case TextureFunction::LOD:
{
- TIntermTyped *t = arg[1]->getAsTyped();
- Temporary proj(this);
-
- if(textureFunction.proj)
- {
- Instruction *div = emit(sw::Shader::OPCODE_DIV, &proj, arg[1], arg[1]);
- div->dst.mask = 0x3;
-
- switch(t->getNominalSize())
- {
- case 2:
- case 3:
- case 4:
- div->src[1].swizzle = 0x55 * (t->getNominalSize() - 1);
- break;
- default:
- UNREACHABLE(t->getNominalSize());
- break;
- }
- }
- else
- {
- emit(sw::Shader::OPCODE_MOV, &proj, arg[1]);
- }
-
- Instruction *lod = emit(sw::Shader::OPCODE_MOV, &proj, arg[2]);
+ Instruction *lod = emit(sw::Shader::OPCODE_MOV, &coord, arg[2]);
lod->dst.mask = 0x8;
emit(textureFunction.offset ? sw::Shader::OPCODE_TEXLDLOFFSET : sw::Shader::OPCODE_TEXLDL,
- result, &proj, arg[0], textureFunction.offset ? arg[3] : 0);
+ result, &coord, arg[0], textureFunction.offset ? arg[3] : nullptr);
}
break;
case TextureFunction::FETCH:
{
- TIntermTyped *t = arg[1]->getAsTyped();
-
if(argumentCount == 3 || (textureFunction.offset && argumentCount == 4))
{
- TIntermNode* offset = textureFunction.offset ? arg[3] : 0;
+ 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);
@@ -1335,38 +1287,12 @@
break;
case TextureFunction::GRAD:
{
- TIntermTyped *t = arg[1]->getAsTyped();
-
if(argumentCount == 4 || (textureFunction.offset && argumentCount == 5))
{
- Temporary uvwb(this);
-
- if(textureFunction.proj)
- {
- Instruction *div = emit(sw::Shader::OPCODE_DIV, &uvwb, arg[1], arg[1]);
- div->dst.mask = 0x3;
-
- switch(t->getNominalSize())
- {
- case 2:
- case 3:
- case 4:
- div->src[1].swizzle = 0x55 * (t->getNominalSize() - 1);
- break;
- default:
- UNREACHABLE(t->getNominalSize());
- break;
- }
- }
- else
- {
- emit(sw::Shader::OPCODE_MOV, &uvwb, arg[1]);
- }
-
- TIntermNode* offset = textureFunction.offset ? arg[4] : 0;
+ TIntermNode *offset = textureFunction.offset ? arg[4] : nullptr;
emit(textureFunction.offset ? sw::Shader::OPCODE_TEXGRADOFFSET : sw::Shader::OPCODE_TEXGRAD,
- result, &uvwb, arg[0], arg[2], arg[3], offset);
+ result, &coord, arg[0], arg[2], arg[3], offset);
}
else UNREACHABLE(argumentCount);
}