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
parent 279e38ad
...@@ -50,6 +50,7 @@ void OutputHLSL::header() ...@@ -50,6 +50,7 @@ void OutputHLSL::header()
sprintf(semantic, " : TEXCOORD%d", semanticIndex); sprintf(semantic, " : TEXCOORD%d", semanticIndex);
semanticIndex += type.isArray() ? type.getArraySize() : 1; semanticIndex += type.isArray() ? type.getArraySize() : 1;
// Program linking depends on this exact format
varyingInput += " " + typeString(type) + " " + name + arrayString(type) + semantic + ";\n"; varyingInput += " " + typeString(type) + " " + name + arrayString(type) + semantic + ";\n";
varyingGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n"; varyingGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
} }
...@@ -74,7 +75,7 @@ void OutputHLSL::header() ...@@ -74,7 +75,7 @@ void OutputHLSL::header()
"struct PS_INPUT\n" // FIXME: Prevent name clashes "struct PS_INPUT\n" // FIXME: Prevent name clashes
"{\n"; "{\n";
out << varyingInput; out << varyingInput;
out << " float4 gl_FragCoord : TEXCOORD" << HLSL_FRAG_COORD_SEMANTIC << ";\n"; out << " float4 gl_FragCoord : TEXCOORD" << semanticIndex << ";\n";
out << " float __vFace : VFACE;\n" out << " float __vFace : VFACE;\n"
"};\n" "};\n"
"\n"; "\n";
...@@ -147,6 +148,7 @@ void OutputHLSL::header() ...@@ -147,6 +148,7 @@ void OutputHLSL::header()
} }
else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut) else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
{ {
// Program linking depends on this exact format
varyingOutput += " " + typeString(type) + " " + name + arrayString(type) + " : TEXCOORD0;\n"; // Actual semantic index assigned during link varyingOutput += " " + typeString(type) + " " + name + arrayString(type) + " : TEXCOORD0;\n"; // Actual semantic index assigned during link
varyingGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n"; varyingGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
} }
...@@ -177,7 +179,7 @@ void OutputHLSL::header() ...@@ -177,7 +179,7 @@ void OutputHLSL::header()
"{\n" "{\n"
" float4 gl_Position : POSITION;\n" " float4 gl_Position : POSITION;\n"
" float gl_PointSize : PSIZE;\n" " float gl_PointSize : PSIZE;\n"
" float4 gl_FragCoord : TEXCOORD" << HLSL_FRAG_COORD_SEMANTIC << ";\n"; " float4 gl_FragCoord : TEXCOORD0;\n"; // Actual semantic index assigned during link
out << varyingOutput; out << varyingOutput;
out << "};\n" out << "};\n"
"\n" "\n"
...@@ -501,6 +503,7 @@ void OutputHLSL::footer() ...@@ -501,6 +503,7 @@ void OutputHLSL::footer()
if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut) if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
{ {
// Program linking depends on this exact format
out << " output." + name + " = " + name + ";\n"; // FIXME: Prevent name clashes out << " output." + name + " = " + name + ";\n"; // FIXME: Prevent name clashes
} }
} }
......
...@@ -12,11 +12,6 @@ ...@@ -12,11 +12,6 @@
namespace sh namespace sh
{ {
enum
{
HLSL_FRAG_COORD_SEMANTIC = 15 // Semantic index assigned to the gl_FragCoord varying
};
class OutputHLSL : public TIntermTraverser class OutputHLSL : public TIntermTraverser
{ {
public: public:
......
...@@ -41,6 +41,8 @@ Program::Program() ...@@ -41,6 +41,8 @@ Program::Program()
mAttributeName[index] = NULL; mAttributeName[index] = NULL;
} }
mPixelHLSL = NULL;
mVertexHLSL = NULL;
mInfoLog = NULL; mInfoLog = NULL;
unlink(); unlink();
...@@ -398,6 +400,92 @@ ID3DXBuffer *Program::compileToBinary(const char *hlsl, const char *profile, ID3 ...@@ -398,6 +400,92 @@ ID3DXBuffer *Program::compileToBinary(const char *hlsl, const char *profile, ID3
return NULL; 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, // 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 // compiling them into binaries, determining the attribute mappings, and collecting
// a list of uniforms // a list of uniforms
...@@ -410,9 +498,6 @@ void Program::link() ...@@ -410,9 +498,6 @@ void Program::link()
unlink(); unlink();
delete[] mInfoLog;
mInfoLog = NULL;
if (!mFragmentShader || !mFragmentShader->isCompiled()) if (!mFragmentShader || !mFragmentShader->isCompiled())
{ {
return; return;
...@@ -427,10 +512,21 @@ void Program::link() ...@@ -427,10 +512,21 @@ void Program::link()
const char *vertexProfile = context->getVertexShaderProfile(); const char *vertexProfile = context->getVertexShaderProfile();
const char *pixelProfile = context->getPixelShaderProfile(); const char *pixelProfile = context->getPixelShaderProfile();
const char *pixelHLSL = mFragmentShader->linkHLSL(); const char *ps = mFragmentShader->getHLSL();
const char *vertexHLSL = mVertexShader->linkHLSL(pixelHLSL); const char *vs = mVertexShader->getHLSL();
ID3DXBuffer *vertexBinary = compileToBinary(vertexHLSL, vertexProfile, &mConstantTableVS);
ID3DXBuffer *pixelBinary = compileToBinary(pixelHLSL, pixelProfile, &mConstantTablePS); 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) if (vertexBinary && pixelBinary)
{ {
...@@ -968,9 +1064,6 @@ void Program::unlink(bool destroy) ...@@ -968,9 +1064,6 @@ void Program::unlink(bool destroy)
delete[] mAttributeName[index]; delete[] mAttributeName[index];
mAttributeName[index] = NULL; mAttributeName[index] = NULL;
} }
delete[] mInfoLog;
mInfoLog = NULL;
} }
if (mPixelExecutable) if (mPixelExecutable)
...@@ -1013,6 +1106,15 @@ void Program::unlink(bool destroy) ...@@ -1013,6 +1106,15 @@ void Program::unlink(bool destroy)
mUniforms.pop_back(); mUniforms.pop_back();
} }
delete[] mPixelHLSL;
mPixelHLSL = NULL;
delete[] mVertexHLSL;
mVertexHLSL = NULL;
delete[] mInfoLog;
mInfoLog = NULL;
mLinked = false; mLinked = false;
} }
......
...@@ -83,7 +83,25 @@ class Program ...@@ -83,7 +83,25 @@ class Program
ID3DXBuffer *compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable); ID3DXBuffer *compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable);
void unlink(bool destroy = false); void unlink(bool destroy = false);
struct Varying
{
Varying(const std::string &name, char *declaration) : name(name), declaration(declaration)
{
link = -1;
}
int link;
std::string name;
char *declaration;
};
typedef std::vector<Varying> VaryingArray;
void parseVaryings(const char *structure, char *hlsl, VaryingArray &varyings);
bool linkVaryings();
bool linkAttributes(); bool linkAttributes();
bool linkUniforms(ID3DXConstantTable *constantTable); bool linkUniforms(ID3DXConstantTable *constantTable);
bool defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name = ""); bool defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name = "");
bool defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name); bool defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name);
...@@ -102,6 +120,9 @@ class Program ...@@ -102,6 +120,9 @@ class Program
FragmentShader *mFragmentShader; FragmentShader *mFragmentShader;
VertexShader *mVertexShader; VertexShader *mVertexShader;
char *mPixelHLSL;
char *mVertexHLSL;
IDirect3DPixelShader9 *mPixelExecutable; IDirect3DPixelShader9 *mPixelExecutable;
IDirect3DVertexShader9 *mVertexExecutable; IDirect3DVertexShader9 *mVertexExecutable;
ID3DXConstantTable *mConstantTablePS; ID3DXConstantTable *mConstantTablePS;
......
...@@ -171,7 +171,7 @@ bool Shader::isCompiled() ...@@ -171,7 +171,7 @@ bool Shader::isCompiled()
return mHlsl != NULL; return mHlsl != NULL;
} }
const char *Shader::linkHLSL() const char *Shader::getHLSL()
{ {
return mHlsl; return mHlsl;
} }
...@@ -306,45 +306,6 @@ void VertexShader::compile() ...@@ -306,45 +306,6 @@ void VertexShader::compile()
parseAttributes(); parseAttributes();
} }
const char *VertexShader::linkHLSL(const char *pixelHLSL)
{
if (mHlsl && pixelHLSL)
{
const char *input = strstr(pixelHLSL, "struct PS_INPUT");
char *output = strstr(mHlsl, "struct VS_OUTPUT");
while (*input != '}' && output)
{
char varyingName[100];
unsigned int semanticIndex;
int matches = sscanf(input, "%s : TEXCOORD%d;", varyingName, &semanticIndex);
if (matches == 2 && semanticIndex != sh::HLSL_FRAG_COORD_SEMANTIC)
{
ASSERT(semanticIndex < MAX_VARYING_VECTORS);
char *varying = strstr(output, varyingName);
if (varying)
{
ASSERT(semanticIndex <= 9); // Single character
varying = strstr(varying, " : TEXCOORD0;");
varying[11] = '0' + semanticIndex;
}
else
{
return NULL;
}
input = strstr(input, ";");
}
input++;
}
}
return mHlsl;
}
const char *VertexShader::getAttributeName(unsigned int attributeIndex) const char *VertexShader::getAttributeName(unsigned int attributeIndex)
{ {
if (attributeIndex < MAX_VERTEX_ATTRIBS) if (attributeIndex < MAX_VERTEX_ATTRIBS)
......
...@@ -39,7 +39,7 @@ class Shader ...@@ -39,7 +39,7 @@ class Shader
virtual void compile() = 0; virtual void compile() = 0;
bool isCompiled(); bool isCompiled();
const char *linkHLSL(); const char *getHLSL();
void attach(); void attach();
void detach(); void detach();
...@@ -90,7 +90,6 @@ class VertexShader : public Shader ...@@ -90,7 +90,6 @@ class VertexShader : public Shader
GLenum getType(); GLenum getType();
void compile(); void compile();
const char *linkHLSL(const char *pixelHLSL);
const char *getAttributeName(unsigned int attributeIndex); const char *getAttributeName(unsigned int attributeIndex);
bool isActiveAttribute(const char *attributeName); bool isActiveAttribute(const char *attributeName);
int getInputMapping(const char *attributeName); int getInputMapping(const char *attributeName);
......
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