Compiler - implement proper varying linking
TRAC #11716
Signed-off-by: Shannon Woods
Signed-off-by: Daniel Koch
Author: Nicolas Capens
git-svn-id: https://angleproject.googlecode.com/svn/trunk@97 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Program.cpp b/src/libGLESv2/Program.cpp
index 3030ac1..252c5a4 100644
--- a/src/libGLESv2/Program.cpp
+++ b/src/libGLESv2/Program.cpp
@@ -41,6 +41,8 @@
mAttributeName[index] = NULL;
}
+ mPixelHLSL = NULL;
+ mVertexHLSL = NULL;
mInfoLog = NULL;
unlink();
@@ -398,6 +400,92 @@
return NULL;
}
+void Program::parseVaryings(const char *structure, char *hlsl, VaryingArray &varyings)
+{
+ char *input = strstr(hlsl, structure);
+ input += strlen(structure);
+
+ while (input && *input != '}')
+ {
+ char varyingType[256];
+ char varyingName[256];
+ unsigned int semanticIndex;
+ int matches = sscanf(input, " %s %s : TEXCOORD%d;", varyingType, varyingName, &semanticIndex);
+
+ if (matches == 3)
+ {
+ ASSERT(semanticIndex <= 9); // Single character
+
+ varyings.push_back(Varying(varyingName, input));
+ }
+
+ input = strstr(input, ";");
+ input += 2;
+ }
+}
+
+bool Program::linkVaryings()
+{
+ if (!mPixelHLSL || !mVertexHLSL)
+ {
+ return false;
+ }
+
+ VaryingArray vertexVaryings;
+ VaryingArray pixelVaryings;
+
+ parseVaryings("struct VS_OUTPUT\n{\n", mVertexHLSL, vertexVaryings);
+ parseVaryings("struct PS_INPUT\n{\n", mPixelHLSL, pixelVaryings);
+
+ for (unsigned int out = 0; out < vertexVaryings.size(); out++)
+ {
+ unsigned int in;
+ for (in = 0; in < pixelVaryings.size(); in++)
+ {
+ if (vertexVaryings[out].name == pixelVaryings[in].name)
+ {
+ pixelVaryings[in].link = out;
+ vertexVaryings[out].link = in;
+
+ break;
+ }
+ }
+
+ if (in != pixelVaryings.size())
+ {
+ // FIXME: Verify matching type and qualifiers
+
+ char *outputSemantic = strstr(vertexVaryings[out].declaration, " : TEXCOORD");
+ char *inputSemantic = strstr(pixelVaryings[in].declaration, " : TEXCOORD");
+ outputSemantic[11] = inputSemantic[11];
+ }
+ else
+ {
+ // Comment out the declaration and output assignment
+ vertexVaryings[out].declaration[0] = '/';
+ vertexVaryings[out].declaration[1] = '/';
+
+ char outputString[256];
+ sprintf(outputString, " output.%s = ", vertexVaryings[out].name.c_str());
+ char *varyingOutput = strstr(mVertexHLSL, outputString);
+
+ varyingOutput[0] = '/';
+ varyingOutput[1] = '/';
+ }
+ }
+
+ // Verify that each pixel varying has been linked to a vertex varying
+ for (unsigned int in = 0; in < pixelVaryings.size(); in++)
+ {
+ if (pixelVaryings[in].link < 0)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
// compiling them into binaries, determining the attribute mappings, and collecting
// a list of uniforms
@@ -410,9 +498,6 @@
unlink();
- delete[] mInfoLog;
- mInfoLog = NULL;
-
if (!mFragmentShader || !mFragmentShader->isCompiled())
{
return;
@@ -427,10 +512,21 @@
const char *vertexProfile = context->getVertexShaderProfile();
const char *pixelProfile = context->getPixelShaderProfile();
- const char *pixelHLSL = mFragmentShader->linkHLSL();
- const char *vertexHLSL = mVertexShader->linkHLSL(pixelHLSL);
- ID3DXBuffer *vertexBinary = compileToBinary(vertexHLSL, vertexProfile, &mConstantTableVS);
- ID3DXBuffer *pixelBinary = compileToBinary(pixelHLSL, pixelProfile, &mConstantTablePS);
+ const char *ps = mFragmentShader->getHLSL();
+ const char *vs = mVertexShader->getHLSL();
+
+ mPixelHLSL = new char[strlen(ps) + 1];
+ strcpy(mPixelHLSL, ps);
+ mVertexHLSL = new char[strlen(vs) + 1];
+ strcpy(mVertexHLSL, vs);
+
+ if (!linkVaryings())
+ {
+ return;
+ }
+
+ ID3DXBuffer *vertexBinary = compileToBinary(mVertexHLSL, vertexProfile, &mConstantTableVS);
+ ID3DXBuffer *pixelBinary = compileToBinary(mPixelHLSL, pixelProfile, &mConstantTablePS);
if (vertexBinary && pixelBinary)
{
@@ -968,9 +1064,6 @@
delete[] mAttributeName[index];
mAttributeName[index] = NULL;
}
-
- delete[] mInfoLog;
- mInfoLog = NULL;
}
if (mPixelExecutable)
@@ -1013,6 +1106,15 @@
mUniforms.pop_back();
}
+ delete[] mPixelHLSL;
+ mPixelHLSL = NULL;
+
+ delete[] mVertexHLSL;
+ mVertexHLSL = NULL;
+
+ delete[] mInfoLog;
+ mInfoLog = NULL;
+
mLinked = false;
}