diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 90c5d32449..ffd7cc703b 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -386,8 +386,11 @@ bool AudioMixer::prepareMixForListeningNode(Node* node) { // loop through all other nodes that have sufficient audio to mix DependencyManager::get()->eachNode([&](const SharedNodePointer& otherNode){ - // make sure that we have audio data for this other node and that it isn't being ignored by our listening node - if (otherNode->getLinkedData() && !node->isIgnoringNodeWithID(otherNode->getUUID())) { + // make sure that we have audio data for this other node + // and that it isn't being ignored by our listening node + // and that it isn't ignoring our listening node + if (otherNode->getLinkedData() + && !node->isIgnoringNodeWithID(otherNode->getUUID()) && !otherNode->isIgnoringNodeWithID(node->getUUID())) { AudioMixerClientData* otherNodeClientData = (AudioMixerClientData*) otherNode->getLinkedData(); // enumerate the ARBs attached to the otherNode and add all that should be added to mix diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 041449dc57..2c9fadc7b1 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -230,9 +230,11 @@ void AvatarMixer::broadcastAvatarData() { [&](const SharedNodePointer& otherNode)->bool { // make sure we have data for this avatar, that it isn't the same node, // and isn't an avatar that the viewing node has ignored + // or that has ignored the viewing node if (!otherNode->getLinkedData() || otherNode->getUUID() == node->getUUID() - || node->isIgnoringNodeWithID(otherNode->getUUID())) { + || node->isIgnoringNodeWithID(otherNode->getUUID()) + || otherNode->isIgnoringNodeWithID(node->getUUID())) { return false; } else { return true; diff --git a/interface/resources/images/steam-min-spec-failed.png b/interface/resources/images/steam-min-spec-failed.png index 99abac9e1c..0061167a92 100644 Binary files a/interface/resources/images/steam-min-spec-failed.png and b/interface/resources/images/steam-min-spec-failed.png differ diff --git a/libraries/gl/src/gl/OpenGLVersionChecker.cpp b/libraries/gl/src/gl/OpenGLVersionChecker.cpp index 428bf86c6f..371f9ed2dc 100644 --- a/libraries/gl/src/gl/OpenGLVersionChecker.cpp +++ b/libraries/gl/src/gl/OpenGLVersionChecker.cpp @@ -50,7 +50,7 @@ QJsonObject OpenGLVersionChecker::checkVersion(bool& valid, bool& override) { valid = true; override = false; - QGLWidget* glWidget = new QGLWidget(); + QGLWidget* glWidget = new QGLWidget(getDefaultGLFormat()); valid = glWidget->isValid(); // Inform user if no OpenGL support if (!valid) { diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index 3513d7a05b..719989a07a 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -307,11 +307,20 @@ void GLBackend::render(const 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; } @@ -326,13 +335,24 @@ 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 + } +#else +#endif void GLBackend::do_resetStages(const Batch& batch, size_t paramOffset) { resetStages(); @@ -385,8 +405,11 @@ void GLBackend::do_popProfileRange(const Batch& batch, size_t paramOffset) { // term strategy is to get rid of any GL calls in favor of the HIFI GPU API // 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()); +#ifdef GPU_STEREO_CAMERA_BUFFER +#define GET_UNIFORM_LOCATION(shaderUniformLoc) _pipeline._programShader->getUniformLocation(shaderUniformLoc, (GLShader::Version) isStereo()) +#else #define GET_UNIFORM_LOCATION(shaderUniformLoc) shaderUniformLoc +#endif void GLBackend::do_glUniform1i(const Batch& batch, size_t paramOffset) { if (_pipeline._program == 0) { diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.h b/libraries/gpu-gl/src/gpu/gl/GLBackend.h index ef4b75bd75..950ac65a3f 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.h @@ -29,6 +29,29 @@ #include "GLShared.h" + +// Different versions for the stereo drawcall +// Current preferred is "instanced" which draw the shape twice but instanced and rely on clipping plane to draw left/right side only +//#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 { namespace gl { class GLBackend : public Backend, public std::enable_shared_from_this { @@ -206,7 +229,10 @@ protected: void renderPassTransfer(const Batch& batch); void renderPassDraw(const Batch& batch); + +#ifdef GPU_STEREO_DRAWCALL_DOUBLED void setupStereoSide(int side); +#endif virtual void initInput() final; virtual void killInput() final; @@ -271,7 +297,19 @@ protected: }; 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; @@ -372,8 +410,8 @@ protected: void resetQueryStage(); struct QueryStageState { - - }; + uint32_t _rangeQueryDepth { 0 }; + } _queryStage; void resetStages(); diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendInput.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendInput.cpp index 7be6c9c401..cac214b01e 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendInput.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendInput.cpp @@ -154,3 +154,4 @@ void GLBackend::do_setIndirectBuffer(const Batch& batch, size_t paramOffset) { (void)CHECK_GL_ERROR(); } + diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp index ed0b9607e6..81d38c3339 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp @@ -48,7 +48,13 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) { // check the program cache // pick the program version + // check the program cache + // pick the program version +#ifdef GPU_STEREO_CAMERA_BUFFER + GLuint glprogram = pipelineObject->_program->getProgram((GLShader::Version) isStereo()); +#else GLuint glprogram = pipelineObject->_program->getProgram(); +#endif if (_pipeline._program != glprogram) { _pipeline._program = glprogram; diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp index 19d008da2c..06848aa563 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendQuery.cpp @@ -16,8 +16,10 @@ using namespace gpu::gl; // Eventually, we want to test with TIME_ELAPSED instead of TIMESTAMP #ifdef Q_OS_MAC +const uint32_t MAX_RANGE_QUERY_DEPTH = 1; static bool timeElapsed = true; #else +const uint32_t MAX_RANGE_QUERY_DEPTH = 10000; static bool timeElapsed = false; #endif @@ -25,12 +27,16 @@ void GLBackend::do_beginQuery(const Batch& batch, size_t paramOffset) { auto query = batch._queries.get(batch._params[paramOffset]._uint); GLQuery* glquery = syncGPUObject(*query); if (glquery) { + ++_queryStage._rangeQueryDepth; glGetInteger64v(GL_TIMESTAMP, (GLint64*)&glquery->_batchElapsedTime); if (timeElapsed) { - glBeginQuery(GL_TIME_ELAPSED, glquery->_endqo); + if (_queryStage._rangeQueryDepth <= MAX_RANGE_QUERY_DEPTH) { + glBeginQuery(GL_TIME_ELAPSED, glquery->_endqo); + } } else { glQueryCounter(glquery->_beginqo, GL_TIMESTAMP); } + glquery->_rangeQueryDepth = _queryStage._rangeQueryDepth; (void)CHECK_GL_ERROR(); } } @@ -40,10 +46,13 @@ void GLBackend::do_endQuery(const Batch& batch, size_t paramOffset) { GLQuery* glquery = syncGPUObject(*query); if (glquery) { if (timeElapsed) { - glEndQuery(GL_TIME_ELAPSED); + if (_queryStage._rangeQueryDepth <= MAX_RANGE_QUERY_DEPTH) { + glEndQuery(GL_TIME_ELAPSED); + } } else { glQueryCounter(glquery->_endqo, GL_TIMESTAMP); } + --_queryStage._rangeQueryDepth; GLint64 now; glGetInteger64v(GL_TIMESTAMP, &now); glquery->_batchElapsedTime = now - glquery->_batchElapsedTime; @@ -55,20 +64,24 @@ void GLBackend::do_endQuery(const Batch& batch, size_t paramOffset) { void GLBackend::do_getQuery(const Batch& batch, size_t paramOffset) { auto query = batch._queries.get(batch._params[paramOffset]._uint); GLQuery* glquery = syncGPUObject(*query); - if (glquery) { - glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT_AVAILABLE, &glquery->_result); - if (glquery->_result == GL_TRUE) { - if (timeElapsed) { - glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT, &glquery->_result); - } else { - GLuint64 start, end; - glGetQueryObjectui64v(glquery->_beginqo, GL_QUERY_RESULT, &start); - glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT, &end); - glquery->_result = end - start; - } + if (glquery) { + if (glquery->_rangeQueryDepth > MAX_RANGE_QUERY_DEPTH) { query->triggerReturnHandler(glquery->_result, glquery->_batchElapsedTime); + } else { + glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT_AVAILABLE, &glquery->_result); + if (glquery->_result == GL_TRUE) { + if (timeElapsed) { + glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT, &glquery->_result); + } else { + GLuint64 start, end; + glGetQueryObjectui64v(glquery->_beginqo, GL_QUERY_RESULT, &start); + glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT, &end); + glquery->_result = end - start; + } + query->triggerReturnHandler(glquery->_result, glquery->_batchElapsedTime); + } + (void)CHECK_GL_ERROR(); } - (void)CHECK_GL_ERROR(); } } diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp index 369785b4f1..f3da18ba1d 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp @@ -31,10 +31,25 @@ void GLBackend::do_setProjectionTransform(const Batch& batch, size_t paramOffset void GLBackend::do_setViewportTransform(const Batch& batch, size_t paramOffset) { memcpy(&_transform._viewport, batch.readData(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; @@ -103,13 +118,21 @@ 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) { - _cameras.push_back((_camera.getEyeCamera(0, stereo, _view))); - _cameras.push_back((_camera.getEyeCamera(1, stereo, _view))); - } else { - _cameras.push_back((_camera.recomputeDerived(_view))); - } + 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 + } } // Flags are clean @@ -125,9 +148,13 @@ 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(); } @@ -138,7 +165,6 @@ void GLBackend::TransformStageState::bindCurrentCamera(int eye) const { } } - void GLBackend::resetTransformStage() { glDisableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); _transform._enabledDrawcallInfoBuffer = false; diff --git a/libraries/gpu-gl/src/gpu/gl/GLQuery.h b/libraries/gpu-gl/src/gpu/gl/GLQuery.h index bf10d002e6..1f6922963e 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLQuery.h +++ b/libraries/gpu-gl/src/gpu/gl/GLQuery.h @@ -49,6 +49,7 @@ public: const GLuint _beginqo = { 0 }; GLuint64 _result { (GLuint64)-1 }; GLuint64 _batchElapsedTime { (GLuint64) 0 }; + uint32_t _rangeQueryDepth { 0 }; protected: GLQuery(const std::weak_ptr& backend, const Query& query, GLuint endId, GLuint beginId) : Parent(backend, query, endId), _beginqo(beginId) {} diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp index f8d493c25b..23439a640a 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp @@ -54,9 +54,24 @@ static const std::array DOMAIN_DEFINES { { "#define GPU_GEOMETRY_SHADER", } }; +// Stereo specific defines +static const std::string stereoVersion { +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + "#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 + "#define GPU_TRANSFORM_IS_STEREO\n#define GPU_TRANSFORM_STEREO_CAMERA\n#define GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED" +#else + "#define GPU_TRANSFORM_IS_STEREO" +#endif +#endif +}; + // Versions specific of the shader static const std::array VERSION_DEFINES { { - "" + "", + stereoVersion } }; GLShader* compileBackendShader(GLBackend& backend, const Shader& shader) { @@ -181,7 +196,8 @@ bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::Bin // Define the public slots only from the default version if (version == 0) { shader.defineSlots(uniforms, buffers, textures, samplers, inputs, outputs); - } else { + } // else + { GLShader::UniformMapping mapping; for (auto srcUniform : shader.getUniforms()) { mapping[srcUniform._location] = uniforms.findLocation(srcUniform._name); diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.h b/libraries/gpu-gl/src/gpu/gl/GLShader.h index e75e96cf16..40dd0b7be9 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.h +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.h @@ -19,6 +19,8 @@ public: enum Version { Mono = 0, + Stereo, + NumVersions }; @@ -40,8 +42,8 @@ public: GLint getUniformLocation(GLint srcLoc, Version version = Mono) { // THIS will be used in the future PR as we grow the number of versions - // return _uniformMappings[version][srcLoc]; - return srcLoc; + return _uniformMappings[version][srcLoc]; + // return srcLoc; } const std::weak_ptr _backend; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp index 6c2b2f434e..a87d0ad6b8 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.cpp @@ -25,11 +25,14 @@ void GL41Backend::do_draw(const Batch& batch, size_t paramOffset) { uint32 startVertex = batch._params[paramOffset + 0]._uint; if (isStereo()) { +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawArraysInstanced(mode, startVertex, numVertices, 2); +#else setupStereoSide(0); glDrawArrays(mode, startVertex, numVertices); setupStereoSide(1); glDrawArrays(mode, startVertex, numVertices); - +#endif _stats._DSNumTriangles += 2 * numVertices / 3; _stats._DSNumDrawcalls += 2; @@ -55,11 +58,14 @@ void GL41Backend::do_drawIndexed(const 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); +#else setupStereoSide(0); glDrawElements(mode, numIndices, glType, indexBufferByteOffset); setupStereoSide(1); glDrawElements(mode, numIndices, glType, indexBufferByteOffset); - +#endif _stats._DSNumTriangles += 2 * numIndices / 3; _stats._DSNumDrawcalls += 2; } else { @@ -83,11 +89,14 @@ void GL41Backend::do_drawInstanced(const Batch& batch, size_t paramOffset) { if (isStereo()) { GLint trueNumInstances = 2 * numInstances; +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawArraysInstanced(mode, startVertex, numVertices, trueNumInstances); +#else setupStereoSide(0); - glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances); + glDrawArraysInstanced(mode, startVertex, numVertices, numInstances); setupStereoSide(1); - glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances); - + glDrawArraysInstanced(mode, startVertex, numVertices, numInstances); +#endif _stats._DSNumTriangles += (trueNumInstances * numVertices) / 3; _stats._DSNumDrawcalls += trueNumInstances; } else { @@ -124,10 +133,14 @@ void GL41Backend::do_drawIndexedInstanced(const Batch& batch, size_t paramOffset if (isStereo()) { GLint trueNumInstances = 2 * numInstances; +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glbackend_glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances, 0, startInstance); +#else 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; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp index 376b9e1c2f..638841b170 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp @@ -101,7 +101,11 @@ void GL41Backend::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-gl/src/gpu/gl41/GL41BackendTransform.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTransform.cpp index 21ea906ec8..aa0a83689c 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTransform.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTransform.cpp @@ -96,7 +96,11 @@ void GL41Backend::updateTransform(const Batch& batch) { if (!_transform._enabledDrawcallInfoBuffer) { glEnableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is enabled glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer); +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, (isStereo() ? 2 : 1)); +#else glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, 1); +#endif _transform._enabledDrawcallInfoBuffer = true; } glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0, _transform._drawCallInfoOffsets[batch._currentNamedCall]); diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp index bae6326e8f..d7dde8b7d6 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp @@ -25,10 +25,14 @@ void GL45Backend::do_draw(const Batch& batch, size_t paramOffset) { uint32 startVertex = batch._params[paramOffset + 0]._uint; if (isStereo()) { +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawArraysInstanced(mode, startVertex, numVertices, 2); +#else setupStereoSide(0); glDrawArrays(mode, startVertex, numVertices); setupStereoSide(1); glDrawArrays(mode, startVertex, numVertices); +#endif _stats._DSNumTriangles += 2 * numVertices / 3; _stats._DSNumDrawcalls += 2; @@ -55,11 +59,14 @@ void GL45Backend::do_drawIndexed(const 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); +#else setupStereoSide(0); glDrawElements(mode, numIndices, glType, indexBufferByteOffset); setupStereoSide(1); glDrawElements(mode, numIndices, glType, indexBufferByteOffset); - +#endif _stats._DSNumTriangles += 2 * numIndices / 3; _stats._DSNumDrawcalls += 2; } else { @@ -83,10 +90,14 @@ void GL45Backend::do_drawInstanced(const Batch& batch, size_t paramOffset) { if (isStereo()) { GLint trueNumInstances = 2 * numInstances; +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawArraysInstanced(mode, startVertex, numVertices, trueNumInstances); +#else setupStereoSide(0); glDrawArraysInstanced(mode, startVertex, numVertices, numInstances); setupStereoSide(1); glDrawArraysInstanced(mode, startVertex, numVertices, numInstances); +#endif _stats._DSNumTriangles += (trueNumInstances * numVertices) / 3; _stats._DSNumDrawcalls += trueNumInstances; @@ -112,10 +123,15 @@ void GL45Backend::do_drawIndexedInstanced(const Batch& batch, size_t paramOffset if (isStereo()) { GLint trueNumInstances = 2 * numInstances; + +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, trueNumInstances, 0, startInstance); +#else setupStereoSide(0); glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); setupStereoSide(1); glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance); +#endif _stats._DSNumTriangles += (trueNumInstances * numIndices) / 3; _stats._DSNumDrawcalls += trueNumInstances; } else { diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp index 694bbe6f9c..25f8c83074 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp @@ -72,9 +72,14 @@ void GL45Backend::updateInput() { assert(frequency == attrib._frequency); } + (void)CHECK_GL_ERROR(); } +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glVertexBindingDivisor(bufferChannelNum, frequency * (isStereo() ? 2 : 1)); +#else glVertexBindingDivisor(bufferChannelNum, frequency); +#endif } diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTransform.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTransform.cpp index edd23b1d4c..57862eb983 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTransform.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTransform.cpp @@ -84,7 +84,11 @@ void GL45Backend::updateTransform(const Batch& batch) { glEnableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is enabled glVertexAttribIFormat(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0); glVertexAttribBinding(gpu::Stream::DRAW_CALL_INFO, gpu::Stream::DRAW_CALL_INFO); +#ifdef GPU_STEREO_DRAWCALL_INSTANCED + glVertexBindingDivisor(gpu::Stream::DRAW_CALL_INFO, (isStereo() ? 2 : 1)); +#else glVertexBindingDivisor(gpu::Stream::DRAW_CALL_INFO, 1); +#endif _transform._enabledDrawcallInfoBuffer = true; } // NOTE: A stride of zero in BindVertexBuffer signifies that all elements are sourced from the same location, diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 12a1cd10f1..db7808e781 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -22,29 +22,84 @@ 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 GPU_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 GPU_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 GPU_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 } vec3 getEyeWorldPos() { - return _camera._viewInverse[3].xyz; + return getTransformCamera()._viewInverse[3].xyz; } - bool cam_isStereo() { +#ifdef GPU_TRANSFORM_IS_STEREO + return getTransformCamera()._stereoInfo.x > 0.0; +#else return _camera._stereoInfo.x > 0.0; +#endif } float cam_getStereoSide() { +#ifdef GPU_TRANSFORM_IS_STEREO +#ifdef GPU_TRANSFORM_STEREO_CAMERA + return getTransformCamera()._stereoInfo.y; +#else return _camera._stereoInfo.y; +#endif +#else + return _camera._stereoInfo.y; +#endif } <@endfunc@> - <@func declareStandardObjectTransform()@> struct TransformObject { mat4 _model; @@ -92,6 +147,25 @@ 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 @@ -108,6 +182,8 @@ TransformObject getTransformObject() { <$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$> <$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos; + + <$transformStereoClipsSpace($cameraTransform$, $clipPos$)$> } <@endfunc@> @@ -117,6 +193,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@> @@ -135,11 +213,10 @@ TransformObject getTransformObject() { <@endfunc@> <@func transformModelToWorldDir(cameraTransform, objectTransform, modelDir, worldDir)@> - { // transformModelToEyeDir + { // transformModelToEyeDir vec3 mr0 = <$objectTransform$>._modelInverse[0].xyz; vec3 mr1 = <$objectTransform$>._modelInverse[1].xyz; vec3 mr2 = <$objectTransform$>._modelInverse[2].xyz; - <$worldDir$> = vec3(dot(mr0, <$modelDir$>), dot(mr1, <$modelDir$>), dot(mr2, <$modelDir$>)); } <@endfunc@> @@ -173,6 +250,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 5df1aa0a4a..6fd9532fa1 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)$> } diff --git a/libraries/render-utils/src/deferred_light_limited.slv b/libraries/render-utils/src/deferred_light_limited.slv index 0525509f0b..36e281ab5b 100644 --- a/libraries/render-utils/src/deferred_light_limited.slv +++ b/libraries/render-utils/src/deferred_light_limited.slv @@ -24,7 +24,7 @@ out vec4 _texCoord0; void main(void) { if (sphereParam.w != 0.0) { - + // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); @@ -33,9 +33,14 @@ void main(void) { vec4 projected = gl_Position / gl_Position.w; projected.xy = (projected.xy + 1.0) * 0.5; +#ifdef GPU_TRANSFORM_IS_STEREO +#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN +#else if (cam_isStereo()) { projected.x = 0.5 * (projected.x + cam_getStereoSide()); } +#endif +#endif _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; } else { const float depth = -1.0; //Draw at near plane @@ -47,11 +52,27 @@ void main(void) { ); vec4 pos = UNIT_QUAD[gl_VertexID]; + +#ifdef GPU_TRANSFORM_IS_STEREO +#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN + TransformCamera cam = getTransformCamera(); + <$transformStereoClipsSpace(cam, pos)$> +#endif +#endif + _texCoord0 = vec4((pos.xy + 1.0) * 0.5, 0.0, 1.0); +#ifdef GPU_TRANSFORM_IS_STEREO +#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN +#else if (cam_isStereo()) { _texCoord0.x = 0.5 * (_texCoord0.x + cam_getStereoSide()); } +#endif +#endif + gl_Position = pos; + } + } diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index 4a1a0472aa..935d756b28 100755 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -46,9 +46,14 @@ void main(void) { vec4 projected = gl_Position / gl_Position.w; projected.xy = (projected.xy + 1.0) * 0.5; +#ifdef GPU_TRANSFORM_IS_STEREO +#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN +#else if (cam_isStereo()) { projected.x = 0.5 * (projected.x + cam_getStereoSide()); } +#endif +#endif _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; } else { const float depth = -1.0; //Draw at near plane @@ -60,10 +65,24 @@ void main(void) { ); vec4 pos = UNIT_QUAD[gl_VertexID]; +#ifdef GPU_TRANSFORM_IS_STEREO +#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN + TransformCamera cam = getTransformCamera(); + <$transformStereoClipsSpace(cam, pos)$> +#endif +#endif + _texCoord0 = vec4((pos.xy + 1.0) * 0.5, 0.0, 1.0); + +#ifdef GPU_TRANSFORM_IS_STEREO +#ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN +#else if (cam_isStereo()) { _texCoord0.x = 0.5 * (_texCoord0.x + cam_getStereoSide()); } +#endif +#endif + gl_Position = pos; } }