diff --git a/libraries/entities-renderer/src/RenderableProceduralItemShader.h b/libraries/entities-renderer/src/RenderableProceduralItemShader.h index a01a6b8571..1afd3bc608 100644 --- a/libraries/entities-renderer/src/RenderableProceduralItemShader.h +++ b/libraries/entities-renderer/src/RenderableProceduralItemShader.h @@ -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; diff --git a/libraries/gpu/src/gpu/Config.slh b/libraries/gpu/src/gpu/Config.slh index 3da92df7c1..ae556a3828 100644 --- a/libraries/gpu/src/gpu/Config.slh +++ b/libraries/gpu/src/gpu/Config.slh @@ -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@> diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index f51448f8fd..c27da793d2 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -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) { diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 9806c17db4..7b9d69fbbd 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -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; + using UniformMappingVersions = std::vector; - 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), diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 60ec478a8e..d36d37d597 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -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); } diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index c27c5dd97d..86149c3f07 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -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& 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; } diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index da11507965..b28f271f9d 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -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