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
Program::Data::Data()
: mAttachedFragmentShader(nullptr),
mAttachedVertexShader(nullptr),
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS)
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
mBinaryRetrieveableHint(false)
{
}
......@@ -791,6 +792,18 @@ GLint Program::getBinaryLength() const
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()
{
mRefCount--;
......
......@@ -215,6 +215,8 @@ class Program : angle::NonCopyable
// TODO(jmadill): use unordered/hash map when available
std::map<int, VariableLocation> mOutputVariables;
bool mBinaryRetrieveableHint;
};
Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle);
......@@ -237,6 +239,8 @@ class Program : angle::NonCopyable
Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length);
Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const;
GLint getBinaryLength() const;
void setBinaryRetrievableHint(bool retrievable);
bool getBinaryRetrievableHint() const;
int getInfoLogLength() const;
void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
......
......@@ -37,6 +37,7 @@ class ProgramImpl : angle::NonCopyable
virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *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 GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0;
......
......@@ -25,6 +25,7 @@ class MockProgramImpl : public rx::ProgramImpl
MOCK_METHOD2(load, LinkResult(gl::InfoLog &, gl::BinaryInputStream *));
MOCK_METHOD1(save, gl::Error(gl::BinaryOutputStream *));
MOCK_METHOD1(setBinaryRetrievableHint, void(bool));
MOCK_METHOD2(link, LinkResult(const gl::Data &, gl::InfoLog &));
MOCK_METHOD2(validate, GLboolean(const gl::Caps &, gl::InfoLog *));
......
......@@ -1104,6 +1104,10 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
return gl::Error(GL_NO_ERROR);
}
void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */)
{
}
gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
ShaderExecutableD3D **outExecutable)
{
......
......@@ -150,8 +150,9 @@ class ProgramD3D : public ProgramImpl
bool usesGeometryShader(GLenum drawMode) const;
bool usesInstancedPointSpriteEmulation() const;
LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
gl::Error save(gl::BinaryOutputStream *stream);
LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
gl::Error save(gl::BinaryOutputStream *stream) override;
void setBinaryRetrievableHint(bool retrievable) override;
gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
ShaderExecutableD3D **outExectuable);
......
......@@ -47,6 +47,11 @@ gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
return gl::Error(GL_INVALID_OPERATION);
}
void ProgramGL::setBinaryRetrievableHint(bool retrievable)
{
UNIMPLEMENTED();
}
LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog)
{
// Reset the program state, delete the current program if one exists
......
......@@ -33,6 +33,7 @@ class ProgramGL : public ProgramImpl
LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
gl::Error save(gl::BinaryOutputStream *stream) override;
void setBinaryRetrievableHint(bool retrievable) override;
LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
......
......@@ -2223,4 +2223,49 @@ bool ValidateGenVertexArraysBase(Context *context, GLsizei n)
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);
bool ValidateDeleteVertexArraysBase(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.
extern const char *g_ExceedsMaxElementErrorMessage;
}
......
......@@ -1037,4 +1037,35 @@ bool ValidateIsVertexArrayOES(Context *context)
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);
bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n);
bool ValidateGenVertexArraysOES(Context *context, GLsizei n);
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_
......@@ -1322,4 +1322,61 @@ bool ValidateIsVertexArray(Context *context)
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);
bool ValidateDeleteVertexArrays(Context *context, GLsizei n);
bool ValidateGenVertexArrays(Context *context, GLsizei n);
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_
......@@ -2082,6 +2082,7 @@ void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params)
case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
case GL_TRANSFORM_FEEDBACK_VARYINGS:
case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
context->recordError(Error(GL_INVALID_ENUM));
return;
}
......@@ -2134,6 +2135,9 @@ void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params)
case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
*params = programObject->getTransformFeedbackVaryingMaxLength();
break;
case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
*params = programObject->getBinaryRetrievableHint();
break;
default:
context->recordError(Error(GL_INVALID_ENUM));
......
......@@ -751,14 +751,14 @@ void GL_APIENTRY GetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l
Context *context = GetValidGlobalContext();
if (context)
{
Program *programObject = context->getProgram(program);
if (!programObject || !programObject->isLinked())
if (!ValidateGetProgramBinaryOES(context, program, bufSize, length, binaryFormat, binary))
{
context->recordError(Error(GL_INVALID_OPERATION));
return;
}
Program *programObject = context->getProgram(program);
ASSERT(programObject != nullptr);
Error error = programObject->saveBinary(binaryFormat, binary, bufSize, length);
if (error.isError())
{
......@@ -776,19 +776,13 @@ void GL_APIENTRY ProgramBinaryOES(GLuint program, GLenum binaryFormat, const voi
Context *context = GetValidGlobalContext();
if (context)
{
const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == programBinaryFormats.end())
if (!ValidateProgramBinaryOES(context, program, binaryFormat, binary, length))
{
context->recordError(Error(GL_INVALID_ENUM));
return;
}
Program *programObject = context->getProgram(program);
if (!programObject)
{
context->recordError(Error(GL_INVALID_OPERATION));
return;
}
ASSERT(programObject != nullptr);
Error error = programObject->loadBinary(binaryFormat, binary, length);
if (error.isError())
......
......@@ -3072,14 +3072,20 @@ void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* leng
Context *context = GetValidGlobalContext();
if (context)
{
if (context->getClientVersion() < 3)
if (!ValidateGetProgramBinary(context, program, bufSize, length, binaryFormat, binary))
{
context->recordError(Error(GL_INVALID_OPERATION));
return;
}
// TODO: Pipe through to the OES extension for now, needs proper validation
return GetProgramBinaryOES(program, bufSize, length, binaryFormat, binary);
Program *programObject = context->getProgram(program);
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
Context *context = GetValidGlobalContext();
if (context)
{
if (context->getClientVersion() < 3)
if (!ValidateProgramBinary(context, program, binaryFormat, binary, length))
{
context->recordError(Error(GL_INVALID_OPERATION));
return;
}
// TODO: Pipe through to the OES extension for now, needs proper validation
return ProgramBinaryOES(program, binaryFormat, binary, length);
Program *programObject = context->getProgram(program);
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)
Context *context = GetValidGlobalContext();
if (context)
{
if (context->getClientVersion() < 3)
if (!ValidateProgramParameter(context, program, pname, value))
{
context->recordError(Error(GL_INVALID_OPERATION));
return;
}
// glProgramParameteri
UNIMPLEMENTED();
gl::Program *programObject = context->getProgram(program);
ASSERT(programObject != nullptr);
switch (pname)
{
case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
programObject->setBinaryRetrievableHint(value != GL_FALSE);
break;
default:
UNREACHABLE();
}
}
}
......
......@@ -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.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_binary = 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.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