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
GLenum shaderComponentType = UniformComponentType(shaderAttrib.type);
int shaderComponentCount = UniformComponentCount(shaderAttrib.type);
std::string padString = "";
// Perform integer to float conversion (if necessary)
bool requiresTypeConversion = (shaderComponentType == GL_FLOAT && vertexFormat.mType != GL_FLOAT);
// TODO: normalization for 32-bit integer formats
ASSERT(!requiresTypeConversion || !vertexFormat.mNormalized);
if (requiresTypeConversion || !padString.empty())
if (requiresTypeConversion)
{
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
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
std::map<int, VariableLocation> *programOutputVars) 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;
......
......@@ -85,12 +85,14 @@ VariableLocation::VariableLocation(const std::string &name, unsigned int element
ProgramBinary::VertexExecutable::VertexExecutable(rx::Renderer *const renderer,
const VertexFormat inputLayout[],
const GLenum signature[],
rx::ShaderExecutable *shaderExecutable)
: mShaderExecutable(shaderExecutable)
{
for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
{
mInputs[attributeIndex] = inputLayout[attributeIndex];
mSignature[attributeIndex] = signature[attributeIndex];
}
}
......@@ -99,11 +101,11 @@ ProgramBinary::VertexExecutable::~VertexExecutable()
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;
}
......@@ -206,11 +208,14 @@ rx::ShaderExecutable *ProgramBinary::getPixelExecutable() const
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++)
{
if (mVertexExecutables[executableIndex]->matchesInputLayout(inputLayout))
if (mVertexExecutables[executableIndex]->matchesSignature(signature))
{
return mVertexExecutables[executableIndex]->shaderExecutable();
}
......@@ -240,7 +245,7 @@ rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const Ver
}
else
{
mVertexExecutables.push_back(new VertexExecutable(mRenderer, inputLayout, vertexExecutable));
mVertexExecutables.push_back(new VertexExecutable(mRenderer, inputLayout, signature, vertexExecutable));
}
return vertexExecutable;
......@@ -1234,11 +1239,11 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
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->mNormalized);
stream.read(&vertexInput->mComponents);
......@@ -1260,7 +1265,12 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
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);
}
......
......@@ -218,16 +218,19 @@ class ProgramBinary : public RefCountObject
public:
VertexExecutable(rx::Renderer *const renderer,
const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS],
const GLenum signature[MAX_VERTEX_ATTRIBS],
rx::ShaderExecutable *shaderExecutable);
~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 GLenum *signature() const { return mSignature; }
rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
private:
VertexFormat mInputs[MAX_VERTEX_ATTRIBS];
GLenum mSignature[MAX_VERTEX_ATTRIBS];
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