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 = 1) out vec4 _fragColor1;
layout(location = 2) out vec4 _fragColor2;

View file

@ -13,11 +13,11 @@
<@if GLPROFILE == PC_GL @>
<@def GPU_FEATURE_PROFILE GPU_CORE@>
<@def VERSION_HEADER #version 410 core@>
<@def VERSION_HEADER //PC 410 core@>
<@elif GLPROFILE == MAC_GL @>
<@def GPU_FEATURE_PROFILE GPU_CORE@>
<@def VERSION_HEADER #version 410 core@>
<@def VERSION_HEADER //MAC 410 core@>
<@else@>
<@def GPU_FEATURE_PROFILE GPU_CORE@>
<@def VERSION_HEADER #version 410 core@>
<@def VERSION_HEADER //410 core@>
<@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 DO_IT_NOW(call, offset) runLastCommand();
#define DO_IT_NOW(call, offset)
#define GET_UNIFORM_LOCATION(shaderUniformLoc) shaderUniformLoc
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
@ -472,14 +471,11 @@ void Batch::_glActiveBindTexture(GLenum unit, GLenum target, GLuint texture) {
_params.push_back(texture);
_params.push_back(target);
_params.push_back(unit);
DO_IT_NOW(_glActiveBindTexture, 3);
}
void GLBackend::do_glActiveBindTexture(Batch& batch, size_t paramOffset) {
glActiveTexture(batch._params[paramOffset + 2]._uint);
glBindTexture(
batch._params[paramOffset + 1]._uint,
GET_UNIFORM_LOCATION(batch._params[paramOffset + 1]._uint),
batch._params[paramOffset + 0]._uint);
(void) CHECK_GL_ERROR();
@ -492,8 +488,6 @@ void Batch::_glUniform1i(GLint location, GLint v0) {
ADD_COMMAND_GL(glUniform1i);
_params.push_back(v0);
_params.push_back(location);
DO_IT_NOW(_glUniform1i, 1);
}
void GLBackend::do_glUniform1i(Batch& batch, size_t paramOffset) {
if (_pipeline._program == 0) {
@ -503,7 +497,7 @@ void GLBackend::do_glUniform1i(Batch& batch, size_t paramOffset) {
}
updatePipeline();
glUniform1f(
batch._params[paramOffset + 1]._int,
GET_UNIFORM_LOCATION(batch._params[paramOffset + 1]._int),
batch._params[paramOffset + 0]._int);
(void) CHECK_GL_ERROR();
}
@ -515,8 +509,6 @@ void Batch::_glUniform1f(GLint location, GLfloat v0) {
ADD_COMMAND_GL(glUniform1f);
_params.push_back(v0);
_params.push_back(location);
DO_IT_NOW(_glUniform1f, 1);
}
void GLBackend::do_glUniform1f(Batch& batch, size_t paramOffset) {
if (_pipeline._program == 0) {
@ -527,7 +519,7 @@ void GLBackend::do_glUniform1f(Batch& batch, size_t paramOffset) {
updatePipeline();
glUniform1f(
batch._params[paramOffset + 1]._int,
GET_UNIFORM_LOCATION(batch._params[paramOffset + 1]._int),
batch._params[paramOffset + 0]._float);
(void) CHECK_GL_ERROR();
}
@ -538,8 +530,6 @@ void Batch::_glUniform2f(GLint location, GLfloat v0, GLfloat v1) {
_params.push_back(v1);
_params.push_back(v0);
_params.push_back(location);
DO_IT_NOW(_glUniform2f, 1);
}
void GLBackend::do_glUniform2f(Batch& batch, size_t paramOffset) {
@ -550,7 +540,7 @@ void GLBackend::do_glUniform2f(Batch& batch, size_t paramOffset) {
}
updatePipeline();
glUniform2f(
batch._params[paramOffset + 2]._int,
GET_UNIFORM_LOCATION(batch._params[paramOffset + 2]._int),
batch._params[paramOffset + 1]._float,
batch._params[paramOffset + 0]._float);
(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(v0);
_params.push_back(location);
DO_IT_NOW(_glUniform3f, 1);
}
void GLBackend::do_glUniform3f(Batch& batch, size_t paramOffset) {
@ -575,7 +563,7 @@ void GLBackend::do_glUniform3f(Batch& batch, size_t paramOffset) {
}
updatePipeline();
glUniform3f(
batch._params[paramOffset + 3]._int,
GET_UNIFORM_LOCATION(batch._params[paramOffset + 3]._int),
batch._params[paramOffset + 2]._float,
batch._params[paramOffset + 1]._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(v0);
_params.push_back(location);
DO_IT_NOW(_glUniform4f, 1);
}
@ -604,7 +590,7 @@ void GLBackend::do_glUniform4f(Batch& batch, size_t paramOffset) {
}
updatePipeline();
glUniform4f(
batch._params[paramOffset + 4]._int,
GET_UNIFORM_LOCATION(batch._params[paramOffset + 4]._int),
batch._params[paramOffset + 3]._float,
batch._params[paramOffset + 2]._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(count);
_params.push_back(location);
DO_IT_NOW(_glUniform3fv, 3);
}
void GLBackend::do_glUniform3fv(Batch& batch, size_t paramOffset) {
if (_pipeline._program == 0) {
@ -630,7 +614,7 @@ void GLBackend::do_glUniform3fv(Batch& batch, size_t paramOffset) {
}
updatePipeline();
glUniform3fv(
batch._params[paramOffset + 2]._int,
GET_UNIFORM_LOCATION(batch._params[paramOffset + 2]._int),
batch._params[paramOffset + 1]._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(count);
_params.push_back(location);
DO_IT_NOW(_glUniform4fv, 3);
}
void GLBackend::do_glUniform4fv(Batch& batch, size_t paramOffset) {
if (_pipeline._program == 0) {
@ -656,7 +638,7 @@ void GLBackend::do_glUniform4fv(Batch& batch, size_t paramOffset) {
}
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;
const GLfloat* value = (const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint);
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(count);
_params.push_back(location);
DO_IT_NOW(_glUniform4iv, 3);
}
void GLBackend::do_glUniform4iv(Batch& batch, size_t paramOffset) {
if (_pipeline._program == 0) {
@ -682,7 +662,7 @@ void GLBackend::do_glUniform4iv(Batch& batch, size_t paramOffset) {
}
updatePipeline();
glUniform4iv(
batch._params[paramOffset + 2]._int,
GET_UNIFORM_LOCATION(batch._params[paramOffset + 2]._int),
batch._params[paramOffset + 1]._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(count);
_params.push_back(location);
DO_IT_NOW(_glUniformMatrix4fv, 4);
}
void GLBackend::do_glUniformMatrix4fv(Batch& batch, size_t paramOffset) {
if (_pipeline._program == 0) {
@ -708,7 +686,7 @@ void GLBackend::do_glUniformMatrix4fv(Batch& batch, size_t paramOffset) {
}
updatePipeline();
glUniformMatrix4fv(
batch._params[paramOffset + 3]._int,
GET_UNIFORM_LOCATION(batch._params[paramOffset + 3]._int),
batch._params[paramOffset + 2]._uint,
batch._params[paramOffset + 1]._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(green);
_params.push_back(red);
DO_IT_NOW(_glColor4f, 4);
}
void GLBackend::do_glColor4f(Batch& batch, size_t paramOffset) {

View file

@ -153,17 +153,40 @@ public:
class GLShader : public GPUObject {
public:
GLuint _shader;
GLuint _program;
enum Version {
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();
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 GLuint getShaderID(const ShaderPointer& shader);
class GLState : public GPUObject {
public:
@ -464,6 +487,7 @@ protected:
PipelinePointer _pipeline;
GLuint _program;
GLShader* _programShader;
bool _invalidProgram;
State::Data _stateCache;
@ -475,6 +499,7 @@ protected:
PipelineStageState() :
_pipeline(),
_program(0),
_programShader(nullptr),
_invalidProgram(false),
_stateCache(State::DEFAULT),
_stateSignatureCache(0),

View file

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

View file

@ -13,27 +13,205 @@
using namespace gpu;
GLBackend::GLShader::GLShader() :
_shader(0),
_program(0)
{}
GLBackend::GLShader::GLShader()
{
}
GLBackend::GLShader::~GLShader() {
if (_shader != 0) {
glDeleteShader(_shader);
}
if (_program != 0) {
glDeleteProgram(_program);
for (auto& so : _shaderObjects) {
if (so.glshader != 0) {
glDeleteShader(so.glshader);
}
if (so.glprogram != 0) {
glDeleteProgram(so.glprogram);
}
}
}
void makeBindings(GLBackend::GLShader* shader) {
if(!shader || !shader->_program) {
bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, GLuint &programObject) {
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;
}
GLuint glprogram = shader->_program;
GLuint glprogram = shaderObject.glprogram;
GLint loc = -1;
//Check for gpu specific attribute slotBindings
loc = glGetAttribLocation(glprogram, "inPosition");
if (loc >= 0 && loc != gpu::Stream::POSITION) {
@ -96,226 +274,111 @@ void makeBindings(GLBackend::GLShader* shader) {
loc = glGetProgramResourceIndex(glprogram, GL_SHADER_STORAGE_BLOCK, "transformObjectBuffer");
if (loc >= 0) {
glShaderStorageBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT);
shader->_transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT;
shaderObject.transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT;
}
#else
loc = glGetUniformLocation(glprogram, "transformObjectBuffer");
if (loc >= 0) {
glProgramUniform1i(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT);
shader->_transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT;
shaderObject.transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT;
}
#endif
loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer");
if (loc >= 0) {
glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT);
shader->_transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
shaderObject.transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
}
(void)CHECK_GL_ERROR();
}
GLBackend::GLShader* compileShader(const Shader& shader) {
GLBackend::GLShader* compileBackendShader(const Shader& shader) {
// Any GLSLprogram ? normally yes...
const std::string& shaderSource = shader.getSource().getCode();
if (shaderSource.empty()) {
qCDebug(gpulogging) << "GLShader::compileShader - no GLSL shader source code ? so failed to create";
return nullptr;
}
// GLSL version
const std::string glslVersion = {
"#version 410 core"
};
// 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()];
// Create the shader object
GLuint glshader = glCreateShader(shaderDomain);
if (!glshader) {
qCDebug(gpulogging) << "GLShader::compileShader - failed to create the gl shader object";
return nullptr;
}
// Domain specific defines
const std::string domainDefines[NUM_SHADER_DOMAINS] = {
"#define VERTEX_SHADER",
"#define PIXEL_SHADER"
};
// Assign the source
const GLchar* srcstr = shaderSource.c_str();
glShaderSource(glshader, 1, &srcstr, NULL);
// Compile !
glCompileShader(glshader);
// check if shader compiled
GLint compiled = 0;
glGetShaderiv(glshader, GL_COMPILE_STATUS, &compiled);
// Versions specific of the shader
const std::string versionDefines[GLBackend::GLShader::NumVersions] = {
""
};
// 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();
GLBackend::GLShader::ShaderObjects shaderObjects;
for (int version = 0; version < GLBackend::GLShader::NumVersions; version++) {
auto& shaderObject = shaderObjects[version];
std::string shaderDefines = glslVersion + "\n" + domainDefines[shader.getType()] + "\n" + versionDefines[version];
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
GLBackend::GLShader* object = new GLBackend::GLShader();
object->_shader = glshader;
object->_program = glprogram;
makeBindings(object);
object->_shaderObjects = shaderObjects;
return object;
}
GLBackend::GLShader* compileProgram(const Shader& program) {
if(!program.isProgram()) {
GLBackend::GLShader* compileBackendProgram(const Shader& program) {
if (!program.isProgram()) {
return nullptr;
}
// Let's go through every shaders and make sure they are ready to go
std::vector< GLuint > shaderObjects;
for (auto subShader : program.getShaders()) {
GLuint so = GLBackend::getShaderID(subShader);
if (!so) {
qCDebug(gpulogging) << "GLShader::compileProgram - One of the shaders of the program is not compiled?";
GLBackend::GLShader::ShaderObjects programObjects;
for (int version = 0; version < GLBackend::GLShader::NumVersions; version++) {
auto& programObject = programObjects[version];
// 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;
}
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);
// 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
// So far so good, the program versions have all been created successfully
GLBackend::GLShader* object = new GLBackend::GLShader();
object->_shader = 0;
object->_program = glprogram;
makeBindings(object);
object->_shaderObjects = programObjects;
return object;
}
@ -329,14 +392,14 @@ GLBackend::GLShader* GLBackend::syncGPUObject(const Shader& shader) {
}
// need to have a gpu object?
if (shader.isProgram()) {
GLShader* tempObject = compileProgram(shader);
if (tempObject) {
GLShader* tempObject = compileBackendProgram(shader);
if (tempObject) {
object = tempObject;
Backend::setGPUObject(shader, object);
}
} else if (shader.isDomain()) {
GLShader* tempObject = compileShader(shader);
if (tempObject) {
GLShader* tempObject = compileBackendShader(shader);
if (tempObject) {
object = tempObject;
Backend::setGPUObject(shader, object);
}
@ -345,23 +408,6 @@ GLBackend::GLShader* GLBackend::syncGPUObject(const Shader& shader) {
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 {
public:
gpu::Element _element;
@ -714,27 +760,38 @@ bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindin
return false;
}
if (object->_program) {
Shader::SlotSet buffers;
makeUniformBlockSlots(object->_program, slotBindings, buffers);
// Apply bindings to all program versions and generate list of slots from default version
for (int version = 0; version < GLBackend::GLShader::NumVersions; version++) {
auto& shaderObject = object->_shaderObjects[version];
if (shaderObject.glprogram) {
Shader::SlotSet buffers;
makeUniformBlockSlots(shaderObject.glprogram, slotBindings, buffers);
Shader::SlotSet uniforms;
Shader::SlotSet textures;
Shader::SlotSet samplers;
makeUniformSlots(object->_program, slotBindings, uniforms, textures, samplers);
Shader::SlotSet inputs;
makeInputSlots(object->_program, slotBindings, inputs);
Shader::SlotSet uniforms;
Shader::SlotSet textures;
Shader::SlotSet samplers;
makeUniformSlots(shaderObject.glprogram, slotBindings, uniforms, textures, samplers);
Shader::SlotSet outputs;
makeOutputSlots(object->_program, slotBindings, outputs);
Shader::SlotSet inputs;
makeInputSlots(shaderObject.glprogram, slotBindings, inputs);
shader.defineSlots(uniforms, buffers, textures, samplers, inputs, outputs);
} else if (object->_shader) {
Shader::SlotSet outputs;
makeOutputSlots(shaderObject.glprogram, slotBindings, outputs);
// 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;
}

View file

@ -27,7 +27,7 @@ ToneMappingEffect::ToneMappingEffect() {
}
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
//
// Draw texture 0 fetched at texcoord.xy