Commit b543afff by Geoff Lang

Update Program, ProgramBinary and HLSLCompiler to use Error objects.

BUG=angle:520 Change-Id: Ibbe8c95780fecfb68f4558e99e3a761107da6aee Reviewed-on: https://chromium-review.googlesource.com/220790Reviewed-by: 's avatarShannon Woods <shannonwoods@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent e61209af
...@@ -638,33 +638,44 @@ void Context::useProgram(GLuint program) ...@@ -638,33 +638,44 @@ void Context::useProgram(GLuint program)
} }
} }
void Context::linkProgram(GLuint program) Error Context::linkProgram(GLuint program)
{ {
Program *programObject = mResourceManager->getProgram(program); Program *programObject = mResourceManager->getProgram(program);
bool linked = programObject->link(getCaps()); Error error = programObject->link(getCaps());
if (error.isError())
{
return error;
}
// if the current program was relinked successfully we // if the current program was relinked successfully we
// need to install the new executables // need to install the new executables
if (linked && program == mState.getCurrentProgramId()) if (programObject->isLinked() && program == mState.getCurrentProgramId())
{ {
mState.setCurrentProgramBinary(programObject->getProgramBinary()); mState.setCurrentProgramBinary(programObject->getProgramBinary());
} }
return Error(GL_NO_ERROR);
} }
void Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length) Error Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length)
{ {
Program *programObject = mResourceManager->getProgram(program); Program *programObject = mResourceManager->getProgram(program);
bool loaded = programObject->setProgramBinary(binaryFormat, binary, length); Error error = programObject->setProgramBinary(binaryFormat, binary, length);
if (error.isError())
{
return error;
}
// if the current program was reloaded successfully we // if the current program was reloaded successfully we
// need to install the new executables // need to install the new executables
if (loaded && program == mState.getCurrentProgramId()) if (programObject->isLinked() && program == mState.getCurrentProgramId())
{ {
mState.setCurrentProgramBinary(programObject->getProgramBinary()); mState.setCurrentProgramBinary(programObject->getProgramBinary());
} }
return Error(GL_NO_ERROR);
} }
void Context::bindTransformFeedback(GLuint transformFeedback) void Context::bindTransformFeedback(GLuint transformFeedback)
......
...@@ -130,8 +130,8 @@ class Context ...@@ -130,8 +130,8 @@ class Context
void bindPixelPackBuffer(GLuint buffer); void bindPixelPackBuffer(GLuint buffer);
void bindPixelUnpackBuffer(GLuint buffer); void bindPixelUnpackBuffer(GLuint buffer);
void useProgram(GLuint program); void useProgram(GLuint program);
void linkProgram(GLuint program); Error linkProgram(GLuint program);
void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length); Error setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
void bindTransformFeedback(GLuint transformFeedback); void bindTransformFeedback(GLuint transformFeedback);
Error beginQuery(GLenum target, GLuint query); Error beginQuery(GLenum target, GLuint query);
......
...@@ -244,7 +244,7 @@ void Program::bindAttributeLocation(GLuint index, const char *name) ...@@ -244,7 +244,7 @@ void Program::bindAttributeLocation(GLuint index, const char *name)
// Links the HLSL code of the vertex and pixel shader by matching up their varyings, // Links the HLSL code of the vertex and pixel shader by matching up their varyings,
// compiling them into binaries, determining the attribute mappings, and collecting // compiling them into binaries, determining the attribute mappings, and collecting
// a list of uniforms // a list of uniforms
bool Program::link(const Caps &caps) Error Program::link(const Caps &caps)
{ {
unlink(false); unlink(false);
...@@ -252,10 +252,15 @@ bool Program::link(const Caps &caps) ...@@ -252,10 +252,15 @@ bool Program::link(const Caps &caps)
resetUniformBlockBindings(); resetUniformBlockBindings();
mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader, LinkResult result = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps); mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps);
if (result.error.isError())
{
return result.error;
}
return mLinked; mLinked = result.linkSuccess;
return gl::Error(GL_NO_ERROR);
} }
int AttributeBindings::getAttributeBinding(const std::string &name) const int AttributeBindings::getAttributeBinding(const std::string &name) const
...@@ -303,21 +308,22 @@ ProgramBinary* Program::getProgramBinary() const ...@@ -303,21 +308,22 @@ ProgramBinary* Program::getProgramBinary() const
return mProgramBinary.get(); return mProgramBinary.get();
} }
bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length) Error Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
{ {
unlink(false); unlink(false);
mInfoLog.reset(); mInfoLog.reset();
mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length); LinkResult result = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
if (result.error.isError())
if (!mLinked)
{ {
mProgramBinary.set(NULL); mProgramBinary.set(NULL);
return result.error;
} }
return mLinked; mLinked = result.linkSuccess;
return Error(GL_NO_ERROR);
} }
void Program::release() void Program::release()
......
...@@ -77,9 +77,9 @@ class Program ...@@ -77,9 +77,9 @@ class Program
void bindAttributeLocation(GLuint index, const char *name); void bindAttributeLocation(GLuint index, const char *name);
bool link(const Caps &caps); Error link(const Caps &caps);
bool isLinked(); bool isLinked();
bool setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length); Error setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length);
ProgramBinary *getProgramBinary() const; ProgramBinary *getProgramBinary() const;
int getInfoLogLength() const; int getInfoLogLength() const;
......
...@@ -107,6 +107,12 @@ LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, ...@@ -107,6 +107,12 @@ LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size,
{ {
} }
LinkResult::LinkResult(bool linkSuccess, const Error &error)
: linkSuccess(linkSuccess),
error(error)
{
}
unsigned int ProgramBinary::mCurrentSerial = 1; unsigned int ProgramBinary::mCurrentSerial = 1;
ProgramBinary::ProgramBinary(rx::ProgramImpl *impl) ProgramBinary::ProgramBinary(rx::ProgramImpl *impl)
...@@ -854,10 +860,10 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shade ...@@ -854,10 +860,10 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shade
return true; return true;
} }
bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length) LinkResult ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length)
{ {
#ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
return false; return LinkResult(false, Error(GL_NO_ERROR));
#else #else
ASSERT(binaryFormat == mProgram->getBinaryFormat()); ASSERT(binaryFormat == mProgram->getBinaryFormat());
...@@ -869,7 +875,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina ...@@ -869,7 +875,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (format != mProgram->getBinaryFormat()) if (format != mProgram->getBinaryFormat())
{ {
infoLog.append("Invalid program binary format."); infoLog.append("Invalid program binary format.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
int majorVersion = stream.readInt<int>(); int majorVersion = stream.readInt<int>();
...@@ -877,7 +883,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina ...@@ -877,7 +883,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION) if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
{ {
infoLog.append("Invalid program binary version."); infoLog.append("Invalid program binary version.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
...@@ -885,14 +891,14 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina ...@@ -885,14 +891,14 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0)
{ {
infoLog.append("Invalid program binary version."); infoLog.append("Invalid program binary version.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
int compileFlags = stream.readInt<int>(); int compileFlags = stream.readInt<int>();
if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
{ {
infoLog.append("Mismatched compilation flags."); infoLog.append("Mismatched compilation flags.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
...@@ -932,7 +938,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina ...@@ -932,7 +938,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (stream.error()) if (stream.error())
{ {
infoLog.append("Invalid program binary."); infoLog.append("Invalid program binary.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
mUniforms.resize(uniformCount); mUniforms.resize(uniformCount);
...@@ -965,7 +971,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina ...@@ -965,7 +971,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (stream.error()) if (stream.error())
{ {
infoLog.append("Invalid program binary."); infoLog.append("Invalid program binary.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
mUniformBlocks.resize(uniformBlockCount); mUniformBlocks.resize(uniformBlockCount);
...@@ -994,7 +1000,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina ...@@ -994,7 +1000,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (stream.error()) if (stream.error())
{ {
infoLog.append("Invalid program binary."); infoLog.append("Invalid program binary.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
mUniformIndex.resize(uniformIndexCount); mUniformIndex.resize(uniformIndexCount);
...@@ -1005,18 +1011,19 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina ...@@ -1005,18 +1011,19 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
stream.readInt(&mUniformIndex[uniformIndexIndex].index); stream.readInt(&mUniformIndex[uniformIndexIndex].index);
} }
if (!mProgram->load(infoLog, &stream)) LinkResult result = mProgram->load(infoLog, &stream);
if (result.error.isError() || !result.linkSuccess)
{ {
return false; return result;
} }
mProgram->initializeUniformStorage(mUniforms); mProgram->initializeUniformStorage(mUniforms);
return true; return LinkResult(true, Error(GL_NO_ERROR));
#endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD #endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
} }
bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length)
{ {
if (binaryFormat) if (binaryFormat)
{ {
...@@ -1108,15 +1115,7 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL ...@@ -1108,15 +1115,7 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL
stream.writeInt(mUniformIndex[i].index); stream.writeInt(mUniformIndex[i].index);
} }
if (!mProgram->save(&stream)) mProgram->save(&stream);
{
if (length)
{
*length = 0;
}
return false;
}
GLsizei streamLength = stream.length(); GLsizei streamLength = stream.length();
const void *streamData = stream.data(); const void *streamData = stream.data();
...@@ -1128,7 +1127,10 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL ...@@ -1128,7 +1127,10 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL
*length = 0; *length = 0;
} }
return false; // TODO: This should be moved to the validation layer but computing the size of the binary before saving
// it causes the save to happen twice. It may be possible to write the binary to a separate buffer, validate
// sizes and then copy it.
return Error(GL_INVALID_OPERATION);
} }
if (binary) if (binary)
...@@ -1146,34 +1148,33 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL ...@@ -1146,34 +1148,33 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL
*length = streamLength; *length = streamLength;
} }
return true; return Error(GL_NO_ERROR);
} }
GLint ProgramBinary::getLength() GLint ProgramBinary::getLength()
{ {
GLint length; GLint length;
if (save(NULL, NULL, INT_MAX, &length)) Error error = save(NULL, NULL, INT_MAX, &length);
{ if (error.isError())
return length;
}
else
{ {
return 0; return 0;
} }
return length;
} }
bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, LinkResult ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps) const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps)
{ {
if (!fragmentShader || !fragmentShader->isCompiled()) if (!fragmentShader || !fragmentShader->isCompiled())
{ {
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER); ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
if (!vertexShader || !vertexShader->isCompiled()) if (!vertexShader || !vertexShader->isCompiled())
{ {
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
ASSERT(vertexShader->getType() == GL_VERTEX_SHADER); ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
...@@ -1187,22 +1188,21 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin ...@@ -1187,22 +1188,21 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
int registers; int registers;
std::vector<LinkedVarying> linkedVaryings; std::vector<LinkedVarying> linkedVaryings;
if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode, LinkResult result = mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode,
&registers, &linkedVaryings, &mOutputVariables, caps)) &registers, &linkedVaryings, &mOutputVariables, caps);
if (result.error.isError() || !result.linkSuccess)
{ {
return false; return result;
} }
bool success = true;
if (!linkAttributes(infoLog, attributeBindings, vertexShader)) if (!linkAttributes(infoLog, attributeBindings, vertexShader))
{ {
success = false; return LinkResult(false, Error(GL_NO_ERROR));
} }
if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps)) if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps))
{ {
success = false; return LinkResult(false, Error(GL_NO_ERROR));
} }
// special case for gl_DepthRange, the only built-in uniform (also a struct) // special case for gl_DepthRange, the only built-in uniform (also a struct)
...@@ -1217,28 +1217,26 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin ...@@ -1217,28 +1217,26 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps)) if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps))
{ {
success = false; return LinkResult(false, Error(GL_NO_ERROR));
} }
if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings, if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
transformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), caps)) transformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), caps))
{ {
success = false; return LinkResult(false, Error(GL_NO_ERROR));
} }
if (success) // TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called,
// however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling.
result = mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers);
if (result.error.isError() || !result.linkSuccess)
{ {
// TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called, infoLog.append("Failed to create D3D shaders.");
// however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling. reset();
if (!mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers)) return result;
{
infoLog.append("Failed to create D3D shaders.");
success = false;
reset();
}
} }
return success; return LinkResult(true, Error(GL_NO_ERROR));
} }
// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
......
...@@ -86,6 +86,14 @@ struct LinkedVarying ...@@ -86,6 +86,14 @@ struct LinkedVarying
unsigned int semanticIndexCount; unsigned int semanticIndexCount;
}; };
struct LinkResult
{
bool linkSuccess;
Error error;
LinkResult(bool linkSuccess, const Error &error);
};
// This is the result of linking a program. It is the state that would be passed to ProgramBinary. // This is the result of linking a program. It is the state that would be passed to ProgramBinary.
class ProgramBinary : public RefCountObject class ProgramBinary : public RefCountObject
{ {
...@@ -138,12 +146,13 @@ class ProgramBinary : public RefCountObject ...@@ -138,12 +146,13 @@ class ProgramBinary : public RefCountObject
Error applyUniforms(); Error applyUniforms();
Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps); Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps);
bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length); LinkResult load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length); Error save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
GLint getLength(); GLint getLength();
bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, LinkResult link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps); const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
const Caps &caps);
void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
......
...@@ -3654,7 +3654,12 @@ void __stdcall glLinkProgram(GLuint program) ...@@ -3654,7 +3654,12 @@ void __stdcall glLinkProgram(GLuint program)
} }
} }
context->linkProgram(program); gl::Error error = context->linkProgram(program);
if (error.isError())
{
context->recordError(error);
return;
}
} }
} }
...@@ -8402,9 +8407,10 @@ void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l ...@@ -8402,9 +8407,10 @@ void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l
return; return;
} }
if (!programBinary->save(binaryFormat, binary, bufSize, length)) gl::Error error = programBinary->save(binaryFormat, binary, bufSize, length);
if (error.isError())
{ {
context->recordError(gl::Error(GL_INVALID_OPERATION)); context->recordError(error);
return; return;
} }
} }
...@@ -8433,7 +8439,12 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat, ...@@ -8433,7 +8439,12 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat,
return; return;
} }
context->setProgramBinary(program, binaryFormat, binary, length); gl::Error error = context->setProgramBinary(program, binaryFormat, binary, length);
if (error.isError())
{
context->recordError(error);
return;
}
} }
} }
......
...@@ -32,16 +32,16 @@ public: ...@@ -32,16 +32,16 @@ public:
virtual sh::Attribute *getShaderAttributes() = 0; virtual sh::Attribute *getShaderAttributes() = 0;
virtual GLenum getBinaryFormat() = 0; virtual GLenum getBinaryFormat() = 0;
virtual bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0; virtual gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
virtual bool save(gl::BinaryOutputStream *stream) = 0; virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
virtual bool compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, virtual gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
int registers) = 0; int registers) = 0;
virtual bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, virtual gl::LinkResult link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
int *registers, std::vector<gl::LinkedVarying> *linkedVaryings, int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps) = 0; std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps) = 0;
virtual void initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms) = 0; virtual void initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms) = 0;
......
...@@ -196,12 +196,13 @@ class Renderer ...@@ -196,12 +196,13 @@ class Renderer
// Shader operations // Shader operations
virtual void releaseShaderCompiler() = 0; virtual void releaseShaderCompiler() = 0;
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, virtual gl::Error loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers) = 0; bool separatedOutputBuffers, ShaderExecutable **outExecutable) = 0;
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type, virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround) = 0; bool separatedOutputBuffers, D3DWorkaroundType workaround,
ShaderExecutable **outExectuable) = 0;
virtual UniformStorage *createUniformStorage(size_t storageSize) = 0; virtual UniformStorage *createUniformStorage(size_t storageSize) = 0;
// Image operations // Image operations
......
...@@ -82,8 +82,8 @@ void HLSLCompiler::release() ...@@ -82,8 +82,8 @@ void HLSLCompiler::release()
} }
} }
ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
const std::vector<CompileConfig> &configs) const const std::vector<CompileConfig> &configs, ID3DBlob **outCompiledBlob) const
{ {
ASSERT(mD3DCompilerModule && mD3DCompileFunc); ASSERT(mD3DCompilerModule && mD3DCompileFunc);
...@@ -115,13 +115,15 @@ ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string ...@@ -115,13 +115,15 @@ ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
return binary; *outCompiledBlob = binary;
return gl::Error(GL_NO_ERROR);
} }
else else
{ {
if (result == E_OUTOFMEMORY) if (result == E_OUTOFMEMORY)
{ {
return gl::error<ID3DBlob*>(GL_OUT_OF_MEMORY, NULL); *outCompiledBlob = NULL;
return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result);
} }
infoLog.append("Warning: D3D shader compilation failed with %s flags.", configs[i].name.c_str()); infoLog.append("Warning: D3D shader compilation failed with %s flags.", configs[i].name.c_str());
...@@ -133,7 +135,9 @@ ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string ...@@ -133,7 +135,9 @@ ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
} }
} }
return NULL; // None of the configurations succeeded in compiling this shader but the compiler is still intact
*outCompiledBlob = NULL;
return gl::Error(GL_NO_ERROR);
} }
} }
#ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ #ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ #define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
#include "libGLESv2/Error.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "common/platform.h" #include "common/platform.h"
...@@ -33,8 +35,10 @@ class HLSLCompiler ...@@ -33,8 +35,10 @@ class HLSLCompiler
bool initialize(); bool initialize();
void release(); void release();
ID3DBlob *compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, // Attempt to compile a HLSL shader using the supplied configurations, may output a NULL compiled blob
const std::vector<CompileConfig> &configs) const; // even if no GL errors are returned.
gl::Error compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
const std::vector<CompileConfig> &configs, ID3DBlob **outCompiledBlob) const;
private: private:
DISALLOW_COPY_AND_ASSIGN(HLSLCompiler); DISALLOW_COPY_AND_ASSIGN(HLSLCompiler);
......
...@@ -47,21 +47,21 @@ class ProgramD3D : public ProgramImpl ...@@ -47,21 +47,21 @@ class ProgramD3D : public ProgramImpl
bool usesGeometryShader() const; bool usesGeometryShader() const;
GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; } GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; }
bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream); gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
bool save(gl::BinaryOutputStream *stream); gl::Error save(gl::BinaryOutputStream *stream);
ShaderExecutable *getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo); gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExectuable);
ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout); gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout, ShaderExecutable **outExectuable);
ShaderExecutable *getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]); gl::Error getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable);
ShaderExecutable *getGeometryExecutable() const { return mGeometryExecutable; } ShaderExecutable *getGeometryExecutable() const { return mGeometryExecutable; }
bool compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
int registers); int registers);
bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, gl::LinkResult link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
int *registers, std::vector<gl::LinkedVarying> *linkedVaryings, int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps); std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps);
void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const;
......
...@@ -139,7 +139,15 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl ...@@ -139,7 +139,15 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS]; gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS];
GetInputLayout(attributes, shaderInputLayout); GetInputLayout(attributes, shaderInputLayout);
ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation()); ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation());
ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programD3D->getVertexExecutableForInputLayout(shaderInputLayout));
ShaderExecutable *shader = NULL;
gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader);
if (error.isError())
{
return error;
}
ShaderExecutable *shader11 = ShaderExecutable11::makeShaderExecutable11(shader);
D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS];
for (unsigned int j = 0; j < ilKey.elementCount; ++j) for (unsigned int j = 0; j < ilKey.elementCount; ++j)
...@@ -147,7 +155,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl ...@@ -147,7 +155,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
descs[j] = ilKey.elements[j].desc; descs[j] = ilKey.elements[j].desc;
} }
HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout); HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader11->getFunction(), shader11->getLength(), &inputLayout);
if (FAILED(result)) if (FAILED(result))
{ {
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result);
......
...@@ -1344,8 +1344,21 @@ gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::V ...@@ -1344,8 +1344,21 @@ gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::V
bool rasterizerDiscard, bool transformFeedbackActive) bool rasterizerDiscard, bool transformFeedbackActive)
{ {
ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation()); ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation());
ShaderExecutable *vertexExe = programD3D->getVertexExecutableForInputLayout(inputLayout);
ShaderExecutable *pixelExe = programD3D->getPixelExecutableForFramebuffer(framebuffer); ShaderExecutable *vertexExe = NULL;
gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe);
if (error.isError())
{
return error;
}
ShaderExecutable *pixelExe = NULL;
error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe);
if (error.isError())
{
return error;
}
ShaderExecutable *geometryExe = programD3D->getGeometryExecutable(); ShaderExecutable *geometryExe = programD3D->getGeometryExecutable();
ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL); ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL);
...@@ -2201,13 +2214,10 @@ void Renderer11::releaseShaderCompiler() ...@@ -2201,13 +2214,10 @@ void Renderer11::releaseShaderCompiler()
ShaderD3D::releaseCompiler(); ShaderD3D::releaseCompiler();
} }
ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type, gl::Error Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers) bool separatedOutputBuffers, ShaderExecutable **outExecutable)
{ {
ShaderExecutable11 *executable = NULL;
HRESULT result;
switch (type) switch (type)
{ {
case rx::SHADER_VERTEX: case rx::SHADER_VERTEX:
...@@ -2215,8 +2225,12 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length ...@@ -2215,8 +2225,12 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length
ID3D11VertexShader *vertexShader = NULL; ID3D11VertexShader *vertexShader = NULL;
ID3D11GeometryShader *streamOutShader = NULL; ID3D11GeometryShader *streamOutShader = NULL;
result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader); HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader);
ASSERT(SUCCEEDED(result)); ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result);
}
if (transformFeedbackVaryings.size() > 0) if (transformFeedbackVaryings.size() > 0)
{ {
...@@ -2242,51 +2256,55 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length ...@@ -2242,51 +2256,55 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length
result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(), result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(),
NULL, 0, 0, NULL, &streamOutShader); NULL, 0, 0, NULL, &streamOutShader);
ASSERT(SUCCEEDED(result)); ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create steam output shader, result: 0x%X.", result);
}
} }
if (vertexShader) *outExecutable = new ShaderExecutable11(function, length, vertexShader, streamOutShader);
{
executable = new ShaderExecutable11(function, length, vertexShader, streamOutShader);
}
} }
break; break;
case rx::SHADER_PIXEL: case rx::SHADER_PIXEL:
{ {
ID3D11PixelShader *pixelShader = NULL; ID3D11PixelShader *pixelShader = NULL;
result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader); HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader);
ASSERT(SUCCEEDED(result)); ASSERT(SUCCEEDED(result));
if (FAILED(result))
if (pixelShader)
{ {
executable = new ShaderExecutable11(function, length, pixelShader); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader, result: 0x%X.", result);
} }
*outExecutable = new ShaderExecutable11(function, length, pixelShader);
} }
break; break;
case rx::SHADER_GEOMETRY: case rx::SHADER_GEOMETRY:
{ {
ID3D11GeometryShader *geometryShader = NULL; ID3D11GeometryShader *geometryShader = NULL;
result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader); HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader);
ASSERT(SUCCEEDED(result)); ASSERT(SUCCEEDED(result));
if (FAILED(result))
if (geometryShader)
{ {
executable = new ShaderExecutable11(function, length, geometryShader); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create geometry shader, result: 0x%X.", result);
} }
*outExecutable = new ShaderExecutable11(function, length, geometryShader);
} }
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; return gl::Error(GL_INVALID_OPERATION);
} }
return executable; return gl::Error(GL_NO_ERROR);
} }
ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type, gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround) bool separatedOutputBuffers, D3DWorkaroundType workaround,
ShaderExecutable **outExectuable)
{ {
const char *profileType = NULL; const char *profileType = NULL;
switch (type) switch (type)
...@@ -2302,7 +2320,7 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const st ...@@ -2302,7 +2320,7 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const st
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
return NULL; return gl::Error(GL_INVALID_OPERATION);
} }
unsigned int profileMajorVersion = 0; unsigned int profileMajorVersion = 0;
...@@ -2323,7 +2341,7 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const st ...@@ -2323,7 +2341,7 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const st
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
return NULL; return gl::Error(GL_INVALID_OPERATION);
} }
std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion); std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
...@@ -2346,17 +2364,30 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const st ...@@ -2346,17 +2364,30 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const st
configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation" )); configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation" ));
configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization")); configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));
ID3DBlob *binary = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs); ID3DBlob *binary = NULL;
gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, &binary);
if (error.isError())
{
return error;
}
// It's possible that binary is NULL if the compiler failed in all configurations. Set the executable to NULL
// and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK.
if (!binary) if (!binary)
{ {
return NULL; *outExectuable = NULL;
return gl::Error(GL_NO_ERROR);
} }
ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers); transformFeedbackVaryings, separatedOutputBuffers, outExectuable);
SafeRelease(binary); SafeRelease(binary);
if (error.isError())
{
return error;
}
return executable; return gl::Error(GL_NO_ERROR);
} }
rx::UniformStorage *Renderer11::createUniformStorage(size_t storageSize) rx::UniformStorage *Renderer11::createUniformStorage(size_t storageSize)
......
...@@ -141,12 +141,13 @@ class Renderer11 : public Renderer ...@@ -141,12 +141,13 @@ class Renderer11 : public Renderer
// Shader operations // Shader operations
virtual void releaseShaderCompiler(); virtual void releaseShaderCompiler();
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, virtual gl::Error loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers); bool separatedOutputBuffers, ShaderExecutable **outExecutable);
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type, virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround); bool separatedOutputBuffers, D3DWorkaroundType workaround,
ShaderExecutable **outExectuable);
virtual UniformStorage *createUniformStorage(size_t storageSize); virtual UniformStorage *createUniformStorage(size_t storageSize);
// Image operations // Image operations
......
...@@ -114,7 +114,7 @@ void Blit9::initGeometry() ...@@ -114,7 +114,7 @@ void Blit9::initGeometry()
template <class D3DShaderType> template <class D3DShaderType>
gl::Error Blit9::setShader(ShaderId source, const char *profile, gl::Error Blit9::setShader(ShaderId source, const char *profile,
D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length), gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader),
HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)) HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
{ {
IDirect3DDevice9 *device = mRenderer->getDevice(); IDirect3DDevice9 *device = mRenderer->getDevice();
...@@ -130,10 +130,10 @@ gl::Error Blit9::setShader(ShaderId source, const char *profile, ...@@ -130,10 +130,10 @@ gl::Error Blit9::setShader(ShaderId source, const char *profile,
const BYTE* shaderCode = g_shaderCode[source]; const BYTE* shaderCode = g_shaderCode[source];
size_t shaderSize = g_shaderSize[source]; size_t shaderSize = g_shaderSize[source];
shader = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize); gl::Error error = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize, &shader);
if (!shader) if (error.isError())
{ {
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader for blit operation"); return error;
} }
mCompiledShaders[source] = shader; mCompiledShaders[source] = shader;
......
...@@ -76,7 +76,7 @@ class Blit9 ...@@ -76,7 +76,7 @@ class Blit9
template <class D3DShaderType> template <class D3DShaderType>
gl::Error setShader(ShaderId source, const char *profile, gl::Error setShader(ShaderId source, const char *profile,
D3DShaderType *(Renderer9::*createShader)(const DWORD *, size_t length), gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader),
HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)); HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*));
gl::Error setVertexShader(ShaderId shader); gl::Error setVertexShader(ShaderId shader);
......
...@@ -566,14 +566,14 @@ void Renderer9::freeEventQuery(IDirect3DQuery9* query) ...@@ -566,14 +566,14 @@ void Renderer9::freeEventQuery(IDirect3DQuery9* query)
} }
} }
IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length) gl::Error Renderer9::createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader)
{ {
return mVertexShaderCache.create(function, length); return mVertexShaderCache.create(function, length, outShader);
} }
IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length) gl::Error Renderer9::createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader)
{ {
return mPixelShaderCache.create(function, length); return mPixelShaderCache.create(function, length, outShader);
} }
HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer) HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer)
...@@ -1671,8 +1671,20 @@ gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::Ve ...@@ -1671,8 +1671,20 @@ gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::Ve
ASSERT(!rasterizerDiscard); ASSERT(!rasterizerDiscard);
ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation()); ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation());
ShaderExecutable *vertexExe = programD3D->getVertexExecutableForInputLayout(inputLayout);
ShaderExecutable *pixelExe = programD3D->getPixelExecutableForFramebuffer(framebuffer); ShaderExecutable *vertexExe = NULL;
gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe);
if (error.isError())
{
return error;
}
ShaderExecutable *pixelExe = NULL;
error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe);
if (error.isError())
{
return error;
}
IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL); IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL);
IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL); IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL);
...@@ -2791,46 +2803,49 @@ void Renderer9::releaseShaderCompiler() ...@@ -2791,46 +2803,49 @@ void Renderer9::releaseShaderCompiler()
ShaderD3D::releaseCompiler(); ShaderD3D::releaseCompiler();
} }
ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type, gl::Error Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers) bool separatedOutputBuffers, ShaderExecutable **outExecutable)
{ {
// Transform feedback is not supported in ES2 or D3D9 // Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0); ASSERT(transformFeedbackVaryings.size() == 0);
ShaderExecutable9 *executable = NULL;
switch (type) switch (type)
{ {
case rx::SHADER_VERTEX: case rx::SHADER_VERTEX:
{ {
IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length); IDirect3DVertexShader9 *vshader = NULL;
if (vshader) gl::Error error = createVertexShader((DWORD*)function, length, &vshader);
if (error.isError())
{ {
executable = new ShaderExecutable9(function, length, vshader); return error;
} }
*outExecutable = new ShaderExecutable9(function, length, vshader);
} }
break; break;
case rx::SHADER_PIXEL: case rx::SHADER_PIXEL:
{ {
IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length); IDirect3DPixelShader9 *pshader = NULL;
if (pshader) gl::Error error = createPixelShader((DWORD*)function, length, &pshader);
if (error.isError())
{ {
executable = new ShaderExecutable9(function, length, pshader); return error;
} }
*outExecutable = new ShaderExecutable9(function, length, pshader);
} }
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; return gl::Error(GL_INVALID_OPERATION);
} }
return executable; return gl::Error(GL_NO_ERROR);
} }
ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type, gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround) bool separatedOutputBuffers, D3DWorkaroundType workaround,
ShaderExecutable **outExectuable)
{ {
// Transform feedback is not supported in ES2 or D3D9 // Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0); ASSERT(transformFeedbackVaryings.size() == 0);
...@@ -2846,7 +2861,7 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std ...@@ -2846,7 +2861,7 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
return NULL; return gl::Error(GL_INVALID_OPERATION);
} }
unsigned int profileMajorVersion = (getMajorShaderModel() >= 3) ? 3 : 2; unsigned int profileMajorVersion = (getMajorShaderModel() >= 3) ? 3 : 2;
unsigned int profileMinorVersion = 0; unsigned int profileMinorVersion = 0;
...@@ -2880,17 +2895,30 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std ...@@ -2880,17 +2895,30 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std
configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control" )); configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control" ));
configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control")); configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control"));
ID3DBlob *binary = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs); ID3DBlob *binary = NULL;
gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, &binary);
if (error.isError())
{
return error;
}
// It's possible that binary is NULL if the compiler failed in all configurations. Set the executable to NULL
// and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK.
if (!binary) if (!binary)
{ {
return NULL; *outExectuable = NULL;
return gl::Error(GL_NO_ERROR);
} }
ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers); transformFeedbackVaryings, separatedOutputBuffers, outExectuable);
SafeRelease(binary); SafeRelease(binary);
if (error.isError())
{
return error;
}
return executable; return gl::Error(GL_NO_ERROR);
} }
rx::UniformStorage *Renderer9::createUniformStorage(size_t storageSize) rx::UniformStorage *Renderer9::createUniformStorage(size_t storageSize)
......
...@@ -56,8 +56,8 @@ class Renderer9 : public Renderer ...@@ -56,8 +56,8 @@ class Renderer9 : public Renderer
void freeEventQuery(IDirect3DQuery9* query); void freeEventQuery(IDirect3DQuery9* query);
// resource creation // resource creation
IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length); gl::Error createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader);
IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length); gl::Error createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader);
HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer); HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer);
HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer); HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer);
virtual gl::Error generateSwizzle(gl::Texture *texture); virtual gl::Error generateSwizzle(gl::Texture *texture);
...@@ -143,12 +143,13 @@ class Renderer9 : public Renderer ...@@ -143,12 +143,13 @@ class Renderer9 : public Renderer
// Shader operations // Shader operations
virtual void releaseShaderCompiler(); virtual void releaseShaderCompiler();
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, virtual gl::Error loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers); bool separatedOutputBuffers, ShaderExecutable **outExecutable);
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type, virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround); bool separatedOutputBuffers, D3DWorkaroundType workaround,
ShaderExecutable **outExectuable);
virtual UniformStorage *createUniformStorage(size_t storageSize); virtual UniformStorage *createUniformStorage(size_t storageSize);
// Image operations // Image operations
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#ifndef LIBGLESV2_RENDERER_SHADER_CACHE_H_ #ifndef LIBGLESV2_RENDERER_SHADER_CACHE_H_
#define LIBGLESV2_RENDERER_SHADER_CACHE_H_ #define LIBGLESV2_RENDERER_SHADER_CACHE_H_
#include "libGLESv2/Error.h"
#include "common/debug.h" #include "common/debug.h"
#include <cstddef> #include <cstddef>
...@@ -37,21 +39,22 @@ class ShaderCache ...@@ -37,21 +39,22 @@ class ShaderCache
mDevice = device; mDevice = device;
} }
ShaderObject *create(const DWORD *function, size_t length) gl::Error create(const DWORD *function, size_t length, ShaderObject **outShaderObject)
{ {
std::string key(reinterpret_cast<const char*>(function), length); std::string key(reinterpret_cast<const char*>(function), length);
typename Map::iterator it = mMap.find(key); typename Map::iterator it = mMap.find(key);
if (it != mMap.end()) if (it != mMap.end())
{ {
it->second->AddRef(); it->second->AddRef();
return it->second; *outShaderObject = it->second;
return gl::Error(GL_NO_ERROR);
} }
ShaderObject *shader; ShaderObject *shader;
HRESULT result = createShader(function, &shader); HRESULT result = createShader(function, &shader);
if (FAILED(result)) if (FAILED(result))
{ {
return NULL; return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader, result: 0x%X.", result);
} }
// Random eviction policy. // Random eviction policy.
...@@ -64,7 +67,8 @@ class ShaderCache ...@@ -64,7 +67,8 @@ class ShaderCache
shader->AddRef(); shader->AddRef();
mMap[key] = shader; mMap[key] = shader;
return shader; *outShaderObject = shader;
return gl::Error(GL_NO_ERROR);
} }
void clear() void clear()
......
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