From d05e23b2787b0b6636d418de0bb7da96c55c6621 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 16 Mar 2016 18:35:07 -0700 Subject: [PATCH 01/28] Early work on batching stereo better --- libraries/gpu/src/gpu/GLBackend.cpp | 28 +++++++++++++++----- libraries/gpu/src/gpu/GLBackendTransform.cpp | 5 ++-- libraries/gpu/src/gpu/Transform.slh | 16 +++++++++++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 14e4397b83..6fedf66af1 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -248,7 +248,10 @@ void GLBackend::render(Batch& batch) { if (!batch.isStereoEnabled()) { _stereo._enable = false; } + _stereo._enable =batch.isStereoEnabled(); + glEnable(GL_CLIP_DISTANCE0); + { PROFILE_RANGE("Transfer"); renderPassTransfer(batch); @@ -259,13 +262,15 @@ void GLBackend::render(Batch& batch) { renderPassDraw(batch); } - if (_stereo._enable) { + /* if (_stereo._enable) { PROFILE_RANGE("RightRender"); _stereo._pass = 1; renderPassDraw(batch); _stereo._pass = 0; - } + }*/ + glDisable(GL_CLIP_DISTANCE0); + // Restore the saved stereo state for the next batch _stereo._enable = savedStereo; } @@ -326,7 +331,12 @@ void GLBackend::do_draw(Batch& batch, size_t paramOffset) { GLenum mode = _primitiveToGLmode[primitiveType]; uint32 numVertices = batch._params[paramOffset + 1]._uint; uint32 startVertex = batch._params[paramOffset + 0]._uint; - glDrawArrays(mode, startVertex, numVertices); + if (isStereo()) { + glDrawArraysInstanced(mode, startVertex, numVertices, 2); + } else { + glDrawArrays(mode, startVertex, numVertices); + } + (void) CHECK_GL_ERROR(); } @@ -341,7 +351,11 @@ void GLBackend::do_drawIndexed(Batch& batch, size_t paramOffset) { auto typeByteSize = TYPE_SIZE[_input._indexBufferType]; GLvoid* indexBufferByteOffset = reinterpret_cast(startIndex * typeByteSize + _input._indexBufferOffset); - glDrawElements(mode, numIndices, glType, indexBufferByteOffset); + if (isStereo()) { + glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, 2); + } else { + glDrawElements(mode, numIndices, glType, indexBufferByteOffset); + } (void) CHECK_GL_ERROR(); } @@ -352,7 +366,7 @@ void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) { uint32 numVertices = batch._params[paramOffset + 2]._uint; uint32 startVertex = batch._params[paramOffset + 1]._uint; - glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances); + glDrawArraysInstancedARB(mode, startVertex, numVertices, (isStereo() ? 2 * numInstances : numInstances)); (void) CHECK_GL_ERROR(); } @@ -370,9 +384,9 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) { GLvoid* indexBufferByteOffset = reinterpret_cast(startIndex * typeByteSize + _input._indexBufferOffset); #if (GPU_INPUT_PROFILE == GPU_CORE_43) - glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); + glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, (isStereo() ? 2 * numInstances : numInstances), 0, startInstance); #else - glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, numInstances); + glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, (isStereo() ? 2 * numInstances : numInstances)); Q_UNUSED(startInstance); #endif (void)CHECK_GL_ERROR(); diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 19cb7fb2a9..2bef3c606e 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -32,6 +32,7 @@ void GLBackend::do_setViewportTransform(Batch& batch, size_t paramOffset) { memcpy(&_transform._viewport, batch.editData(batch._params[paramOffset]._uint), sizeof(Vec4i)); ivec4& vp = _transform._viewport; + glViewport(vp.x, vp.y, vp.z, vp.w); // Where we assign the GL viewport if (_stereo._enable) { @@ -41,7 +42,7 @@ void GLBackend::do_setViewportTransform(Batch& batch, size_t paramOffset) { } } - glViewport(vp.x, vp.y, vp.z, vp.w); +// glViewport(vp.x, vp.y, vp.z, vp.w); // The Viewport is tagged invalid because the CameraTransformUBO is not up to date and will need update on next drawcall _transform._invalidViewport = true; @@ -213,7 +214,7 @@ void GLBackend::updateTransform(const Batch& batch) { glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer); glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0, _transform._drawCallInfoOffsets[batch._currentNamedCall]); - glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, 1); + glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, (isStereo() ? 2: 1)); } (void)CHECK_GL_ERROR(); diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 52ddf92158..7a1af8d655 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -76,6 +76,18 @@ TransformObject getTransformObject() { <$viewport$> = <$cameraTransform$>._viewport; <@endfunc@> +<@func transformStereoClipsSpace(cameraTransform, clipPos)@> + { + vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1)); + vec2 eyeOffsetScale = vec2(-0.5, +0.5); + uint eyeIndex = gl_InstanceID % 2; + gl_ClipDistance[0] = dot(<$clipPos$>, eyeClipEdge[eyeIndex]); + float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w; + <$clipPos$>.x = newClipPosX; + } +<@endfunc@> + + <@func transformModelToEyeWorldAlignedPos(cameraTransform, objectTransform, modelPos, eyeWorldAlignedPos)@> { // _transformModelToEyeWorldAlignedPos @@ -92,6 +104,8 @@ TransformObject getTransformObject() { <$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$> <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos; + + <$transformStereoClipsSpace($cameraTransform$, $clipPos$)$> } <@endfunc@> @@ -101,6 +115,8 @@ TransformObject getTransformObject() { <$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$> <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos; <$eyePos$> = vec4((<$cameraTransform$>._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0); + + <$transformStereoClipsSpace($cameraTransform$, $clipPos$)$> } <@endfunc@> From 9f4516da892ad3699747ece57208e985e072f366 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 21 Mar 2016 09:36:16 -0700 Subject: [PATCH 02/28] Working on batching the stereo --- libraries/gpu/src/gpu/GLBackend.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 6fedf66af1..151982017e 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -248,14 +248,14 @@ void GLBackend::render(Batch& batch) { if (!batch.isStereoEnabled()) { _stereo._enable = false; } - _stereo._enable =batch.isStereoEnabled(); - - glEnable(GL_CLIP_DISTANCE0); { PROFILE_RANGE("Transfer"); renderPassTransfer(batch); } + _stereo._enable =batch.isStereoEnabled(); + + glEnable(GL_CLIP_DISTANCE0); { PROFILE_RANGE(_stereo._enable ? "LeftRender" : "Render"); From 9aface432d0488d3342a2fc523e075b0c5a39202 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 1 Apr 2016 19:10:14 -0700 Subject: [PATCH 03/28] Steping into 2 version tshaders --- libraries/gpu/src/gpu/GLBackend.h | 11 +++++++++-- libraries/gpu/src/gpu/Transform.slh | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index f5abacd279..6cc8a35c15 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -97,8 +97,15 @@ public: class GLShader : public GPUObject { public: - GLuint _shader; - GLuint _program; + enum Version { + Mono = 0, + Stereo, + + NumVersions + }; + + GLuint _shader[NumVersions]; + GLuint _program[NumVersions]; GLint _transformCameraSlot = -1; GLint _transformObjectSlot = -1; diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 7a1af8d655..eeda1e3bc6 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -78,12 +78,15 @@ TransformObject getTransformObject() { <@func transformStereoClipsSpace(cameraTransform, clipPos)@> { +#ifdef GPU_TRANSFORM_IS_STEREO vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1)); vec2 eyeOffsetScale = vec2(-0.5, +0.5); uint eyeIndex = gl_InstanceID % 2; gl_ClipDistance[0] = dot(<$clipPos$>, eyeClipEdge[eyeIndex]); float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w; <$clipPos$>.x = newClipPosX; +#else +#endif } <@endfunc@> From 0ba6c89c6e32082c0e0eaec03e6c8d77033acfb3 Mon Sep 17 00:00:00 2001 From: samcake Date: Sun, 3 Apr 2016 18:25:38 -0700 Subject: [PATCH 04/28] WOrk in progress, generating several versions of the shader --- libraries/gpu/src/gpu/GLBackend.h | 9 +- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 6 +- libraries/gpu/src/gpu/GLBackendShader.cpp | 216 +++++++++++--------- 3 files changed, 137 insertions(+), 94 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 6cc8a35c15..2c3f22711f 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -112,9 +112,16 @@ public: GLShader(); ~GLShader(); + + GLuint getProgram(bool isStereo) const { + if (isStereo && _program[1]) { + return _program[1]; + } else { + return _program[0]; + } + } }; static GLShader* syncGPUObject(const Shader& shader); - static GLuint getShaderID(const ShaderPointer& shader); class GLState : public GPUObject { public: diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 046f1ff0e5..83c0c1e074 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -80,8 +80,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; + // pick the program version + GLuint glprogram = pipelineObject->_program->getProgram(isStereo()); + if (_pipeline._program != glprogram) { + _pipeline._program = glprogram; _pipeline._invalidProgram = true; } diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index c27c5dd97d..7e01f04c1e 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -13,25 +13,34 @@ using namespace gpu; -GLBackend::GLShader::GLShader() : - _shader(0), - _program(0) -{} +GLBackend::GLShader::GLShader() +{ + for (auto& so : _shader) { + so = 0; + } + for (auto& po : _program) { + po = 0; + } +} GLBackend::GLShader::~GLShader() { - if (_shader != 0) { - glDeleteShader(_shader); + for (auto so : _shader) { + if (so != 0) { + glDeleteShader(so); + } } - if (_program != 0) { - glDeleteProgram(_program); + for (auto po : _program) { + if (po != 0) { + glDeleteProgram(po); + } } } void makeBindings(GLBackend::GLShader* shader) { - if(!shader || !shader->_program) { + if(!shader || !shader->_program[0]) { return; } - GLuint glprogram = shader->_program; + GLuint glprogram = shader->_program[0]; GLint loc = -1; //Check for gpu specific attribute slotBindings @@ -115,18 +124,12 @@ void makeBindings(GLBackend::GLShader* shader) { (void)CHECK_GL_ERROR(); } -GLBackend::GLShader* compileShader(const Shader& shader) { - // Any GLSLprogram ? normally yes... - const std::string& shaderSource = shader.getSource().getCode(); +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 nullptr; + return false; } - // Shader domain - const GLenum SHADER_DOMAINS[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER }; - GLenum shaderDomain = SHADER_DOMAINS[shader.getType()]; - // Create the shader object GLuint glshader = glCreateShader(shaderDomain); if (!glshader) { @@ -135,8 +138,8 @@ GLBackend::GLShader* compileShader(const Shader& shader) { } // Assign the source - const GLchar* srcstr = shaderSource.c_str(); - glShaderSource(glshader, 1, &srcstr, NULL); + const GLchar* srcstr[] = { defines.c_str(), shaderSource.c_str() }; + glShaderSource(glshader, 2, srcstr, NULL); // Compile ! glCompileShader(glshader); @@ -148,26 +151,26 @@ GLBackend::GLShader* compileShader(const Shader& shader) { // if compilation fails if (!compiled) { // save the source code to a temp file so we can debug easily - /* std::ofstream filestream; + /* std::ofstream filestream; filestream.open("debugshader.glsl"); if (filestream.is_open()) { - filestream << shaderSource->source; - filestream.close(); + filestream << shaderSource->source; + filestream.close(); } */ GLint infoLength = 0; glGetShaderiv(glshader, GL_INFO_LOG_LENGTH, &infoLength); - char* temp = new char[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(); + filestream << std::string(temp); + filestream.close(); } */ @@ -178,7 +181,7 @@ GLBackend::GLShader* compileShader(const Shader& shader) { delete[] temp; glDeleteShader(glshader); - return nullptr; + return false; } GLuint glprogram = 0; @@ -187,7 +190,7 @@ GLBackend::GLShader* compileShader(const Shader& shader) { GLuint glprogram = glCreateProgram(); if (!glprogram) { qCDebug(gpulogging) << "GLShader::compileShader - failed to create the gl shader & gl program object"; - return nullptr; + return false; } glProgramParameteri(glprogram, GL_PROGRAM_SEPARABLE, GL_TRUE); @@ -203,15 +206,15 @@ GLBackend::GLShader* compileShader(const Shader& shader) { std::ofstream filestream; filestream.open("debugshader.glsl"); if (filestream.is_open()) { - filestream << shaderSource->source; - filestream.close(); + filestream << shaderSource->source; + filestream.close(); } */ GLint infoLength = 0; glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength); - char* temp = new char[infoLength] ; + char* temp = new char[infoLength]; glGetProgramInfoLog(glprogram, infoLength, NULL, temp); qCDebug(gpulogging) << "GLShader::compileShader - failed to LINK the gl program object :"; @@ -220,49 +223,30 @@ GLBackend::GLShader* compileShader(const Shader& shader) { /* filestream.open("debugshader.glsl.info.txt"); if (filestream.is_open()) { - filestream << String(temp); - filestream.close(); + filestream << String(temp); + filestream.close(); } */ delete[] temp; glDeleteShader(glshader); glDeleteProgram(glprogram); - return nullptr; + return false; } #endif - // So far so good, the shader is created successfully - GLBackend::GLShader* object = new GLBackend::GLShader(); - object->_shader = glshader; - object->_program = glprogram; + shaderObject = glshader; + programObject = glprogram; - makeBindings(object); - - return object; + return true; } -GLBackend::GLShader* compileProgram(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?"; - return nullptr; - } - shaderObjects.push_back(so); - } - - // so far so good, program is almost done, need to link: +GLuint compileProgram(const std::vector& shaderObjects) { + // A brand new program: GLuint glprogram = glCreateProgram(); if (!glprogram) { qCDebug(gpulogging) << "GLShader::compileProgram - failed to create the gl program object"; - return nullptr; + return 0; } // glProgramParameteri(glprogram, GL_PROGRAM_, GL_TRUE); @@ -283,15 +267,15 @@ GLBackend::GLShader* compileProgram(const Shader& program) { std::ofstream filestream; filestream.open("debugshader.glsl"); if (filestream.is_open()) { - filestream << shaderSource->source; - filestream.close(); + filestream << shaderSource->source; + filestream.close(); } */ GLint infoLength = 0; glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength); - char* temp = new char[infoLength] ; + char* temp = new char[infoLength]; glGetProgramInfoLog(glprogram, infoLength, NULL, temp); qCDebug(gpulogging) << "GLShader::compileProgram - failed to LINK the gl program object :"; @@ -300,20 +284,87 @@ GLBackend::GLShader* compileProgram(const Shader& program) { /* filestream.open("debugshader.glsl.info.txt"); if (filestream.is_open()) { - filestream << std::string(temp); - filestream.close(); + filestream << std::string(temp); + filestream.close(); } */ delete[] temp; glDeleteProgram(glprogram); + return false; + } + + return glprogram; +} + +GLBackend::GLShader* compileBackendShader(const Shader& shader) { + // Any GLSLprogram ? normally yes... + const std::string& shaderSource = shader.getSource().getCode(); + + // Shader domain + const GLenum SHADER_DOMAINS[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER }; + GLenum shaderDomain = SHADER_DOMAINS[shader.getType()]; + + // First make default version of the shader + std::string shaderDefines; + GLuint glshader{ 0 }; + GLuint glprogram{ 0 }; + bool result = compileShader(shaderDomain, shaderSource, shaderDefines, glshader, glprogram); + if (!result) { + return nullptr; + } + + // So far so good, the shader is created successfully + GLBackend::GLShader* object = new GLBackend::GLShader(); + object->_shader[0] = glshader; + object->_program[0] = glprogram; + + makeBindings(object); + + { + shaderDefines = "#define GPU_TRANSFORM_IS_STEREO"; + GLuint glshader{ 0 }; + GLuint glprogram{ 0 }; + bool result = compileShader(shaderDomain, shaderSource, shaderDefines, glshader, glprogram); + if (!result) { + return nullptr; + } + object->_shader[1] = glshader; + object->_program[1] = glprogram; + + } + + return object; +} + +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()) { + auto object = GLBackend::syncGPUObject(*subShader); + GLuint so = 0; + if (object) { + so = object->_shader[0]; + } else { + qCDebug(gpulogging) << "GLShader::compileBackendProgram - One of the shaders of the program is not compiled?"; + return nullptr; + } + shaderObjects.push_back(so); + } + + GLuint glprogram = compileProgram(shaderObjects); + if (glprogram == 0) { return nullptr; } // So far so good, the program is created successfully GLBackend::GLShader* object = new GLBackend::GLShader(); - object->_shader = 0; - object->_program = glprogram; + object->_shader[0] = 0; + object->_program[0] = glprogram; makeBindings(object); @@ -329,13 +380,13 @@ GLBackend::GLShader* GLBackend::syncGPUObject(const Shader& shader) { } // need to have a gpu object? if (shader.isProgram()) { - GLShader* tempObject = compileProgram(shader); + GLShader* tempObject = compileBackendProgram(shader); if (tempObject) { object = tempObject; Backend::setGPUObject(shader, object); } } else if (shader.isDomain()) { - GLShader* tempObject = compileShader(shader); + GLShader* tempObject = compileBackendShader(shader); if (tempObject) { object = tempObject; Backend::setGPUObject(shader, object); @@ -345,23 +396,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,20 +748,20 @@ bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindin return false; } - if (object->_program) { + if (object->_program[0]) { Shader::SlotSet buffers; - makeUniformBlockSlots(object->_program, slotBindings, buffers); + makeUniformBlockSlots(object->_program[0], slotBindings, buffers); Shader::SlotSet uniforms; Shader::SlotSet textures; Shader::SlotSet samplers; - makeUniformSlots(object->_program, slotBindings, uniforms, textures, samplers); + makeUniformSlots(object->_program[0], slotBindings, uniforms, textures, samplers); Shader::SlotSet inputs; - makeInputSlots(object->_program, slotBindings, inputs); + makeInputSlots(object->_program[0], slotBindings, inputs); Shader::SlotSet outputs; - makeOutputSlots(object->_program, slotBindings, outputs); + makeOutputSlots(object->_program[0], slotBindings, outputs); shader.defineSlots(uniforms, buffers, textures, samplers, inputs, outputs); From d3a87f8db2c55b98746c6f8200d8b6e7b20a67fb Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 4 Apr 2016 18:25:23 -0700 Subject: [PATCH 05/28] need to merge, commiting at a broken state --- interface/src/Application.cpp | 3 +- .../src/RenderableProceduralItemShader.h | 2 +- libraries/gpu/src/gpu/Config.slh | 6 +- libraries/gpu/src/gpu/GLBackend.h | 20 +- libraries/gpu/src/gpu/GLBackendShader.cpp | 324 +++++++++--------- libraries/gpu/src/gpu/GLBackendTransform.cpp | 2 + libraries/gpu/src/gpu/Transform.slh | 9 + .../render-utils/src/ToneMappingEffect.cpp | 2 +- 8 files changed, 191 insertions(+), 177 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0172b3ce3a..64b7296053 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1632,7 +1632,8 @@ void Application::paintGL() { renderArgs._boomOffset = boomOffset; // Viewport is assigned to the size of the framebuffer renderArgs._viewport = ivec4(0, 0, size.width(), size.height()); - if (displayPlugin->isStereo()) { + // if (displayPlugin->isStereo()) { + if (true) { // Stereo modes will typically have a larger projection matrix overall, // so we ask for the 'mono' projection matrix, which for stereo and HMD // plugins will imply the combined projection for both eyes. 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..0322332e30 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 //410 core@> <@elif GLPROFILE == MAC_GL @> <@def GPU_FEATURE_PROFILE GPU_CORE@> - <@def VERSION_HEADER #version 410 core@> + <@def VERSION_HEADER //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.h b/libraries/gpu/src/gpu/GLBackend.h index 2c3f22711f..9ee42dbcd7 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -104,20 +105,25 @@ public: NumVersions }; - GLuint _shader[NumVersions]; - GLuint _program[NumVersions]; + struct ShaderObject { + GLuint glshader{ 0 }; + GLuint glprogram{ 0 }; + GLint transformCameraSlot{ -1 }; + GLint transformObjectSlot{ -1 }; + }; - GLint _transformCameraSlot = -1; - GLint _transformObjectSlot = -1; + using ShaderObjects = std::array< ShaderObject, NumVersions >; GLShader(); ~GLShader(); + ShaderObjects _shaderObjects; + GLuint getProgram(bool isStereo) const { - if (isStereo && _program[1]) { - return _program[1]; + if (isStereo && _shaderObjects[Stereo].glprogram) { + return _shaderObjects[Stereo].glprogram; } else { - return _program[0]; + return _shaderObjects[Mono].glprogram; } } }; diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 7e01f04c1e..d6aed882fc 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -15,113 +15,17 @@ using namespace gpu; GLBackend::GLShader::GLShader() { - for (auto& so : _shader) { - so = 0; - } - for (auto& po : _program) { - po = 0; - } } GLBackend::GLShader::~GLShader() { - for (auto so : _shader) { - if (so != 0) { - glDeleteShader(so); + for (auto& so : _shaderObjects) { + if (so.glshader != 0) { + glDeleteShader(so.glshader); + } + if (so.glprogram != 0) { + glDeleteProgram(so.glprogram); } } - for (auto po : _program) { - if (po != 0) { - glDeleteProgram(po); - } - } -} - -void makeBindings(GLBackend::GLShader* shader) { - if(!shader || !shader->_program[0]) { - return; - } - GLuint glprogram = shader->_program[0]; - GLint loc = -1; - - //Check for gpu specific attribute slotBindings - loc = glGetAttribLocation(glprogram, "inPosition"); - if (loc >= 0 && loc != gpu::Stream::POSITION) { - glBindAttribLocation(glprogram, gpu::Stream::POSITION, "inPosition"); - } - - loc = glGetAttribLocation(glprogram, "inNormal"); - if (loc >= 0 && loc != gpu::Stream::NORMAL) { - glBindAttribLocation(glprogram, gpu::Stream::NORMAL, "inNormal"); - } - - loc = glGetAttribLocation(glprogram, "inColor"); - if (loc >= 0 && loc != gpu::Stream::COLOR) { - glBindAttribLocation(glprogram, gpu::Stream::COLOR, "inColor"); - } - - loc = glGetAttribLocation(glprogram, "inTexCoord0"); - if (loc >= 0 && loc != gpu::Stream::TEXCOORD) { - glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD, "inTexCoord0"); - } - - loc = glGetAttribLocation(glprogram, "inTangent"); - if (loc >= 0 && loc != gpu::Stream::TANGENT) { - glBindAttribLocation(glprogram, gpu::Stream::TANGENT, "inTangent"); - } - - loc = glGetAttribLocation(glprogram, "inTexCoord1"); - if (loc >= 0 && loc != gpu::Stream::TEXCOORD1) { - glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "inTexCoord1"); - } - - loc = glGetAttribLocation(glprogram, "inSkinClusterIndex"); - if (loc >= 0 && loc != gpu::Stream::SKIN_CLUSTER_INDEX) { - glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_INDEX, "inSkinClusterIndex"); - } - - loc = glGetAttribLocation(glprogram, "inSkinClusterWeight"); - if (loc >= 0 && loc != gpu::Stream::SKIN_CLUSTER_WEIGHT) { - glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "inSkinClusterWeight"); - } - - loc = glGetAttribLocation(glprogram, "_drawCallInfo"); - if (loc >= 0 && loc != gpu::Stream::DRAW_CALL_INFO) { - glBindAttribLocation(glprogram, gpu::Stream::DRAW_CALL_INFO, "_drawCallInfo"); - } - - // Link again to take into account the assigned attrib location - glLinkProgram(glprogram); - - GLint linked = 0; - glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); - if (!linked) { - qCDebug(gpulogging) << "GLShader::makeBindings - failed to link after assigning slotBindings?"; - } - - // now assign the ubo binding, then DON't relink! - - //Check for gpu specific uniform slotBindings -#ifdef GPU_SSBO_DRAW_CALL_INFO - loc = glGetProgramResourceIndex(glprogram, GL_SHADER_STORAGE_BLOCK, "transformObjectBuffer"); - if (loc >= 0) { - glShaderStorageBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); - shader->_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; - } -#endif - - loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer"); - if (loc >= 0) { - glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT); - shader->_transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT; - } - - (void)CHECK_GL_ERROR(); } bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, GLuint &programObject) { @@ -138,8 +42,8 @@ bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const s } // Assign the source - const GLchar* srcstr[] = { defines.c_str(), shaderSource.c_str() }; - glShaderSource(glshader, 2, srcstr, NULL); + const GLchar* srcstr[] = { "#version 410 core\n", defines.c_str(), shaderSource.c_str() }; + glShaderSource(glshader, 3, srcstr, NULL); // Compile ! glCompileShader(glshader); @@ -241,7 +145,7 @@ bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const s return true; } -GLuint compileProgram(const std::vector& shaderObjects) { +GLuint compileProgram(const std::vector& glshaders) { // A brand new program: GLuint glprogram = glCreateProgram(); if (!glprogram) { @@ -251,7 +155,7 @@ GLuint compileProgram(const std::vector& shaderObjects) { // glProgramParameteri(glprogram, GL_PROGRAM_, GL_TRUE); // Create the program from the sub shaders - for (auto so : shaderObjects) { + for (auto so : glshaders) { glAttachShader(glprogram, so); } @@ -291,12 +195,101 @@ GLuint compileProgram(const std::vector& shaderObjects) { delete[] temp; glDeleteProgram(glprogram); - return false; + return 0; } return glprogram; } + +void makeProgramBindings(GLBackend::GLShader::ShaderObject& shaderObject) { + if (!shaderObject.glprogram) { + return; + } + GLuint glprogram = shaderObject.glprogram; + GLint loc = -1; + + //Check for gpu specific attribute slotBindings + loc = glGetAttribLocation(glprogram, "inPosition"); + if (loc >= 0 && loc != gpu::Stream::POSITION) { + glBindAttribLocation(glprogram, gpu::Stream::POSITION, "inPosition"); + } + + loc = glGetAttribLocation(glprogram, "inNormal"); + if (loc >= 0 && loc != gpu::Stream::NORMAL) { + glBindAttribLocation(glprogram, gpu::Stream::NORMAL, "inNormal"); + } + + loc = glGetAttribLocation(glprogram, "inColor"); + if (loc >= 0 && loc != gpu::Stream::COLOR) { + glBindAttribLocation(glprogram, gpu::Stream::COLOR, "inColor"); + } + + loc = glGetAttribLocation(glprogram, "inTexCoord0"); + if (loc >= 0 && loc != gpu::Stream::TEXCOORD) { + glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD, "inTexCoord0"); + } + + loc = glGetAttribLocation(glprogram, "inTangent"); + if (loc >= 0 && loc != gpu::Stream::TANGENT) { + glBindAttribLocation(glprogram, gpu::Stream::TANGENT, "inTangent"); + } + + loc = glGetAttribLocation(glprogram, "inTexCoord1"); + if (loc >= 0 && loc != gpu::Stream::TEXCOORD1) { + glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "inTexCoord1"); + } + + loc = glGetAttribLocation(glprogram, "inSkinClusterIndex"); + if (loc >= 0 && loc != gpu::Stream::SKIN_CLUSTER_INDEX) { + glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_INDEX, "inSkinClusterIndex"); + } + + loc = glGetAttribLocation(glprogram, "inSkinClusterWeight"); + if (loc >= 0 && loc != gpu::Stream::SKIN_CLUSTER_WEIGHT) { + glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "inSkinClusterWeight"); + } + + loc = glGetAttribLocation(glprogram, "_drawCallInfo"); + if (loc >= 0 && loc != gpu::Stream::DRAW_CALL_INFO) { + glBindAttribLocation(glprogram, gpu::Stream::DRAW_CALL_INFO, "_drawCallInfo"); + } + + // Link again to take into account the assigned attrib location + glLinkProgram(glprogram); + + GLint linked = 0; + glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); + if (!linked) { + qCDebug(gpulogging) << "GLShader::makeBindings - failed to link after assigning slotBindings?"; + } + + // now assign the ubo binding, then DON't relink! + + //Check for gpu specific uniform slotBindings +#ifdef GPU_SSBO_DRAW_CALL_INFO + loc = glGetProgramResourceIndex(glprogram, GL_SHADER_STORAGE_BLOCK, "transformObjectBuffer"); + if (loc >= 0) { + glShaderStorageBlockBinding(glprogram, loc, 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); + shaderObject.transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT; + } +#endif + + loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer"); + if (loc >= 0) { + glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT); + shaderObject.transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT; + } + + (void)CHECK_GL_ERROR(); +} + GLBackend::GLShader* compileBackendShader(const Shader& shader) { // Any GLSLprogram ? normally yes... const std::string& shaderSource = shader.getSource().getCode(); @@ -305,35 +298,27 @@ GLBackend::GLShader* compileBackendShader(const Shader& shader) { const GLenum SHADER_DOMAINS[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER }; GLenum shaderDomain = SHADER_DOMAINS[shader.getType()]; - // First make default version of the shader - std::string shaderDefines; - GLuint glshader{ 0 }; - GLuint glprogram{ 0 }; - bool result = compileShader(shaderDomain, shaderSource, shaderDefines, glshader, glprogram); - if (!result) { - return nullptr; + // Make several versions of the shader + std::string shaderDefines[GLBackend::GLShader::NumVersions] = { + "", + "#define GPU_TRANSFORM_IS_STEREO" + }; + + GLBackend::GLShader::ShaderObjects shaderObjects; + + for (int version = 0; version < GLBackend::GLShader::NumVersions; version++) { + auto& shaderObject = shaderObjects[version]; + + bool result = compileShader(shaderDomain, shaderSource, shaderDefines[version], shaderObject.glshader, shaderObject.glprogram); + if (!result) { + return nullptr; + } } // So far so good, the shader is created successfully GLBackend::GLShader* object = new GLBackend::GLShader(); - object->_shader[0] = glshader; - object->_program[0] = glprogram; + object->_shaderObjects = shaderObjects; - makeBindings(object); - - { - shaderDefines = "#define GPU_TRANSFORM_IS_STEREO"; - GLuint glshader{ 0 }; - GLuint glprogram{ 0 }; - bool result = compileShader(shaderDomain, shaderSource, shaderDefines, glshader, glprogram); - if (!result) { - return nullptr; - } - object->_shader[1] = glshader; - object->_program[1] = glprogram; - - } - return object; } @@ -342,31 +327,37 @@ GLBackend::GLShader* compileBackendProgram(const Shader& program) { 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()) { - auto object = GLBackend::syncGPUObject(*subShader); - GLuint so = 0; - if (object) { - so = object->_shader[0]; - } else { - qCDebug(gpulogging) << "GLShader::compileBackendProgram - 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); } - GLuint glprogram = compileProgram(shaderObjects); - if (glprogram == 0) { - 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] = 0; - object->_program[0] = glprogram; - - makeBindings(object); + object->_shaderObjects = programObjects; return object; } @@ -748,25 +739,30 @@ bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindin return false; } - if (object->_program[0]) { - Shader::SlotSet buffers; - makeUniformBlockSlots(object->_program[0], 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]; - Shader::SlotSet uniforms; - Shader::SlotSet textures; - Shader::SlotSet samplers; - makeUniformSlots(object->_program[0], slotBindings, uniforms, textures, samplers); - - Shader::SlotSet inputs; - makeInputSlots(object->_program[0], slotBindings, inputs); + if (shaderObject.glprogram) { + Shader::SlotSet buffers; + makeUniformBlockSlots(shaderObject.glprogram, slotBindings, buffers); - Shader::SlotSet outputs; - makeOutputSlots(object->_program[0], slotBindings, outputs); + Shader::SlotSet uniforms; + Shader::SlotSet textures; + Shader::SlotSet samplers; + makeUniformSlots(shaderObject.glprogram, slotBindings, uniforms, textures, samplers); - shader.defineSlots(uniforms, buffers, textures, samplers, inputs, outputs); + Shader::SlotSet inputs; + makeInputSlots(shaderObject.glprogram, slotBindings, inputs); - } 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); + } + } } return true; diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 2bef3c606e..8188a7b4a6 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -191,8 +191,10 @@ void GLBackend::TransformStageState::update(size_t commandIndex, const StereoSta } if (offset != INVALID_OFFSET) { // We include both camera offsets for stereo + GLuint rangeSize = sizeof(Backend::TransformCamera); if (stereo._enable && stereo._pass) { offset += _cameraUboSize; + rangeSize += sizeof(Backend::TransformCamera); } glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _cameraBuffer, offset, sizeof(Backend::TransformCamera)); diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index eeda1e3bc6..5cad525989 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -21,10 +21,19 @@ struct TransformCamera { }; layout(std140) uniform transformCameraBuffer { +#ifdef GPU_TRANSFORM_IS_STEREO + TransformCamera _camera[2]; +#else TransformCamera _camera; +#endif }; TransformCamera getTransformCamera() { +#ifdef GPU_TRANSFORM_IS_STEREO + uint eyeIndex = gl_InstanceID % 2; + return _camera[eyeIndex]; +#else return _camera; +#endif } <@endfunc@> 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 From 8964c2427d501ee4914b016b0875e6e69d923049 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 8 Apr 2016 18:47:21 -0700 Subject: [PATCH 06/28] adding support for the 2 versions of the shaders nad solving the mapping of uniforms that arise with it --- libraries/gpu/src/gpu/GLBackend.cpp | 22 +++++++----- libraries/gpu/src/gpu/GLBackend.h | 16 +++++++++ libraries/gpu/src/gpu/GLBackendPipeline.cpp | 3 ++ libraries/gpu/src/gpu/GLBackendShader.cpp | 35 +++++++++++++++---- libraries/gpu/src/gpu/Transform.slh | 19 ++++++++-- .../render-utils/src/MeshPartPayload.cpp | 3 +- 6 files changed, 78 insertions(+), 20 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 2bbac01e25..e16407a449 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -523,8 +523,10 @@ void GLBackend::do_glUniform1i(Batch& batch, size_t paramOffset) { return; } updatePipeline(); + GLint location = _pipeline._programShader->getUniformLocation(isStereo(), batch._params[paramOffset + 1]._int); + glUniform1f( - batch._params[paramOffset + 1]._int, + location, batch._params[paramOffset + 0]._int); (void) CHECK_GL_ERROR(); } @@ -546,9 +548,10 @@ void GLBackend::do_glUniform1f(Batch& batch, size_t paramOffset) { return; } updatePipeline(); + GLint location = _pipeline._programShader->getUniformLocation(isStereo(), batch._params[paramOffset + 1]._int); glUniform1f( - batch._params[paramOffset + 1]._int, + location, batch._params[paramOffset + 0]._float); (void) CHECK_GL_ERROR(); } @@ -571,7 +574,7 @@ void GLBackend::do_glUniform2f(Batch& batch, size_t paramOffset) { } updatePipeline(); glUniform2f( - batch._params[paramOffset + 2]._int, + _pipeline._programShader->getUniformLocation(isStereo(), batch._params[paramOffset + 2]._int), batch._params[paramOffset + 1]._float, batch._params[paramOffset + 0]._float); (void) CHECK_GL_ERROR(); @@ -596,7 +599,7 @@ void GLBackend::do_glUniform3f(Batch& batch, size_t paramOffset) { } updatePipeline(); glUniform3f( - batch._params[paramOffset + 3]._int, + _pipeline._programShader->getUniformLocation(isStereo(), batch._params[paramOffset + 3]._int), batch._params[paramOffset + 2]._float, batch._params[paramOffset + 1]._float, batch._params[paramOffset + 0]._float); @@ -625,7 +628,7 @@ void GLBackend::do_glUniform4f(Batch& batch, size_t paramOffset) { } updatePipeline(); glUniform4f( - batch._params[paramOffset + 4]._int, + _pipeline._programShader->getUniformLocation(isStereo(), batch._params[paramOffset + 4]._int), batch._params[paramOffset + 3]._float, batch._params[paramOffset + 2]._float, batch._params[paramOffset + 1]._float, @@ -651,7 +654,7 @@ void GLBackend::do_glUniform3fv(Batch& batch, size_t paramOffset) { } updatePipeline(); glUniform3fv( - batch._params[paramOffset + 2]._int, + _pipeline._programShader->getUniformLocation(isStereo(), batch._params[paramOffset + 2]._int), batch._params[paramOffset + 1]._uint, (const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint)); @@ -677,7 +680,7 @@ void GLBackend::do_glUniform4fv(Batch& batch, size_t paramOffset) { } updatePipeline(); - GLint location = batch._params[paramOffset + 2]._int; + GLint location = _pipeline._programShader->getUniformLocation(isStereo(), 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); @@ -703,7 +706,7 @@ void GLBackend::do_glUniform4iv(Batch& batch, size_t paramOffset) { } updatePipeline(); glUniform4iv( - batch._params[paramOffset + 2]._int, + _pipeline._programShader->getUniformLocation(isStereo(), batch._params[paramOffset + 2]._int), batch._params[paramOffset + 1]._uint, (const GLint*)batch.editData(batch._params[paramOffset + 0]._uint)); @@ -728,8 +731,9 @@ void GLBackend::do_glUniformMatrix4fv(Batch& batch, size_t paramOffset) { return; } updatePipeline(); + GLint location = _pipeline._programShader->getUniformLocation(isStereo(), batch._params[paramOffset + 3]._int); glUniformMatrix4fv( - batch._params[paramOffset + 3]._int, + location, batch._params[paramOffset + 2]._uint, batch._params[paramOffset + 1]._uint, (const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint)); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index f2888e33a9..2ddd73ac78 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -153,11 +153,16 @@ public: using ShaderObjects = std::array< ShaderObject, NumVersions >; + using UniformMapping = std::map; + using UniformMappingVersions = std::vector; + GLShader(); ~GLShader(); ShaderObjects _shaderObjects; + UniformMappingVersions _uniformMappings; + GLuint getProgram(bool isStereo) const { if (isStereo && _shaderObjects[Stereo].glprogram) { return _shaderObjects[Stereo].glprogram; @@ -165,6 +170,15 @@ public: return _shaderObjects[Mono].glprogram; } } + + GLint getUniformLocation(bool isStereo, GLint srcLoc) { + if (isStereo) { + if (srcLoc >= 0) { + return _uniformMappings[0][srcLoc]; + } + } + return srcLoc; + } }; static GLShader* syncGPUObject(const Shader& shader); @@ -467,6 +481,7 @@ protected: PipelinePointer _pipeline; GLuint _program; + GLShader* _programShader; bool _invalidProgram; State::Data _stateCache; @@ -478,6 +493,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 c3607bf8ff..f43ea1ea73 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; @@ -84,6 +85,7 @@ void GLBackend::do_setPipeline(Batch& batch, size_t paramOffset) { GLuint glprogram = pipelineObject->_program->getProgram(isStereo()); if (_pipeline._program != glprogram) { _pipeline._program = glprogram; + _pipeline._programShader = pipelineObject->_program; _pipeline._invalidProgram = true; } @@ -144,6 +146,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 d6aed882fc..8c6788b510 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -42,8 +42,9 @@ bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const s } // Assign the source + const int NUM_SOURCE_STRINGS = 3; const GLchar* srcstr[] = { "#version 410 core\n", defines.c_str(), shaderSource.c_str() }; - glShaderSource(glshader, 3, srcstr, NULL); + glShaderSource(glshader, NUM_SOURCE_STRINGS, srcstr, NULL); // Compile ! glCompileShader(glshader); @@ -79,7 +80,9 @@ bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const s */ qCWarning(gpulogging) << "GLShader::compileShader - failed to compile the gl shader object:"; - qCWarning(gpulogging) << srcstr; + for (auto s : srcstr) { + qCWarning(gpulogging) << s; + } qCWarning(gpulogging) << "GLShader::compileShader - errors:"; qCWarning(gpulogging) << temp; delete[] temp; @@ -295,21 +298,34 @@ GLBackend::GLShader* compileBackendShader(const Shader& shader) { const std::string& shaderSource = shader.getSource().getCode(); // 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()]; - // Make several versions of the shader - std::string shaderDefines[GLBackend::GLShader::NumVersions] = { + // Domain specific defines + const std::string domainDefines[NUM_SHADER_DOMAINS] = { + "#define VERTEX_SHADER", + "#define PIXEL_SHADER" + }; + + // Versions specific of the shader + const std::string versionDefines[GLBackend::GLShader::NumVersions] = { "", "#define GPU_TRANSFORM_IS_STEREO" }; + GLBackend::GLShader::ShaderObjects shaderObjects; for (int version = 0; version < GLBackend::GLShader::NumVersions; version++) { auto& shaderObject = shaderObjects[version]; - bool result = compileShader(shaderDomain, shaderSource, shaderDefines[version], shaderObject.glshader, shaderObject.glprogram); + std::string shaderDefines = domainDefines[shader.getType()] + "\n" + versionDefines[version]; + + bool result = compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader, shaderObject.glprogram); if (!result) { return nullptr; } @@ -742,7 +758,6 @@ bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindin // 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); @@ -761,6 +776,12 @@ bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindin // 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); } } } diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 5cad525989..23ecc857f5 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -27,10 +27,23 @@ layout(std140) uniform transformCameraBuffer { TransformCamera _camera; #endif }; + +#ifdef GPU_TRANSFORM_IS_STEREO +#ifdef VERTEX_SHADER +flat out int _stereoSide; +#endif + +#ifdef PIXEL_SHADER +flat in int _stereoSide; +#endif +#endif + TransformCamera getTransformCamera() { #ifdef GPU_TRANSFORM_IS_STEREO - uint eyeIndex = gl_InstanceID % 2; - return _camera[eyeIndex]; +#ifdef VERTEX_SHADER + _stereoSide = gl_InstanceID % 2; +#endif + return _camera[_stereoSide]; #else return _camera; #endif @@ -77,8 +90,8 @@ TransformObject getTransformObject() { <@func declareStandardTransform()@> -<$declareStandardObjectTransform()$> <$declareStandardCameraTransform()$> +<$declareStandardObjectTransform()$> <@endfunc@> <@func transformCameraViewport(cameraTransform, viewport)@> diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 102aada9cb..b85bd94798 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -246,7 +246,8 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat // Texcoord transforms ? if (locations->texcoordMatrices >= 0) { - batch._glUniformMatrix4fv(locations->texcoordMatrices, 2, false, (const float*)&texcoordTransform); + //batch._glUniformMatrix4fv(locations->texcoordMatrices, 2, false, (const float*)&texcoordTransform); + batch._glUniformMatrix4fv(locations->texcoordMatrices, (materialKey.isLightmapMap() ? 2 : 1), false, (const float*)&texcoordTransform); } } From 1138af9765827611d2cc0ecfe10b572f31cd0cf2 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 11 Apr 2016 01:19:46 -0700 Subject: [PATCH 07/28] FIrst real stereo version --- interface/src/Application.cpp | 3 +-- libraries/gpu/src/gpu/GLBackend.cpp | 24 ++++++++------------ libraries/gpu/src/gpu/GLBackend.h | 12 ++++++++-- libraries/gpu/src/gpu/GLBackendTransform.cpp | 22 ++++++------------ 4 files changed, 28 insertions(+), 33 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f82756b995..a6555352dd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1674,8 +1674,7 @@ void Application::paintGL() { renderArgs._boomOffset = boomOffset; // Viewport is assigned to the size of the framebuffer renderArgs._viewport = ivec4(0, 0, size.width(), size.height()); - // if (displayPlugin->isStereo()) { - if (true) { + if (displayPlugin->isStereo()) { // Stereo modes will typically have a larger projection matrix overall, // so we ask for the 'mono' projection matrix, which for stereo and HMD // plugins will imply the combined projection for both eyes. diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index e16407a449..b44d4e97ef 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -251,26 +251,20 @@ void GLBackend::render(Batch& batch) { PROFILE_RANGE("Transfer"); renderPassTransfer(batch); } - // _stereo._enable =batch.isStereoEnabled(); - if (_stereo._enable) + if (_stereo._enable) { glEnable(GL_CLIP_DISTANCE0); + } { - PROFILE_RANGE(_stereo._enable ? "LeftRender" : "Render"); + PROFILE_RANGE(_stereo._enable ? "Render Stereo" : "Render"); renderPassDraw(batch); } - /* if (_stereo._enable) { - PROFILE_RANGE("RightRender"); - _stereo._pass = 1; - renderPassDraw(batch); - _stereo._pass = 0; - }*/ - - if (_stereo._enable) + if (_stereo._enable) { glDisable(GL_CLIP_DISTANCE0); - + } + // Restore the saved stereo state for the next batch _stereo._enable = savedStereo; } @@ -335,11 +329,12 @@ void GLBackend::do_draw(Batch& batch, size_t paramOffset) { if (isStereo()) { glDrawArraysInstanced(mode, startVertex, numVertices, 2); _stats._DSNumTriangles += 2 * numVertices / 3; + _stats._DSNumDrawcalls += 2; } else { glDrawArrays(mode, startVertex, numVertices); _stats._DSNumTriangles += numVertices / 3; + _stats._DSNumDrawcalls++; } - _stats._DSNumDrawcalls++; _stats._DSNumAPIDrawcalls++; (void) CHECK_GL_ERROR(); @@ -359,11 +354,12 @@ void GLBackend::do_drawIndexed(Batch& batch, size_t paramOffset) { if (isStereo()) { glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, 2); _stats._DSNumTriangles += 2 * numIndices / 3; + _stats._DSNumDrawcalls += 2; } else { glDrawElements(mode, numIndices, glType, indexBufferByteOffset); _stats._DSNumTriangles += numIndices / 3; + _stats._DSNumDrawcalls++; } - _stats._DSNumDrawcalls++; _stats._DSNumAPIDrawcalls++; (void) CHECK_GL_ERROR(); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 2ddd73ac78..7c04add684 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -396,7 +396,15 @@ protected: void resetTransformStage(); struct TransformStageState { - using TransformCameras = std::vector; + struct Cameras { + TransformCamera _cams[2]; + + Cameras() {}; + Cameras(const TransformCamera& cam) { memcpy(_cams, &cam, sizeof(TransformCamera)); }; + Cameras(const TransformCamera& camL, const TransformCamera& camR) { memcpy(_cams, &camL, sizeof(TransformCamera)); memcpy(_cams + 1, &camR, sizeof(TransformCamera)); }; + }; + + using TransformCameras = std::vector; TransformCamera _camera; TransformCameras _cameras; @@ -407,7 +415,7 @@ protected: GLuint _cameraBuffer { 0 }; GLuint _drawCallInfoBuffer { 0 }; GLuint _objectBufferTexture { 0 }; - size_t _cameraUboSize { 0 }; + size_t _cameraUboSize { 0 }; // 2 sizes, one for mono, one for stereo Transform _view; Mat4 _projection; Vec4i _viewport { 0, 0, 1, 1 }; diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 8188a7b4a6..333fa90480 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -66,7 +66,7 @@ void GLBackend::initTransform() { #ifndef GPU_SSBO_DRAW_CALL_INFO glGenTextures(1, &_transform._objectBufferTexture); #endif - size_t cameraSize = sizeof(TransformCamera); + size_t cameraSize = sizeof(TransformStageState::Cameras); while (_transform._cameraUboSize < cameraSize) { _transform._cameraUboSize += _uboAlignment; } @@ -112,14 +112,11 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo if (_invalidView || _invalidProj || _invalidViewport) { size_t offset = _cameraUboSize * _cameras.size(); + _cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset)); if (stereo._enable) { - _cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset)); - for (int i = 0; i < 2; ++i) { - _cameras.push_back(_camera.getEyeCamera(i, stereo, _view)); - } + _cameras.push_back(Cameras(_camera.getEyeCamera(0, stereo, _view), _camera.getEyeCamera(1, stereo, _view)) ); } else { - _cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset)); - _cameras.push_back(_camera.recomputeDerived(_view)); + _cameras.push_back(Cameras(_camera.recomputeDerived(_view))); } } @@ -133,7 +130,7 @@ void GLBackend::TransformStageState::transfer(const Batch& batch) const { if (!_cameras.empty()) { bufferData.resize(_cameraUboSize * _cameras.size()); for (size_t i = 0; i < _cameras.size(); ++i) { - memcpy(bufferData.data() + (_cameraUboSize * i), &_cameras[i], sizeof(TransformCamera)); + memcpy(bufferData.data() + (_cameraUboSize * i), &_cameras[i], sizeof(Cameras)); } glBindBuffer(GL_UNIFORM_BUFFER, _cameraBuffer); glBufferData(GL_UNIFORM_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW); @@ -191,13 +188,8 @@ void GLBackend::TransformStageState::update(size_t commandIndex, const StereoSta } if (offset != INVALID_OFFSET) { // We include both camera offsets for stereo - GLuint rangeSize = sizeof(Backend::TransformCamera); - if (stereo._enable && stereo._pass) { - offset += _cameraUboSize; - rangeSize += sizeof(Backend::TransformCamera); - } - glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, - _cameraBuffer, offset, sizeof(Backend::TransformCamera)); + GLuint rangeSize = sizeof(Cameras); + glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _cameraBuffer, offset, rangeSize); } (void)CHECK_GL_ERROR(); From 8a233ec9a17cd7494b08a50837c702996ed11915 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 11 Apr 2016 12:32:59 -0700 Subject: [PATCH 08/28] the stereo rendering is working correctly, will now look for more performances --- libraries/gpu/src/gpu/GLBackendInput.cpp | 4 ++-- libraries/gpu/src/gpu/Transform.slh | 4 +++- libraries/model/src/model/skybox.slv | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendInput.cpp b/libraries/gpu/src/gpu/GLBackendInput.cpp index 75f4be3cbe..9ef71ec6a8 100755 --- a/libraries/gpu/src/gpu/GLBackendInput.cpp +++ b/libraries/gpu/src/gpu/GLBackendInput.cpp @@ -120,7 +120,7 @@ void GLBackend::updateInput() { glVertexAttribFormat(slot + locNum, count, type, isNormalized, offset + locNum * perLocationSize); glVertexAttribBinding(slot + locNum, attrib._channel); } - glVertexBindingDivisor(attrib._channel, attrib._frequency); + glVertexBindingDivisor(attrib._channel, attrib._frequency * (isStereo() ? 2 : 1)); } (void) CHECK_GL_ERROR(); } @@ -239,7 +239,7 @@ void GLBackend::updateInput() { for (size_t locNum = 0; locNum < locationCount; ++locNum) { glVertexAttribPointer(slot + (GLuint)locNum, count, type, isNormalized, stride, reinterpret_cast(pointer + perLocationStride * (GLuint)locNum)); - glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency); + glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency * (isStereo() ? 2 : 1)); } // TODO: Support properly the IAttrib version diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 23ecc857f5..fc52f03971 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -103,7 +103,7 @@ TransformObject getTransformObject() { #ifdef GPU_TRANSFORM_IS_STEREO vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1)); vec2 eyeOffsetScale = vec2(-0.5, +0.5); - uint eyeIndex = gl_InstanceID % 2; + uint eyeIndex = _stereoSide; gl_ClipDistance[0] = dot(<$clipPos$>, eyeClipEdge[eyeIndex]); float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w; <$clipPos$>.x = newClipPosX; @@ -189,6 +189,8 @@ TransformObject getTransformObject() { <@func transformEyeToClipPos(cameraTransform, eyePos, clipPos)@> { // transformEyeToClipPos <$clipPos$> = <$cameraTransform$>._projection * vec4(<$eyePos$>.xyz, 1.0); + + <$transformStereoClipsSpace($cameraTransform$, $clipPos$)$> } <@endfunc@> diff --git a/libraries/model/src/model/skybox.slv b/libraries/model/src/model/skybox.slv index 810afb1033..b78bb632fa 100755 --- a/libraries/model/src/model/skybox.slv +++ b/libraries/model/src/model/skybox.slv @@ -36,4 +36,6 @@ void main(void) { // Position is supposed to come in clip space gl_Position = vec4(inPosition.xy, 0.0, 1.0); + + <$transformStereoClipsSpace(cam, gl_Position)$> } \ No newline at end of file From 816a35099aea5201e2446d10510cea235ceb234d Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 11 Apr 2016 18:34:52 -0700 Subject: [PATCH 09/28] Adding tcpu timer on some jobs --- libraries/render-utils/src/AntialiasingEffect.cpp | 3 ++- libraries/render-utils/src/RenderDeferredTask.cpp | 9 ++++++--- libraries/render-utils/src/RenderDeferredTask.h | 14 +++++++++++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index 6c26b16124..c49fd70ff7 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -56,6 +56,7 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() { auto height = _antialiasingBuffer->getHeight(); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); _antialiasingTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); + _antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture); // Good to go add the brand new pipeline _antialiasingPipeline = gpu::Pipeline::create(program, state); @@ -126,7 +127,7 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re // FXAA step getAntialiasingPipeline(); batch.setResourceTexture(0, framebufferCache->getLightingTexture()); - _antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture); + // _antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture); batch.setFramebuffer(_antialiasingBuffer); batch.setPipeline(getAntialiasingPipeline()); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index ba5b2a59d5..eb7b303d9f 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -176,6 +176,8 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont assert(renderContext->args); assert(renderContext->args->_viewFrustum); + quint64 msecsElapsed = _cpuTimer.restart(); + auto config = std::static_pointer_cast(renderContext->jobConfig); RenderArgs* args = renderContext->args; @@ -185,9 +187,6 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); - config->setNumDrawn((int)inItems.size()); - emit config->numDrawnChanged(); - glm::mat4 projMat; Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); @@ -199,6 +198,10 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); args->_batch = nullptr; }); + + msecsElapsed = _cpuTimer.elapsed(); + config->setNumDrawn((int)inItems.size()); + config->setCPUTiming(msecsElapsed); } DrawOverlay3D::DrawOverlay3D(bool opaque) : diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 9fb6802992..1e60e32cbe 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -12,6 +12,8 @@ #ifndef hifi_RenderDeferredTask_h #define hifi_RenderDeferredTask_h +#include + #include #include @@ -42,10 +44,14 @@ class DrawConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) + Q_PROPERTY(quint64 cpuTiming READ getCPUTiming NOTIFY numDrawnChanged) + public: - int getNumDrawn() { return numDrawn; } - void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } + int getNumDrawn() { return _numDrawn; } + void setNumDrawn(int num) { _numDrawn = num; emit numDrawnChanged(); } + quint64 getCPUTiming() { return _cpuTiming; } + void setCPUTiming(quint64 timing) { _cpuTiming = timing; emit numDrawnChanged(); } int maxDrawn{ -1 }; @@ -54,7 +60,8 @@ signals: void dirty(); protected: - int numDrawn{ 0 }; + int _numDrawn{ 0 }; + int _cpuTiming{ 0 }; }; class DrawDeferred { @@ -70,6 +77,7 @@ public: protected: render::ShapePlumberPointer _shapePlumber; int _maxDrawn; // initialized by Config + QElapsedTimer _cpuTimer; }; class DrawStencilDeferred { From 042a4196695ad306d481ca08ac9cdbc2181da4aa Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 12 Apr 2016 02:44:10 -0700 Subject: [PATCH 10/28] Adding counters, not sure they are really useful or that this is the best way to do this... --- examples/utilities/render/stats.qml | 35 ++++++++++++++++++- .../render-utils/src/RenderDeferredTask.cpp | 5 +++ .../render-utils/src/RenderDeferredTask.h | 20 ++++++++++- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/examples/utilities/render/stats.qml b/examples/utilities/render/stats.qml index 4988c23e3b..832e85f39b 100644 --- a/examples/utilities/render/stats.qml +++ b/examples/utilities/render/stats.qml @@ -182,7 +182,40 @@ Item { color: "#E2334D" } ] - } + } + + PlotPerf { + title: "Timing" + height: parent.evalEvenHeight() + object: parent.drawOpaqueConfig + valueUnit: "ms" + plots: [ + { + object: Render.getConfig("RenderDeferred"), + prop: "cpuTiming", + label: "Lighting", + color: "#E2334D" + }, + { + object: Render.getConfig("DrawOpaqueDeferred"), + prop: "cpuTiming", + label: "Opaques", + color: "#1AC567" + }, + { + object: Render.getConfig("DrawTransparentDeferred"), + prop: "cpuTiming", + label: "Translucents", + color: "#00B4EF" + }, + { + object: Render.getConfig("RenderDeferred"), + prop: "cpuTiming", + label: "Lighting", + color: "#E2334D" + } + ] + } } } diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index eb7b303d9f..ee7d5fc394 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -45,7 +45,12 @@ void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderC } void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + quint64 msecsElapsed = _cpuTimer.restart(); + auto config = std::static_pointer_cast(renderContext->jobConfig); + DependencyManager::get()->render(renderContext); + + config->setCPUTiming(_cpuTimer.elapsed()); } RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 1e60e32cbe..b060d9ae39 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -31,12 +31,30 @@ public: using JobModel = render::Job::Model; }; +class RenderDeferredConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(quint64 cpuTiming READ getCPUTiming NOTIFY dirty) + +public: + + quint64 getCPUTiming() { return _cpuTiming; } + void setCPUTiming(quint64 timing) { _cpuTiming = timing; emit dirty(); } + +signals: + void dirty(); + +protected: + int _cpuTiming{ 0 }; +}; class RenderDeferred { public: - using JobModel = render::Job::Model; + using Config = RenderDeferredConfig; + using JobModel = render::Job::Model; + void configure(const Config& config) {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + QElapsedTimer _cpuTimer; }; From ab9f41f5eb3a2c4324fe23ac392e48101a5aa721 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 12 Apr 2016 15:29:31 -0700 Subject: [PATCH 11/28] Trying something a bit more radical for timing --- examples/utilities/render/stats.qml | 9 ++++--- libraries/gpu/src/gpu/Framebuffer.cpp | 2 ++ .../render-utils/src/AntialiasingEffect.cpp | 1 - .../render-utils/src/RenderDeferredTask.cpp | 10 ------- .../render-utils/src/RenderDeferredTask.h | 26 +------------------ libraries/render/src/render/Task.h | 16 ++++++++++++ libraries/shared/src/PerfStat.cpp | 1 + libraries/shared/src/PerfStat.h | 2 +- 8 files changed, 26 insertions(+), 41 deletions(-) diff --git a/examples/utilities/render/stats.qml b/examples/utilities/render/stats.qml index 832e85f39b..5f0628c312 100644 --- a/examples/utilities/render/stats.qml +++ b/examples/utilities/render/stats.qml @@ -189,28 +189,29 @@ Item { height: parent.evalEvenHeight() object: parent.drawOpaqueConfig valueUnit: "ms" + valueScale: 1000 plots: [ { object: Render.getConfig("RenderDeferred"), - prop: "cpuTiming", + prop: "cpuRunTime", label: "Lighting", color: "#E2334D" }, { object: Render.getConfig("DrawOpaqueDeferred"), - prop: "cpuTiming", + prop: "cpuRunTime", label: "Opaques", color: "#1AC567" }, { object: Render.getConfig("DrawTransparentDeferred"), - prop: "cpuTiming", + prop: "cpuRunTime", label: "Translucents", color: "#00B4EF" }, { object: Render.getConfig("RenderDeferred"), - prop: "cpuTiming", + prop: "cpuRunTime", label: "Lighting", color: "#E2334D" } diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index abaa0f9ef1..ac7b136550 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -118,12 +118,14 @@ void Framebuffer::resize(uint16 width, uint16 height, uint16 numSamples) { if (_renderBuffers[i]) { _renderBuffers[i]._texture->resize2D(width, height, numSamples); _numSamples = _renderBuffers[i]._texture->getNumSamples(); + ++_colorStamps[i]; } } if (_depthStencilBuffer) { _depthStencilBuffer._texture->resize2D(width, height, numSamples); _numSamples = _depthStencilBuffer._texture->getNumSamples(); + ++_depthStamp; } _width = width; diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index c49fd70ff7..1f00d468b0 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -127,7 +127,6 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re // FXAA step getAntialiasingPipeline(); batch.setResourceTexture(0, framebufferCache->getLightingTexture()); - // _antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture); batch.setFramebuffer(_antialiasingBuffer); batch.setPipeline(getAntialiasingPipeline()); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index ee7d5fc394..f725d9149c 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -45,12 +45,7 @@ void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderC } void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - quint64 msecsElapsed = _cpuTimer.restart(); - auto config = std::static_pointer_cast(renderContext->jobConfig); - DependencyManager::get()->render(renderContext); - - config->setCPUTiming(_cpuTimer.elapsed()); } RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { @@ -181,8 +176,6 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont assert(renderContext->args); assert(renderContext->args->_viewFrustum); - quint64 msecsElapsed = _cpuTimer.restart(); - auto config = std::static_pointer_cast(renderContext->jobConfig); RenderArgs* args = renderContext->args; @@ -204,9 +197,7 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont args->_batch = nullptr; }); - msecsElapsed = _cpuTimer.elapsed(); config->setNumDrawn((int)inItems.size()); - config->setCPUTiming(msecsElapsed); } DrawOverlay3D::DrawOverlay3D(bool opaque) : @@ -221,7 +212,6 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon auto config = std::static_pointer_cast(renderContext->jobConfig); - config->setNumDrawn((int)inItems.size()); emit config->numDrawnChanged(); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index b060d9ae39..05f2d77fdd 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -31,45 +31,23 @@ public: using JobModel = render::Job::Model; }; -class RenderDeferredConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(quint64 cpuTiming READ getCPUTiming NOTIFY dirty) - -public: - - quint64 getCPUTiming() { return _cpuTiming; } - void setCPUTiming(quint64 timing) { _cpuTiming = timing; emit dirty(); } - -signals: - void dirty(); - -protected: - int _cpuTiming{ 0 }; -}; class RenderDeferred { public: - using Config = RenderDeferredConfig; - using JobModel = render::Job::Model; - void configure(const Config& config) {} + using JobModel = render::Job::Model; void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - QElapsedTimer _cpuTimer; - }; class DrawConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) - Q_PROPERTY(quint64 cpuTiming READ getCPUTiming NOTIFY numDrawnChanged) public: int getNumDrawn() { return _numDrawn; } void setNumDrawn(int num) { _numDrawn = num; emit numDrawnChanged(); } - quint64 getCPUTiming() { return _cpuTiming; } - void setCPUTiming(quint64 timing) { _cpuTiming = timing; emit numDrawnChanged(); } int maxDrawn{ -1 }; @@ -79,7 +57,6 @@ signals: protected: int _numDrawn{ 0 }; - int _cpuTiming{ 0 }; }; class DrawDeferred { @@ -95,7 +72,6 @@ public: protected: render::ShapePlumberPointer _shapePlumber; int _maxDrawn; // initialized by Config - QElapsedTimer _cpuTimer; }; class DrawStencilDeferred { diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index eabdc99338..ece0274c2d 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -127,6 +127,10 @@ protected: // A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled) class JobConfig : public QObject { Q_OBJECT + Q_PROPERTY(quint64 cpuRunTime READ getCPUTRunTime NOTIFY dirty()) + + quint64 _CPURunTime{ 0 }; + public: using Persistent = PersistentConfig; @@ -151,11 +155,16 @@ public: Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); } Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); emit loaded(); } + // Running Time measurement + void setCPURunTime(quint64 ustime) { _CPURunTime = ustime; } + quint64 getCPUTRunTime() const { return _CPURunTime; } + public slots: void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); emit loaded(); } signals: void loaded(); + void dirty(); }; class TaskConfig : public JobConfig { @@ -223,7 +232,10 @@ public: virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; protected: + void setCPURunTime(quint64 ustime) { std::static_pointer_cast(_config)->setCPURunTime(ustime); } QConfigPointer _config; + + friend class Job; }; using ConceptPointer = std::shared_ptr; @@ -254,6 +266,7 @@ public: renderContext->jobConfig = std::static_pointer_cast(_config); if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { jobRun(_data, sceneContext, renderContext, _input.get(), _output.edit()); + } renderContext->jobConfig.reset(); } @@ -278,8 +291,11 @@ public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { PerformanceTimer perfTimer(_name.c_str()); PROFILE_RANGE(_name.c_str()); + auto start = usecTimestampNow(); _concept->run(sceneContext, renderContext); + + _concept->setCPURunTime(usecTimestampNow() - start); } protected: diff --git a/libraries/shared/src/PerfStat.cpp b/libraries/shared/src/PerfStat.cpp index 615330e13f..676d147dd5 100644 --- a/libraries/shared/src/PerfStat.cpp +++ b/libraries/shared/src/PerfStat.cpp @@ -147,3 +147,4 @@ void PerformanceTimer::dumpAllTimerRecords() { << "usecs over" << i.value().getCount() << "calls"; } } + diff --git a/libraries/shared/src/PerfStat.h b/libraries/shared/src/PerfStat.h index f8903a7ef3..5a66990b16 100644 --- a/libraries/shared/src/PerfStat.h +++ b/libraries/shared/src/PerfStat.h @@ -78,7 +78,7 @@ public: PerformanceTimer(const QString& name); ~PerformanceTimer(); - + static bool isActive(); static void setActive(bool active); From 0477f89b1b0d839b3010991e27eeadeb52a9133b Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 12 Apr 2016 17:05:23 -0700 Subject: [PATCH 12/28] Justing exposing the timer correctly --- examples/utilities/render/stats.qml | 13 +++++++------ libraries/gpu/src/gpu/Context.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/examples/utilities/render/stats.qml b/examples/utilities/render/stats.qml index c444cbd226..25f7f06fea 100644 --- a/examples/utilities/render/stats.qml +++ b/examples/utilities/render/stats.qml @@ -206,13 +206,8 @@ Item { object: parent.drawOpaqueConfig valueUnit: "ms" valueScale: 1000 + valueNumDigits: "1" plots: [ - { - object: Render.getConfig("RenderDeferred"), - prop: "cpuRunTime", - label: "Lighting", - color: "#E2334D" - }, { object: Render.getConfig("DrawOpaqueDeferred"), prop: "cpuRunTime", @@ -229,6 +224,12 @@ Item { object: Render.getConfig("RenderDeferred"), prop: "cpuRunTime", label: "Lighting", + color: "#FED959" + }, + { + object: Render.getConfig("RenderDeferredTask"), + prop: "cpuRunTime", + label: "RenderFrame", color: "#E2334D" } ] diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 869db97be7..7f18587c90 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -205,6 +205,7 @@ protected: static void incrementBufferGPUCount(); static void decrementBufferGPUCount(); static void updateBufferGPUMemoryUsage(Size prevObjectSize, Size newObjectSize); + static void incrementTextureGPUCount(); static void decrementTextureGPUCount(); static void updateTextureGPUMemoryUsage(Size prevObjectSize, Size newObjectSize); From e9a0365454517492f0d0e1fdfef88cb70d24a3fe Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 13 Apr 2016 00:16:04 -0700 Subject: [PATCH 13/28] Removing an include not needed --- libraries/render-utils/src/RenderDeferredTask.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 05f2d77fdd..cb0ba1b58c 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -12,8 +12,6 @@ #ifndef hifi_RenderDeferredTask_h #define hifi_RenderDeferredTask_h -#include - #include #include From 8800dd84f17665f882e5ec574d857108cc37c388 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 13 Apr 2016 01:25:46 -0700 Subject: [PATCH 14/28] Trying to use several FBO instead to avoid changing the REnderBUffers for overlay but... --- interface/src/ui/ApplicationOverlay.cpp | 61 +++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 54b56ea4f8..39109bbc11 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -251,15 +251,46 @@ static const auto DEPTH_FORMAT = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPT std::mutex _textureGuard; using Lock = std::unique_lock; std::queue _availableTextures; +std::mutex _framebufferGuard; +std::queue _availableFramebuffers; + +std::mutex _usedFramebufferGuard; +std::list _usedFramebuffers; void ApplicationOverlay::buildFramebufferObject() { PROFILE_RANGE(__FUNCTION__); auto uiSize = qApp->getUiSize(); - if (!_overlayFramebuffer || uiSize != _overlayFramebuffer->getSize()) { - _overlayFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + auto width = uiSize.x; + auto height = uiSize.y; + if (!_overlayDepthTexture) { + _overlayDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(DEPTH_FORMAT, width, height, DEFAULT_SAMPLER)); } + if (!_overlayFramebuffer) { + { + Lock lock(_framebufferGuard); + if (!_availableFramebuffers.empty()) { + _overlayFramebuffer = _availableFramebuffers.front(); + _availableFramebuffers.pop(); + } + } + + if (!_overlayFramebuffer) { + _overlayFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + const gpu::Sampler OVERLAY_SAMPLER(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP); + auto colorBuffer = gpu::TexturePointer(gpu::Texture::create2D(COLOR_FORMAT, width, height, OVERLAY_SAMPLER)); + _overlayFramebuffer->setRenderBuffer(0, colorBuffer); + _overlayFramebuffer->setDepthStencilBuffer(_overlayDepthTexture, DEPTH_FORMAT); + } + } + + + if (_overlayFramebuffer && (uiSize != _overlayFramebuffer->getSize())) { + _overlayFramebuffer->resize(width, height); + } + + /* auto width = uiSize.x; auto height = uiSize.y; if (!_overlayFramebuffer->getDepthStencilBuffer()) { @@ -288,6 +319,7 @@ void ApplicationOverlay::buildFramebufferObject() { auto colorBuffer = gpu::TexturePointer(gpu::Texture::create2D(COLOR_FORMAT, width, height, OVERLAY_SAMPLER)); _overlayFramebuffer->setRenderBuffer(0, colorBuffer); } + */ } gpu::TexturePointer ApplicationOverlay::acquireOverlay() { @@ -299,14 +331,33 @@ gpu::TexturePointer ApplicationOverlay::acquireOverlay() { if (!textureId) { qDebug() << "Missing texture"; } - _overlayFramebuffer->setRenderBuffer(0, gpu::TexturePointer()); + { + Lock lockAvailable(_framebufferGuard); + // Lock lock(_usedFramebufferGuard); + _usedFramebuffers.push_back(_overlayFramebuffer); + } + _overlayFramebuffer.reset(); return result; } void ApplicationOverlay::releaseOverlay(gpu::TexturePointer texture) { if (texture) { - Lock lock(_textureGuard); - _availableTextures.push(texture); + { + Lock lockAvailable(_framebufferGuard); + // Lock lockUsed(_usedFramebufferGuard); + auto& fboit = _usedFramebuffers.begin(); + for (; fboit != _usedFramebuffers.end(); fboit++) { + _availableFramebuffers.push(*fboit); + if ((*fboit)->getRenderBuffer(0) == texture) { + fboit++; + break; + } + } + _usedFramebuffers.erase(_usedFramebuffers.begin(), fboit); + } + + // Lock lock(_textureGuard); + // _availableTextures.push(texture); } else { qWarning() << "Attempted to release null texture"; } From de4345bdc5879316130db1d67d3a9580ec492276 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 13 Apr 2016 01:27:57 -0700 Subject: [PATCH 15/28] Trying to use several FBO instead to avoid changing the REnderBUffers for overlay but... --- interface/src/ui/ApplicationOverlay.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 39109bbc11..d445b8b684 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -253,8 +253,6 @@ using Lock = std::unique_lock; std::queue _availableTextures; std::mutex _framebufferGuard; std::queue _availableFramebuffers; - -std::mutex _usedFramebufferGuard; std::list _usedFramebuffers; void ApplicationOverlay::buildFramebufferObject() { @@ -332,8 +330,7 @@ gpu::TexturePointer ApplicationOverlay::acquireOverlay() { qDebug() << "Missing texture"; } { - Lock lockAvailable(_framebufferGuard); - // Lock lock(_usedFramebufferGuard); + Lock lock(_framebufferGuard); _usedFramebuffers.push_back(_overlayFramebuffer); } _overlayFramebuffer.reset(); @@ -344,7 +341,6 @@ void ApplicationOverlay::releaseOverlay(gpu::TexturePointer texture) { if (texture) { { Lock lockAvailable(_framebufferGuard); - // Lock lockUsed(_usedFramebufferGuard); auto& fboit = _usedFramebuffers.begin(); for (; fboit != _usedFramebuffers.end(); fboit++) { _availableFramebuffers.push(*fboit); @@ -357,7 +353,7 @@ void ApplicationOverlay::releaseOverlay(gpu::TexturePointer texture) { } // Lock lock(_textureGuard); - // _availableTextures.push(texture); + // _availableTextures.push(texture); } else { qWarning() << "Attempted to release null texture"; } From 41d4d3b2d71a18a31d9267ea3e6d6e16f05064a7 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 13 Apr 2016 19:21:17 -0700 Subject: [PATCH 16/28] Providing a cleaner way to try different paths and exploring a simpler way --- interface/src/ui/ApplicationOverlay.cpp | 59 ++--------- libraries/gpu/src/gpu/GLBackend.cpp | 104 ++++++++++++++++--- libraries/gpu/src/gpu/GLBackend.h | 21 +++- libraries/gpu/src/gpu/GLBackendInput.cpp | 9 ++ libraries/gpu/src/gpu/GLBackendShader.cpp | 9 +- libraries/gpu/src/gpu/GLBackendTransform.cpp | 55 ++++++---- libraries/gpu/src/gpu/Transform.slh | 39 +++++-- 7 files changed, 201 insertions(+), 95 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index d445b8b684..02b2de8838 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -251,44 +251,15 @@ static const auto DEPTH_FORMAT = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPT std::mutex _textureGuard; using Lock = std::unique_lock; std::queue _availableTextures; -std::mutex _framebufferGuard; -std::queue _availableFramebuffers; -std::list _usedFramebuffers; void ApplicationOverlay::buildFramebufferObject() { PROFILE_RANGE(__FUNCTION__); auto uiSize = qApp->getUiSize(); - auto width = uiSize.x; - auto height = uiSize.y; - if (!_overlayDepthTexture) { - _overlayDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(DEPTH_FORMAT, width, height, DEFAULT_SAMPLER)); + if (!_overlayFramebuffer || uiSize != _overlayFramebuffer->getSize()) { + _overlayFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); } - if (!_overlayFramebuffer) { - { - Lock lock(_framebufferGuard); - if (!_availableFramebuffers.empty()) { - _overlayFramebuffer = _availableFramebuffers.front(); - _availableFramebuffers.pop(); - } - } - - if (!_overlayFramebuffer) { - _overlayFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); - const gpu::Sampler OVERLAY_SAMPLER(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP); - auto colorBuffer = gpu::TexturePointer(gpu::Texture::create2D(COLOR_FORMAT, width, height, OVERLAY_SAMPLER)); - _overlayFramebuffer->setRenderBuffer(0, colorBuffer); - _overlayFramebuffer->setDepthStencilBuffer(_overlayDepthTexture, DEPTH_FORMAT); - } - } - - - if (_overlayFramebuffer && (uiSize != _overlayFramebuffer->getSize())) { - _overlayFramebuffer->resize(width, height); - } - - /* auto width = uiSize.x; auto height = uiSize.y; if (!_overlayFramebuffer->getDepthStencilBuffer()) { @@ -310,14 +281,13 @@ void ApplicationOverlay::buildFramebufferObject() { _overlayFramebuffer->setRenderBuffer(0, newColorAttachment); } } - + // If the overlay framebuffer still has no color attachment, no textures were available for rendering, so build a new one if (!_overlayFramebuffer->getRenderBuffer(0)) { const gpu::Sampler OVERLAY_SAMPLER(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP); auto colorBuffer = gpu::TexturePointer(gpu::Texture::create2D(COLOR_FORMAT, width, height, OVERLAY_SAMPLER)); _overlayFramebuffer->setRenderBuffer(0, colorBuffer); } - */ } gpu::TexturePointer ApplicationOverlay::acquireOverlay() { @@ -329,31 +299,14 @@ gpu::TexturePointer ApplicationOverlay::acquireOverlay() { if (!textureId) { qDebug() << "Missing texture"; } - { - Lock lock(_framebufferGuard); - _usedFramebuffers.push_back(_overlayFramebuffer); - } - _overlayFramebuffer.reset(); + _overlayFramebuffer->setRenderBuffer(0, gpu::TexturePointer()); return result; } void ApplicationOverlay::releaseOverlay(gpu::TexturePointer texture) { if (texture) { - { - Lock lockAvailable(_framebufferGuard); - auto& fboit = _usedFramebuffers.begin(); - for (; fboit != _usedFramebuffers.end(); fboit++) { - _availableFramebuffers.push(*fboit); - if ((*fboit)->getRenderBuffer(0) == texture) { - fboit++; - break; - } - } - _usedFramebuffers.erase(_usedFramebuffers.begin(), fboit); - } - - // Lock lock(_textureGuard); - // _availableTextures.push(texture); + Lock lock(_textureGuard); + _availableTextures.push(texture); } else { qWarning() << "Attempted to release null texture"; } diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index b44d4e97ef..c1ed7d90f6 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -251,19 +251,23 @@ void GLBackend::render(Batch& batch) { PROFILE_RANGE("Transfer"); renderPassTransfer(batch); } - + +#ifdef GPU_STEREO_DRAWCALL_INSTANCED if (_stereo._enable) { glEnable(GL_CLIP_DISTANCE0); } +#endif { PROFILE_RANGE(_stereo._enable ? "Render Stereo" : "Render"); renderPassDraw(batch); } +#ifdef GPU_STEREO_DRAWCALL_INSTANCED if (_stereo._enable) { glDisable(GL_CLIP_DISTANCE0); } +#endif // Restore the saved stereo state for the next batch _stereo._enable = savedStereo; @@ -320,6 +324,25 @@ void GLBackend::syncCache() { glEnable(GL_LINE_SMOOTH); } +#ifdef GPU_STEREO_DRAWCALL_DOUBLED +void GLBackend::setupStereoSide(int side) { + ivec4 vp = _transform._viewport; + vp.z /= 2; + glViewport(vp.x + side * vp.z, vp.y, vp.z, vp.w); + + +#ifdef GPU_STEREO_CAMERA_BUFFER +#ifdef GPU_STEREO_DRAWCALL_DOUBLED + glVertexAttribI1i(14, side); +#endif +#else + _transform.bindCurrentCamera(side); +#endif + +} +#endif + + void GLBackend::do_draw(Batch& batch, size_t paramOffset) { Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; GLenum mode = _primitiveToGLmode[primitiveType]; @@ -327,9 +350,18 @@ void GLBackend::do_draw(Batch& batch, size_t paramOffset) { uint32 startVertex = batch._params[paramOffset + 0]._uint; if (isStereo()) { +#ifdef GPU_STEREO_DRAWCALL_INSTANCED glDrawArraysInstanced(mode, startVertex, numVertices, 2); +#endif +#ifdef GPU_STEREO_DRAWCALL_DOUBLED + setupStereoSide(0); + glDrawArrays(mode, startVertex, numVertices); + setupStereoSide(1); + glDrawArrays(mode, startVertex, numVertices); +#endif _stats._DSNumTriangles += 2 * numVertices / 3; _stats._DSNumDrawcalls += 2; + } else { glDrawArrays(mode, startVertex, numVertices); _stats._DSNumTriangles += numVertices / 3; @@ -352,7 +384,15 @@ void GLBackend::do_drawIndexed(Batch& batch, size_t paramOffset) { GLvoid* indexBufferByteOffset = reinterpret_cast(startIndex * typeByteSize + _input._indexBufferOffset); if (isStereo()) { +#ifdef GPU_STEREO_DRAWCALL_INSTANCED glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, 2); +#endif +#ifdef GPU_STEREO_DRAWCALL_DOUBLED + setupStereoSide(0); + glDrawElements(mode, numIndices, glType, indexBufferByteOffset); + setupStereoSide(1); + glDrawElements(mode, numIndices, glType, indexBufferByteOffset); +#endif _stats._DSNumTriangles += 2 * numIndices / 3; _stats._DSNumDrawcalls += 2; } else { @@ -372,15 +412,39 @@ void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) { uint32 numVertices = batch._params[paramOffset + 2]._uint; uint32 startVertex = batch._params[paramOffset + 1]._uint; - GLint trueNumInstances = (isStereo() ? 2 * numInstances : numInstances); - glDrawArraysInstancedARB(mode, startVertex, numVertices, trueNumInstances); - _stats._DSNumTriangles += (trueNumInstances * numVertices) / 3; - _stats._DSNumDrawcalls += trueNumInstances; + + if (isStereo()) { + GLint trueNumInstances = (isStereo() ? 2 * numInstances : numInstances); + +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawArraysInstancedARB(mode, startVertex, numVertices, trueNumInstances); +#endif +#ifdef GPU_STEREO_DRAWCALL_DOUBLED + setupStereoSide(0); + glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances); + setupStereoSide(1); + glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances); +#endif + _stats._DSNumTriangles += (trueNumInstances * numVertices) / 3; + _stats._DSNumDrawcalls += trueNumInstances; + } else { + glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances); + _stats._DSNumTriangles += (numInstances * numVertices) / 3; + _stats._DSNumDrawcalls += numInstances; + } _stats._DSNumAPIDrawcalls++; (void) CHECK_GL_ERROR(); } +void glbackend_glDrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex, GLuint baseinstance) { +#if (GPU_INPUT_PROFILE == GPU_CORE_43) + glDrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, primcount, basevertex, baseinstance); +#else + glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances); +#endif +} + void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) { GLint numInstances = batch._params[paramOffset + 4]._uint; GLenum mode = _primitiveToGLmode[(Primitive)batch._params[paramOffset + 3]._uint]; @@ -396,14 +460,30 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) { GLint trueNumInstances = (isStereo() ? 2 * numInstances : numInstances); -#if (GPU_INPUT_PROFILE == GPU_CORE_43) - glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances, 0, startInstance); -#else - glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances); - Q_UNUSED(startInstance); + if (isStereo()) { + GLint trueNumInstances = (isStereo() ? 2 * numInstances : numInstances); + +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances, 0, startInstance); #endif - _stats._DSNumTriangles += (trueNumInstances * numIndices) / 3; - _stats._DSNumDrawcalls += trueNumInstances; +#ifdef GPU_STEREO_DRAWCALL_DOUBLED + setupStereoSide(0); + glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); + setupStereoSide(1); + glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); +#endif + _stats._DSNumTriangles += (trueNumInstances * numIndices) / 3; + _stats._DSNumDrawcalls += trueNumInstances; + } else { +#if (GPU_INPUT_PROFILE == GPU_CORE_43) + glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); +#else + glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, numInstances); +#endif + _stats._DSNumTriangles += (numInstances * numIndices) / 3; + _stats._DSNumDrawcalls += numInstances; + } + _stats._DSNumAPIDrawcalls++; (void)CHECK_GL_ERROR(); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index c0d1e90831..3a8778c2a9 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -23,6 +23,9 @@ #include "Context.h" +#define GPU_STEREO_DRAWCALL_DOUBLED +//#define GPU_STEREO_CAMERA_BUFFER + namespace gpu { class GLTextureTransferHelper; @@ -183,7 +186,8 @@ public: GLuint getProgram(bool isStereo) const { if (isStereo && _shaderObjects[Stereo].glprogram) { return _shaderObjects[Stereo].glprogram; - } else { + } else + { return _shaderObjects[Mono].glprogram; } } @@ -331,6 +335,10 @@ protected: void renderPassTransfer(Batch& batch); void renderPassDraw(Batch& batch); +#ifdef GPU_STEREO_DRAWCALL_DOUBLED + void setupStereoSide(int side); +#endif + void initTextureTransferHelper(); static void transferGPUObject(const TexturePointer& texture); @@ -413,6 +421,7 @@ protected: void resetTransformStage(); struct TransformStageState { +#ifdef GPU_STEREO_CAMERA_BUFFER struct Cameras { TransformCamera _cams[2]; @@ -421,7 +430,11 @@ protected: Cameras(const TransformCamera& camL, const TransformCamera& camR) { memcpy(_cams, &camL, sizeof(TransformCamera)); memcpy(_cams + 1, &camR, sizeof(TransformCamera)); }; }; - using TransformCameras = std::vector; + using CameraBufferElement = Cameras; +#else + using CameraBufferElement = TransformCamera; +#endif + using TransformCameras = std::vector; TransformCamera _camera; TransformCameras _cameras; @@ -432,7 +445,7 @@ protected: GLuint _cameraBuffer { 0 }; GLuint _drawCallInfoBuffer { 0 }; GLuint _objectBufferTexture { 0 }; - size_t _cameraUboSize { 0 }; // 2 sizes, one for mono, one for stereo + size_t _cameraUboSize { 0 }; Transform _view; Mat4 _projection; Vec4i _viewport { 0, 0, 1, 1 }; @@ -445,9 +458,11 @@ protected: using List = std::list; List _cameraOffsets; mutable List::const_iterator _camerasItr; + mutable size_t _currentCameraOffset; void preUpdate(size_t commandIndex, const StereoState& stereo); void update(size_t commandIndex, const StereoState& stereo) const; + void bindCurrentCamera(int stereoSide) const; void transfer(const Batch& batch) const; } _transform; diff --git a/libraries/gpu/src/gpu/GLBackendInput.cpp b/libraries/gpu/src/gpu/GLBackendInput.cpp index 9ef71ec6a8..8ab5d81be1 100755 --- a/libraries/gpu/src/gpu/GLBackendInput.cpp +++ b/libraries/gpu/src/gpu/GLBackendInput.cpp @@ -120,7 +120,11 @@ void GLBackend::updateInput() { glVertexAttribFormat(slot + locNum, count, type, isNormalized, offset + locNum * perLocationSize); glVertexAttribBinding(slot + locNum, attrib._channel); } +#ifdef GPU_STEREO_DRAWCALL_INSTANCED glVertexBindingDivisor(attrib._channel, attrib._frequency * (isStereo() ? 2 : 1)); +#else + glVertexBindingDivisor(attrib._channel, attrib._frequency); +#endif } (void) CHECK_GL_ERROR(); } @@ -239,7 +243,12 @@ void GLBackend::updateInput() { for (size_t locNum = 0; locNum < locationCount; ++locNum) { glVertexAttribPointer(slot + (GLuint)locNum, count, type, isNormalized, stride, reinterpret_cast(pointer + perLocationStride * (GLuint)locNum)); + +#ifdef GPU_STEREO_DRAWCALL_INSTANCED glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency * (isStereo() ? 2 : 1)); +#else + glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency); +#endif } // TODO: Support properly the IAttrib version diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 8c6788b510..68e2075573 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -312,9 +312,16 @@ GLBackend::GLShader* compileBackendShader(const Shader& shader) { }; // Versions specific of the shader +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + const std::string stereoVersion("#define GPU_TRANSFORM_IS_STEREO/n#define GPU_TRANSFORM_STEREO_CAMERA/n#define GPU_TRANSFORM_STEREO_CAMERA_INSTANCED/n#define GPU_TRANSFORM_STEREO_SPLIT_SCREEN"); +#endif +#ifdef GPU_STEREO_DRAWCALL_DOUBLED + // const std::string stereoVersion("#define GPU_TRANSFORM_IS_STEREO/n#define GPU_TRANSFORM_STEREO_CAMERA/n#define GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED"); + const std::string stereoVersion("#define GPU_TRANSFORM_IS_STEREO"); +#endif const std::string versionDefines[GLBackend::GLShader::NumVersions] = { "", - "#define GPU_TRANSFORM_IS_STEREO" + stereoVersion }; diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 333fa90480..80ba0f82b5 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -34,16 +34,6 @@ void GLBackend::do_setViewportTransform(Batch& batch, size_t paramOffset) { ivec4& vp = _transform._viewport; glViewport(vp.x, vp.y, vp.z, vp.w); - // Where we assign the GL viewport - if (_stereo._enable) { - vp.z /= 2; - if (_stereo._pass) { - vp.x += vp.z; - } - } - -// glViewport(vp.x, vp.y, vp.z, vp.w); - // The Viewport is tagged invalid because the CameraTransformUBO is not up to date and will need update on next drawcall _transform._invalidViewport = true; } @@ -66,7 +56,7 @@ void GLBackend::initTransform() { #ifndef GPU_SSBO_DRAW_CALL_INFO glGenTextures(1, &_transform._objectBufferTexture); #endif - size_t cameraSize = sizeof(TransformStageState::Cameras); + size_t cameraSize = sizeof(TransformStageState::CameraBufferElement); while (_transform._cameraUboSize < cameraSize) { _transform._cameraUboSize += _uboAlignment; } @@ -114,10 +104,20 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo size_t offset = _cameraUboSize * _cameras.size(); _cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset)); if (stereo._enable) { - _cameras.push_back(Cameras(_camera.getEyeCamera(0, stereo, _view), _camera.getEyeCamera(1, stereo, _view)) ); +#ifdef GPU_STEREO_CAMERA_BUFFER + _cameras.push_back(CameraBufferElement(_camera.getEyeCamera(0, stereo, _view), _camera.getEyeCamera(1, stereo, _view))); +#else + _cameras.push_back((_camera.getEyeCamera(0, stereo, _view))); + _cameras.push_back((_camera.getEyeCamera(1, stereo, _view))); +#endif } else { - _cameras.push_back(Cameras(_camera.recomputeDerived(_view))); +#ifdef GPU_STEREO_CAMERA_BUFFER + _cameras.push_back(CameraBufferElement(_camera.recomputeDerived(_view))); +#else + _cameras.push_back((_camera.recomputeDerived(_view))); +#endif } + } // Flags are clean @@ -130,7 +130,7 @@ void GLBackend::TransformStageState::transfer(const Batch& batch) const { if (!_cameras.empty()) { bufferData.resize(_cameraUboSize * _cameras.size()); for (size_t i = 0; i < _cameras.size(); ++i) { - memcpy(bufferData.data() + (_cameraUboSize * i), &_cameras[i], sizeof(Cameras)); + memcpy(bufferData.data() + (_cameraUboSize * i), &_cameras[i], sizeof(CameraBufferElement)); } glBindBuffer(GL_UNIFORM_BUFFER, _cameraBuffer); glBufferData(GL_UNIFORM_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW); @@ -178,23 +178,33 @@ void GLBackend::TransformStageState::transfer(const Batch& batch) const { CHECK_GL_ERROR(); } +static const size_t INVALID_OFFSET = (size_t)-1; void GLBackend::TransformStageState::update(size_t commandIndex, const StereoState& stereo) const { - static const size_t INVALID_OFFSET = (size_t)-1; size_t offset = INVALID_OFFSET; while ((_camerasItr != _cameraOffsets.end()) && (commandIndex >= (*_camerasItr).first)) { offset = (*_camerasItr).second; ++_camerasItr; } - if (offset != INVALID_OFFSET) { - // We include both camera offsets for stereo - GLuint rangeSize = sizeof(Cameras); - glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _cameraBuffer, offset, rangeSize); + _currentCameraOffset = offset; + +#ifdef GPU_STEREO_CAMERA_BUFFER + bindCurrentCamera(0); +#else + if (!stereo._enable) { + bindCurrentCamera(0); } +#endif (void)CHECK_GL_ERROR(); } +void GLBackend::TransformStageState::bindCurrentCamera(int eye) const { + if (_currentCameraOffset != INVALID_OFFSET) { + glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _cameraBuffer, _currentCameraOffset + eye * _cameraUboSize, sizeof(CameraBufferElement)); + } +} + void GLBackend::updateTransform(const Batch& batch) { _transform.update(_commandIndex, _stereo); @@ -208,7 +218,12 @@ void GLBackend::updateTransform(const Batch& batch) { glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer); glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0, _transform._drawCallInfoOffsets[batch._currentNamedCall]); - glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, (isStereo() ? 2: 1)); + +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, (isStereo() ? 2 : 1)); +#else + glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, 1); +#endif } (void)CHECK_GL_ERROR(); diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index fc52f03971..20e7ec0d02 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -22,28 +22,51 @@ struct TransformCamera { layout(std140) uniform transformCameraBuffer { #ifdef GPU_TRANSFORM_IS_STEREO - TransformCamera _camera[2]; +#ifdef GPU_TRANSFORM_STEREO_CAMERA + TransformCamera _camera[2] +#else + TransformCamera _camera; +#endif #else TransformCamera _camera; #endif }; -#ifdef GPU_TRANSFORM_IS_STEREO #ifdef VERTEX_SHADER +#ifdef GPU_TRANSFORM_IS_STEREO + +#ifdef GPU_TRANSFORM_STEREO_CAMERA +#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED +layout(location=14) in int _inStereoSide; +#endif + flat out int _stereoSide; #endif +#endif + +#endif + #ifdef PIXEL_SHADER +#ifdef GPU_TRANSFORM_STEREO_CAMERA flat in int _stereoSide; #endif #endif TransformCamera getTransformCamera() { #ifdef GPU_TRANSFORM_IS_STEREO -#ifdef VERTEX_SHADER - _stereoSide = gl_InstanceID % 2; -#endif - return _camera[_stereoSide]; + #ifdef GPU_TRANSFORM_STEREO_CAMERA + #ifdef VERTEX_SHADER + #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED + _stereoSide = _inStereoSide; + #else + _stereoSide = gl_InstanceID % 2; + #endif + #endif + return _camera[_stereoSide]; + #else + return _camera; + #endif #else return _camera; #endif @@ -101,12 +124,16 @@ TransformObject getTransformObject() { <@func transformStereoClipsSpace(cameraTransform, clipPos)@> { #ifdef GPU_TRANSFORM_IS_STEREO + +#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1)); vec2 eyeOffsetScale = vec2(-0.5, +0.5); uint eyeIndex = _stereoSide; gl_ClipDistance[0] = dot(<$clipPos$>, eyeClipEdge[eyeIndex]); float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w; <$clipPos$>.x = newClipPosX; +#endif + #else #endif } From c6414208e875ecfb77a8dc564f29643faca3ab16 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 14 Apr 2016 03:25:32 -0700 Subject: [PATCH 17/28] Use the dumber version of the stereo technique and fix a warning --- libraries/gpu/src/gpu/GLBackend.cpp | 8 ++++---- libraries/gpu/src/gpu/GLBackend.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index d8a4267588..4e1caea816 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -440,9 +440,11 @@ void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) { void glbackend_glDrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex, GLuint baseinstance) { #if (GPU_INPUT_PROFILE == GPU_CORE_43) - glDrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, primcount, basevertex, baseinstance); + //glDrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, primcount, basevertex, baseinstance); + glDrawElementsInstanced(mode, count, type, indices, primcount); + #else - glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances); + glDrawElementsInstanced(mode, count, type, indices, primcount); #endif } @@ -459,8 +461,6 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) { auto typeByteSize = TYPE_SIZE[_input._indexBufferType]; GLvoid* indexBufferByteOffset = reinterpret_cast(startIndex * typeByteSize + _input._indexBufferOffset); - GLint trueNumInstances = (isStereo() ? 2 * numInstances : numInstances); - if (isStereo()) { GLint trueNumInstances = (isStereo() ? 2 * numInstances : numInstances); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 7a3a108559..2a90401947 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -24,8 +24,8 @@ #include "Context.h" // PIck one from the 3 -//#define GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE -#define GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER +#define GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE +//#define GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER //#define GPU_STEREO_TECHNIQUE_INSTANCED From c1ed0e2e140a3fcad57bf5671ba1e9ac3a3169cb Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 15 Apr 2016 20:02:15 -0700 Subject: [PATCH 18/28] Enabling sbo --- libraries/gl/src/gl/Config.h | 2 +- libraries/gpu/src/gpu/GLBackend.cpp | 27 +------------------- libraries/gpu/src/gpu/GLBackend.h | 5 ++-- libraries/gpu/src/gpu/GLBackendShader.cpp | 2 +- libraries/gpu/src/gpu/GLBackendTransform.cpp | 15 ++++++++--- libraries/gpu/src/gpu/Transform.slh | 6 ++--- 6 files changed, 20 insertions(+), 37 deletions(-) diff --git a/libraries/gl/src/gl/Config.h b/libraries/gl/src/gl/Config.h index 8f7582c271..a7d2c27db2 100644 --- a/libraries/gl/src/gl/Config.h +++ b/libraries/gl/src/gl/Config.h @@ -51,7 +51,7 @@ #if (GPU_INPUT_PROFILE == GPU_CORE_43) // Deactivate SSBO for now, we've run into some issues // on GL 4.3 capable GPUs not behaving as expected -//#define GPU_SSBO_DRAW_CALL_INFO +#define GPU_SSBO_DRAW_CALL_INFO #endif diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 4e1caea816..538472325d 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -559,9 +559,6 @@ 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) - #ifdef GPU_STEREO_CAMERA_BUFFER #define GET_UNIFORM_LOCATION(shaderUniformLoc) _pipeline._programShader->getUniformLocation(isStereo(), shaderUniformLoc) #else @@ -576,9 +573,6 @@ 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); @@ -596,9 +590,8 @@ 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) { // We should call updatePipeline() to bind the program but we are not doing that @@ -620,8 +613,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) { @@ -643,8 +634,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) { @@ -668,8 +657,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) { @@ -696,8 +683,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); } @@ -724,8 +709,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) { @@ -750,8 +733,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) { @@ -776,8 +757,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) { @@ -802,8 +781,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) { @@ -828,8 +805,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 2a90401947..42ab800cf7 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -23,7 +23,7 @@ #include "Context.h" -// PIck one from the 3 +// Pick one from the 3: THis version is the most efficient as of now #define GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE //#define GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER //#define GPU_STEREO_TECHNIQUE_INSTANCED @@ -461,7 +461,8 @@ protected: mutable std::map _drawCallInfoOffsets; - GLuint _objectBuffer { 0 }; + mutable int batchNum{ 0 }; + GLuint _objectBuffer[2]; GLuint _cameraBuffer { 0 }; GLuint _drawCallInfoBuffer { 0 }; GLuint _objectBufferTexture { 0 }; diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index d318bfff7e..7ce27b8f2a 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -43,7 +43,7 @@ bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const s // Assign the source const int NUM_SOURCE_STRINGS = 3; - const GLchar* srcstr[] = { "#version 410 core\n", defines.c_str(), shaderSource.c_str() }; + const GLchar* srcstr[] = { "#version 430 core\n", defines.c_str(), shaderSource.c_str() }; glShaderSource(glshader, NUM_SOURCE_STRINGS, srcstr, NULL); // Compile ! diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index a1958d9d71..788e14ab1f 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -67,7 +67,9 @@ void GLBackend::do_setDepthRangeTransform(Batch& batch, size_t paramOffset) { } void GLBackend::initTransform() { - glGenBuffers(1, &_transform._objectBuffer); + + glGenBuffers(2, _transform._objectBuffer); +// glGenBuffers(1, &_transform._objectBuffer); glGenBuffers(1, &_transform._cameraBuffer); glGenBuffers(1, &_transform._drawCallInfoBuffer); #ifndef GPU_SSBO_DRAW_CALL_INFO @@ -80,7 +82,8 @@ void GLBackend::initTransform() { } void GLBackend::killTransform() { - glDeleteBuffers(1, &_transform._objectBuffer); + glDeleteBuffers(2, _transform._objectBuffer); + // glDeleteBuffers(1, &_transform._objectBuffer); glDeleteBuffers(1, &_transform._cameraBuffer); glDeleteBuffers(1, &_transform._drawCallInfoBuffer); #ifndef GPU_SSBO_DRAW_CALL_INFO @@ -160,7 +163,10 @@ void GLBackend::TransformStageState::transfer(const Batch& batch) const { memcpy(bufferData.data(), batch._objects.data(), byteSize); #ifdef GPU_SSBO_DRAW_CALL_INFO - glBindBuffer(GL_SHADER_STORAGE_BUFFER, _objectBuffer); + batchNum++; + // glBindBuffer(GL_SHADER_STORAGE_BUFFER, _objectBuffer); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, _objectBuffer[batchNum % 2]); + //glBindBuffer(GL_SHADER_STORAGE_BUFFER, _objectBuffer); glBufferData(GL_SHADER_STORAGE_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); #else @@ -186,7 +192,8 @@ void GLBackend::TransformStageState::transfer(const Batch& batch) const { } #ifdef GPU_SSBO_DRAW_CALL_INFO - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, TRANSFORM_OBJECT_SLOT, _objectBuffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, TRANSFORM_OBJECT_SLOT, _objectBuffer[batchNum % 2]); + // glBindBufferBase(GL_SHADER_STORAGE_BUFFER, TRANSFORM_OBJECT_SLOT, _objectBuffer); #else glActiveTexture(GL_TEXTURE0 + TRANSFORM_OBJECT_SLOT); glBindTexture(GL_TEXTURE_BUFFER, _objectBufferTexture); diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index ba006d5c73..b7e3b0f6d3 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -83,7 +83,7 @@ struct TransformObject { layout(location=15) in ivec2 _drawCallInfo; -<@if FALSE @> +!> // Disable SSBOs for now layout(std140) buffer transformObjectBuffer { TransformObject _object[]; @@ -91,7 +91,7 @@ layout(std140) buffer transformObjectBuffer { TransformObject getTransformObject() { return _object[_drawCallInfo.x]; } -<@else@> + uniform samplerBuffer transformObjectBuffer; TransformObject getTransformObject() { @@ -109,7 +109,7 @@ TransformObject getTransformObject() { return object; } -<@endif@> +<@endif@>!> <@endfunc@> From 0531f90675404a4456fb98da5931fa068fb0b43b Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 18 Apr 2016 00:22:05 -0700 Subject: [PATCH 19/28] Adding state sorting for free --- .../render-utils/src/MeshPartPayload.cpp | 4 +- .../render-utils/src/RenderDeferredTask.cpp | 37 +++++++++++++- .../render-utils/src/RenderDeferredTask.h | 18 +++++++ libraries/render/src/render/DrawTask.cpp | 51 +++++++++++++++++++ libraries/render/src/render/DrawTask.h | 1 + 5 files changed, 107 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index b85bd94798..a273d92112 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -246,8 +246,8 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat // Texcoord transforms ? if (locations->texcoordMatrices >= 0) { - //batch._glUniformMatrix4fv(locations->texcoordMatrices, 2, false, (const float*)&texcoordTransform); - batch._glUniformMatrix4fv(locations->texcoordMatrices, (materialKey.isLightmapMap() ? 2 : 1), false, (const float*)&texcoordTransform); + batch._glUniformMatrix4fv(locations->texcoordMatrices, 2, false, (const float*)&texcoordTransform); + // batch._glUniformMatrix4fv(locations->texcoordMatrices, (materialKey.isLightmapMap() ? 2 : 1), false, (const float*)&texcoordTransform); } } diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index f725d9149c..0924c8ed28 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -96,7 +96,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { addJob("PrepareDeferred"); // Render opaque objects in DeferredBuffer - addJob("DrawOpaqueDeferred", opaques, shapePlumber); + addJob("DrawOpaqueDeferred", opaques, shapePlumber); // Once opaque is all rendered create stencil background addJob("DrawOpaqueStencil"); @@ -170,7 +170,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend for (auto job : _jobs) { job.run(sceneContext, renderContext); } -}; +} void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) { assert(renderContext->args); @@ -200,6 +200,39 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont config->setNumDrawn((int)inItems.size()); } + +void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) { + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + + auto config = std::static_pointer_cast(renderContext->jobConfig); + + RenderArgs* args = renderContext->args; + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + glm::mat4 projMat; + Transform viewMat; + args->_viewFrustum->evalProjectionMatrix(projMat); + args->_viewFrustum->evalViewTransform(viewMat); + + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + + if (_stateSort) { + renderStateSortShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); + } else { + renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); + } + args->_batch = nullptr; + }); + + config->setNumDrawn((int)inItems.size()); +} + DrawOverlay3D::DrawOverlay3D(bool opaque) : _shapePlumber(std::make_shared()), _opaquePass(opaque) { diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index cb0ba1b58c..a0e0004388 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -41,6 +41,7 @@ class DrawConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) + Q_PROPERTY(bool stateSort MEMBER stateSort NOTIFY dirty) public: @@ -48,6 +49,7 @@ public: void setNumDrawn(int num) { _numDrawn = num; emit numDrawnChanged(); } int maxDrawn{ -1 }; + bool stateSort{ true }; signals: void numDrawnChanged(); @@ -72,6 +74,22 @@ protected: int _maxDrawn; // initialized by Config }; +class DrawStateSortDeferred { +public: + using Config = DrawConfig; + using JobModel = render::Job::ModelI; + + DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + + void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; } + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemBounds& inItems); + +protected: + render::ShapePlumberPointer _shapePlumber; + int _maxDrawn; // initialized by Config + bool _stateSort; +}; + class DrawStencilDeferred { public: using JobModel = render::Job::Model; diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 08ff97fd17..259dc037dd 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -65,6 +65,57 @@ void render::renderShapes(const SceneContextPointer& sceneContext, const RenderC } } +void render::renderStateSortShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, + const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems) { + auto& scene = sceneContext->_scene; + RenderArgs* args = renderContext->args; + + int numItemsToDraw = (int)inItems.size(); + if (maxDrawnItems != -1) { + numItemsToDraw = glm::min(numItemsToDraw, maxDrawnItems); + } + + using SortedPipelines = std::vector< render::ShapeKey >; + using SortedShapes = std::unordered_map< render::ShapeKey, std::vector< Item >, render::ShapeKey::Hash, render::ShapeKey::KeyEqual >; + SortedPipelines sortedPipelines; + SortedShapes sortedShapes; + std::vector< Item > ownPipelineBucket; + + + for (auto i = 0; i < numItemsToDraw; ++i) { + auto item = scene->getItem(inItems[i].id); + + { + assert(item.getKey().isShape()); + const auto& key = item.getShapeKey(); + if (key.isValid() && !key.hasOwnPipeline()) { + auto& bucket = sortedShapes[key]; + if (bucket.empty()) { + sortedPipelines.push_back(key); + } + bucket.push_back(item); + } else if (key.hasOwnPipeline()) { + ownPipelineBucket.push_back(item); + } else { + qDebug() << "Item could not be rendered: invalid key ?" << key; + } + } + } + + // THen render + for (auto& pipelineKey : sortedPipelines) { + auto& bucket = sortedShapes[pipelineKey]; + args->_pipeline = shapeContext->pickPipeline(args, pipelineKey); + for (auto& item : bucket) { + item.render(args); + } + } + args->_pipeline = nullptr; + for (auto& item : ownPipelineBucket) { + item.render(args); + } +} + void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 8a0f951028..aa564980c4 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -18,6 +18,7 @@ namespace render { void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, int maxDrawnItems = -1); void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); +void renderStateSortShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); From 1a154bb3bea72def71e2b00ecfb6533d30f5d1a8 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 19 Apr 2016 10:47:54 -0700 Subject: [PATCH 20/28] Revert the changes to use SSAO AND 2 buffers --- libraries/gl/src/gl/Config.h | 2 +- libraries/gpu/src/gpu/GLBackend.h | 3 +-- libraries/gpu/src/gpu/GLBackendTransform.cpp | 15 ++++----------- libraries/gpu/src/gpu/Transform.slh | 6 +++--- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/libraries/gl/src/gl/Config.h b/libraries/gl/src/gl/Config.h index a7d2c27db2..8f7582c271 100644 --- a/libraries/gl/src/gl/Config.h +++ b/libraries/gl/src/gl/Config.h @@ -51,7 +51,7 @@ #if (GPU_INPUT_PROFILE == GPU_CORE_43) // Deactivate SSBO for now, we've run into some issues // on GL 4.3 capable GPUs not behaving as expected -#define GPU_SSBO_DRAW_CALL_INFO +//#define GPU_SSBO_DRAW_CALL_INFO #endif diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 2175322302..b25ec42fc9 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -461,8 +461,7 @@ protected: mutable std::map _drawCallInfoOffsets; - mutable int batchNum{ 0 }; - GLuint _objectBuffer[2]; + GLuint _objectBuffer { 0 }; GLuint _cameraBuffer { 0 }; GLuint _drawCallInfoBuffer { 0 }; GLuint _objectBufferTexture { 0 }; diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 788e14ab1f..a1958d9d71 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -67,9 +67,7 @@ void GLBackend::do_setDepthRangeTransform(Batch& batch, size_t paramOffset) { } void GLBackend::initTransform() { - - glGenBuffers(2, _transform._objectBuffer); -// glGenBuffers(1, &_transform._objectBuffer); + glGenBuffers(1, &_transform._objectBuffer); glGenBuffers(1, &_transform._cameraBuffer); glGenBuffers(1, &_transform._drawCallInfoBuffer); #ifndef GPU_SSBO_DRAW_CALL_INFO @@ -82,8 +80,7 @@ void GLBackend::initTransform() { } void GLBackend::killTransform() { - glDeleteBuffers(2, _transform._objectBuffer); - // glDeleteBuffers(1, &_transform._objectBuffer); + glDeleteBuffers(1, &_transform._objectBuffer); glDeleteBuffers(1, &_transform._cameraBuffer); glDeleteBuffers(1, &_transform._drawCallInfoBuffer); #ifndef GPU_SSBO_DRAW_CALL_INFO @@ -163,10 +160,7 @@ void GLBackend::TransformStageState::transfer(const Batch& batch) const { memcpy(bufferData.data(), batch._objects.data(), byteSize); #ifdef GPU_SSBO_DRAW_CALL_INFO - batchNum++; - // glBindBuffer(GL_SHADER_STORAGE_BUFFER, _objectBuffer); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, _objectBuffer[batchNum % 2]); - //glBindBuffer(GL_SHADER_STORAGE_BUFFER, _objectBuffer); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, _objectBuffer); glBufferData(GL_SHADER_STORAGE_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); #else @@ -192,8 +186,7 @@ void GLBackend::TransformStageState::transfer(const Batch& batch) const { } #ifdef GPU_SSBO_DRAW_CALL_INFO - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, TRANSFORM_OBJECT_SLOT, _objectBuffer[batchNum % 2]); - // glBindBufferBase(GL_SHADER_STORAGE_BUFFER, TRANSFORM_OBJECT_SLOT, _objectBuffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, TRANSFORM_OBJECT_SLOT, _objectBuffer); #else glActiveTexture(GL_TEXTURE0 + TRANSFORM_OBJECT_SLOT); glBindTexture(GL_TEXTURE_BUFFER, _objectBufferTexture); diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index b7e3b0f6d3..ba006d5c73 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -83,7 +83,7 @@ struct TransformObject { layout(location=15) in ivec2 _drawCallInfo; -!> +<@if FALSE @> // Disable SSBOs for now layout(std140) buffer transformObjectBuffer { TransformObject _object[]; @@ -91,7 +91,7 @@ layout(std140) buffer transformObjectBuffer { TransformObject getTransformObject() { return _object[_drawCallInfo.x]; } - +<@else@> uniform samplerBuffer transformObjectBuffer; TransformObject getTransformObject() { @@ -109,7 +109,7 @@ TransformObject getTransformObject() { return object; } -<@endif@>!> +<@endif@> <@endfunc@> From 21b0341e505555a33314708a13525b92006f712a Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 19 Apr 2016 10:51:44 -0700 Subject: [PATCH 21/28] REmoving extra cruff --- libraries/render-utils/src/RenderDeferredTask.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index f5f411be31..5588d1ac28 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -42,15 +42,12 @@ class DrawConfig : public render::Job::Config { Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY newStats) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) - Q_PROPERTY(bool stateSort MEMBER stateSort NOTIFY dirty) - public: int getNumDrawn() { return _numDrawn; } void setNumDrawn(int numDrawn) { _numDrawn = numDrawn; emit newStats(); } int maxDrawn{ -1 }; - bool stateSort{ true }; signals: void newStats(); From 28521aa66a5b5fa4a89a4c3e962bd40b79b78fd5 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 19 Apr 2016 11:01:41 -0700 Subject: [PATCH 22/28] REmoving uneeded changes --- libraries/render/src/render/DrawTask.cpp | 5 ++--- libraries/render/src/render/Task.h | 1 - libraries/shared/src/PerfStat.cpp | 1 - libraries/shared/src/PerfStat.h | 1 - 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 82ebe74663..2f0d81db3f 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -107,10 +107,9 @@ void render::renderStateSortShapes(const SceneContextPointer& sceneContext, cons args->_pipeline = shapeContext->pickPipeline(args, pipelineKey); for (auto& item : bucket) { item.render(args); - } - } + } + } args->_pipeline = nullptr; - for (auto& item : ownPipelineBucket) { item.render(args); } diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index a4cfc55c18..300c0efd56 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -267,7 +267,6 @@ public: renderContext->jobConfig = std::static_pointer_cast(_config); if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { jobRun(_data, sceneContext, renderContext, _input.get(), _output.edit()); - } renderContext->jobConfig.reset(); } diff --git a/libraries/shared/src/PerfStat.cpp b/libraries/shared/src/PerfStat.cpp index 676d147dd5..615330e13f 100644 --- a/libraries/shared/src/PerfStat.cpp +++ b/libraries/shared/src/PerfStat.cpp @@ -147,4 +147,3 @@ void PerformanceTimer::dumpAllTimerRecords() { << "usecs over" << i.value().getCount() << "calls"; } } - diff --git a/libraries/shared/src/PerfStat.h b/libraries/shared/src/PerfStat.h index 5a66990b16..622eb1cd84 100644 --- a/libraries/shared/src/PerfStat.h +++ b/libraries/shared/src/PerfStat.h @@ -78,7 +78,6 @@ public: PerformanceTimer(const QString& name); ~PerformanceTimer(); - static bool isActive(); static void setActive(bool active); From 474d667f27fb0273fdb6ddfea80f5bbe0263d6f4 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 19 Apr 2016 11:03:35 -0700 Subject: [PATCH 23/28] One more uneeded change --- libraries/shared/src/PerfStat.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/shared/src/PerfStat.h b/libraries/shared/src/PerfStat.h index 622eb1cd84..5a66990b16 100644 --- a/libraries/shared/src/PerfStat.h +++ b/libraries/shared/src/PerfStat.h @@ -78,6 +78,7 @@ public: PerformanceTimer(const QString& name); ~PerformanceTimer(); + static bool isActive(); static void setActive(bool active); From 71edae6d7637a089b7300e924b8ff57ed1fba1c7 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 19 Apr 2016 12:38:33 -0700 Subject: [PATCH 24/28] Removing the different versions of stereo drawcall to make a simple PR --- libraries/gpu/src/gpu/GLBackend.cpp | 52 ++------------- libraries/gpu/src/gpu/GLBackend.h | 38 +---------- libraries/gpu/src/gpu/GLBackendShader.cpp | 17 +---- libraries/gpu/src/gpu/GLBackendTransform.cpp | 32 --------- libraries/gpu/src/gpu/Transform.slh | 70 -------------------- 5 files changed, 9 insertions(+), 200 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 7b6d6c0467..18aad91dcc 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -253,23 +253,11 @@ void GLBackend::render(Batch& batch) { renderPassTransfer(batch); } -#ifdef GPU_STEREO_DRAWCALL_INSTANCED - if (_stereo._enable) { - glEnable(GL_CLIP_DISTANCE0); - } -#endif - { PROFILE_RANGE(_stereo._enable ? "Render Stereo" : "Render"); renderPassDraw(batch); } -#ifdef GPU_STEREO_DRAWCALL_INSTANCED - if (_stereo._enable) { - glDisable(GL_CLIP_DISTANCE0); - } -#endif - // Restore the saved stereo state for the next batch _stereo._enable = savedStereo; } @@ -325,23 +313,13 @@ void GLBackend::syncCache() { glEnable(GL_LINE_SMOOTH); } -#ifdef GPU_STEREO_DRAWCALL_DOUBLED void GLBackend::setupStereoSide(int side) { ivec4 vp = _transform._viewport; vp.z /= 2; glViewport(vp.x + side * vp.z, vp.y, vp.z, vp.w); - -#ifdef GPU_STEREO_CAMERA_BUFFER -#ifdef GPU_STEREO_DRAWCALL_DOUBLED - glVertexAttribI1i(14, side); -#endif -#else _transform.bindCurrentCamera(side); -#endif - } -#endif void GLBackend::do_draw(Batch& batch, size_t paramOffset) { @@ -351,15 +329,11 @@ void GLBackend::do_draw(Batch& batch, size_t paramOffset) { uint32 startVertex = batch._params[paramOffset + 0]._uint; if (isStereo()) { -#ifdef GPU_STEREO_DRAWCALL_INSTANCED - glDrawArraysInstanced(mode, startVertex, numVertices, 2); -#endif -#ifdef GPU_STEREO_DRAWCALL_DOUBLED setupStereoSide(0); glDrawArrays(mode, startVertex, numVertices); setupStereoSide(1); glDrawArrays(mode, startVertex, numVertices); -#endif + _stats._DSNumTriangles += 2 * numVertices / 3; _stats._DSNumDrawcalls += 2; @@ -385,15 +359,11 @@ void GLBackend::do_drawIndexed(Batch& batch, size_t paramOffset) { GLvoid* indexBufferByteOffset = reinterpret_cast(startIndex * typeByteSize + _input._indexBufferOffset); if (isStereo()) { -#ifdef GPU_STEREO_DRAWCALL_INSTANCED - glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, 2); -#endif -#ifdef GPU_STEREO_DRAWCALL_DOUBLED setupStereoSide(0); glDrawElements(mode, numIndices, glType, indexBufferByteOffset); setupStereoSide(1); glDrawElements(mode, numIndices, glType, indexBufferByteOffset); -#endif + _stats._DSNumTriangles += 2 * numIndices / 3; _stats._DSNumDrawcalls += 2; } else { @@ -417,15 +387,11 @@ void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) { if (isStereo()) { GLint trueNumInstances = (isStereo() ? 2 * numInstances : numInstances); -#ifdef GPU_STEREO_DRAWCALL_INSTANCED - glDrawArraysInstancedARB(mode, startVertex, numVertices, trueNumInstances); -#endif -#ifdef GPU_STEREO_DRAWCALL_DOUBLED setupStereoSide(0); glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances); setupStereoSide(1); glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances); -#endif + _stats._DSNumTriangles += (trueNumInstances * numVertices) / 3; _stats._DSNumDrawcalls += trueNumInstances; } else { @@ -464,23 +430,15 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) { if (isStereo()) { GLint trueNumInstances = (isStereo() ? 2 * numInstances : numInstances); -#ifdef GPU_STEREO_DRAWCALL_INSTANCED - glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances, 0, startInstance); -#endif -#ifdef GPU_STEREO_DRAWCALL_DOUBLED setupStereoSide(0); glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); setupStereoSide(1); glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); -#endif + _stats._DSNumTriangles += (trueNumInstances * numIndices) / 3; _stats._DSNumDrawcalls += trueNumInstances; } else { -#if (GPU_INPUT_PROFILE == GPU_CORE_43) - glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); -#else - glDrawElementsInstanced(mode, numIndices, glType, indexBufferByteOffset, numInstances); -#endif + glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); _stats._DSNumTriangles += (numInstances * numIndices) / 3; _stats._DSNumDrawcalls += numInstances; } diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 7683b01425..38475d415a 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -23,27 +23,6 @@ #include "Context.h" -// Pick one from the 3: THis version is the most efficient as of now -#define GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE -//#define GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER -//#define GPU_STEREO_TECHNIQUE_INSTANCED - - -// Let these be configured by the one define picked above -#ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE -#define GPU_STEREO_DRAWCALL_DOUBLED -#endif - -#ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER -#define GPU_STEREO_DRAWCALL_DOUBLED -#define GPU_STEREO_CAMERA_BUFFER -#endif - -#ifdef GPU_STEREO_TECHNIQUE_INSTANCED -#define GPU_STEREO_DRAWCALL_INSTANCED -#define GPU_STEREO_CAMERA_BUFFER -#endif - namespace gpu { class GLTextureTransferHelper; @@ -177,7 +156,6 @@ public: public: enum Version { Mono = 0, - Stereo, NumVersions }; @@ -205,7 +183,7 @@ public: } GLint getUniformLocation(GLint srcLoc, Version version = Mono) { - // THIS will be used in the next PR + // THIS will be used in the future PR as we grow the number of versions // return _uniformMappings[version][srcLoc]; return srcLoc; } @@ -348,9 +326,7 @@ protected: void renderPassTransfer(Batch& batch); void renderPassDraw(Batch& batch); -#ifdef GPU_STEREO_DRAWCALL_DOUBLED void setupStereoSide(int side); -#endif void initTextureTransferHelper(); static void transferGPUObject(const TexturePointer& texture); @@ -434,19 +410,7 @@ protected: void resetTransformStage(); struct TransformStageState { -#ifdef GPU_STEREO_CAMERA_BUFFER - struct Cameras { - TransformCamera _cams[2]; - - Cameras() {}; - Cameras(const TransformCamera& cam) { memcpy(_cams, &cam, sizeof(TransformCamera)); }; - Cameras(const TransformCamera& camL, const TransformCamera& camR) { memcpy(_cams, &camL, sizeof(TransformCamera)); memcpy(_cams + 1, &camR, sizeof(TransformCamera)); }; - }; - - using CameraBufferElement = Cameras; -#else using CameraBufferElement = TransformCamera; -#endif using TransformCameras = std::vector; TransformCamera _camera; diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 6feaee94ed..bb538038f3 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -312,24 +312,13 @@ GLBackend::GLShader* compileBackendShader(const Shader& shader) { // Domain specific defines const std::string domainDefines[NUM_SHADER_DOMAINS] = { - "#define VERTEX_SHADER", - "#define PIXEL_SHADER" + "#define GPU_VERTEX_SHADER", + "#define GPU_PIXEL_SHADER" }; // Versions specific of the shader -#ifdef GPU_STEREO_DRAWCALL_INSTANCED - const std::string stereoVersion("#define GPU_TRANSFORM_IS_STEREO\n#define GPU_TRANSFORM_STEREO_CAMERA\n#define GPU_TRANSFORM_STEREO_CAMERA_INSTANCED\n#define GPU_TRANSFORM_STEREO_SPLIT_SCREEN"); -#endif -#ifdef GPU_STEREO_DRAWCALL_DOUBLED -#ifdef GPU_STEREO_CAMERA_BUFFER - const std::string stereoVersion("#define GPU_TRANSFORM_IS_STEREO\n#define GPU_TRANSFORM_STEREO_CAMERA\n#define GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED"); -#else - const std::string stereoVersion("#define GPU_TRANSFORM_IS_STEREO"); -#endif -#endif const std::string versionDefines[GLBackend::GLShader::NumVersions] = { - "", - stereoVersion + "" }; GLBackend::GLShader::ShaderObjects shaderObjects; diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index a1958d9d71..fa54acf72c 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -31,25 +31,10 @@ void GLBackend::do_setProjectionTransform(Batch& batch, size_t paramOffset) { void GLBackend::do_setViewportTransform(Batch& batch, size_t paramOffset) { memcpy(&_transform._viewport, batch.editData(batch._params[paramOffset]._uint), sizeof(Vec4i)); -#ifdef GPU_STEREO_DRAWCALL_INSTANCED - { - ivec4& vp = _transform._viewport; - glViewport(vp.x, vp.y, vp.z, vp.w); - - // Where we assign the GL viewport - if (_stereo._enable) { - vp.z /= 2; - if (_stereo._pass) { - vp.x += vp.z; - } - } - } -#else if (!_inRenderTransferPass && !isStereo()) { ivec4& vp = _transform._viewport; glViewport(vp.x, vp.y, vp.z, vp.w); } -#endif // The Viewport is tagged invalid because the CameraTransformUBO is not up to date and will need update on next drawcall _transform._invalidViewport = true; @@ -121,18 +106,10 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo size_t offset = _cameraUboSize * _cameras.size(); _cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset)); if (stereo._enable) { -#ifdef GPU_STEREO_CAMERA_BUFFER - _cameras.push_back(CameraBufferElement(_camera.getEyeCamera(0, stereo, _view), _camera.getEyeCamera(1, stereo, _view))); -#else _cameras.push_back((_camera.getEyeCamera(0, stereo, _view))); _cameras.push_back((_camera.getEyeCamera(1, stereo, _view))); -#endif } else { -#ifdef GPU_STEREO_CAMERA_BUFFER - _cameras.push_back(CameraBufferElement(_camera.recomputeDerived(_view))); -#else _cameras.push_back((_camera.recomputeDerived(_view))); -#endif } } @@ -206,13 +183,9 @@ void GLBackend::TransformStageState::update(size_t commandIndex, const StereoSta } if (offset != INVALID_OFFSET) { -#ifdef GPU_STEREO_CAMERA_BUFFER - bindCurrentCamera(0); -#else if (!stereo._enable) { bindCurrentCamera(0); } -#endif } (void)CHECK_GL_ERROR(); } @@ -236,12 +209,7 @@ void GLBackend::updateTransform(const Batch& batch) { glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer); glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0, _transform._drawCallInfoOffsets[batch._currentNamedCall]); - -#ifdef GPU_STEREO_DRAWCALL_INSTANCED - glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, (isStereo() ? 2 : 1)); -#else glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, 1); -#endif } (void)CHECK_GL_ERROR(); diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index ba006d5c73..078b19d494 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -21,56 +21,11 @@ struct TransformCamera { }; layout(std140) uniform transformCameraBuffer { -#ifdef GPU_TRANSFORM_IS_STEREO -#ifdef GPU_TRANSFORM_STEREO_CAMERA - TransformCamera _camera[2]; -#else TransformCamera _camera; -#endif -#else - TransformCamera _camera; -#endif }; -#ifdef VERTEX_SHADER -#ifdef GPU_TRANSFORM_IS_STEREO - -#ifdef GPU_TRANSFORM_STEREO_CAMERA -#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED -layout(location=14) in int _inStereoSide; -#endif - -flat out int _stereoSide; -#endif - -#endif - -#endif - -#ifdef PIXEL_SHADER -#ifdef GPU_TRANSFORM_STEREO_CAMERA -flat in int _stereoSide; -#endif -#endif - TransformCamera getTransformCamera() { -#ifdef GPU_TRANSFORM_IS_STEREO - #ifdef GPU_TRANSFORM_STEREO_CAMERA - #ifdef VERTEX_SHADER - #ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED - _stereoSide = _inStereoSide; - #endif - #ifdef GPU_TRANSFORM_STEREO_CAMERA_INSTANCED - _stereoSide = gl_InstanceID % 2; - #endif - #endif - return _camera[_stereoSide]; - #else - return _camera; - #endif -#else return _camera; -#endif } <@endfunc@> @@ -122,25 +77,6 @@ TransformObject getTransformObject() { <$viewport$> = <$cameraTransform$>._viewport; <@endfunc@> -<@func transformStereoClipsSpace(cameraTransform, clipPos)@> - { -#ifdef GPU_TRANSFORM_IS_STEREO - -#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN - vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1)); - vec2 eyeOffsetScale = vec2(-0.5, +0.5); - uint eyeIndex = _stereoSide; - gl_ClipDistance[0] = dot(<$clipPos$>, eyeClipEdge[eyeIndex]); - float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w; - <$clipPos$>.x = newClipPosX; -#endif - -#else -#endif - } -<@endfunc@> - - <@func transformModelToEyeWorldAlignedPos(cameraTransform, objectTransform, modelPos, eyeWorldAlignedPos)@> { // _transformModelToEyeWorldAlignedPos @@ -157,8 +93,6 @@ TransformObject getTransformObject() { <$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$> <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos; - - <$transformStereoClipsSpace($cameraTransform$, $clipPos$)$> } <@endfunc@> @@ -168,8 +102,6 @@ TransformObject getTransformObject() { <$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$> <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos; <$eyePos$> = vec4((<$cameraTransform$>._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0); - - <$transformStereoClipsSpace($cameraTransform$, $clipPos$)$> } <@endfunc@> @@ -217,8 +149,6 @@ TransformObject getTransformObject() { <@func transformEyeToClipPos(cameraTransform, eyePos, clipPos)@> { // transformEyeToClipPos <$clipPos$> = <$cameraTransform$>._projection * vec4(<$eyePos$>.xyz, 1.0); - - <$transformStereoClipsSpace($cameraTransform$, $clipPos$)$> } <@endfunc@> From 4c2cdc8704e2bd9c1d7ef0ec2f58442cbe63174e Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 19 Apr 2016 12:46:56 -0700 Subject: [PATCH 25/28] A bit more clean up --- libraries/gpu/src/gpu/GLBackend.cpp | 6 ++---- libraries/gpu/src/gpu/GLBackendInput.cpp | 5 ----- libraries/model/src/model/skybox.slv | 2 -- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 18aad91dcc..298040c8b4 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -517,11 +517,9 @@ void GLBackend::resetStages() { #define ADD_COMMAND_GL(call) _commands.push_back(COMMAND_##call); _commandOffsets.push_back(_params.size()); -#ifdef GPU_STEREO_CAMERA_BUFFER -#define GET_UNIFORM_LOCATION(shaderUniformLoc) _pipeline._programShader->getUniformLocation(shaderUniformLoc, isStereo()) -#else +// As long as we don;t use several versions of shaders we can avoid this more complex code path +// #define GET_UNIFORM_LOCATION(shaderUniformLoc) _pipeline._programShader->getUniformLocation(shaderUniformLoc, isStereo()); #define GET_UNIFORM_LOCATION(shaderUniformLoc) shaderUniformLoc -#endif 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 diff --git a/libraries/gpu/src/gpu/GLBackendInput.cpp b/libraries/gpu/src/gpu/GLBackendInput.cpp index 8ab5d81be1..1bb7a9b5db 100755 --- a/libraries/gpu/src/gpu/GLBackendInput.cpp +++ b/libraries/gpu/src/gpu/GLBackendInput.cpp @@ -243,12 +243,7 @@ void GLBackend::updateInput() { for (size_t locNum = 0; locNum < locationCount; ++locNum) { glVertexAttribPointer(slot + (GLuint)locNum, count, type, isNormalized, stride, reinterpret_cast(pointer + perLocationStride * (GLuint)locNum)); - -#ifdef GPU_STEREO_DRAWCALL_INSTANCED - glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency * (isStereo() ? 2 : 1)); -#else glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency); -#endif } // TODO: Support properly the IAttrib version diff --git a/libraries/model/src/model/skybox.slv b/libraries/model/src/model/skybox.slv index b78bb632fa..810afb1033 100755 --- a/libraries/model/src/model/skybox.slv +++ b/libraries/model/src/model/skybox.slv @@ -36,6 +36,4 @@ void main(void) { // Position is supposed to come in clip space gl_Position = vec4(inPosition.xy, 0.0, 1.0); - - <$transformStereoClipsSpace(cam, gl_Position)$> } \ No newline at end of file From f2f092e9c8f44f94a6ee8e273f18085c275c61b4 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 20 Apr 2016 15:42:30 -0700 Subject: [PATCH 26/28] Cleanup thanks to review --- libraries/gpu/src/gpu/GLBackend.cpp | 4 ++-- libraries/gpu/src/gpu/GLBackendInput.cpp | 4 ---- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 4 ---- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 298040c8b4..0c5a0cfb42 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -385,7 +385,7 @@ void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) { if (isStereo()) { - GLint trueNumInstances = (isStereo() ? 2 * numInstances : numInstances); + GLint trueNumInstances = 2 * numInstances; setupStereoSide(0); glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances); @@ -428,7 +428,7 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) { GLvoid* indexBufferByteOffset = reinterpret_cast(startIndex * typeByteSize + _input._indexBufferOffset); if (isStereo()) { - GLint trueNumInstances = (isStereo() ? 2 * numInstances : numInstances); + GLint trueNumInstances = 2 * numInstances; setupStereoSide(0); glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); diff --git a/libraries/gpu/src/gpu/GLBackendInput.cpp b/libraries/gpu/src/gpu/GLBackendInput.cpp index 1bb7a9b5db..75f4be3cbe 100755 --- a/libraries/gpu/src/gpu/GLBackendInput.cpp +++ b/libraries/gpu/src/gpu/GLBackendInput.cpp @@ -120,11 +120,7 @@ void GLBackend::updateInput() { glVertexAttribFormat(slot + locNum, count, type, isNormalized, offset + locNum * perLocationSize); glVertexAttribBinding(slot + locNum, attrib._channel); } -#ifdef GPU_STEREO_DRAWCALL_INSTANCED - glVertexBindingDivisor(attrib._channel, attrib._frequency * (isStereo() ? 2 : 1)); -#else glVertexBindingDivisor(attrib._channel, attrib._frequency); -#endif } (void) CHECK_GL_ERROR(); } diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index ccf38ec071..0b539f75b9 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -85,11 +85,7 @@ void GLBackend::do_setPipeline(Batch& batch, size_t paramOffset) { // check the program cache // pick the program version -#ifdef GPU_STEREO_CAMERA_BUFFER - GLuint glprogram = pipelineObject->_program->getProgram(isStereo()); -#else GLuint glprogram = pipelineObject->_program->getProgram(); -#endif if (_pipeline._program != glprogram) { _pipeline._program = glprogram; From 2bc8191fa628b49492e1f02c6c5d4ddbe5ae94b8 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 20 Apr 2016 18:04:11 -0700 Subject: [PATCH 27/28] one more comment from review --- libraries/gpu/src/gpu/GLBackend.h | 3 ++- libraries/gpu/src/gpu/GLBackendTransform.cpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 38475d415a..bf94cf9b87 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -320,6 +320,7 @@ public: void do_setStateColorWriteMask(uint32 mask); protected: + static const size_t INVALID_OFFSET = (size_t)-1; bool _inRenderTransferPass; @@ -435,7 +436,7 @@ protected: using List = std::list; List _cameraOffsets; mutable List::const_iterator _camerasItr; - mutable size_t _currentCameraOffset; + mutable size_t _currentCameraOffset{ INVALID_OFFSET }; void preUpdate(size_t commandIndex, const StereoState& stereo); void update(size_t commandIndex, const StereoState& stereo) const; diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index fa54acf72c..ae8f28fbe3 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -171,8 +171,10 @@ void GLBackend::TransformStageState::transfer(const Batch& batch) const { #endif CHECK_GL_ERROR(); + + // Make sure the current Camera offset is unknown before render Draw + _currentCameraOffset = INVALID_OFFSET; } -static const size_t INVALID_OFFSET = (size_t)-1; void GLBackend::TransformStageState::update(size_t commandIndex, const StereoState& stereo) const { size_t offset = INVALID_OFFSET; From 018196a0702a400aadadc693b679d7653395f3b8 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 21 Apr 2016 09:58:36 -0700 Subject: [PATCH 28/28] One more review comment --- libraries/gpu/src/gpu/GLBackend.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 0c5a0cfb42..011d0f8e70 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -406,9 +406,7 @@ void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) { void glbackend_glDrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex, GLuint baseinstance) { #if (GPU_INPUT_PROFILE == GPU_CORE_43) - //glDrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, primcount, basevertex, baseinstance); - glDrawElementsInstanced(mode, count, type, indices, primcount); - + glDrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, primcount, basevertex, baseinstance); #else glDrawElementsInstanced(mode, count, type, indices, primcount); #endif