Added support for swizzled matrix assignments and a new "combined" shader test type, with compiles the same source for both vs/fs, but with differing entry points.
Also added a new ETranslateOpTransposeMatrixSwizzles options, which controls how hlsl matrix.m_<row><col> syntax maps to glsl matrix[<row>][<col>]
This commit is contained in:
Родитель
ceae3709d2
Коммит
3249bb36b4
|
@ -239,11 +239,13 @@ void TGlslOutputTraverser::outputLineDirective (int line)
|
|||
|
||||
|
||||
|
||||
TGlslOutputTraverser::TGlslOutputTraverser(TInfoSink& i, std::vector<GlslFunction*> &funcList, std::vector<GlslStruct*> &sList, bool usePrecision)
|
||||
TGlslOutputTraverser::TGlslOutputTraverser(TInfoSink& i, std::vector<GlslFunction*> &funcList, std::vector<GlslStruct*> &sList, bool usePrecision, bool transposeMatrixSwizzles)
|
||||
: infoSink(i)
|
||||
, generatingCode(true)
|
||||
, functionList(funcList)
|
||||
, structList(sList)
|
||||
, transposeMatrixSwizzles(transposeMatrixSwizzles)
|
||||
, swizzleAssignTempCounter(0)
|
||||
, m_UsePrecision(usePrecision)
|
||||
, m_LastLineOutput(-1)
|
||||
{
|
||||
|
@ -622,7 +624,7 @@ bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, T
|
|||
goit->generatingCode = true;
|
||||
return false;
|
||||
|
||||
case EOpMatrixSwizzle:
|
||||
case EOpMatrixSwizzle:
|
||||
current->beginStatement();
|
||||
// This presently only works for swizzles as rhs operators
|
||||
goit->visitConstantUnion = TGlslOutputTraverser::traverseImmediateConstant;
|
||||
|
@ -636,8 +638,13 @@ bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, T
|
|||
for (int ii = 0; ii < (int)goit->indexList.size(); ii++)
|
||||
{
|
||||
int val = goit->indexList[ii];
|
||||
collumn[ii] = val/4;
|
||||
row[ii] = val%4;
|
||||
if (goit->transposeMatrixSwizzles) {
|
||||
collumn[ii] = val%4;
|
||||
row[ii] = val/4;
|
||||
} else {
|
||||
collumn[ii] = val/4;
|
||||
row[ii] = val%4;
|
||||
}
|
||||
}
|
||||
bool sameCollumn = true;
|
||||
for (int ii = 1; ii < (int)goit->indexList.size(); ii++)
|
||||
|
@ -662,7 +669,7 @@ bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, T
|
|||
|
||||
// Might need to account for different types here
|
||||
assert( (int)goit->indexList.size() != 1); //should have hit same collumn case
|
||||
out << "vec" << (int)goit->indexList.size() << "( ";
|
||||
out << "vec" << (int)goit->indexList.size() << "(";
|
||||
const char fields[] = "xyzw";
|
||||
if (node->getLeft())
|
||||
node->getLeft()->traverse(goit);
|
||||
|
@ -736,6 +743,50 @@ bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, T
|
|||
|
||||
if (infix)
|
||||
{
|
||||
// special case for swizzled matrix assignment
|
||||
if (node->getLeft() && node->getRight()) {
|
||||
TIntermBinary* lval = node->getLeft()->getAsBinaryNode();
|
||||
|
||||
if (lval && lval->getOp() == EOpMatrixSwizzle) {
|
||||
static const char* vec_swizzles = "xyzw";
|
||||
TIntermTyped* rval = node->getRight();
|
||||
TIntermTyped* lexp = lval->getLeft();
|
||||
|
||||
goit->visitConstantUnion = TGlslOutputTraverser::traverseImmediateConstant;
|
||||
goit->generatingCode = false;
|
||||
|
||||
lval->getRight()->traverse(goit);
|
||||
|
||||
goit->visitConstantUnion = TGlslOutputTraverser::traverseConstantUnion;
|
||||
goit->generatingCode = true;
|
||||
|
||||
std::vector<int> swizzles = goit->indexList;
|
||||
goit->indexList.clear();
|
||||
|
||||
char temp_rval[128];
|
||||
snprintf(temp_rval, 128, "xlat_swiztemp%d", goit->swizzleAssignTempCounter++);
|
||||
unsigned n_swizzles = swizzles.size();
|
||||
current->beginStatement();
|
||||
out << "vec" << n_swizzles << " " << temp_rval << " = ";
|
||||
|
||||
rval->traverse(goit);
|
||||
current->endStatement();
|
||||
|
||||
for (unsigned i = 0; i != n_swizzles; ++i) {
|
||||
unsigned a = swizzles[i] / 4, b = swizzles[i] % 4;
|
||||
unsigned col = goit->transposeMatrixSwizzles ? a : b;
|
||||
unsigned row = goit->transposeMatrixSwizzles ? b : a;
|
||||
|
||||
current->beginStatement();
|
||||
lexp->traverse(goit);
|
||||
out << "[" << row << "][" << col << "] = " << temp_rval << "." << vec_swizzles[i];
|
||||
current->endStatement();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsParens)
|
||||
out << '(';
|
||||
|
||||
|
@ -751,7 +802,7 @@ bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, T
|
|||
else
|
||||
{
|
||||
if (assign)
|
||||
{
|
||||
{
|
||||
// Need to traverse the left child twice to allow for the assign and the op
|
||||
// This is OK, because we know it is an lvalue
|
||||
if (node->getLeft())
|
||||
|
|
|
@ -32,7 +32,7 @@ private:
|
|||
void outputLineDirective (int line);
|
||||
|
||||
public:
|
||||
TGlslOutputTraverser (TInfoSink& i, std::vector<GlslFunction*> &funcList, std::vector<GlslStruct*> &sList, bool usePrecision);
|
||||
TGlslOutputTraverser (TInfoSink& i, std::vector<GlslFunction*> &funcList, std::vector<GlslStruct*> &sList, bool usePrecision, bool transposeMatrixSwizzles);
|
||||
GlslStruct *createStructFromType( TType *type );
|
||||
bool parseInitializer( TIntermBinary *node );
|
||||
|
||||
|
@ -59,7 +59,9 @@ public:
|
|||
|
||||
// Persistent data for collecting indices
|
||||
std::vector<int> indexList;
|
||||
|
||||
|
||||
bool transposeMatrixSwizzles;
|
||||
unsigned swizzleAssignTempCounter;
|
||||
bool m_UsePrecision;
|
||||
int m_LastLineOutput;
|
||||
};
|
||||
|
|
|
@ -40,9 +40,9 @@ void HlslCrossCompiler::TransformAST (TIntermNode *root)
|
|||
PropagateMutableUniforms (root, infoSink);
|
||||
}
|
||||
|
||||
void HlslCrossCompiler::ProduceGLSL (TIntermNode *root, bool usePrecision)
|
||||
void HlslCrossCompiler::ProduceGLSL (TIntermNode *root, bool usePrecision, bool transposeMatSwizzles)
|
||||
{
|
||||
m_GlslProduced = true;
|
||||
TGlslOutputTraverser glslTraverse (infoSink, functionList, structList, usePrecision);
|
||||
TGlslOutputTraverser glslTraverse (infoSink, functionList, structList, usePrecision, transposeMatSwizzles);
|
||||
root->traverse(&glslTraverse);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
TInfoSink& getInfoSink() { return infoSink; }
|
||||
|
||||
void TransformAST (TIntermNode* root);
|
||||
void ProduceGLSL (TIntermNode* root, bool usePrecision);
|
||||
void ProduceGLSL (TIntermNode* root, bool usePrecision, bool transposeMatSwizzles);
|
||||
bool IsASTTransformed() const { return m_ASTTransformed; }
|
||||
bool IsGlslProduced() const { return m_GlslProduced; }
|
||||
|
||||
|
|
|
@ -267,7 +267,7 @@ int C_DECL Hlsl2Glsl_Parse( const ShHandle handle,
|
|||
intermediate.outputTree(parseContext.treeRoot);
|
||||
|
||||
compiler->TransformAST (parseContext.treeRoot);
|
||||
compiler->ProduceGLSL (parseContext.treeRoot, (options & ETranslateOpUsePrecision) ? true : false);
|
||||
compiler->ProduceGLSL (parseContext.treeRoot, (options & ETranslateOpUsePrecision) ? true : false, (options & ETranslateOpTransposeMatrixSwizzles) ? true : false);
|
||||
}
|
||||
else if (!success)
|
||||
{
|
||||
|
|
|
@ -121,6 +121,7 @@ enum TTranslateOptions
|
|||
ETranslateOpNone = 0,
|
||||
ETranslateOpIntermediate = (1<<0),
|
||||
ETranslateOpUsePrecision = (1<<1),
|
||||
ETranslateOpTransposeMatrixSwizzles = (1<<2),
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
#line 12
|
||||
struct PS_INPUT {
|
||||
vec4 position;
|
||||
vec2 uv;
|
||||
};
|
||||
#line 7
|
||||
struct VS_INPUT {
|
||||
vec4 position;
|
||||
vec2 uv;
|
||||
};
|
||||
uniform sampler2D diffuse_map;
|
||||
vec4 ps_main( in PS_INPUT xlat_var_input );
|
||||
#line 29
|
||||
vec4 ps_main( in PS_INPUT xlat_var_input ) {
|
||||
vec4 c = vec4(1.00000, 1.00000, 1.00000, 1.00000);
|
||||
#line 30
|
||||
c = texture2D( diffuse_map, xlat_var_input.uv);
|
||||
return c;
|
||||
}
|
||||
varying vec2 xlv_TEXCOORD0;
|
||||
void main() {
|
||||
vec4 xl_retval;
|
||||
PS_INPUT xlt_xlat_var_input;
|
||||
xlt_xlat_var_input.position = vec4(0.0);
|
||||
xlt_xlat_var_input.uv = vec2( xlv_TEXCOORD0);
|
||||
xl_retval = ps_main( xlt_xlat_var_input);
|
||||
gl_FragData[0] = vec4( xl_retval);
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
#line 12
|
||||
struct PS_INPUT {
|
||||
highp vec4 position;
|
||||
highp vec2 uv;
|
||||
};
|
||||
#line 7
|
||||
struct VS_INPUT {
|
||||
highp vec4 position;
|
||||
highp vec2 uv;
|
||||
};
|
||||
uniform sampler2D diffuse_map;
|
||||
mediump vec4 ps_main( in PS_INPUT xlat_var_input );
|
||||
#line 29
|
||||
mediump vec4 ps_main( in PS_INPUT xlat_var_input ) {
|
||||
mediump vec4 c = vec4(1.00000, 1.00000, 1.00000, 1.00000);
|
||||
#line 30
|
||||
c = texture2D( diffuse_map, xlat_var_input.uv);
|
||||
return c;
|
||||
}
|
||||
varying highp vec2 xlv_TEXCOORD0;
|
||||
void main() {
|
||||
mediump vec4 xl_retval;
|
||||
PS_INPUT xlt_xlat_var_input;
|
||||
xlt_xlat_var_input.position = vec4(0.0);
|
||||
xlt_xlat_var_input.uv = vec2( xlv_TEXCOORD0);
|
||||
xl_retval = ps_main( xlt_xlat_var_input);
|
||||
gl_FragData[0] = vec4( xl_retval);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
float4x4 world;
|
||||
float4x4 view;
|
||||
float4x4 proj;
|
||||
|
||||
sampler2D diffuse_map;
|
||||
|
||||
struct VS_INPUT {
|
||||
float4 position : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct PS_INPUT {
|
||||
float4 position : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
PS_INPUT vs_main(VS_INPUT input) {
|
||||
PS_INPUT o;
|
||||
float4 wp = mul(input.position, world);
|
||||
|
||||
view._m30_m31_m32 = world._m30_m31_m32;
|
||||
|
||||
o.position = mul(mul(wp, view), proj);
|
||||
o.uv = input.uv;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
half4 ps_main(PS_INPUT input) : COLOR0 {
|
||||
half4 c = half4(1, 1, 1, 1);
|
||||
c = tex2D(diffuse_map, input.uv);
|
||||
return c;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
#line 12
|
||||
struct PS_INPUT {
|
||||
vec4 position;
|
||||
vec2 uv;
|
||||
};
|
||||
#line 7
|
||||
struct VS_INPUT {
|
||||
vec4 position;
|
||||
vec2 uv;
|
||||
};
|
||||
uniform mat4 proj;
|
||||
uniform mat4 world;
|
||||
uniform mat4 view;
|
||||
mat4 xlat_mutable_view;
|
||||
PS_INPUT vs_main( in VS_INPUT xlat_var_input );
|
||||
#line 17
|
||||
PS_INPUT vs_main( in VS_INPUT xlat_var_input ) {
|
||||
vec4 wp;
|
||||
PS_INPUT o;
|
||||
wp = (xlat_var_input.position * world);
|
||||
#line 21
|
||||
vec3 xlat_swiztemp0 = world[3].xyz;
|
||||
xlat_mutable_view[3][0] = xlat_swiztemp0.x;
|
||||
xlat_mutable_view[3][1] = xlat_swiztemp0.y;
|
||||
xlat_mutable_view[3][2] = xlat_swiztemp0.z;
|
||||
o.position = ((wp * xlat_mutable_view) * proj);
|
||||
o.uv = xlat_var_input.uv;
|
||||
#line 26
|
||||
return o;
|
||||
}
|
||||
varying vec2 xlv_TEXCOORD0;
|
||||
void main() {
|
||||
PS_INPUT xl_retval;
|
||||
xlat_mutable_view = view;
|
||||
VS_INPUT xlt_xlat_var_input;
|
||||
xlt_xlat_var_input.position = vec4( gl_Vertex);
|
||||
xlt_xlat_var_input.uv = vec2( gl_MultiTexCoord0);
|
||||
xl_retval = vs_main( xlt_xlat_var_input);
|
||||
gl_Position = vec4( xl_retval.position);
|
||||
xlv_TEXCOORD0 = vec2( xl_retval.uv);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
#line 12
|
||||
struct PS_INPUT {
|
||||
highp vec4 position;
|
||||
highp vec2 uv;
|
||||
};
|
||||
#line 7
|
||||
struct VS_INPUT {
|
||||
highp vec4 position;
|
||||
highp vec2 uv;
|
||||
};
|
||||
uniform highp mat4 proj;
|
||||
uniform highp mat4 world;
|
||||
uniform highp mat4 view;
|
||||
highp mat4 xlat_mutable_view;
|
||||
PS_INPUT vs_main( in VS_INPUT xlat_var_input );
|
||||
#line 17
|
||||
PS_INPUT vs_main( in VS_INPUT xlat_var_input ) {
|
||||
highp vec4 wp;
|
||||
PS_INPUT o;
|
||||
wp = (xlat_var_input.position * world);
|
||||
#line 21
|
||||
vec3 xlat_swiztemp0 = world[3].xyz;
|
||||
xlat_mutable_view[3][0] = xlat_swiztemp0.x;
|
||||
xlat_mutable_view[3][1] = xlat_swiztemp0.y;
|
||||
xlat_mutable_view[3][2] = xlat_swiztemp0.z;
|
||||
o.position = ((wp * xlat_mutable_view) * proj);
|
||||
o.uv = xlat_var_input.uv;
|
||||
#line 26
|
||||
return o;
|
||||
}
|
||||
varying highp vec2 xlv_TEXCOORD0;
|
||||
void main() {
|
||||
PS_INPUT xl_retval;
|
||||
xlat_mutable_view = view;
|
||||
VS_INPUT xlt_xlat_var_input;
|
||||
xlt_xlat_var_input.position = vec4( gl_Vertex);
|
||||
xlt_xlat_var_input.uv = vec2( gl_MultiTexCoord0);
|
||||
xl_retval = vs_main( xlt_xlat_var_input);
|
||||
gl_Position = vec4( xl_retval.position);
|
||||
xlv_TEXCOORD0 = vec2( xl_retval.uv);
|
||||
}
|
|
@ -212,11 +212,13 @@ static bool CheckGLSL (bool vertex, const char* source)
|
|||
return res;
|
||||
}
|
||||
|
||||
static bool TestFile (bool vertex,
|
||||
const std::string& inputPath,
|
||||
const std::string& outputPath,
|
||||
bool usePrecision,
|
||||
bool doCheckGLSL)
|
||||
enum TestRun { VERTEX, FRAGMENT, BOTH, NUM_RUN_TYPES };
|
||||
static bool TestFile (TestRun type,
|
||||
const std::string& inputPath,
|
||||
const std::string& outputPath,
|
||||
const char* entryPoint,
|
||||
bool usePrecision,
|
||||
bool doCheckGLSL)
|
||||
{
|
||||
std::string input;
|
||||
if (!ReadStringFromFile (inputPath.c_str(), input))
|
||||
|
@ -224,8 +226,9 @@ static bool TestFile (bool vertex,
|
|||
printf (" failed to read input file\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ShHandle parser = Hlsl2Glsl_ConstructCompiler (vertex ? EShLangVertex : EShLangFragment);
|
||||
|
||||
static const EShLanguage langs[] = {EShLangVertex, EShLangFragment};
|
||||
ShHandle parser = Hlsl2Glsl_ConstructCompiler (langs[type]);
|
||||
|
||||
const char* sourceStr = input.c_str();
|
||||
|
||||
|
@ -255,12 +258,13 @@ static bool TestFile (bool vertex,
|
|||
};
|
||||
Hlsl2Glsl_SetUserAttributeNames (parser, kAttribSemantic, kAttribString, 1);
|
||||
Hlsl2Glsl_UseUserVaryings (parser, true);
|
||||
int translateOk = Hlsl2Glsl_Translate (parser, "main", options);
|
||||
|
||||
int translateOk = Hlsl2Glsl_Translate (parser, entryPoint, options);
|
||||
const char* infoLog = Hlsl2Glsl_GetInfoLog( parser );
|
||||
if (translateOk)
|
||||
{
|
||||
std::string text = Hlsl2Glsl_GetShader (parser);
|
||||
|
||||
|
||||
std::string output;
|
||||
ReadStringFromFile (outputPath.c_str(), output);
|
||||
|
||||
|
@ -273,7 +277,7 @@ static bool TestFile (bool vertex,
|
|||
printf (" does not match expected output\n");
|
||||
res = false;
|
||||
}
|
||||
if (doCheckGLSL && !CheckGLSL (vertex, text.c_str()))
|
||||
if (doCheckGLSL && !CheckGLSL (type == VERTEX, text.c_str()))
|
||||
{
|
||||
res = false;
|
||||
}
|
||||
|
@ -295,6 +299,39 @@ static bool TestFile (bool vertex,
|
|||
return res;
|
||||
}
|
||||
|
||||
static bool TestCombinedFile(const std::string& inputPath,
|
||||
bool usePrecision,
|
||||
bool checkGL)
|
||||
{
|
||||
std::string outname = inputPath.substr (0,inputPath.size()-7);
|
||||
std::string frag_out, vert_out;
|
||||
|
||||
if (usePrecision) {
|
||||
vert_out = outname + "-vertex-outES.txt";
|
||||
frag_out = outname + "-fragment-outES.txt";
|
||||
} else {
|
||||
vert_out = outname + "-vertex-out.txt";
|
||||
frag_out = outname + "-fragment-out.txt";
|
||||
}
|
||||
|
||||
bool res = TestFile(VERTEX, inputPath, vert_out, "vs_main", usePrecision, !usePrecision && checkGL);
|
||||
return res & TestFile(FRAGMENT, inputPath, frag_out, "ps_main", usePrecision, !usePrecision && checkGL);
|
||||
}
|
||||
|
||||
static bool TestFile (TestRun type,
|
||||
const std::string& inputPath,
|
||||
bool usePrecision,
|
||||
bool checkGL)
|
||||
{
|
||||
std::string outname = inputPath.substr (0,inputPath.size()-7);
|
||||
|
||||
if (usePrecision) {
|
||||
return TestFile(type, inputPath, outname + "-outES.txt", "main", true, false);
|
||||
} else {
|
||||
return TestFile(type, inputPath, outname + "-out.txt", "main", false, checkGL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, const char** argv)
|
||||
{
|
||||
|
@ -312,10 +349,10 @@ int main (int argc, const char** argv)
|
|||
|
||||
std::string baseFolder = argv[1];
|
||||
|
||||
static const char* kTypeName[2] = { "vertex", "fragment" };
|
||||
static const char* kTypeName[NUM_RUN_TYPES] = { "vertex", "fragment", "combined" };
|
||||
size_t tests = 0;
|
||||
size_t errors = 0;
|
||||
for (int type = 0; type < 2; ++type)
|
||||
for (int type = 0; type < NUM_RUN_TYPES; ++type)
|
||||
{
|
||||
printf ("testing %s...\n", kTypeName[type]);
|
||||
std::string testFolder = baseFolder + "/" + kTypeName[type];
|
||||
|
@ -326,26 +363,22 @@ int main (int argc, const char** argv)
|
|||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
std::string inname = inputFiles[i];
|
||||
bool ok = true;
|
||||
|
||||
printf ("test %s\n", inname.c_str());
|
||||
std::string outname = inname.substr (0,inname.size()-7) + "-out.txt";
|
||||
std::string outnameES = inname.substr (0,inname.size()-7) + "-outES.txt";
|
||||
bool ok = TestFile (type==0,
|
||||
testFolder + "/" + inname,
|
||||
testFolder + "/" + outname,
|
||||
false,
|
||||
hasOpenGL);
|
||||
if (ok)
|
||||
{
|
||||
ok = TestFile (type==0,
|
||||
testFolder + "/" + inname,
|
||||
testFolder + "/" + outnameES,
|
||||
true,
|
||||
false);
|
||||
|
||||
if (type == BOTH) {
|
||||
ok = TestCombinedFile(testFolder + "/" + inname, false, hasOpenGL);
|
||||
if (ok)
|
||||
ok = TestCombinedFile(testFolder + "/" + inname, true, false);
|
||||
} else {
|
||||
ok = TestFile(TestRun(type), testFolder + "/" + inname, false, hasOpenGL);
|
||||
if (ok)
|
||||
ok = TestFile(TestRun(type), testFolder + "/" + inname, true, false);
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
++errors;
|
||||
}
|
||||
}
|
||||
}
|
||||
clock_t time1 = clock();
|
||||
|
|
Загрузка…
Ссылка в новой задаче