Adding shader versioning and defines from GLBackendShader allowing for runtime defines injection to shaders and more

This commit is contained in:
samcake 2016-04-18 18:24:27 -07:00
parent c6deff16d6
commit cadb53b703
7 changed files with 334 additions and 272 deletions

View file

@ -18,7 +18,7 @@
// //
const QString SHADER_COMMON = R"SHADER(#version 410 core const QString SHADER_COMMON = R"SHADER(
layout(location = 0) out vec4 _fragColor0; layout(location = 0) out vec4 _fragColor0;
layout(location = 1) out vec4 _fragColor1; layout(location = 1) out vec4 _fragColor1;
layout(location = 2) out vec4 _fragColor2; layout(location = 2) out vec4 _fragColor2;

View file

@ -13,11 +13,11 @@
<@if GLPROFILE == PC_GL @> <@if GLPROFILE == PC_GL @>
<@def GPU_FEATURE_PROFILE GPU_CORE@> <@def GPU_FEATURE_PROFILE GPU_CORE@>
<@def VERSION_HEADER #version 410 core@> <@def VERSION_HEADER //PC 410 core@>
<@elif GLPROFILE == MAC_GL @> <@elif GLPROFILE == MAC_GL @>
<@def GPU_FEATURE_PROFILE GPU_CORE@> <@def GPU_FEATURE_PROFILE GPU_CORE@>
<@def VERSION_HEADER #version 410 core@> <@def VERSION_HEADER //MAC 410 core@>
<@else@> <@else@>
<@def GPU_FEATURE_PROFILE GPU_CORE@> <@def GPU_FEATURE_PROFILE GPU_CORE@>
<@def VERSION_HEADER #version 410 core@> <@def VERSION_HEADER //410 core@>
<@endif@> <@endif@>

View file

@ -461,8 +461,7 @@ void GLBackend::resetStages() {
#define ADD_COMMAND_GL(call) _commands.push_back(COMMAND_##call); _commandOffsets.push_back(_params.size()); #define ADD_COMMAND_GL(call) _commands.push_back(COMMAND_##call); _commandOffsets.push_back(_params.size());
//#define DO_IT_NOW(call, offset) runLastCommand(); #define GET_UNIFORM_LOCATION(shaderUniformLoc) shaderUniformLoc
#define DO_IT_NOW(call, offset)
void Batch::_glActiveBindTexture(GLenum unit, GLenum target, GLuint texture) { void Batch::_glActiveBindTexture(GLenum unit, GLenum target, GLuint texture) {
// clean the cache on the texture unit we are going to use so the next call to setResourceTexture() at the same slot works fine // clean the cache on the texture unit we are going to use so the next call to setResourceTexture() at the same slot works fine
@ -472,14 +471,11 @@ void Batch::_glActiveBindTexture(GLenum unit, GLenum target, GLuint texture) {
_params.push_back(texture); _params.push_back(texture);
_params.push_back(target); _params.push_back(target);
_params.push_back(unit); _params.push_back(unit);
DO_IT_NOW(_glActiveBindTexture, 3);
} }
void GLBackend::do_glActiveBindTexture(Batch& batch, size_t paramOffset) { void GLBackend::do_glActiveBindTexture(Batch& batch, size_t paramOffset) {
glActiveTexture(batch._params[paramOffset + 2]._uint); glActiveTexture(batch._params[paramOffset + 2]._uint);
glBindTexture( glBindTexture(
batch._params[paramOffset + 1]._uint, GET_UNIFORM_LOCATION(batch._params[paramOffset + 1]._uint),
batch._params[paramOffset + 0]._uint); batch._params[paramOffset + 0]._uint);
(void) CHECK_GL_ERROR(); (void) CHECK_GL_ERROR();
@ -492,8 +488,6 @@ void Batch::_glUniform1i(GLint location, GLint v0) {
ADD_COMMAND_GL(glUniform1i); ADD_COMMAND_GL(glUniform1i);
_params.push_back(v0); _params.push_back(v0);
_params.push_back(location); _params.push_back(location);
DO_IT_NOW(_glUniform1i, 1);
} }
void GLBackend::do_glUniform1i(Batch& batch, size_t paramOffset) { void GLBackend::do_glUniform1i(Batch& batch, size_t paramOffset) {
if (_pipeline._program == 0) { if (_pipeline._program == 0) {
@ -503,7 +497,7 @@ void GLBackend::do_glUniform1i(Batch& batch, size_t paramOffset) {
} }
updatePipeline(); updatePipeline();
glUniform1f( glUniform1f(
batch._params[paramOffset + 1]._int, GET_UNIFORM_LOCATION(batch._params[paramOffset + 1]._int),
batch._params[paramOffset + 0]._int); batch._params[paramOffset + 0]._int);
(void) CHECK_GL_ERROR(); (void) CHECK_GL_ERROR();
} }
@ -515,8 +509,6 @@ void Batch::_glUniform1f(GLint location, GLfloat v0) {
ADD_COMMAND_GL(glUniform1f); ADD_COMMAND_GL(glUniform1f);
_params.push_back(v0); _params.push_back(v0);
_params.push_back(location); _params.push_back(location);
DO_IT_NOW(_glUniform1f, 1);
} }
void GLBackend::do_glUniform1f(Batch& batch, size_t paramOffset) { void GLBackend::do_glUniform1f(Batch& batch, size_t paramOffset) {
if (_pipeline._program == 0) { if (_pipeline._program == 0) {
@ -527,7 +519,7 @@ void GLBackend::do_glUniform1f(Batch& batch, size_t paramOffset) {
updatePipeline(); updatePipeline();
glUniform1f( glUniform1f(
batch._params[paramOffset + 1]._int, GET_UNIFORM_LOCATION(batch._params[paramOffset + 1]._int),
batch._params[paramOffset + 0]._float); batch._params[paramOffset + 0]._float);
(void) CHECK_GL_ERROR(); (void) CHECK_GL_ERROR();
} }
@ -538,8 +530,6 @@ void Batch::_glUniform2f(GLint location, GLfloat v0, GLfloat v1) {
_params.push_back(v1); _params.push_back(v1);
_params.push_back(v0); _params.push_back(v0);
_params.push_back(location); _params.push_back(location);
DO_IT_NOW(_glUniform2f, 1);
} }
void GLBackend::do_glUniform2f(Batch& batch, size_t paramOffset) { void GLBackend::do_glUniform2f(Batch& batch, size_t paramOffset) {
@ -550,7 +540,7 @@ void GLBackend::do_glUniform2f(Batch& batch, size_t paramOffset) {
} }
updatePipeline(); updatePipeline();
glUniform2f( glUniform2f(
batch._params[paramOffset + 2]._int, GET_UNIFORM_LOCATION(batch._params[paramOffset + 2]._int),
batch._params[paramOffset + 1]._float, batch._params[paramOffset + 1]._float,
batch._params[paramOffset + 0]._float); batch._params[paramOffset + 0]._float);
(void) CHECK_GL_ERROR(); (void) CHECK_GL_ERROR();
@ -563,8 +553,6 @@ void Batch::_glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
_params.push_back(v1); _params.push_back(v1);
_params.push_back(v0); _params.push_back(v0);
_params.push_back(location); _params.push_back(location);
DO_IT_NOW(_glUniform3f, 1);
} }
void GLBackend::do_glUniform3f(Batch& batch, size_t paramOffset) { void GLBackend::do_glUniform3f(Batch& batch, size_t paramOffset) {
@ -575,7 +563,7 @@ void GLBackend::do_glUniform3f(Batch& batch, size_t paramOffset) {
} }
updatePipeline(); updatePipeline();
glUniform3f( glUniform3f(
batch._params[paramOffset + 3]._int, GET_UNIFORM_LOCATION(batch._params[paramOffset + 3]._int),
batch._params[paramOffset + 2]._float, batch._params[paramOffset + 2]._float,
batch._params[paramOffset + 1]._float, batch._params[paramOffset + 1]._float,
batch._params[paramOffset + 0]._float); batch._params[paramOffset + 0]._float);
@ -591,8 +579,6 @@ void Batch::_glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLf
_params.push_back(v1); _params.push_back(v1);
_params.push_back(v0); _params.push_back(v0);
_params.push_back(location); _params.push_back(location);
DO_IT_NOW(_glUniform4f, 1);
} }
@ -604,7 +590,7 @@ void GLBackend::do_glUniform4f(Batch& batch, size_t paramOffset) {
} }
updatePipeline(); updatePipeline();
glUniform4f( glUniform4f(
batch._params[paramOffset + 4]._int, GET_UNIFORM_LOCATION(batch._params[paramOffset + 4]._int),
batch._params[paramOffset + 3]._float, batch._params[paramOffset + 3]._float,
batch._params[paramOffset + 2]._float, batch._params[paramOffset + 2]._float,
batch._params[paramOffset + 1]._float, batch._params[paramOffset + 1]._float,
@ -619,8 +605,6 @@ void Batch::_glUniform3fv(GLint location, GLsizei count, const GLfloat* value) {
_params.push_back(cacheData(count * VEC3_SIZE, value)); _params.push_back(cacheData(count * VEC3_SIZE, value));
_params.push_back(count); _params.push_back(count);
_params.push_back(location); _params.push_back(location);
DO_IT_NOW(_glUniform3fv, 3);
} }
void GLBackend::do_glUniform3fv(Batch& batch, size_t paramOffset) { void GLBackend::do_glUniform3fv(Batch& batch, size_t paramOffset) {
if (_pipeline._program == 0) { if (_pipeline._program == 0) {
@ -630,7 +614,7 @@ void GLBackend::do_glUniform3fv(Batch& batch, size_t paramOffset) {
} }
updatePipeline(); updatePipeline();
glUniform3fv( glUniform3fv(
batch._params[paramOffset + 2]._int, GET_UNIFORM_LOCATION(batch._params[paramOffset + 2]._int),
batch._params[paramOffset + 1]._uint, batch._params[paramOffset + 1]._uint,
(const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint)); (const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint));
@ -645,8 +629,6 @@ void Batch::_glUniform4fv(GLint location, GLsizei count, const GLfloat* value) {
_params.push_back(cacheData(count * VEC4_SIZE, value)); _params.push_back(cacheData(count * VEC4_SIZE, value));
_params.push_back(count); _params.push_back(count);
_params.push_back(location); _params.push_back(location);
DO_IT_NOW(_glUniform4fv, 3);
} }
void GLBackend::do_glUniform4fv(Batch& batch, size_t paramOffset) { void GLBackend::do_glUniform4fv(Batch& batch, size_t paramOffset) {
if (_pipeline._program == 0) { if (_pipeline._program == 0) {
@ -656,7 +638,7 @@ void GLBackend::do_glUniform4fv(Batch& batch, size_t paramOffset) {
} }
updatePipeline(); updatePipeline();
GLint location = batch._params[paramOffset + 2]._int; GLint location = GET_UNIFORM_LOCATION(batch._params[paramOffset + 2]._int);
GLsizei count = batch._params[paramOffset + 1]._uint; GLsizei count = batch._params[paramOffset + 1]._uint;
const GLfloat* value = (const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint); const GLfloat* value = (const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint);
glUniform4fv(location, count, value); glUniform4fv(location, count, value);
@ -671,8 +653,6 @@ void Batch::_glUniform4iv(GLint location, GLsizei count, const GLint* value) {
_params.push_back(cacheData(count * VEC4_SIZE, value)); _params.push_back(cacheData(count * VEC4_SIZE, value));
_params.push_back(count); _params.push_back(count);
_params.push_back(location); _params.push_back(location);
DO_IT_NOW(_glUniform4iv, 3);
} }
void GLBackend::do_glUniform4iv(Batch& batch, size_t paramOffset) { void GLBackend::do_glUniform4iv(Batch& batch, size_t paramOffset) {
if (_pipeline._program == 0) { if (_pipeline._program == 0) {
@ -682,7 +662,7 @@ void GLBackend::do_glUniform4iv(Batch& batch, size_t paramOffset) {
} }
updatePipeline(); updatePipeline();
glUniform4iv( glUniform4iv(
batch._params[paramOffset + 2]._int, GET_UNIFORM_LOCATION(batch._params[paramOffset + 2]._int),
batch._params[paramOffset + 1]._uint, batch._params[paramOffset + 1]._uint,
(const GLint*)batch.editData(batch._params[paramOffset + 0]._uint)); (const GLint*)batch.editData(batch._params[paramOffset + 0]._uint));
@ -697,8 +677,6 @@ void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpo
_params.push_back(transpose); _params.push_back(transpose);
_params.push_back(count); _params.push_back(count);
_params.push_back(location); _params.push_back(location);
DO_IT_NOW(_glUniformMatrix4fv, 4);
} }
void GLBackend::do_glUniformMatrix4fv(Batch& batch, size_t paramOffset) { void GLBackend::do_glUniformMatrix4fv(Batch& batch, size_t paramOffset) {
if (_pipeline._program == 0) { if (_pipeline._program == 0) {
@ -708,7 +686,7 @@ void GLBackend::do_glUniformMatrix4fv(Batch& batch, size_t paramOffset) {
} }
updatePipeline(); updatePipeline();
glUniformMatrix4fv( glUniformMatrix4fv(
batch._params[paramOffset + 3]._int, GET_UNIFORM_LOCATION(batch._params[paramOffset + 3]._int),
batch._params[paramOffset + 2]._uint, batch._params[paramOffset + 2]._uint,
batch._params[paramOffset + 1]._uint, batch._params[paramOffset + 1]._uint,
(const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint)); (const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint));
@ -722,8 +700,6 @@ void Batch::_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
_params.push_back(blue); _params.push_back(blue);
_params.push_back(green); _params.push_back(green);
_params.push_back(red); _params.push_back(red);
DO_IT_NOW(_glColor4f, 4);
} }
void GLBackend::do_glColor4f(Batch& batch, size_t paramOffset) { void GLBackend::do_glColor4f(Batch& batch, size_t paramOffset) {

View file

@ -153,17 +153,40 @@ public:
class GLShader : public GPUObject { class GLShader : public GPUObject {
public: public:
GLuint _shader; enum Version {
GLuint _program; Mono = 0,
NumVersions
};
struct ShaderObject {
GLuint glshader{ 0 };
GLuint glprogram{ 0 };
GLint transformCameraSlot{ -1 };
GLint transformObjectSlot{ -1 };
};
using ShaderObjects = std::array< ShaderObject, NumVersions >;
using UniformMapping = std::vector<GLint>;
using UniformMappingVersions = std::vector<UniformMapping>;
GLint _transformCameraSlot = -1;
GLint _transformObjectSlot = -1;
GLShader(); GLShader();
~GLShader(); ~GLShader();
ShaderObjects _shaderObjects;
UniformMappingVersions _uniformMappings;
GLuint getProgram() const {
return _shaderObjects[Mono].glprogram;
}
GLint getUniformLocation(GLint srcLoc) {
return _uniformMappings[Mono][srcLoc];
}
}; };
static GLShader* syncGPUObject(const Shader& shader); static GLShader* syncGPUObject(const Shader& shader);
static GLuint getShaderID(const ShaderPointer& shader);
class GLState : public GPUObject { class GLState : public GPUObject {
public: public:
@ -464,6 +487,7 @@ protected:
PipelinePointer _pipeline; PipelinePointer _pipeline;
GLuint _program; GLuint _program;
GLShader* _programShader;
bool _invalidProgram; bool _invalidProgram;
State::Data _stateCache; State::Data _stateCache;
@ -475,6 +499,7 @@ protected:
PipelineStageState() : PipelineStageState() :
_pipeline(), _pipeline(),
_program(0), _program(0),
_programShader(nullptr),
_invalidProgram(false), _invalidProgram(false),
_stateCache(State::DEFAULT), _stateCache(State::DEFAULT),
_stateSignatureCache(0), _stateSignatureCache(0),

View file

@ -69,6 +69,7 @@ void GLBackend::do_setPipeline(Batch& batch, size_t paramOffset) {
_pipeline._pipeline.reset(); _pipeline._pipeline.reset();
_pipeline._program = 0; _pipeline._program = 0;
_pipeline._programShader = nullptr;
_pipeline._invalidProgram = true; _pipeline._invalidProgram = true;
_pipeline._state = nullptr; _pipeline._state = nullptr;
@ -80,8 +81,10 @@ void GLBackend::do_setPipeline(Batch& batch, size_t paramOffset) {
} }
// check the program cache // check the program cache
if (_pipeline._program != pipelineObject->_program->_program) { GLuint glprogram = pipelineObject->_program->getProgram();
_pipeline._program = pipelineObject->_program->_program; if (_pipeline._program != glprogram) {
_pipeline._program = glprogram;
_pipeline._programShader = pipelineObject->_program;
_pipeline._invalidProgram = true; _pipeline._invalidProgram = true;
} }
@ -142,6 +145,7 @@ void GLBackend::resetPipelineStage() {
// Second the shader side // Second the shader side
_pipeline._invalidProgram = false; _pipeline._invalidProgram = false;
_pipeline._program = 0; _pipeline._program = 0;
_pipeline._programShader = nullptr;
_pipeline._pipeline.reset(); _pipeline._pipeline.reset();
glUseProgram(0); glUseProgram(0);
} }

View file

@ -13,27 +13,205 @@
using namespace gpu; using namespace gpu;
GLBackend::GLShader::GLShader() : GLBackend::GLShader::GLShader()
_shader(0), {
_program(0) }
{}
GLBackend::GLShader::~GLShader() { GLBackend::GLShader::~GLShader() {
if (_shader != 0) { for (auto& so : _shaderObjects) {
glDeleteShader(_shader); if (so.glshader != 0) {
} glDeleteShader(so.glshader);
if (_program != 0) { }
glDeleteProgram(_program); if (so.glprogram != 0) {
glDeleteProgram(so.glprogram);
}
} }
} }
void makeBindings(GLBackend::GLShader* shader) { bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, GLuint &programObject) {
if(!shader || !shader->_program) { if (shaderSource.empty()) {
qCDebug(gpulogging) << "GLShader::compileShader - no GLSL shader source code ? so failed to create";
return false;
}
// Create the shader object
GLuint glshader = glCreateShader(shaderDomain);
if (!glshader) {
qCDebug(gpulogging) << "GLShader::compileShader - failed to create the gl shader object";
return nullptr;
}
// Assign the source
const int NUM_SOURCE_STRINGS = 2;
const GLchar* srcstr[] = { defines.c_str(), shaderSource.c_str() };
glShaderSource(glshader, NUM_SOURCE_STRINGS, srcstr, NULL);
// Compile !
glCompileShader(glshader);
// check if shader compiled
GLint compiled = 0;
glGetShaderiv(glshader, GL_COMPILE_STATUS, &compiled);
// if compilation fails
if (!compiled) {
// save the source code to a temp file so we can debug easily
/* std::ofstream filestream;
filestream.open("debugshader.glsl");
if (filestream.is_open()) {
filestream << shaderSource->source;
filestream.close();
}
*/
GLint infoLength = 0;
glGetShaderiv(glshader, GL_INFO_LOG_LENGTH, &infoLength);
char* temp = new char[infoLength];
glGetShaderInfoLog(glshader, infoLength, NULL, temp);
/*
filestream.open("debugshader.glsl.info.txt");
if (filestream.is_open()) {
filestream << std::string(temp);
filestream.close();
}
*/
qCWarning(gpulogging) << "GLShader::compileShader - failed to compile the gl shader object:";
for (auto s : srcstr) {
qCWarning(gpulogging) << s;
}
qCWarning(gpulogging) << "GLShader::compileShader - errors:";
qCWarning(gpulogging) << temp;
delete[] temp;
glDeleteShader(glshader);
return false;
}
GLuint glprogram = 0;
#ifdef SEPARATE_PROGRAM
// so far so good, program is almost done, need to link:
GLuint glprogram = glCreateProgram();
if (!glprogram) {
qCDebug(gpulogging) << "GLShader::compileShader - failed to create the gl shader & gl program object";
return false;
}
glProgramParameteri(glprogram, GL_PROGRAM_SEPARABLE, GL_TRUE);
glAttachShader(glprogram, glshader);
glLinkProgram(glprogram);
GLint linked = 0;
glGetProgramiv(glprogram, GL_LINK_STATUS, &linked);
if (!linked) {
/*
// save the source code to a temp file so we can debug easily
std::ofstream filestream;
filestream.open("debugshader.glsl");
if (filestream.is_open()) {
filestream << shaderSource->source;
filestream.close();
}
*/
GLint infoLength = 0;
glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength);
char* temp = new char[infoLength];
glGetProgramInfoLog(glprogram, infoLength, NULL, temp);
qCDebug(gpulogging) << "GLShader::compileShader - failed to LINK the gl program object :";
qCDebug(gpulogging) << temp;
/*
filestream.open("debugshader.glsl.info.txt");
if (filestream.is_open()) {
filestream << String(temp);
filestream.close();
}
*/
delete[] temp;
glDeleteShader(glshader);
glDeleteProgram(glprogram);
return false;
}
#endif
shaderObject = glshader;
programObject = glprogram;
return true;
}
GLuint compileProgram(const std::vector<GLuint>& glshaders) {
// A brand new program:
GLuint glprogram = glCreateProgram();
if (!glprogram) {
qCDebug(gpulogging) << "GLShader::compileProgram - failed to create the gl program object";
return 0;
}
// glProgramParameteri(glprogram, GL_PROGRAM_, GL_TRUE);
// Create the program from the sub shaders
for (auto so : glshaders) {
glAttachShader(glprogram, so);
}
// Link!
glLinkProgram(glprogram);
GLint linked = 0;
glGetProgramiv(glprogram, GL_LINK_STATUS, &linked);
if (!linked) {
/*
// save the source code to a temp file so we can debug easily
std::ofstream filestream;
filestream.open("debugshader.glsl");
if (filestream.is_open()) {
filestream << shaderSource->source;
filestream.close();
}
*/
GLint infoLength = 0;
glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength);
char* temp = new char[infoLength];
glGetProgramInfoLog(glprogram, infoLength, NULL, temp);
qCDebug(gpulogging) << "GLShader::compileProgram - failed to LINK the gl program object :";
qCDebug(gpulogging) << temp;
/*
filestream.open("debugshader.glsl.info.txt");
if (filestream.is_open()) {
filestream << std::string(temp);
filestream.close();
}
*/
delete[] temp;
glDeleteProgram(glprogram);
return 0;
}
return glprogram;
}
void makeProgramBindings(GLBackend::GLShader::ShaderObject& shaderObject) {
if (!shaderObject.glprogram) {
return; return;
} }
GLuint glprogram = shader->_program; GLuint glprogram = shaderObject.glprogram;
GLint loc = -1; GLint loc = -1;
//Check for gpu specific attribute slotBindings //Check for gpu specific attribute slotBindings
loc = glGetAttribLocation(glprogram, "inPosition"); loc = glGetAttribLocation(glprogram, "inPosition");
if (loc >= 0 && loc != gpu::Stream::POSITION) { if (loc >= 0 && loc != gpu::Stream::POSITION) {
@ -96,226 +274,111 @@ void makeBindings(GLBackend::GLShader* shader) {
loc = glGetProgramResourceIndex(glprogram, GL_SHADER_STORAGE_BLOCK, "transformObjectBuffer"); loc = glGetProgramResourceIndex(glprogram, GL_SHADER_STORAGE_BLOCK, "transformObjectBuffer");
if (loc >= 0) { if (loc >= 0) {
glShaderStorageBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); glShaderStorageBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT);
shader->_transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT; shaderObject.transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT;
} }
#else #else
loc = glGetUniformLocation(glprogram, "transformObjectBuffer"); loc = glGetUniformLocation(glprogram, "transformObjectBuffer");
if (loc >= 0) { if (loc >= 0) {
glProgramUniform1i(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); glProgramUniform1i(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT);
shader->_transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT; shaderObject.transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT;
} }
#endif #endif
loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer"); loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer");
if (loc >= 0) { if (loc >= 0) {
glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT); glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT);
shader->_transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT; shaderObject.transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
} }
(void)CHECK_GL_ERROR(); (void)CHECK_GL_ERROR();
} }
GLBackend::GLShader* compileShader(const Shader& shader) { GLBackend::GLShader* compileBackendShader(const Shader& shader) {
// Any GLSLprogram ? normally yes... // Any GLSLprogram ? normally yes...
const std::string& shaderSource = shader.getSource().getCode(); const std::string& shaderSource = shader.getSource().getCode();
if (shaderSource.empty()) {
qCDebug(gpulogging) << "GLShader::compileShader - no GLSL shader source code ? so failed to create"; // GLSL version
return nullptr; const std::string glslVersion = {
} "#version 410 core"
};
// Shader domain // Shader domain
const GLenum SHADER_DOMAINS[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER }; const int NUM_SHADER_DOMAINS = 2;
const GLenum SHADER_DOMAINS[NUM_SHADER_DOMAINS] = {
GL_VERTEX_SHADER,
GL_FRAGMENT_SHADER
};
GLenum shaderDomain = SHADER_DOMAINS[shader.getType()]; GLenum shaderDomain = SHADER_DOMAINS[shader.getType()];
// Create the shader object // Domain specific defines
GLuint glshader = glCreateShader(shaderDomain); const std::string domainDefines[NUM_SHADER_DOMAINS] = {
if (!glshader) { "#define VERTEX_SHADER",
qCDebug(gpulogging) << "GLShader::compileShader - failed to create the gl shader object"; "#define PIXEL_SHADER"
return nullptr; };
}
// Assign the source
const GLchar* srcstr = shaderSource.c_str();
glShaderSource(glshader, 1, &srcstr, NULL);
// Compile !
glCompileShader(glshader);
// check if shader compiled // Versions specific of the shader
GLint compiled = 0; const std::string versionDefines[GLBackend::GLShader::NumVersions] = {
glGetShaderiv(glshader, GL_COMPILE_STATUS, &compiled); ""
};
// if compilation fails GLBackend::GLShader::ShaderObjects shaderObjects;
if (!compiled) {
// save the source code to a temp file so we can debug easily for (int version = 0; version < GLBackend::GLShader::NumVersions; version++) {
/* std::ofstream filestream; auto& shaderObject = shaderObjects[version];
filestream.open("debugshader.glsl");
if (filestream.is_open()) { std::string shaderDefines = glslVersion + "\n" + domainDefines[shader.getType()] + "\n" + versionDefines[version];
filestream << shaderSource->source;
filestream.close(); bool result = compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader, shaderObject.glprogram);
if (!result) {
return nullptr;
} }
*/
GLint infoLength = 0;
glGetShaderiv(glshader, GL_INFO_LOG_LENGTH, &infoLength);
char* temp = new char[infoLength] ;
glGetShaderInfoLog(glshader, infoLength, NULL, temp);
/*
filestream.open("debugshader.glsl.info.txt");
if (filestream.is_open()) {
filestream << std::string(temp);
filestream.close();
}
*/
qCWarning(gpulogging) << "GLShader::compileShader - failed to compile the gl shader object:";
qCWarning(gpulogging) << srcstr;
qCWarning(gpulogging) << "GLShader::compileShader - errors:";
qCWarning(gpulogging) << temp;
delete[] temp;
glDeleteShader(glshader);
return nullptr;
} }
GLuint glprogram = 0;
#ifdef SEPARATE_PROGRAM
// so far so good, program is almost done, need to link:
GLuint glprogram = glCreateProgram();
if (!glprogram) {
qCDebug(gpulogging) << "GLShader::compileShader - failed to create the gl shader & gl program object";
return nullptr;
}
glProgramParameteri(glprogram, GL_PROGRAM_SEPARABLE, GL_TRUE);
glAttachShader(glprogram, glshader);
glLinkProgram(glprogram);
GLint linked = 0;
glGetProgramiv(glprogram, GL_LINK_STATUS, &linked);
if (!linked) {
/*
// save the source code to a temp file so we can debug easily
std::ofstream filestream;
filestream.open("debugshader.glsl");
if (filestream.is_open()) {
filestream << shaderSource->source;
filestream.close();
}
*/
GLint infoLength = 0;
glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength);
char* temp = new char[infoLength] ;
glGetProgramInfoLog(glprogram, infoLength, NULL, temp);
qCDebug(gpulogging) << "GLShader::compileShader - failed to LINK the gl program object :";
qCDebug(gpulogging) << temp;
/*
filestream.open("debugshader.glsl.info.txt");
if (filestream.is_open()) {
filestream << String(temp);
filestream.close();
}
*/
delete[] temp;
glDeleteShader(glshader);
glDeleteProgram(glprogram);
return nullptr;
}
#endif
// So far so good, the shader is created successfully // So far so good, the shader is created successfully
GLBackend::GLShader* object = new GLBackend::GLShader(); GLBackend::GLShader* object = new GLBackend::GLShader();
object->_shader = glshader; object->_shaderObjects = shaderObjects;
object->_program = glprogram;
makeBindings(object);
return object; return object;
} }
GLBackend::GLShader* compileProgram(const Shader& program) { GLBackend::GLShader* compileBackendProgram(const Shader& program) {
if(!program.isProgram()) { if (!program.isProgram()) {
return nullptr; return nullptr;
} }
// Let's go through every shaders and make sure they are ready to go GLBackend::GLShader::ShaderObjects programObjects;
std::vector< GLuint > shaderObjects;
for (auto subShader : program.getShaders()) { for (int version = 0; version < GLBackend::GLShader::NumVersions; version++) {
GLuint so = GLBackend::getShaderID(subShader); auto& programObject = programObjects[version];
if (!so) {
qCDebug(gpulogging) << "GLShader::compileProgram - One of the shaders of the program is not compiled?"; // Let's go through every shaders and make sure they are ready to go
std::vector< GLuint > shaderGLObjects;
for (auto subShader : program.getShaders()) {
auto object = GLBackend::syncGPUObject(*subShader);
if (object) {
shaderGLObjects.push_back(object->_shaderObjects[version].glshader);
} else {
qCDebug(gpulogging) << "GLShader::compileBackendProgram - One of the shaders of the program is not compiled?";
return nullptr;
}
}
GLuint glprogram = compileProgram(shaderGLObjects);
if (glprogram == 0) {
return nullptr; return nullptr;
} }
shaderObjects.push_back(so);
programObject.glprogram = glprogram;
makeProgramBindings(programObject);
} }
// so far so good, program is almost done, need to link:
GLuint glprogram = glCreateProgram();
if (!glprogram) {
qCDebug(gpulogging) << "GLShader::compileProgram - failed to create the gl program object";
return nullptr;
}
// glProgramParameteri(glprogram, GL_PROGRAM_, GL_TRUE); // So far so good, the program versions have all been created successfully
// Create the program from the sub shaders
for (auto so : shaderObjects) {
glAttachShader(glprogram, so);
}
// Link!
glLinkProgram(glprogram);
GLint linked = 0;
glGetProgramiv(glprogram, GL_LINK_STATUS, &linked);
if (!linked) {
/*
// save the source code to a temp file so we can debug easily
std::ofstream filestream;
filestream.open("debugshader.glsl");
if (filestream.is_open()) {
filestream << shaderSource->source;
filestream.close();
}
*/
GLint infoLength = 0;
glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength);
char* temp = new char[infoLength] ;
glGetProgramInfoLog(glprogram, infoLength, NULL, temp);
qCDebug(gpulogging) << "GLShader::compileProgram - failed to LINK the gl program object :";
qCDebug(gpulogging) << temp;
/*
filestream.open("debugshader.glsl.info.txt");
if (filestream.is_open()) {
filestream << std::string(temp);
filestream.close();
}
*/
delete[] temp;
glDeleteProgram(glprogram);
return nullptr;
}
// So far so good, the program is created successfully
GLBackend::GLShader* object = new GLBackend::GLShader(); GLBackend::GLShader* object = new GLBackend::GLShader();
object->_shader = 0; object->_shaderObjects = programObjects;
object->_program = glprogram;
makeBindings(object);
return object; return object;
} }
@ -329,14 +392,14 @@ GLBackend::GLShader* GLBackend::syncGPUObject(const Shader& shader) {
} }
// need to have a gpu object? // need to have a gpu object?
if (shader.isProgram()) { if (shader.isProgram()) {
GLShader* tempObject = compileProgram(shader); GLShader* tempObject = compileBackendProgram(shader);
if (tempObject) { if (tempObject) {
object = tempObject; object = tempObject;
Backend::setGPUObject(shader, object); Backend::setGPUObject(shader, object);
} }
} else if (shader.isDomain()) { } else if (shader.isDomain()) {
GLShader* tempObject = compileShader(shader); GLShader* tempObject = compileBackendShader(shader);
if (tempObject) { if (tempObject) {
object = tempObject; object = tempObject;
Backend::setGPUObject(shader, object); Backend::setGPUObject(shader, object);
} }
@ -345,23 +408,6 @@ GLBackend::GLShader* GLBackend::syncGPUObject(const Shader& shader) {
return object; return object;
} }
GLuint GLBackend::getShaderID(const ShaderPointer& shader) {
if (!shader) {
return 0;
}
GLShader* object = GLBackend::syncGPUObject(*shader);
if (object) {
if (shader->isProgram()) {
return object->_program;
} else {
return object->_shader;
}
} else {
return 0;
}
}
class ElementResource { class ElementResource {
public: public:
gpu::Element _element; gpu::Element _element;
@ -714,27 +760,38 @@ bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindin
return false; return false;
} }
if (object->_program) { // Apply bindings to all program versions and generate list of slots from default version
Shader::SlotSet buffers; for (int version = 0; version < GLBackend::GLShader::NumVersions; version++) {
makeUniformBlockSlots(object->_program, slotBindings, buffers); auto& shaderObject = object->_shaderObjects[version];
if (shaderObject.glprogram) {
Shader::SlotSet buffers;
makeUniformBlockSlots(shaderObject.glprogram, slotBindings, buffers);
Shader::SlotSet uniforms; Shader::SlotSet uniforms;
Shader::SlotSet textures; Shader::SlotSet textures;
Shader::SlotSet samplers; Shader::SlotSet samplers;
makeUniformSlots(object->_program, slotBindings, uniforms, textures, samplers); makeUniformSlots(shaderObject.glprogram, slotBindings, uniforms, textures, samplers);
Shader::SlotSet inputs;
makeInputSlots(object->_program, slotBindings, inputs);
Shader::SlotSet outputs; Shader::SlotSet inputs;
makeOutputSlots(object->_program, slotBindings, outputs); makeInputSlots(shaderObject.glprogram, slotBindings, inputs);
shader.defineSlots(uniforms, buffers, textures, samplers, inputs, outputs); Shader::SlotSet outputs;
makeOutputSlots(shaderObject.glprogram, slotBindings, outputs);
} else if (object->_shader) {
// Define the public slots only from the default version
if (version == 0) {
shader.defineSlots(uniforms, buffers, textures, samplers, inputs, outputs);
} else {
GLShader::UniformMapping mapping;
for (auto srcUniform : shader.getUniforms()) {
mapping[srcUniform._location] = uniforms.findLocation(srcUniform._name);
}
object->_uniformMappings.push_back(mapping);
}
}
} }
return true; return true;
} }

View file

@ -27,7 +27,7 @@ ToneMappingEffect::ToneMappingEffect() {
} }
void ToneMappingEffect::init() { void ToneMappingEffect::init() {
const char BlitTextureGamma_frag[] = R"SCRIBE(#version 410 core const char BlitTextureGamma_frag[] = R"SCRIBE(
// Generated on Sat Oct 24 09:34:37 2015 // Generated on Sat Oct 24 09:34:37 2015
// //
// Draw texture 0 fetched at texcoord.xy // Draw texture 0 fetched at texcoord.xy