mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 17:14:59 +02:00
Adding shader versioning and defines from GLBackendShader allowing for runtime defines injection to shaders and more
This commit is contained in:
parent
c6deff16d6
commit
cadb53b703
7 changed files with 334 additions and 272 deletions
|
@ -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;
|
||||
|
|
|
@ -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@>
|
||||
|
|
|
@ -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) {
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue