Commit c5629759 by Geoff Lang

Implement full program binary support for ES3.

Refactor validation to be used in both the OES and ES3 entry points. BUG=angleproject:600 BUG=angleproject:1101 Change-Id: I2008c4ea04ce07910f03ae0b997f8a77b66203d8 Reviewed-on: https://chromium-review.googlesource.com/316620Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 36167ab3
...@@ -225,7 +225,8 @@ VariableLocation::VariableLocation(const std::string &name, unsigned int element ...@@ -225,7 +225,8 @@ VariableLocation::VariableLocation(const std::string &name, unsigned int element
Program::Data::Data() Program::Data::Data()
: mAttachedFragmentShader(nullptr), : mAttachedFragmentShader(nullptr),
mAttachedVertexShader(nullptr), mAttachedVertexShader(nullptr),
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS) mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
mBinaryRetrieveableHint(false)
{ {
} }
...@@ -791,6 +792,18 @@ GLint Program::getBinaryLength() const ...@@ -791,6 +792,18 @@ GLint Program::getBinaryLength() const
return length; return length;
} }
void Program::setBinaryRetrievableHint(bool retrievable)
{
// TODO(jmadill) : replace with dirty bits
mProgram->setBinaryRetrievableHint(retrievable);
mData.mBinaryRetrieveableHint = retrievable;
}
bool Program::getBinaryRetrievableHint() const
{
return mData.mBinaryRetrieveableHint;
}
void Program::release() void Program::release()
{ {
mRefCount--; mRefCount--;
......
...@@ -215,6 +215,8 @@ class Program : angle::NonCopyable ...@@ -215,6 +215,8 @@ class Program : angle::NonCopyable
// TODO(jmadill): use unordered/hash map when available // TODO(jmadill): use unordered/hash map when available
std::map<int, VariableLocation> mOutputVariables; std::map<int, VariableLocation> mOutputVariables;
bool mBinaryRetrieveableHint;
}; };
Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle); Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle);
...@@ -237,6 +239,8 @@ class Program : angle::NonCopyable ...@@ -237,6 +239,8 @@ class Program : angle::NonCopyable
Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length); Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length);
Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const; Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const;
GLint getBinaryLength() const; GLint getBinaryLength() const;
void setBinaryRetrievableHint(bool retrievable);
bool getBinaryRetrievableHint() const;
int getInfoLogLength() const; int getInfoLogLength() const;
void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const; void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
......
...@@ -37,6 +37,7 @@ class ProgramImpl : angle::NonCopyable ...@@ -37,6 +37,7 @@ class ProgramImpl : angle::NonCopyable
virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0; virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
virtual gl::Error save(gl::BinaryOutputStream *stream) = 0; virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
virtual void setBinaryRetrievableHint(bool retrievable) = 0;
virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) = 0; virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) = 0;
virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0; virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0;
......
...@@ -25,6 +25,7 @@ class MockProgramImpl : public rx::ProgramImpl ...@@ -25,6 +25,7 @@ class MockProgramImpl : public rx::ProgramImpl
MOCK_METHOD2(load, LinkResult(gl::InfoLog &, gl::BinaryInputStream *)); MOCK_METHOD2(load, LinkResult(gl::InfoLog &, gl::BinaryInputStream *));
MOCK_METHOD1(save, gl::Error(gl::BinaryOutputStream *)); MOCK_METHOD1(save, gl::Error(gl::BinaryOutputStream *));
MOCK_METHOD1(setBinaryRetrievableHint, void(bool));
MOCK_METHOD2(link, LinkResult(const gl::Data &, gl::InfoLog &)); MOCK_METHOD2(link, LinkResult(const gl::Data &, gl::InfoLog &));
MOCK_METHOD2(validate, GLboolean(const gl::Caps &, gl::InfoLog *)); MOCK_METHOD2(validate, GLboolean(const gl::Caps &, gl::InfoLog *));
......
...@@ -1104,6 +1104,10 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) ...@@ -1104,6 +1104,10 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */)
{
}
gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
ShaderExecutableD3D **outExecutable) ShaderExecutableD3D **outExecutable)
{ {
......
...@@ -150,8 +150,9 @@ class ProgramD3D : public ProgramImpl ...@@ -150,8 +150,9 @@ class ProgramD3D : public ProgramImpl
bool usesGeometryShader(GLenum drawMode) const; bool usesGeometryShader(GLenum drawMode) const;
bool usesInstancedPointSpriteEmulation() const; bool usesInstancedPointSpriteEmulation() const;
LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream); LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
gl::Error save(gl::BinaryOutputStream *stream); gl::Error save(gl::BinaryOutputStream *stream) override;
void setBinaryRetrievableHint(bool retrievable) override;
gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
ShaderExecutableD3D **outExectuable); ShaderExecutableD3D **outExectuable);
......
...@@ -47,6 +47,11 @@ gl::Error ProgramGL::save(gl::BinaryOutputStream *stream) ...@@ -47,6 +47,11 @@ gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
return gl::Error(GL_INVALID_OPERATION); return gl::Error(GL_INVALID_OPERATION);
} }
void ProgramGL::setBinaryRetrievableHint(bool retrievable)
{
UNIMPLEMENTED();
}
LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog) LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog)
{ {
// Reset the program state, delete the current program if one exists // Reset the program state, delete the current program if one exists
......
...@@ -33,6 +33,7 @@ class ProgramGL : public ProgramImpl ...@@ -33,6 +33,7 @@ class ProgramGL : public ProgramImpl
LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override; LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
gl::Error save(gl::BinaryOutputStream *stream) override; gl::Error save(gl::BinaryOutputStream *stream) override;
void setBinaryRetrievableHint(bool retrievable) override;
LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override; LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
......
...@@ -2223,4 +2223,49 @@ bool ValidateGenVertexArraysBase(Context *context, GLsizei n) ...@@ -2223,4 +2223,49 @@ bool ValidateGenVertexArraysBase(Context *context, GLsizei n)
return true; return true;
} }
bool ValidateProgramBinaryBase(Context *context,
GLuint program,
GLenum binaryFormat,
const void *binary,
GLint length)
{
Program *programObject = GetValidProgram(context, program);
if (programObject == nullptr)
{
return false;
}
const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
programBinaryFormats.end())
{
context->recordError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
return false;
}
return true;
}
bool ValidateGetProgramBinaryBase(Context *context,
GLuint program,
GLsizei bufSize,
GLsizei *length,
GLenum *binaryFormat,
void *binary)
{
Program *programObject = GetValidProgram(context, program);
if (programObject == nullptr)
{
return false;
}
if (!programObject->isLinked())
{
context->recordError(Error(GL_INVALID_OPERATION, "Program is not linked."));
return false;
}
return true;
}
} }
...@@ -147,6 +147,18 @@ bool ValidateBindVertexArrayBase(Context *context, GLuint array); ...@@ -147,6 +147,18 @@ bool ValidateBindVertexArrayBase(Context *context, GLuint array);
bool ValidateDeleteVertexArraysBase(Context *context, GLsizei n); bool ValidateDeleteVertexArraysBase(Context *context, GLsizei n);
bool ValidateGenVertexArraysBase(Context *context, GLsizei n); bool ValidateGenVertexArraysBase(Context *context, GLsizei n);
bool ValidateProgramBinaryBase(Context *context,
GLuint program,
GLenum binaryFormat,
const void *binary,
GLint length);
bool ValidateGetProgramBinaryBase(Context *context,
GLuint program,
GLsizei bufSize,
GLsizei *length,
GLenum *binaryFormat,
void *binary);
// Error messages shared here for use in testing. // Error messages shared here for use in testing.
extern const char *g_ExceedsMaxElementErrorMessage; extern const char *g_ExceedsMaxElementErrorMessage;
} }
......
...@@ -1037,4 +1037,35 @@ bool ValidateIsVertexArrayOES(Context *context) ...@@ -1037,4 +1037,35 @@ bool ValidateIsVertexArrayOES(Context *context)
return true; return true;
} }
bool ValidateProgramBinaryOES(Context *context,
GLuint program,
GLenum binaryFormat,
const void *binary,
GLint length)
{
if (!context->getExtensions().getProgramBinary)
{
context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
return false;
}
return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
}
bool ValidateGetProgramBinaryOES(Context *context,
GLuint program,
GLsizei bufSize,
GLsizei *length,
GLenum *binaryFormat,
void *binary)
{
if (!context->getExtensions().getProgramBinary)
{
context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
return false;
}
return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
}
} }
...@@ -38,6 +38,18 @@ bool ValidateBindVertexArrayOES(Context *context, GLuint array); ...@@ -38,6 +38,18 @@ bool ValidateBindVertexArrayOES(Context *context, GLuint array);
bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n); bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n);
bool ValidateGenVertexArraysOES(Context *context, GLsizei n); bool ValidateGenVertexArraysOES(Context *context, GLsizei n);
bool ValidateIsVertexArrayOES(Context *context); bool ValidateIsVertexArrayOES(Context *context);
bool ValidateProgramBinaryOES(Context *context,
GLuint program,
GLenum binaryFormat,
const void *binary,
GLint length);
bool ValidateGetProgramBinaryOES(Context *context,
GLuint program,
GLsizei bufSize,
GLsizei *length,
GLenum *binaryFormat,
void *binary);
} }
#endif // LIBANGLE_VALIDATION_ES2_H_ #endif // LIBANGLE_VALIDATION_ES2_H_
...@@ -1322,4 +1322,61 @@ bool ValidateIsVertexArray(Context *context) ...@@ -1322,4 +1322,61 @@ bool ValidateIsVertexArray(Context *context)
return true; return true;
} }
bool ValidateProgramBinary(Context *context,
GLuint program,
GLenum binaryFormat,
const void *binary,
GLint length)
{
if (context->getClientVersion() < 3)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
}
bool ValidateGetProgramBinary(Context *context,
GLuint program,
GLsizei bufSize,
GLsizei *length,
GLenum *binaryFormat,
void *binary)
{
if (context->getClientVersion() < 3)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
}
bool ValidateProgramParameter(Context *context, GLuint program, GLenum pname, GLint value)
{
if (context->getClientVersion() < 3)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
if (GetValidProgram(context, program) == nullptr)
{
return false;
}
switch (pname)
{
case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
break;
default:
context->recordError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
return false;
}
return true;
}
} }
...@@ -59,6 +59,19 @@ bool ValidateBindVertexArray(Context *context, GLuint array); ...@@ -59,6 +59,19 @@ bool ValidateBindVertexArray(Context *context, GLuint array);
bool ValidateDeleteVertexArrays(Context *context, GLsizei n); bool ValidateDeleteVertexArrays(Context *context, GLsizei n);
bool ValidateGenVertexArrays(Context *context, GLsizei n); bool ValidateGenVertexArrays(Context *context, GLsizei n);
bool ValidateIsVertexArray(Context *context); bool ValidateIsVertexArray(Context *context);
bool ValidateProgramBinary(Context *context,
GLuint program,
GLenum binaryFormat,
const void *binary,
GLint length);
bool ValidateGetProgramBinary(Context *context,
GLuint program,
GLsizei bufSize,
GLsizei *length,
GLenum *binaryFormat,
void *binary);
bool ValidateProgramParameter(Context *context, GLuint program, GLenum pname, GLint value);
} }
#endif // LIBANGLE_VALIDATION_ES3_H_ #endif // LIBANGLE_VALIDATION_ES3_H_
...@@ -2082,6 +2082,7 @@ void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params) ...@@ -2082,6 +2082,7 @@ void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params)
case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
case GL_TRANSFORM_FEEDBACK_VARYINGS: case GL_TRANSFORM_FEEDBACK_VARYINGS:
case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
context->recordError(Error(GL_INVALID_ENUM)); context->recordError(Error(GL_INVALID_ENUM));
return; return;
} }
...@@ -2134,6 +2135,9 @@ void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params) ...@@ -2134,6 +2135,9 @@ void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params)
case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
*params = programObject->getTransformFeedbackVaryingMaxLength(); *params = programObject->getTransformFeedbackVaryingMaxLength();
break; break;
case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
*params = programObject->getBinaryRetrievableHint();
break;
default: default:
context->recordError(Error(GL_INVALID_ENUM)); context->recordError(Error(GL_INVALID_ENUM));
......
...@@ -751,14 +751,14 @@ void GL_APIENTRY GetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l ...@@ -751,14 +751,14 @@ void GL_APIENTRY GetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
Program *programObject = context->getProgram(program); if (!ValidateGetProgramBinaryOES(context, program, bufSize, length, binaryFormat, binary))
if (!programObject || !programObject->isLinked())
{ {
context->recordError(Error(GL_INVALID_OPERATION));
return; return;
} }
Program *programObject = context->getProgram(program);
ASSERT(programObject != nullptr);
Error error = programObject->saveBinary(binaryFormat, binary, bufSize, length); Error error = programObject->saveBinary(binaryFormat, binary, bufSize, length);
if (error.isError()) if (error.isError())
{ {
...@@ -776,19 +776,13 @@ void GL_APIENTRY ProgramBinaryOES(GLuint program, GLenum binaryFormat, const voi ...@@ -776,19 +776,13 @@ void GL_APIENTRY ProgramBinaryOES(GLuint program, GLenum binaryFormat, const voi
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats; if (!ValidateProgramBinaryOES(context, program, binaryFormat, binary, length))
if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == programBinaryFormats.end())
{ {
context->recordError(Error(GL_INVALID_ENUM));
return; return;
} }
Program *programObject = context->getProgram(program); Program *programObject = context->getProgram(program);
if (!programObject) ASSERT(programObject != nullptr);
{
context->recordError(Error(GL_INVALID_OPERATION));
return;
}
Error error = programObject->loadBinary(binaryFormat, binary, length); Error error = programObject->loadBinary(binaryFormat, binary, length);
if (error.isError()) if (error.isError())
......
...@@ -3072,14 +3072,20 @@ void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* leng ...@@ -3072,14 +3072,20 @@ void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* leng
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (context->getClientVersion() < 3) if (!ValidateGetProgramBinary(context, program, bufSize, length, binaryFormat, binary))
{ {
context->recordError(Error(GL_INVALID_OPERATION));
return; return;
} }
// TODO: Pipe through to the OES extension for now, needs proper validation Program *programObject = context->getProgram(program);
return GetProgramBinaryOES(program, bufSize, length, binaryFormat, binary); ASSERT(programObject != nullptr);
Error error = programObject->saveBinary(binaryFormat, binary, bufSize, length);
if (error.isError())
{
context->recordError(error);
return;
}
} }
} }
...@@ -3091,14 +3097,20 @@ void GL_APIENTRY ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid ...@@ -3091,14 +3097,20 @@ void GL_APIENTRY ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (context->getClientVersion() < 3) if (!ValidateProgramBinary(context, program, binaryFormat, binary, length))
{ {
context->recordError(Error(GL_INVALID_OPERATION));
return; return;
} }
// TODO: Pipe through to the OES extension for now, needs proper validation Program *programObject = context->getProgram(program);
return ProgramBinaryOES(program, binaryFormat, binary, length); ASSERT(programObject != nullptr);
Error error = programObject->loadBinary(binaryFormat, binary, length);
if (error.isError())
{
context->recordError(error);
return;
}
} }
} }
...@@ -3110,14 +3122,23 @@ void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value) ...@@ -3110,14 +3122,23 @@ void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (context->getClientVersion() < 3) if (!ValidateProgramParameter(context, program, pname, value))
{ {
context->recordError(Error(GL_INVALID_OPERATION));
return; return;
} }
// glProgramParameteri gl::Program *programObject = context->getProgram(program);
UNIMPLEMENTED(); ASSERT(programObject != nullptr);
switch (pname)
{
case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
programObject->setBinaryRetrievableHint(value != GL_FALSE);
break;
default:
UNREACHABLE();
}
} }
} }
......
...@@ -735,7 +735,6 @@ ...@@ -735,7 +735,6 @@
1101 WIN : dEQP-GLES3.functional.state_query.sampler.sampler_texture_max_lod_getsamplerparameteri = FAIL 1101 WIN : dEQP-GLES3.functional.state_query.sampler.sampler_texture_max_lod_getsamplerparameteri = FAIL
1101 WIN : dEQP-GLES3.functional.state_query.fbo.framebuffer_attachment_x_size_rbo = FAIL 1101 WIN : dEQP-GLES3.functional.state_query.fbo.framebuffer_attachment_x_size_rbo = FAIL
1101 WIN : dEQP-GLES3.functional.state_query.shader.program_attached_shaders = FAIL 1101 WIN : dEQP-GLES3.functional.state_query.shader.program_attached_shaders = FAIL
1101 WIN : dEQP-GLES3.functional.state_query.shader.program_binary = FAIL
1101 WIN : dEQP-GLES3.functional.polygon_offset.fixed16_render_with_units = FAIL 1101 WIN : dEQP-GLES3.functional.polygon_offset.fixed16_render_with_units = FAIL
1101 WIN : dEQP-GLES3.functional.polygon_offset.fixed24_render_with_units = FAIL 1101 WIN : dEQP-GLES3.functional.polygon_offset.fixed24_render_with_units = FAIL
1101 WIN : dEQP-GLES3.functional.lifetime.gen.transform_feedback = FAIL 1101 WIN : dEQP-GLES3.functional.lifetime.gen.transform_feedback = FAIL
......
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