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()
sprintf(semantic, " : TEXCOORD%d", semanticIndex);
semanticIndex += type.isArray() ? type.getArraySize() : 1;
// Program linking depends on this exact format
varyingInput += " " + typeString(type) + " " + name + arrayString(type) + semantic + ";\n";
varyingGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
}
......@@ -74,7 +75,7 @@ void OutputHLSL::header()
"struct PS_INPUT\n" // FIXME: Prevent name clashes
"{\n";
out << varyingInput;
out << " float4 gl_FragCoord : TEXCOORD" << HLSL_FRAG_COORD_SEMANTIC << ";\n";
out << " float4 gl_FragCoord : TEXCOORD" << semanticIndex << ";\n";
out << " float __vFace : VFACE;\n"
"};\n"
"\n";
......@@ -147,6 +148,7 @@ void OutputHLSL::header()
}
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
varyingGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
}
......@@ -177,7 +179,7 @@ void OutputHLSL::header()
"{\n"
" float4 gl_Position : POSITION;\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 << "};\n"
"\n"
......@@ -501,6 +503,7 @@ void OutputHLSL::footer()
if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
{
// Program linking depends on this exact format
out << " output." + name + " = " + name + ";\n"; // FIXME: Prevent name clashes
}
}
......
......@@ -12,11 +12,6 @@
namespace sh
{
enum
{
HLSL_FRAG_COORD_SEMANTIC = 15 // Semantic index assigned to the gl_FragCoord varying
};
class OutputHLSL : public TIntermTraverser
{
public:
......
......@@ -41,6 +41,8 @@ Program::Program()
mAttributeName[index] = NULL;
}
mPixelHLSL = NULL;
mVertexHLSL = NULL;
mInfoLog = NULL;
unlink();
......@@ -398,6 +400,92 @@ ID3DXBuffer *Program::compileToBinary(const char *hlsl, const char *profile, ID3
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 @@ void Program::link()
unlink();
delete[] mInfoLog;
mInfoLog = NULL;
if (!mFragmentShader || !mFragmentShader->isCompiled())
{
return;
......@@ -427,10 +512,21 @@ void Program::link()
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 @@ void Program::unlink(bool destroy)
delete[] mAttributeName[index];
mAttributeName[index] = NULL;
}
delete[] mInfoLog;
mInfoLog = NULL;
}
if (mPixelExecutable)
......@@ -1013,6 +1106,15 @@ void Program::unlink(bool destroy)
mUniforms.pop_back();
}
delete[] mPixelHLSL;
mPixelHLSL = NULL;
delete[] mVertexHLSL;
mVertexHLSL = NULL;
delete[] mInfoLog;
mInfoLog = NULL;
mLinked = false;
}
......
......@@ -83,7 +83,25 @@ class Program
ID3DXBuffer *compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable);
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 linkUniforms(ID3DXConstantTable *constantTable);
bool defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name = "");
bool defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name);
......@@ -102,6 +120,9 @@ class Program
FragmentShader *mFragmentShader;
VertexShader *mVertexShader;
char *mPixelHLSL;
char *mVertexHLSL;
IDirect3DPixelShader9 *mPixelExecutable;
IDirect3DVertexShader9 *mVertexExecutable;
ID3DXConstantTable *mConstantTablePS;
......
......@@ -171,7 +171,7 @@ bool Shader::isCompiled()
return mHlsl != NULL;
}
const char *Shader::linkHLSL()
const char *Shader::getHLSL()
{
return mHlsl;
}
......@@ -306,45 +306,6 @@ void VertexShader::compile()
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)
{
if (attributeIndex < MAX_VERTEX_ATTRIBS)
......
......@@ -39,7 +39,7 @@ class Shader
virtual void compile() = 0;
bool isCompiled();
const char *linkHLSL();
const char *getHLSL();
void attach();
void detach();
......@@ -90,7 +90,6 @@ class VertexShader : public Shader
GLenum getType();
void compile();
const char *linkHLSL(const char *pixelHLSL);
const char *getAttributeName(unsigned int attributeIndex);
bool isActiveAttribute(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