Implemented varying packing

TRAC #11736 The OpenGL ES Shading Language 1.00 rev. 17 appendix A section 7 page 111, details how varyings should be packed into generic varying registers. To implement this the HLSL main() function is now generated and appended to the code during link time, where the packing and mapping can happen. Signed-off-by: Shannon Woods Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@282 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent d7c98101
......@@ -32,7 +32,6 @@ class OutputHLSL : public TIntermTraverser
protected:
void header();
void footer();
// Visit AST nodes and output their code to the body stream
void visitSymbol(TIntermSymbol*);
......@@ -74,6 +73,10 @@ class OutputHLSL : public TIntermTraverser
bool mUsesTextureCube;
bool mUsesTextureCube_bias;
bool mUsesDepthRange;
bool mUsesFragCoord;
bool mUsesPointCoord;
bool mUsesFrontFacing;
bool mUsesPointSize;
bool mUsesXor;
bool mUsesMod1;
bool mUsesMod2;
......
......@@ -121,21 +121,7 @@ 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);
int packVaryings(const Varying *packing[][4]);
bool linkVaryings();
bool linkAttributes();
......@@ -172,8 +158,8 @@ class Program
FragmentShader *mFragmentShader;
VertexShader *mVertexShader;
char *mPixelHLSL;
char *mVertexHLSL;
std::string mPixelHLSL;
std::string mVertexHLSL;
IDirect3DPixelShader9 *mPixelExecutable;
IDirect3DVertexShader9 *mVertexExecutable;
......
......@@ -15,6 +15,7 @@
#include "common/debug.h"
#include "libGLESv2/main.h"
#include "libGLESv2/utilities.h"
namespace gl
{
......@@ -216,39 +217,41 @@ void Shader::releaseCompiler()
mVertexCompiler = NULL;
}
GLenum Shader::parseAttributeType(const std::string &type)
void Shader::parseVaryings()
{
if (type == "float")
{
return GL_FLOAT;
}
else if (type == "float2")
{
return GL_FLOAT_VEC2;
}
else if (type == "float3")
if (mHlsl)
{
return GL_FLOAT_VEC3;
}
else if (type == "float4")
const char *input = strstr(mHlsl, "// Varyings") + 12;
while(true)
{
return GL_FLOAT_VEC4;
}
else if (type == "float2x2")
char varyingType[256];
char varyingName[256];
int matches = sscanf(input, "static %s %s", varyingType, varyingName);
if (matches != 2)
{
return GL_FLOAT_MAT2;
break;
}
else if (type == "float3x3")
char *array = strstr(varyingName, "[");
int size = 1;
if (array)
{
return GL_FLOAT_MAT3;
size = atoi(array + 1);
*array = '\0';
}
else if (type == "float4x4")
{
return GL_FLOAT_MAT4;
varyings.push_back(Varying(parseType(varyingType), varyingName, size, array != NULL));
input = strstr(input, ";") + 2;
}
else UNREACHABLE();
return GL_NONE;
mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL;
mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
}
}
void Shader::compileToHLSL(void *compiler)
......@@ -294,6 +297,124 @@ void Shader::compileToHLSL(void *compiler)
}
}
GLenum Shader::parseType(const std::string &type)
{
if (type == "float")
{
return GL_FLOAT;
}
else if (type == "float2")
{
return GL_FLOAT_VEC2;
}
else if (type == "float3")
{
return GL_FLOAT_VEC3;
}
else if (type == "float4")
{
return GL_FLOAT_VEC4;
}
else if (type == "float2x2")
{
return GL_FLOAT_MAT2;
}
else if (type == "float3x3")
{
return GL_FLOAT_MAT3;
}
else if (type == "float4x4")
{
return GL_FLOAT_MAT4;
}
else UNREACHABLE();
return GL_NONE;
}
// true if varying x has a higher priority in packing than y
bool Shader::compareVarying(const Varying &x, const Varying &y)
{
if(x.type == y.type)
{
return x.size > y.size;
}
switch (x.type)
{
case GL_FLOAT_MAT4: return true;
case GL_FLOAT_MAT2:
switch(y.type)
{
case GL_FLOAT_MAT4: return false;
case GL_FLOAT_MAT2: return true;
case GL_FLOAT_VEC4: return true;
case GL_FLOAT_MAT3: return true;
case GL_FLOAT_VEC3: return true;
case GL_FLOAT_VEC2: return true;
case GL_FLOAT: return true;
default: UNREACHABLE();
}
break;
case GL_FLOAT_VEC4:
switch(y.type)
{
case GL_FLOAT_MAT4: return false;
case GL_FLOAT_MAT2: return false;
case GL_FLOAT_VEC4: return true;
case GL_FLOAT_MAT3: return true;
case GL_FLOAT_VEC3: return true;
case GL_FLOAT_VEC2: return true;
case GL_FLOAT: return true;
default: UNREACHABLE();
}
break;
case GL_FLOAT_MAT3:
switch(y.type)
{
case GL_FLOAT_MAT4: return false;
case GL_FLOAT_MAT2: return false;
case GL_FLOAT_VEC4: return false;
case GL_FLOAT_MAT3: return true;
case GL_FLOAT_VEC3: return true;
case GL_FLOAT_VEC2: return true;
case GL_FLOAT: return true;
default: UNREACHABLE();
}
break;
case GL_FLOAT_VEC3:
switch(y.type)
{
case GL_FLOAT_MAT4: return false;
case GL_FLOAT_MAT2: return false;
case GL_FLOAT_VEC4: return false;
case GL_FLOAT_MAT3: return false;
case GL_FLOAT_VEC3: return true;
case GL_FLOAT_VEC2: return true;
case GL_FLOAT: return true;
default: UNREACHABLE();
}
break;
case GL_FLOAT_VEC2:
switch(y.type)
{
case GL_FLOAT_MAT4: return false;
case GL_FLOAT_MAT2: return false;
case GL_FLOAT_VEC4: return false;
case GL_FLOAT_MAT3: return false;
case GL_FLOAT_VEC3: return false;
case GL_FLOAT_VEC2: return true;
case GL_FLOAT: return true;
default: UNREACHABLE();
}
break;
case GL_FLOAT: return false;
default: UNREACHABLE();
}
return false;
}
VertexShader::VertexShader(Context *context, GLuint handle) : Shader(context, handle)
{
}
......@@ -311,25 +432,22 @@ void VertexShader::compile()
{
compileToHLSL(mVertexCompiler);
parseAttributes();
}
const Attribute &VertexShader::getAttribute(unsigned int semanticIndex)
{
ASSERT(semanticIndex < MAX_VERTEX_ATTRIBS + 1);
return mAttribute[semanticIndex];
parseVaryings();
}
int VertexShader::getSemanticIndex(const std::string &attributeName)
{
if (!attributeName.empty())
{
for (int semanticIndex = 0; semanticIndex < MAX_VERTEX_ATTRIBS; semanticIndex++)
int semanticIndex = 0;
for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++)
{
if (mAttribute[semanticIndex].name == attributeName)
if (attribute->name == attributeName)
{
return semanticIndex;
}
semanticIndex += VariableRowCount(attribute->type);
}
}
......@@ -340,30 +458,23 @@ void VertexShader::parseAttributes()
{
if (mHlsl)
{
const char *input = strstr(mHlsl, "struct VS_INPUT");
const char *input = strstr(mHlsl, "// Attributes") + 14;
for (int attributeIndex = 0; *input != '}'; input++)
while(true)
{
char attributeType[100];
char attributeName[100];
int semanticIndex;
char attributeType[256];
char attributeName[256];
int matches = sscanf(input, "%s _%s : TEXCOORD%d;", attributeType, attributeName, &semanticIndex);
int matches = sscanf(input, "static %s _%s", attributeType, attributeName);
if (matches == 3)
{
if (semanticIndex < MAX_VERTEX_ATTRIBS + 1)
{
mAttribute[semanticIndex].type = parseAttributeType(attributeType);
mAttribute[semanticIndex].name = attributeName;
}
else
if (matches != 2)
{
break;
}
input = strstr(input, ";");
}
mAttributes.push_back(Attribute(parseType(attributeType), attributeName));
input = strstr(input, ";") + 2;
}
}
}
......@@ -384,5 +495,7 @@ GLenum FragmentShader::getType()
void FragmentShader::compile()
{
compileToHLSL(mFragmentCompiler);
parseVaryings();
varyings.sort(compareVarying);
}
}
......@@ -15,13 +15,35 @@
#define GL_APICALL
#include <GLES2/gl2.h>
#include <d3dx9.h>
#include <list>
#include <vector>
#include "libGLESv2/Context.h"
namespace gl
{
struct Varying
{
Varying(GLenum type, const std::string &name, int size, bool array)
: type(type), name(name), size(size), array(array), reg(-1), col(-1)
{
}
GLenum type;
std::string name;
int size; // Number of 'type' elements
bool array;
int reg; // First varying register, assigned during link
int col; // First register element, assigned during link
};
typedef std::list<Varying> VaryingList;
class Shader
{
friend Program;
public:
Shader(Context *context, GLuint handle);
......@@ -48,13 +70,17 @@ class Shader
void flagForDeletion();
static void releaseCompiler();
static GLenum parseAttributeType(const std::string &type);
protected:
DISALLOW_COPY_AND_ASSIGN(Shader);
void parseVaryings();
void compileToHLSL(void *compiler);
static GLenum parseType(const std::string &type);
static bool compareVarying(const Varying &x, const Varying &y);
const GLuint mHandle;
int mAttachCount; // Number of program objects this shader is attached to
bool mDeleteStatus; // Flag to indicate that the shader can be deleted when no longer in use
......@@ -63,6 +89,11 @@ class Shader
char *mHlsl;
char *mInfoLog;
VaryingList varyings;
bool mUsesFragCoord;
bool mUsesFrontFacing;
Context *mContext;
static void *mFragmentCompiler;
......@@ -71,12 +102,24 @@ class Shader
struct Attribute
{
Attribute() : type(GL_NONE), name("")
{
}
Attribute(GLenum type, const std::string &name) : type(type), name(name)
{
}
GLenum type;
std::string name;
};
typedef std::vector<Attribute> AttributeArray;
class VertexShader : public Shader
{
friend Program;
public:
VertexShader(Context *context, GLuint handle);
......@@ -84,7 +127,6 @@ class VertexShader : public Shader
GLenum getType();
void compile();
const Attribute &getAttribute(unsigned int attributeIndex);
int getSemanticIndex(const std::string &attributeName);
private:
......@@ -92,7 +134,7 @@ class VertexShader : public Shader
void parseAttributes();
Attribute mAttribute[MAX_VERTEX_ATTRIBS + 1]; // One extra to report link error
AttributeArray mAttributes;
};
class FragmentShader : public Shader
......
......@@ -91,10 +91,12 @@ size_t UniformTypeSize(GLenum type)
return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type);
}
int AttributeVectorCount(GLenum type)
int VariableRowCount(GLenum type)
{
switch (type)
{
case GL_NONE:
return 0;
case GL_BOOL:
case GL_FLOAT:
case GL_INT:
......@@ -108,20 +110,49 @@ int AttributeVectorCount(GLenum type)
case GL_FLOAT_VEC4:
case GL_INT_VEC4:
return 1;
case GL_FLOAT_MAT2:
return 2;
case GL_FLOAT_MAT3:
return 3;
case GL_FLOAT_MAT4:
return 4;
default:
UNREACHABLE();
}
return 0;
}
int VariableColumnCount(GLenum type)
{
switch (type)
{
case GL_NONE:
return 0;
case GL_BOOL:
case GL_FLOAT:
case GL_INT:
return 1;
case GL_BOOL_VEC2:
case GL_FLOAT_VEC2:
case GL_INT_VEC2:
case GL_FLOAT_MAT2:
return 2;
case GL_INT_VEC3:
case GL_FLOAT_VEC3:
case GL_BOOL_VEC3:
case GL_FLOAT_MAT3:
return 3;
case GL_BOOL_VEC4:
case GL_FLOAT_VEC4:
case GL_INT_VEC4:
case GL_FLOAT_MAT4:
return 4;
default:
UNREACHABLE();
}
return 0;
}
int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
......
......@@ -21,7 +21,8 @@ struct Color;
int UniformComponentCount(GLenum type);
GLenum UniformComponentType(GLenum type);
size_t UniformTypeSize(GLenum type);
int AttributeVectorCount(GLenum type);
int VariableRowCount(GLenum type);
int VariableColumnCount(GLenum type);
int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
......
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