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)
}
}
void Context::linkProgram(GLuint program)
Error Context::linkProgram(GLuint 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
// need to install the new executables
if (linked && program == mState.getCurrentProgramId())
if (programObject->isLinked() && program == mState.getCurrentProgramId())
{
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);
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
// need to install the new executables
if (loaded && program == mState.getCurrentProgramId())
if (programObject->isLinked() && program == mState.getCurrentProgramId())
{
mState.setCurrentProgramBinary(programObject->getProgramBinary());
}
return Error(GL_NO_ERROR);
}
void Context::bindTransformFeedback(GLuint transformFeedback)
......
......@@ -130,8 +130,8 @@ class Context
void bindPixelPackBuffer(GLuint buffer);
void bindPixelUnpackBuffer(GLuint buffer);
void useProgram(GLuint program);
void linkProgram(GLuint program);
void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
Error linkProgram(GLuint program);
Error setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
void bindTransformFeedback(GLuint transformFeedback);
Error beginQuery(GLenum target, GLuint query);
......
......@@ -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,
// compiling them into binaries, determining the attribute mappings, and collecting
// a list of uniforms
bool Program::link(const Caps &caps)
Error Program::link(const Caps &caps)
{
unlink(false);
......@@ -252,10 +252,15 @@ bool Program::link(const Caps &caps)
resetUniformBlockBindings();
mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps);
LinkResult result = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
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
......@@ -303,21 +308,22 @@ ProgramBinary* Program::getProgramBinary() const
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);
mInfoLog.reset();
mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
if (!mLinked)
LinkResult result = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
if (result.error.isError())
{
mProgramBinary.set(NULL);
return result.error;
}
return mLinked;
mLinked = result.linkSuccess;
return Error(GL_NO_ERROR);
}
void Program::release()
......
......@@ -77,9 +77,9 @@ class Program
void bindAttributeLocation(GLuint index, const char *name);
bool link(const Caps &caps);
Error link(const Caps &caps);
bool isLinked();
bool setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length);
Error setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length);
ProgramBinary *getProgramBinary() const;
int getInfoLogLength() const;
......
......@@ -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;
ProgramBinary::ProgramBinary(rx::ProgramImpl *impl)
......@@ -854,10 +860,10 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shade
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
return false;
return LinkResult(false, Error(GL_NO_ERROR));
#else
ASSERT(binaryFormat == mProgram->getBinaryFormat());
......@@ -869,7 +875,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (format != mProgram->getBinaryFormat())
{
infoLog.append("Invalid program binary format.");
return false;
return LinkResult(false, Error(GL_NO_ERROR));
}
int majorVersion = stream.readInt<int>();
......@@ -877,7 +883,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
{
infoLog.append("Invalid program binary version.");
return false;
return LinkResult(false, Error(GL_NO_ERROR));
}
unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
......@@ -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)
{
infoLog.append("Invalid program binary version.");
return false;
return LinkResult(false, Error(GL_NO_ERROR));
}
int compileFlags = stream.readInt<int>();
if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
{
infoLog.append("Mismatched compilation flags.");
return false;
return LinkResult(false, Error(GL_NO_ERROR));
}
for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
......@@ -932,7 +938,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (stream.error())
{
infoLog.append("Invalid program binary.");
return false;
return LinkResult(false, Error(GL_NO_ERROR));
}
mUniforms.resize(uniformCount);
......@@ -965,7 +971,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (stream.error())
{
infoLog.append("Invalid program binary.");
return false;
return LinkResult(false, Error(GL_NO_ERROR));
}
mUniformBlocks.resize(uniformBlockCount);
......@@ -994,7 +1000,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (stream.error())
{
infoLog.append("Invalid program binary.");
return false;
return LinkResult(false, Error(GL_NO_ERROR));
}
mUniformIndex.resize(uniformIndexCount);
......@@ -1005,18 +1011,19 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
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);
return true;
return LinkResult(true, Error(GL_NO_ERROR));
#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)
{
......@@ -1108,15 +1115,7 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL
stream.writeInt(mUniformIndex[i].index);
}
if (!mProgram->save(&stream))
{
if (length)
{
*length = 0;
}
return false;
}
mProgram->save(&stream);
GLsizei streamLength = stream.length();
const void *streamData = stream.data();
......@@ -1128,7 +1127,10 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL
*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)
......@@ -1146,34 +1148,33 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL
*length = streamLength;
}
return true;
return Error(GL_NO_ERROR);
}
GLint ProgramBinary::getLength()
{
GLint length;
if (save(NULL, NULL, INT_MAX, &length))
{
return length;
}
else
Error error = save(NULL, NULL, INT_MAX, &length);
if (error.isError())
{
return 0;
}
return length;
}
bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps)
LinkResult ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps)
{
if (!fragmentShader || !fragmentShader->isCompiled())
{
return false;
return LinkResult(false, Error(GL_NO_ERROR));
}
ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
if (!vertexShader || !vertexShader->isCompiled())
{
return false;
return LinkResult(false, Error(GL_NO_ERROR));
}
ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
......@@ -1187,22 +1188,21 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
int registers;
std::vector<LinkedVarying> linkedVaryings;
if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode,
&registers, &linkedVaryings, &mOutputVariables, caps))
LinkResult result = mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode,
&registers, &linkedVaryings, &mOutputVariables, caps);
if (result.error.isError() || !result.linkSuccess)
{
return false;
return result;
}
bool success = true;
if (!linkAttributes(infoLog, attributeBindings, vertexShader))
{
success = false;
return LinkResult(false, Error(GL_NO_ERROR));
}
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)
......@@ -1217,28 +1217,26 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps))
{
success = false;
return LinkResult(false, Error(GL_NO_ERROR));
}
if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
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,
// however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling.
if (!mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers))
{
infoLog.append("Failed to create D3D shaders.");
success = false;
reset();
}
infoLog.append("Failed to create D3D shaders.");
reset();
return result;
}
return success;
return LinkResult(true, Error(GL_NO_ERROR));
}
// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
......
......@@ -86,6 +86,14 @@ struct LinkedVarying
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.
class ProgramBinary : public RefCountObject
{
......@@ -138,12 +146,13 @@ class ProgramBinary : public RefCountObject
Error applyUniforms();
Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps);
bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
LinkResult load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
Error save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
GLint getLength();
bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps);
LinkResult link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
const Caps &caps);
void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
......
......@@ -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
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;
}
}
......@@ -8433,7 +8439,12 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat,
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:
virtual sh::Attribute *getShaderAttributes() = 0;
virtual GLenum getBinaryFormat() = 0;
virtual bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
virtual bool save(gl::BinaryOutputStream *stream) = 0;
virtual gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
virtual bool compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
int registers) = 0;
virtual gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
int registers) = 0;
virtual bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps) = 0;
virtual gl::LinkResult link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps) = 0;
virtual void initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms) = 0;
......
......@@ -196,12 +196,13 @@ class Renderer
// Shader operations
virtual void releaseShaderCompiler() = 0;
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers) = 0;
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround) = 0;
virtual gl::Error loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, ShaderExecutable **outExecutable) = 0;
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround,
ShaderExecutable **outExectuable) = 0;
virtual UniformStorage *createUniformStorage(size_t storageSize) = 0;
// Image operations
......
......@@ -82,8 +82,8 @@ void HLSLCompiler::release()
}
}
ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
const std::vector<CompileConfig> &configs) const
gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
const std::vector<CompileConfig> &configs, ID3DBlob **outCompiledBlob) const
{
ASSERT(mD3DCompilerModule && mD3DCompileFunc);
......@@ -115,13 +115,15 @@ ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
if (SUCCEEDED(result))
{
return binary;
*outCompiledBlob = binary;
return gl::Error(GL_NO_ERROR);
}
else
{
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());
......@@ -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_
#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
#include "libGLESv2/Error.h"
#include "common/angleutils.h"
#include "common/platform.h"
......@@ -33,8 +35,10 @@ class HLSLCompiler
bool initialize();
void release();
ID3DBlob *compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
const std::vector<CompileConfig> &configs) const;
// Attempt to compile a HLSL shader using the supplied configurations, may output a NULL compiled blob
// 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:
DISALLOW_COPY_AND_ASSIGN(HLSLCompiler);
......
......@@ -47,21 +47,21 @@ class ProgramD3D : public ProgramImpl
bool usesGeometryShader() const;
GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; }
bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
bool save(gl::BinaryOutputStream *stream);
gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
gl::Error save(gl::BinaryOutputStream *stream);
ShaderExecutable *getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo);
ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout);
ShaderExecutable *getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]);
gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExectuable);
gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout, ShaderExecutable **outExectuable);
gl::Error getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable);
ShaderExecutable *getGeometryExecutable() const { return mGeometryExecutable; }
bool compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
int registers);
gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
int registers);
bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps);
gl::LinkResult link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps);
void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const;
......
......@@ -139,7 +139,15 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS];
GetInputLayout(attributes, shaderInputLayout);
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];
for (unsigned int j = 0; j < ilKey.elementCount; ++j)
......@@ -147,7 +155,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
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))
{
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
bool rasterizerDiscard, bool transformFeedbackActive)
{
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();
ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL);
......@@ -2201,13 +2214,10 @@ void Renderer11::releaseShaderCompiler()
ShaderD3D::releaseCompiler();
}
ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers)
gl::Error Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, ShaderExecutable **outExecutable)
{
ShaderExecutable11 *executable = NULL;
HRESULT result;
switch (type)
{
case rx::SHADER_VERTEX:
......@@ -2215,8 +2225,12 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length
ID3D11VertexShader *vertexShader = NULL;
ID3D11GeometryShader *streamOutShader = NULL;
result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader);
HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader);
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)
{
......@@ -2242,51 +2256,55 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length
result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(),
NULL, 0, 0, NULL, &streamOutShader);
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)
{
executable = new ShaderExecutable11(function, length, vertexShader, streamOutShader);
}
*outExecutable = new ShaderExecutable11(function, length, vertexShader, streamOutShader);
}
break;
case rx::SHADER_PIXEL:
{
ID3D11PixelShader *pixelShader = NULL;
result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader);
HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader);
ASSERT(SUCCEEDED(result));
if (pixelShader)
if (FAILED(result))
{
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;
case rx::SHADER_GEOMETRY:
{
ID3D11GeometryShader *geometryShader = NULL;
result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader);
HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader);
ASSERT(SUCCEEDED(result));
if (geometryShader)
if (FAILED(result))
{
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;
default:
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,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround)
gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround,
ShaderExecutable **outExectuable)
{
const char *profileType = NULL;
switch (type)
......@@ -2302,7 +2320,7 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const st
break;
default:
UNREACHABLE();
return NULL;
return gl::Error(GL_INVALID_OPERATION);
}
unsigned int profileMajorVersion = 0;
......@@ -2323,7 +2341,7 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const st
break;
default:
UNREACHABLE();
return NULL;
return gl::Error(GL_INVALID_OPERATION);
}
std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
......@@ -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_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)
{
return NULL;
*outExectuable = NULL;
return gl::Error(GL_NO_ERROR);
}
ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers);
error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers, outExectuable);
SafeRelease(binary);
if (error.isError())
{
return error;
}
return executable;
return gl::Error(GL_NO_ERROR);
}
rx::UniformStorage *Renderer11::createUniformStorage(size_t storageSize)
......
......@@ -141,12 +141,13 @@ class Renderer11 : public Renderer
// Shader operations
virtual void releaseShaderCompiler();
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers);
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround);
virtual gl::Error loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, ShaderExecutable **outExecutable);
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround,
ShaderExecutable **outExectuable);
virtual UniformStorage *createUniformStorage(size_t storageSize);
// Image operations
......
......@@ -114,7 +114,7 @@ void Blit9::initGeometry()
template <class D3DShaderType>
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*))
{
IDirect3DDevice9 *device = mRenderer->getDevice();
......@@ -130,10 +130,10 @@ gl::Error Blit9::setShader(ShaderId source, const char *profile,
const BYTE* shaderCode = g_shaderCode[source];
size_t shaderSize = g_shaderSize[source];
shader = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize);
if (!shader)
gl::Error error = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize, &shader);
if (error.isError())
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader for blit operation");
return error;
}
mCompiledShaders[source] = shader;
......
......@@ -76,7 +76,7 @@ class Blit9
template <class D3DShaderType>
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*));
gl::Error setVertexShader(ShaderId shader);
......
......@@ -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)
......@@ -1671,8 +1671,20 @@ gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::Ve
ASSERT(!rasterizerDiscard);
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);
IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL);
......@@ -2791,46 +2803,49 @@ void Renderer9::releaseShaderCompiler()
ShaderD3D::releaseCompiler();
}
ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers)
gl::Error Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, ShaderExecutable **outExecutable)
{
// Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0);
ShaderExecutable9 *executable = NULL;
switch (type)
{
case rx::SHADER_VERTEX:
{
IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length);
if (vshader)
IDirect3DVertexShader9 *vshader = NULL;
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;
case rx::SHADER_PIXEL:
{
IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length);
if (pshader)
IDirect3DPixelShader9 *pshader = NULL;
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;
default:
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,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround)
gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround,
ShaderExecutable **outExectuable)
{
// Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0);
......@@ -2846,7 +2861,7 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std
break;
default:
UNREACHABLE();
return NULL;
return gl::Error(GL_INVALID_OPERATION);
}
unsigned int profileMajorVersion = (getMajorShaderModel() >= 3) ? 3 : 2;
unsigned int profileMinorVersion = 0;
......@@ -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_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)
{
return NULL;
*outExectuable = NULL;
return gl::Error(GL_NO_ERROR);
}
ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers);
error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers, outExectuable);
SafeRelease(binary);
if (error.isError())
{
return error;
}
return executable;
return gl::Error(GL_NO_ERROR);
}
rx::UniformStorage *Renderer9::createUniformStorage(size_t storageSize)
......
......@@ -56,8 +56,8 @@ class Renderer9 : public Renderer
void freeEventQuery(IDirect3DQuery9* query);
// resource creation
IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length);
IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length);
gl::Error createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader);
gl::Error createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader);
HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer);
HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer);
virtual gl::Error generateSwizzle(gl::Texture *texture);
......@@ -143,12 +143,13 @@ class Renderer9 : public Renderer
// Shader operations
virtual void releaseShaderCompiler();
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers);
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround);
virtual gl::Error loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, ShaderExecutable **outExecutable);
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround,
ShaderExecutable **outExectuable);
virtual UniformStorage *createUniformStorage(size_t storageSize);
// Image operations
......
......@@ -10,6 +10,8 @@
#ifndef LIBGLESV2_RENDERER_SHADER_CACHE_H_
#define LIBGLESV2_RENDERER_SHADER_CACHE_H_
#include "libGLESv2/Error.h"
#include "common/debug.h"
#include <cstddef>
......@@ -37,21 +39,22 @@ class ShaderCache
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);
typename Map::iterator it = mMap.find(key);
if (it != mMap.end())
{
it->second->AddRef();
return it->second;
*outShaderObject = it->second;
return gl::Error(GL_NO_ERROR);
}
ShaderObject *shader;
HRESULT result = createShader(function, &shader);
if (FAILED(result))
{
return NULL;
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader, result: 0x%X.", result);
}
// Random eviction policy.
......@@ -64,7 +67,8 @@ class ShaderCache
shader->AddRef();
mMap[key] = shader;
return shader;
*outShaderObject = shader;
return gl::Error(GL_NO_ERROR);
}
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