Commit 7a29e4ae by Jamie Madill

Stop generating duplicate vertex binaries.

We would generate multiple vertex binaries that result in the same HLSL code, eg for vec2 and vec3 vertex attributes. Eliminate duplicates by using the converted attribute type for testing for matching binaries. BUG=angle:599 Change-Id: I061588164577ff9fa69ebb7d8a3f2bf6bb6fe013 Reviewed-on: https://chromium-review.googlesource.com/197830Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent de0ec75e
...@@ -1027,21 +1027,36 @@ std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &ver ...@@ -1027,21 +1027,36 @@ std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &ver
GLenum shaderComponentType = UniformComponentType(shaderAttrib.type); GLenum shaderComponentType = UniformComponentType(shaderAttrib.type);
int shaderComponentCount = UniformComponentCount(shaderAttrib.type); int shaderComponentCount = UniformComponentCount(shaderAttrib.type);
std::string padString = "";
// Perform integer to float conversion (if necessary) // Perform integer to float conversion (if necessary)
bool requiresTypeConversion = (shaderComponentType == GL_FLOAT && vertexFormat.mType != GL_FLOAT); bool requiresTypeConversion = (shaderComponentType == GL_FLOAT && vertexFormat.mType != GL_FLOAT);
// TODO: normalization for 32-bit integer formats if (requiresTypeConversion)
ASSERT(!requiresTypeConversion || !vertexFormat.mNormalized);
if (requiresTypeConversion || !padString.empty())
{ {
return "float" + Str(shaderComponentCount) + "(" + attribString + padString + ")"; // TODO: normalization for 32-bit integer formats
ASSERT(!vertexFormat.mNormalized && !vertexFormat.mPureInteger);
return "float" + Str(shaderComponentCount) + "(" + attribString + ")";
} }
// No conversion necessary // No conversion necessary
return attribString; return attribString;
} }
void DynamicHLSL::getInputLayoutSignature(const VertexFormat inputLayout[], GLenum signature[]) const
{
for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++)
{
const VertexFormat &vertexFormat = inputLayout[inputIndex];
if (vertexFormat.mType == GL_NONE)
{
signature[inputIndex] = GL_NONE;
}
else
{
bool gpuConverted = ((mRenderer->getVertexConversionType(vertexFormat) & rx::VERTEX_CONVERT_GPU) != 0);
signature[inputIndex] = (gpuConverted ? GL_TRUE : GL_FALSE);
}
}
}
} }
...@@ -45,6 +45,7 @@ class DynamicHLSL ...@@ -45,6 +45,7 @@ class DynamicHLSL
std::map<int, VariableLocation> *programOutputVars) const; std::map<int, VariableLocation> *programOutputVars) const;
std::string generateGeometryShaderHLSL(int registers, const ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const; std::string generateGeometryShaderHLSL(int registers, const ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
void getInputLayoutSignature(const VertexFormat inputLayout[], GLenum signature[]) const;
static const std::string VERTEX_ATTRIBUTE_STUB_STRING; static const std::string VERTEX_ATTRIBUTE_STUB_STRING;
......
...@@ -85,12 +85,14 @@ VariableLocation::VariableLocation(const std::string &name, unsigned int element ...@@ -85,12 +85,14 @@ VariableLocation::VariableLocation(const std::string &name, unsigned int element
ProgramBinary::VertexExecutable::VertexExecutable(rx::Renderer *const renderer, ProgramBinary::VertexExecutable::VertexExecutable(rx::Renderer *const renderer,
const VertexFormat inputLayout[], const VertexFormat inputLayout[],
const GLenum signature[],
rx::ShaderExecutable *shaderExecutable) rx::ShaderExecutable *shaderExecutable)
: mShaderExecutable(shaderExecutable) : mShaderExecutable(shaderExecutable)
{ {
for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
{ {
mInputs[attributeIndex] = inputLayout[attributeIndex]; mInputs[attributeIndex] = inputLayout[attributeIndex];
mSignature[attributeIndex] = signature[attributeIndex];
} }
} }
...@@ -99,11 +101,11 @@ ProgramBinary::VertexExecutable::~VertexExecutable() ...@@ -99,11 +101,11 @@ ProgramBinary::VertexExecutable::~VertexExecutable()
delete mShaderExecutable; delete mShaderExecutable;
} }
bool ProgramBinary::VertexExecutable::matchesInputLayout(const VertexFormat attributes[]) const bool ProgramBinary::VertexExecutable::matchesSignature(const GLenum signature[]) const
{ {
for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
{ {
if (mInputs[attributeIndex] != attributes[attributeIndex]) if (mSignature[attributeIndex] != signature[attributeIndex])
{ {
return false; return false;
} }
...@@ -206,11 +208,14 @@ rx::ShaderExecutable *ProgramBinary::getPixelExecutable() const ...@@ -206,11 +208,14 @@ rx::ShaderExecutable *ProgramBinary::getPixelExecutable() const
return mPixelExecutable; return mPixelExecutable;
} }
rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]) rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])
{ {
GLenum signature[MAX_VERTEX_ATTRIBS];
mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
{ {
if (mVertexExecutables[executableIndex]->matchesInputLayout(inputLayout)) if (mVertexExecutables[executableIndex]->matchesSignature(signature))
{ {
return mVertexExecutables[executableIndex]->shaderExecutable(); return mVertexExecutables[executableIndex]->shaderExecutable();
} }
...@@ -240,7 +245,7 @@ rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const Ver ...@@ -240,7 +245,7 @@ rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const Ver
} }
else else
{ {
mVertexExecutables.push_back(new VertexExecutable(mRenderer, inputLayout, vertexExecutable)); mVertexExecutables.push_back(new VertexExecutable(mRenderer, inputLayout, signature, vertexExecutable));
} }
return vertexExecutable; return vertexExecutable;
...@@ -1234,11 +1239,11 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) ...@@ -1234,11 +1239,11 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
{ {
VertexFormat vertexInputs[gl::MAX_VERTEX_ATTRIBS]; VertexFormat inputLayout[MAX_VERTEX_ATTRIBS];
for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++) for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++)
{ {
VertexFormat *vertexInput = &vertexInputs[inputIndex]; VertexFormat *vertexInput = &inputLayout[inputIndex];
stream.read(&vertexInput->mType); stream.read(&vertexInput->mType);
stream.read(&vertexInput->mNormalized); stream.read(&vertexInput->mNormalized);
stream.read(&vertexInput->mComponents); stream.read(&vertexInput->mComponents);
...@@ -1260,7 +1265,12 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) ...@@ -1260,7 +1265,12 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
return false; return false;
} }
mVertexExecutables.push_back(new VertexExecutable(mRenderer, vertexInputs, shaderExecutable)); // generated converted input layout
GLenum signature[MAX_VERTEX_ATTRIBS];
mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
// add new binary
mVertexExecutables.push_back(new VertexExecutable(mRenderer, inputLayout, signature, shaderExecutable));
stream.skip(vertexShaderSize); stream.skip(vertexShaderSize);
} }
......
...@@ -218,16 +218,19 @@ class ProgramBinary : public RefCountObject ...@@ -218,16 +218,19 @@ class ProgramBinary : public RefCountObject
public: public:
VertexExecutable(rx::Renderer *const renderer, VertexExecutable(rx::Renderer *const renderer,
const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS], const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS],
const GLenum signature[MAX_VERTEX_ATTRIBS],
rx::ShaderExecutable *shaderExecutable); rx::ShaderExecutable *shaderExecutable);
~VertexExecutable(); ~VertexExecutable();
bool matchesInputLayout(const VertexFormat attributes[MAX_VERTEX_ATTRIBS]) const; bool matchesSignature(const GLenum convertedLayout[MAX_VERTEX_ATTRIBS]) const;
const VertexFormat *inputs() const { return mInputs; } const VertexFormat *inputs() const { return mInputs; }
const GLenum *signature() const { return mSignature; }
rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
private: private:
VertexFormat mInputs[MAX_VERTEX_ATTRIBS]; VertexFormat mInputs[MAX_VERTEX_ATTRIBS];
GLenum mSignature[MAX_VERTEX_ATTRIBS];
rx::ShaderExecutable *mShaderExecutable; rx::ShaderExecutable *mShaderExecutable;
}; };
......
#include "ANGLETest.h"
class ProgramBinaryTest : public ANGLETest
{
protected:
ProgramBinaryTest()
{
setWindowWidth(128);
setWindowHeight(128);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
virtual void SetUp()
{
ANGLETest::SetUp();
const std::string vertexShaderSource = SHADER_SOURCE
(
attribute vec4 inputAttribute;
void main()
{
gl_Position = inputAttribute;
}
);
const std::string fragmentShaderSource = SHADER_SOURCE
(
void main()
{
gl_FragColor = vec4(1,0,0,1);
}
);
mProgram = compileProgram(vertexShaderSource, fragmentShaderSource);
if (mProgram == 0)
{
FAIL() << "shader compilation failed.";
}
glGenBuffers(1, &mBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glBufferData(GL_ARRAY_BUFFER, 128, NULL, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
ASSERT_GL_NO_ERROR();
}
virtual void TearDown()
{
glDeleteProgram(mProgram);
glDeleteBuffers(1, &mBuffer);
ANGLETest::TearDown();
}
GLuint mProgram;
GLuint mBuffer;
};
// This tests the assumption that float attribs of different size
// should not internally cause a vertex shader recompile (for conversion).
TEST_F(ProgramBinaryTest, float_dynamic_shader_size)
{
glUseProgram(mProgram);
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 8, NULL);
glEnableVertexAttribArray(0);
glDrawArrays(GL_POINTS, 0, 1);
GLint programLength;
glGetProgramiv(mProgram, GL_PROGRAM_BINARY_LENGTH_OES, &programLength);
EXPECT_GL_NO_ERROR();
for (GLsizei size = 1; size <= 3; size++)
{
glVertexAttribPointer(0, size, GL_FLOAT, GL_FALSE, 8, NULL);
glEnableVertexAttribArray(0);
glDrawArrays(GL_POINTS, 0, 1);
GLint newProgramLength;
glGetProgramiv(mProgram, GL_PROGRAM_BINARY_LENGTH_OES, &newProgramLength);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(programLength, newProgramLength);
}
}
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