Texture function refactoring
To make it easier to branch on the different texture
fetching options, a new TextureFunction class is
introduced here, which performs the string comparisons
and identifies the different options.
I also had to add a 5th argument for textureGradOffset
and textureProjGradOffset.
I added function stubs (with the UNIMPLEMENTED markers)
for all new texture functions.
Change-Id: I58cde91a2bacb0012bdc34ec85b0befa19a85326
Reviewed-on: https://swiftshader-review.googlesource.com/4116
Tested-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 bbfadf4..3245b67 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -113,6 +113,86 @@
return 0;
}
+ OutputASM::TextureFunction::TextureFunction(const TString& nodeName) : method(IMPLICIT), proj(false), offset(false)
+ {
+ TString name = TFunction::unmangleName(nodeName);
+
+ if(name == "texture2D" || name == "textureCube" || name == "texture" || name == "texture3D")
+ {
+ method = IMPLICIT;
+ }
+ else if(name == "texture2DProj" || name == "textureProj")
+ {
+ method = IMPLICIT;
+ proj = true;
+ }
+ else if(name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod")
+ {
+ method = LOD;
+ }
+ else if(name == "texture2DProjLod" || name == "textureProjLod")
+ {
+ method = LOD;
+ proj = true;
+ }
+ else if(name == "textureSize")
+ {
+ method = SIZE;
+ }
+ else if(name == "textureOffset")
+ {
+ method = IMPLICIT;
+ offset = true;
+ }
+ else if(name == "textureProjOffset")
+ {
+ method = IMPLICIT;
+ offset = true;
+ proj = true;
+ }
+ else if(name == "textureLodOffset")
+ {
+ method = LOD;
+ offset = true;
+ }
+ else if(name == "textureProjLodOffset")
+ {
+ method = LOD;
+ proj = true;
+ offset = true;
+ }
+ else if(name == "texelFetch")
+ {
+ method = FETCH;
+ }
+ else if(name == "texelFetchOffset")
+ {
+ method = FETCH;
+ offset = true;
+ }
+ else if(name == "textureGrad")
+ {
+ method = GRAD;
+ }
+ else if(name == "textureGradOffset")
+ {
+ method = GRAD;
+ offset = true;
+ }
+ else if(name == "textureProjGrad")
+ {
+ method = GRAD;
+ proj = true;
+ }
+ else if(name == "textureProjGradOffset")
+ {
+ method = GRAD;
+ proj = true;
+ offset = true;
+ }
+ else UNREACHABLE(0);
+ }
+
OutputASM::OutputASM(TParseContext &context, Shader *shaderObject) : TIntermTraverser(true, true, true), mContext(context), shaderObject(shaderObject)
{
shader = 0;
@@ -1042,105 +1122,161 @@
}
else
{
- TString name = TFunction::unmangleName(node->getName());
-
- if(name == "texture" || name == "texture2D" || name == "textureCube" || name == "texture3D")
+ const TextureFunction textureFunction(node->getName());
+ switch(textureFunction.method)
{
- if(argumentCount == 2)
+ case TextureFunction::IMPLICIT:
{
- emit(sw::Shader::OPCODE_TEX, result, arg[1], arg[0]);
- }
- else if(argumentCount == 3) // bias
- {
- Temporary uvwb(this);
- emit(sw::Shader::OPCODE_MOV, &uvwb, arg[1]);
- Instruction *bias = emit(sw::Shader::OPCODE_MOV, &uvwb, arg[2]);
- bias->dst.mask = 0x8;
+ TIntermTyped *t = arg[1]->getAsTyped();
- Instruction *tex = emit(sw::Shader::OPCODE_TEX, result, &uvwb, arg[0]); // FIXME: Implement an efficient TEXLDB instruction
- tex->bias = true;
- }
- else UNREACHABLE(argumentCount);
- }
- else if(name == "texture2DProj" || name == "textureProj")
- {
- TIntermTyped *t = arg[1]->getAsTyped();
+ TIntermNode* offset = textureFunction.offset ? arg[2] : 0;
- if(argumentCount == 2)
- {
- Instruction *tex = emit(sw::Shader::OPCODE_TEX, result, arg[1], arg[0]);
- tex->project = true;
-
- if(t->getNominalSize() == 3)
+ if(argumentCount == 2 || (textureFunction.offset && argumentCount == 3))
{
- tex->src[0].swizzle = 0xA4;
+ 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;
+ }
+ }
}
- else ASSERT(t->getNominalSize() == 4);
+ 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]);
+ 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
+ tex->bias = true;
+ }
+ else UNREACHABLE(argumentCount);
}
- else if(argumentCount == 3) // bias
+ break;
+ case TextureFunction::LOD:
{
+ TIntermTyped *t = arg[1]->getAsTyped();
Temporary proj(this);
- if(t->getNominalSize() == 3)
+ if(textureFunction.proj)
{
- Instruction *div = emit(sw::Shader::OPCODE_DIV, &proj, arg[1], arg[1]);
- div->src[1].swizzle = 0xAA;
- div->dst.mask = 0x3;
+ 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 if(t->getNominalSize() == 4)
+ else
{
- Instruction *div = emit(sw::Shader::OPCODE_DIV, &proj, arg[1], arg[1]);
- div->src[1].swizzle = 0xFF;
- div->dst.mask = 0x3;
+ emit(sw::Shader::OPCODE_MOV, &proj, arg[1]);
}
- else UNREACHABLE(t->getNominalSize());
- Instruction *bias = emit(sw::Shader::OPCODE_MOV, &proj, arg[2]);
- bias->dst.mask = 0x8;
+ Instruction *lod = emit(sw::Shader::OPCODE_MOV, &proj, arg[2]);
+ lod->dst.mask = 0x8;
- Instruction *tex = emit(sw::Shader::OPCODE_TEX, result, &proj, arg[0]);
- tex->bias = true;
+ emit(textureFunction.offset ? sw::Shader::OPCODE_TEXLDLOFFSET : sw::Shader::OPCODE_TEXLDL,
+ result, &proj, arg[0], textureFunction.offset ? arg[3] : 0);
}
- else UNREACHABLE(argumentCount);
- }
- else if(name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod")
- {
- Temporary uvwb(this);
- emit(sw::Shader::OPCODE_MOV, &uvwb, arg[1]);
- Instruction *lod = emit(sw::Shader::OPCODE_MOV, &uvwb, arg[2]);
- lod->dst.mask = 0x8;
-
- emit(sw::Shader::OPCODE_TEXLDL, result, &uvwb, arg[0]);
- }
- else if(name == "texture2DProjLod" || name == "textureProjLod")
- {
- TIntermTyped *t = arg[1]->getAsTyped();
- Temporary proj(this);
-
- if(t->getNominalSize() == 3)
+ break;
+ case TextureFunction::FETCH:
{
- Instruction *div = emit(sw::Shader::OPCODE_DIV, &proj, arg[1], arg[1]);
- div->src[1].swizzle = 0xAA;
- div->dst.mask = 0x3;
+ TIntermTyped *t = arg[1]->getAsTyped();
+
+ if(argumentCount == 3 || (textureFunction.offset && argumentCount == 4))
+ {
+ TIntermNode* offset = textureFunction.offset ? arg[3] : 0;
+
+ emit(textureFunction.offset ? sw::Shader::OPCODE_TEXELFETCHOFFSET : sw::Shader::OPCODE_TEXELFETCH,
+ result, arg[1], arg[0], arg[2], offset);
+ }
+ else UNREACHABLE(argumentCount);
}
- else if(t->getNominalSize() == 4)
+ break;
+ case TextureFunction::GRAD:
{
- Instruction *div = emit(sw::Shader::OPCODE_DIV, &proj, arg[1], arg[1]);
- div->src[1].swizzle = 0xFF;
- div->dst.mask = 0x3;
+ 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;
+
+ emit(textureFunction.offset ? sw::Shader::OPCODE_TEXGRADOFFSET : sw::Shader::OPCODE_TEXGRAD,
+ result, &uvwb, arg[0], arg[2], arg[3], offset);
+ }
+ else UNREACHABLE(argumentCount);
}
- else UNREACHABLE(t->getNominalSize());
-
- Instruction *lod = emit(sw::Shader::OPCODE_MOV, &proj, arg[2]);
- lod->dst.mask = 0x8;
-
- emit(sw::Shader::OPCODE_TEXLDL, result, &proj, arg[0]);
- }
- else if(name == "textureSize")
- {
+ break;
+ case TextureFunction::SIZE:
emit(sw::Shader::OPCODE_TEXSIZE, result, arg[1], arg[0]);
+ break;
+ default:
+ UNREACHABLE(textureFunction.method);
}
- else UNREACHABLE(0);
}
}
break;
@@ -1483,7 +1619,7 @@
TIntermTyped *condition = node->getCondition();
TIntermTyped *expression = node->getExpression();
TIntermNode *body = node->getBody();
-
+
if(node->getType() == ELoopDoWhile)
{
Temporary iterate(this);
@@ -1607,7 +1743,7 @@
return IsSampler(type.getBasicType()) && (type.getQualifier() == EvqUniform || type.getQualifier() == EvqTemporary);
}
- Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2, TIntermNode *src3, int index)
+ Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2, TIntermNode *src3, TIntermNode *src4, int index)
{
if(isSamplerRegister(dst))
{
@@ -1628,6 +1764,7 @@
argument(instruction->src[1], src1, index);
argument(instruction->src[2], src2, index);
argument(instruction->src[3], src3, index);
+ argument(instruction->src[4], src4, index);
shader->append(instruction);
@@ -1683,7 +1820,7 @@
{
for(int index = 0; index < dst->elementRegisterCount(); index++)
{
- emit(op, dst, src0, src1, src2, 0, index);
+ emit(op, dst, src0, src1, src2, 0, 0, index);
}
}
diff --git a/src/OpenGL/compiler/OutputASM.h b/src/OpenGL/compiler/OutputASM.h
index acb981b..47bd4d1 100644
--- a/src/OpenGL/compiler/OutputASM.h
+++ b/src/OpenGL/compiler/OutputASM.h
@@ -164,6 +164,24 @@
FUNCTION
};
+ struct TextureFunction
+ {
+ TextureFunction(const TString& name);
+
+ enum Method
+ {
+ IMPLICIT, // Mipmap LOD determined implicitly (standard lookup)
+ LOD,
+ SIZE, // textureSize()
+ FETCH,
+ GRAD
+ };
+
+ Method method;
+ bool proj;
+ bool offset;
+ };
+
void emitShader(Scope scope);
// Visit AST nodes and output their code to the body stream
@@ -176,7 +194,7 @@
virtual bool visitBranch(Visit visit, TIntermBranch*);
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, int index = 0);
+ Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0, TIntermNode *src3 = 0, TIntermNode *src4 = 0, int index = 0);
Instruction *emitCast(TIntermTyped *dst, TIntermTyped *src);
void emitBinary(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0);
void emitAssign(sw::Shader::Opcode op, TIntermTyped *result, TIntermTyped *lhs, TIntermTyped *src0, TIntermTyped *src1 = 0);
diff --git a/src/Shader/PixelProgram.cpp b/src/Shader/PixelProgram.cpp
index 46ca81c..f889cfa 100644
--- a/src/Shader/PixelProgram.cpp
+++ b/src/Shader/PixelProgram.cpp
@@ -110,6 +110,7 @@
const Src &src1 = instruction->src[1];
const Src &src2 = instruction->src[2];
const Src &src3 = instruction->src[3];
+ const Src &src4 = instruction->src[4];
bool predicate = instruction->predicate;
Control control = instruction->control;
@@ -122,6 +123,7 @@
Vector4f s1;
Vector4f s2;
Vector4f s3;
+ Vector4f s4;
if(opcode == Shader::OPCODE_TEXKILL) // Takes destination as input
{
@@ -142,6 +144,7 @@
if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegisterF(r, src1);
if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegisterF(r, src2);
if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegisterF(r, src3);
+ if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegisterF(r, src4);
switch(opcode)
{
@@ -275,6 +278,12 @@
case Shader::OPCODE_TEXLDL: TEXLDL(r, d, s0, src1, project, bias); break;
case Shader::OPCODE_TEXSIZE: TEXSIZE(r, d, s0.x, src1); break;
case Shader::OPCODE_TEXKILL: TEXKILL(cMask, d, dst.mask); break;
+ case Shader::OPCODE_TEXOFFSET: TEXOFFSET(r, d, s0, src1, s2, s3, project, bias); break;
+ case Shader::OPCODE_TEXLDLOFFSET: TEXLDL(r, d, s0, src1, s2, project, bias); break;
+ case Shader::OPCODE_TEXELFETCH: TEXELFETCH(r, d, s0, src1, s2); break;
+ case Shader::OPCODE_TEXELFETCHOFFSET: TEXELFETCH(r, d, s0, src1, s2, s3); break;
+ case Shader::OPCODE_TEXGRAD: TEXGRAD(r, d, s0, src1, s2, s3); break;
+ case Shader::OPCODE_TEXGRADOFFSET: TEXGRAD(r, d, s0, src1, s2, s3, s4); break;
case Shader::OPCODE_DISCARD: DISCARD(r, cMask, instruction); break;
case Shader::OPCODE_DFDX: DFDX(d, s0); break;
case Shader::OPCODE_DFDY: DFDY(d, s0); break;
@@ -1030,6 +1039,36 @@
dst.w = tmp[(src1.swizzle >> 6) & 0x3];
}
+ void PixelProgram::TEXOFFSET(Registers &r, Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3, bool project, bool bias)
+ {
+ UNIMPLEMENTED();
+ }
+
+ void PixelProgram::TEXLDL(Registers &r, Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &offset, bool project, bool bias)
+ {
+ UNIMPLEMENTED();
+ }
+
+ void PixelProgram::TEXELFETCH(Registers &r, Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2)
+ {
+ UNIMPLEMENTED();
+ }
+
+ void PixelProgram::TEXELFETCH(Registers &r, Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &offset)
+ {
+ UNIMPLEMENTED();
+ }
+
+ void PixelProgram::TEXGRAD(Registers &r, Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3)
+ {
+ UNIMPLEMENTED();
+ }
+
+ void PixelProgram::TEXGRAD(Registers &r, Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3, Vector4f &offset)
+ {
+ UNIMPLEMENTED();
+ }
+
void PixelProgram::TEXLDD(Registers &r, Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &src2, Vector4f &src3, bool project, bool bias)
{
Vector4f tmp;
diff --git a/src/Shader/PixelProgram.hpp b/src/Shader/PixelProgram.hpp
index 850a7b1..41b9c4a 100644
--- a/src/Shader/PixelProgram.hpp
+++ b/src/Shader/PixelProgram.hpp
@@ -112,6 +112,12 @@
void TEXLDL(Registers &r, Vector4f &dst, Vector4f &src0, const Src &src1, bool project, bool bias);
void TEXSIZE(Registers &r, Vector4f &dst, Float4 &lod, const Src &src1);
void TEXKILL(Int cMask[4], Vector4f &src, unsigned char mask);
+ void TEXOFFSET(Registers &r, Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2, Vector4f &src3, bool project, bool bias);
+ void TEXLDL(Registers &r, Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &src2, bool project, bool bias);
+ void TEXELFETCH(Registers &r, Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2);
+ void TEXELFETCH(Registers &r, Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2, Vector4f &src3);
+ void TEXGRAD(Registers &r, Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2, Vector4f &src3);
+ void TEXGRAD(Registers &r, Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2, Vector4f &src3, Vector4f &src4);
void DISCARD(Registers &r, Int cMask[4], const Shader::Instruction *instruction);
void DFDX(Vector4f &dst, Vector4f &src);
void DFDY(Vector4f &dst, Vector4f &src);
diff --git a/src/Shader/PixelShader.cpp b/src/Shader/PixelShader.cpp
index 9e4cff5..0cd6f1c 100644
--- a/src/Shader/PixelShader.cpp
+++ b/src/Shader/PixelShader.cpp
@@ -299,6 +299,12 @@
case Shader::OPCODE_TEX:
case Shader::OPCODE_TEXLDD:
case Shader::OPCODE_TEXLDL:
+ case Shader::OPCODE_TEXOFFSET:
+ case Shader::OPCODE_TEXLDLOFFSET:
+ case Shader::OPCODE_TEXELFETCH:
+ case Shader::OPCODE_TEXELFETCHOFFSET:
+ case Shader::OPCODE_TEXGRAD:
+ case Shader::OPCODE_TEXGRADOFFSET:
{
int sampler = instruction[i]->src[1].index;
diff --git a/src/Shader/Shader.cpp b/src/Shader/Shader.cpp
index 7767e79..6251359 100644
--- a/src/Shader/Shader.cpp
+++ b/src/Shader/Shader.cpp
@@ -865,6 +865,12 @@
case OPCODE_TEXLDD: return "texldd";
case OPCODE_CMP: return "cmp";
case OPCODE_TEXLDL: return "texldl";
+ case OPCODE_TEXOFFSET: return "texoffset";
+ case OPCODE_TEXLDLOFFSET: return "texldloffset";
+ case OPCODE_TEXELFETCH: return "texelfetch";
+ case OPCODE_TEXELFETCHOFFSET: return "texelfetchoffset";
+ case OPCODE_TEXGRAD: return "texgrad";
+ case OPCODE_TEXGRADOFFSET: return "texgradoffset";
case OPCODE_BREAKP: return "breakp";
case OPCODE_TEXSIZE: return "texsize";
case OPCODE_PHASE: return "phase";
@@ -1772,6 +1778,12 @@
case OPCODE_TEXM3X2DEPTH:
case OPCODE_TEXLDD:
case OPCODE_TEXLDL:
+ case OPCODE_TEXOFFSET:
+ case OPCODE_TEXLDLOFFSET:
+ case OPCODE_TEXELFETCH:
+ case OPCODE_TEXELFETCHOFFSET:
+ case OPCODE_TEXGRAD:
+ case OPCODE_TEXGRADOFFSET:
{
Parameter &dst = instruction[i]->dst;
Parameter &src1 = instruction[i]->src[1];
diff --git a/src/Shader/Shader.hpp b/src/Shader/Shader.hpp
index 18c723b..588f637 100644
--- a/src/Shader/Shader.hpp
+++ b/src/Shader/Shader.hpp
@@ -205,6 +205,12 @@
OPCODE_SMOOTH,
OPCODE_ISNAN,
OPCODE_ISINF,
+ OPCODE_TEXOFFSET,
+ OPCODE_TEXLDLOFFSET,
+ OPCODE_TEXELFETCH,
+ OPCODE_TEXELFETCHOFFSET,
+ OPCODE_TEXGRAD,
+ OPCODE_TEXGRADOFFSET,
OPCODE_FLOATBITSTOINT,
OPCODE_FLOATBITSTOUINT,
OPCODE_INTBITSTOFLOAT,
@@ -511,7 +517,7 @@
unsigned char usageIndex;
DestinationParameter dst;
- SourceParameter src[4];
+ SourceParameter src[5];
union
{
diff --git a/src/Shader/VertexProgram.cpp b/src/Shader/VertexProgram.cpp
index 916a7fd..40c0910 100644
--- a/src/Shader/VertexProgram.cpp
+++ b/src/Shader/VertexProgram.cpp
@@ -103,6 +103,7 @@
Src src1 = instruction->src[1];
Src src2 = instruction->src[2];
Src src3 = instruction->src[3];
+ Src src4 = instruction->src[4];
bool predicate = instruction->predicate;
Control control = instruction->control;
@@ -114,11 +115,13 @@
Vector4f s1;
Vector4f s2;
Vector4f s3;
+ Vector4f s4;
if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegisterF(r, src0);
if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegisterF(r, src1);
if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegisterF(r, src2);
if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegisterF(r, src3);
+ if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegisterF(r, src4);
switch(opcode)
{
@@ -289,6 +292,12 @@
case Shader::OPCODE_NE: notEqual(d, s0, s1); break;
case Shader::OPCODE_TEXLDL: TEXLDL(r, d, s0, src1); break;
case Shader::OPCODE_TEX: TEX(r, d, s0, src1); break;
+ case Shader::OPCODE_TEXOFFSET: TEXOFFSET(r, d, s0, src1, s2, s3); break;
+ case Shader::OPCODE_TEXLDLOFFSET: TEXLDL(r, d, s0, src1, s2); break;
+ case Shader::OPCODE_TEXELFETCH: TEXELFETCH(r, d, s0, src1, s2); break;
+ case Shader::OPCODE_TEXELFETCHOFFSET: TEXELFETCH(r, d, s0, src1, s2, s3); break;
+ case Shader::OPCODE_TEXGRAD: TEXGRAD(r, d, s0, src1, s2, s3); break;
+ case Shader::OPCODE_TEXGRADOFFSET: TEXGRAD(r, d, s0, src1, s2, s3, s4); break;
case Shader::OPCODE_TEXSIZE: TEXSIZE(r, d, s0.x, src1); break;
case Shader::OPCODE_END: break;
default:
@@ -1488,6 +1497,36 @@
dst.w = tmp[(src1.swizzle >> 6) & 0x3];
}
+ void VertexProgram::TEXOFFSET(Registers &r, Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3)
+ {
+ UNIMPLEMENTED();
+ }
+
+ void VertexProgram::TEXLDL(Registers &r, Vector4f &dst, Vector4f &src, const Src&, Vector4f &offset)
+ {
+ UNIMPLEMENTED();
+ }
+
+ void VertexProgram::TEXELFETCH(Registers &r, Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2)
+ {
+ UNIMPLEMENTED();
+ }
+
+ void VertexProgram::TEXELFETCH(Registers &r, Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &offset)
+ {
+ UNIMPLEMENTED();
+ }
+
+ void VertexProgram::TEXGRAD(Registers &r, Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3)
+ {
+ UNIMPLEMENTED();
+ }
+
+ void VertexProgram::TEXGRAD(Registers &r, Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &src2, Vector4f &src3, Vector4f &offset)
+ {
+ UNIMPLEMENTED();
+ }
+
void VertexProgram::TEXSIZE(Registers &r, Vector4f &dst, Float4 &lod, const Src &src1)
{
Pointer<Byte> textureMipmap = r.data + OFFSET(DrawData, mipmap[16]) + src1.index * sizeof(Texture) + OFFSET(Texture, mipmap);
diff --git a/src/Shader/VertexProgram.hpp b/src/Shader/VertexProgram.hpp
index 4c384d7..53427a5 100644
--- a/src/Shader/VertexProgram.hpp
+++ b/src/Shader/VertexProgram.hpp
@@ -79,6 +79,12 @@
void LEAVE(Registers &r);
void TEXLDL(Registers &r, Vector4f &dst, Vector4f &src, const Src&);
void TEX(Registers &r, Vector4f &dst, Vector4f &src, const Src&);
+ void TEXOFFSET(Registers &r, Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2, Vector4f &src3);
+ void TEXLDL(Registers &r, Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2);
+ void TEXELFETCH(Registers &r, Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2);
+ void TEXELFETCH(Registers &r, Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2, Vector4f &src3);
+ void TEXGRAD(Registers &r, Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2, Vector4f &src3);
+ void TEXGRAD(Registers &r, Vector4f &dst, Vector4f &src, const Src&, Vector4f &src2, Vector4f &src3, Vector4f &src4);
void TEXSIZE(Registers &r, Vector4f &dst, Float4 &lod, const Src&);
void sampleTexture(Registers &r, Vector4f &c, const Src &s, Float4 &u, Float4 &v, Float4 &w, Float4 &q);