diff options
Diffstat (limited to 'src/plugins/renderers')
12 files changed, 113 insertions, 65 deletions
diff --git a/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3.cpp b/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3.cpp index 97a256b9c..2a0f449fb 100644 --- a/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3.cpp +++ b/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3.cpp @@ -263,6 +263,17 @@ void GraphicsHelperES3::drawArraysInstanced(GLenum primitiveType, GLint first, G instances); } +void GraphicsHelperES3::drawArraysInstancedBaseInstance(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances, GLsizei baseInstance) +{ + if (baseInstance != 0) + qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL ES 3"; + + m_extraFuncs->glDrawArraysInstanced(primitiveType, + first, + count, + instances); +} + void GraphicsHelperES3::readBuffer(GLenum mode) { m_extraFuncs->glReadBuffer(mode); diff --git a/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp b/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp index 65108800b..5f5bc8578 100644 --- a/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp +++ b/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp @@ -140,7 +140,7 @@ void GraphicsHelperES3_2::setVerticesPerPatch(GLint verticesPerPatch) void GraphicsHelperES3_2::drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex, GLint baseInstance) { if (baseInstance != 0) - qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL ES 2"; + qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL ES 3.2"; m_extraFuncs->glDrawElementsInstancedBaseVertex(primitiveType, primitiveCount, diff --git a/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3_p.h b/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3_p.h index 5c34a8abb..9ac9ea159 100644 --- a/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3_p.h +++ b/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3_p.h @@ -76,6 +76,7 @@ public: void buildUniformBuffer(const QVariant &v, const ShaderUniform &description, QByteArray &buffer) override; void drawBuffers(GLsizei n, const int *bufs) override; void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) override; + void drawArraysInstancedBaseInstance(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances, GLsizei baseInstance) override; void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex = 0, GLint baseInstance = 0) override; void readBuffer(GLenum mode) override; void drawBuffer(GLenum mode) override; diff --git a/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp b/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp index 8e843bca7..d220fb16d 100644 --- a/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp +++ b/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp @@ -105,7 +105,7 @@ void GraphicsHelperGL3_2::drawElementsInstancedBaseVertexBaseInstance(GLenum pri GLint baseInstance) { if (baseInstance != 0) - qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL ES 2"; + qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL 3.2"; // glDrawElements OpenGL 3.1 or greater m_funcs->glDrawElementsInstancedBaseVertex(primitiveType, diff --git a/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp b/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp index 3a8c8bde8..065cb1c0b 100644 --- a/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp +++ b/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp @@ -104,7 +104,7 @@ void GraphicsHelperGL3_3::drawElementsInstancedBaseVertexBaseInstance(GLenum pri GLint baseInstance) { if (baseInstance != 0) - qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL 3"; + qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL 3.3"; // glDrawElements OpenGL 3.1 or greater m_funcs->glDrawElementsInstancedBaseVertex(primitiveType, diff --git a/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp b/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp index f23dd8485..7130bb0be 100644 --- a/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp +++ b/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp @@ -188,16 +188,13 @@ void GraphicsHelperGL4::drawElementsInstancedBaseVertexBaseInstance(GLenum primi GLint baseVertex, GLint baseInstance) { - if (baseInstance != 0) - qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL ES 2"; - - // glDrawElements OpenGL 3.1 or greater - m_funcs->glDrawElementsInstancedBaseVertex(primitiveType, + m_funcs->glDrawElementsInstancedBaseVertexBaseInstance(primitiveType, primitiveCount, indexType, indices, instances, - baseVertex); + baseVertex, + baseInstance); } void GraphicsHelperGL4::drawArraysInstanced(GLenum primitiveType, @@ -634,6 +631,7 @@ UniformType GraphicsHelperGL4::uniformTypeFromGLType(GLenum type) case GL_SAMPLER_1D: case GL_SAMPLER_1D_ARRAY: case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_1D_ARRAY_SHADOW: case GL_SAMPLER_2D: case GL_SAMPLER_2D_RECT: case GL_SAMPLER_2D_SHADOW: @@ -652,6 +650,7 @@ UniformType GraphicsHelperGL4::uniformTypeFromGLType(GLenum type) case GL_INT_SAMPLER_2D: case GL_INT_SAMPLER_3D: case GL_INT_SAMPLER_BUFFER: + case GL_INT_SAMPLER_2D_RECT: case GL_INT_SAMPLER_CUBE: case GL_INT_SAMPLER_CUBE_MAP_ARRAY: case GL_INT_SAMPLER_1D_ARRAY: @@ -662,6 +661,7 @@ UniformType GraphicsHelperGL4::uniformTypeFromGLType(GLenum type) case GL_UNSIGNED_INT_SAMPLER_2D: case GL_UNSIGNED_INT_SAMPLER_3D: case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_2D_RECT: case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: @@ -1078,17 +1078,21 @@ void GraphicsHelperGL4::buildUniformBuffer(const QVariant &v, const ShaderUnifor case GL_INT_SAMPLER_2D: case GL_INT_SAMPLER_3D: case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: case GL_INT_SAMPLER_BUFFER: case GL_INT_SAMPLER_2D_RECT: case GL_UNSIGNED_INT_SAMPLER_1D: case GL_UNSIGNED_INT_SAMPLER_2D: case GL_UNSIGNED_INT_SAMPLER_3D: case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: case GL_UNSIGNED_INT_SAMPLER_BUFFER: case GL_UNSIGNED_INT_SAMPLER_2D_RECT: case GL_SAMPLER_1D_SHADOW: case GL_SAMPLER_2D_SHADOW: case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: case GL_SAMPLER_1D_ARRAY: case GL_SAMPLER_2D_ARRAY: case GL_INT_SAMPLER_1D_ARRAY: @@ -1251,6 +1255,10 @@ uint GraphicsHelperGL4::uniformByteSize(const ShaderUniform &description) case GL_SAMPLER_1D_SHADOW: case GL_SAMPLER_2D_SHADOW: case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: case GL_SAMPLER_1D_ARRAY: case GL_SAMPLER_2D_ARRAY: case GL_INT_SAMPLER_1D_ARRAY: diff --git a/src/plugins/renderers/opengl/graphicshelpers/submissioncontext.cpp b/src/plugins/renderers/opengl/graphicshelpers/submissioncontext.cpp index ab5948e49..7ba67fed9 100644 --- a/src/plugins/renderers/opengl/graphicshelpers/submissioncontext.cpp +++ b/src/plugins/renderers/opengl/graphicshelpers/submissioncontext.cpp @@ -481,6 +481,10 @@ bool SubmissionContext::beginDrawing(QSurface *surface) } m_boundArrayBuffer = nullptr; + + // Record the default FBO value as there's no guarantee it remains constant over time + m_defaultFBO = m_gl->defaultFramebufferObject(); + return true; } @@ -1226,6 +1230,10 @@ bool SubmissionContext::setParameters(ShaderParameterPack ¶meterPack, GLShad } } + // Set the pinned images of the previous material + // to pinable so that we should easily find an available image unit + m_imageContext.deactivateImages(); + // Fill Image Uniform Value with proper image units // so that they can be applied as regular uniforms in a second step for (int i = 0; i < parameterPack.images().size(); ++i) { @@ -1598,7 +1606,7 @@ void SubmissionContext::blitFramebuffer(Qt3DCore::QNodeId inputRenderTargetId, if (!outputBufferIsDefault) { // Note that we use glDrawBuffers, not glDrawBuffer. The // latter is not available with GLES. - const int buf = glAttachmentPoint(outputAttachmentPoint); + const int buf = outputAttachmentPoint; drawBuffers(1, &buf); } diff --git a/src/plugins/renderers/opengl/renderer/renderer.cpp b/src/plugins/renderers/opengl/renderer/renderer.cpp index 5c55d3bb9..24326a546 100644 --- a/src/plugins/renderers/opengl/renderer/renderer.cpp +++ b/src/plugins/renderers/opengl/renderer/renderer.cpp @@ -594,38 +594,50 @@ void Renderer::releaseGraphicsResources() QOpenGLContext *context = m_submissionContext->openGLContext(); Q_ASSERT(context); - if (context->thread() == QThread::currentThread() && context->makeCurrent(offscreenSurface)) { - - // Clean up the graphics context and any resources - const std::vector<HGLTexture> &activeTexturesHandles = m_glResourceManagers->glTextureManager()->activeHandles(); - for (const HGLTexture &textureHandle : activeTexturesHandles) { - GLTexture *tex = m_glResourceManagers->glTextureManager()->data(textureHandle); - tex->destroy(); - } + if (context->thread() == QThread::currentThread()) { + QSurface *lastContextSurface = context->surface(); + + if (context->makeCurrent(offscreenSurface)) { + // Clean up the graphics context and any resources + const std::vector<HGLTexture> &activeTexturesHandles = m_glResourceManagers->glTextureManager()->activeHandles(); + for (const HGLTexture &textureHandle : activeTexturesHandles) { + GLTexture *tex = m_glResourceManagers->glTextureManager()->data(textureHandle); + tex->destroy(); + } - // Do the same thing with buffers - const std::vector<HGLBuffer> &activeBuffers = m_glResourceManagers->glBufferManager()->activeHandles(); - for (const HGLBuffer &bufferHandle : activeBuffers) { - GLBuffer *buffer = m_glResourceManagers->glBufferManager()->data(bufferHandle); - buffer->destroy(m_submissionContext.data()); - } + // Do the same thing with buffers + const std::vector<HGLBuffer> &activeBuffers = m_glResourceManagers->glBufferManager()->activeHandles(); + for (const HGLBuffer &bufferHandle : activeBuffers) { + GLBuffer *buffer = m_glResourceManagers->glBufferManager()->data(bufferHandle); + buffer->destroy(m_submissionContext.data()); + } - // Do the same thing with shaders - const QVector<GLShader *> shaders = m_glResourceManagers->glShaderManager()->takeActiveResources(); - qDeleteAll(shaders); + // Do the same thing with shaders + const QVector<GLShader *> shaders = m_glResourceManagers->glShaderManager()->takeActiveResources(); + qDeleteAll(shaders); - // Do the same thing with VAOs - const std::vector<HVao> &activeVaos = m_glResourceManagers->vaoManager()->activeHandles(); - for (const HVao &vaoHandle : activeVaos) { - OpenGLVertexArrayObject *vao = m_glResourceManagers->vaoManager()->data(vaoHandle); - vao->destroy(); - } + // Do the same thing with VAOs + const std::vector<HVao> &activeVaos = m_glResourceManagers->vaoManager()->activeHandles(); + for (const HVao &vaoHandle : activeVaos) { + OpenGLVertexArrayObject *vao = m_glResourceManagers->vaoManager()->data(vaoHandle); + vao->destroy(); + } - m_submissionContext->releaseRenderTargets(); + m_submissionContext->releaseRenderTargets(); - m_frameProfiler.reset(); - if (m_ownedContext) - context->doneCurrent(); + m_frameProfiler.reset(); + if (m_ownedContext) { + context->doneCurrent(); + } else { + // Leave the context in the state we found it in by restoring + // its last used surface. This satisfies expectations when used + // with QQuickWidgets that surface on current context after + // QQuickRenderControl cleanup is the same as prior to the + // cleanup. Arguably this could also be checked for in + // QQuickWidgetPrivate::invalidateRenderControl. + context->makeCurrent(lastContextSurface); + } + } } else { qWarning() << "Failed to make context current: OpenGL resources will not be destroyed"; } @@ -1168,6 +1180,9 @@ void Renderer::sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager) const std::vector<HShader> &activeShaders = m_nodesManager->shaderManager()->activeHandles(); for (const HShader &handle :activeShaders) { Shader *s = m_nodesManager->shaderManager()->data(handle); + if (!s) + continue; + if (s->requiresFrontendSync()) { QShaderProgram *frontend = static_cast<decltype(frontend)>(manager->lookupNode(s->peerId())); // Could happen as a backend shader might live beyong the frontend @@ -1872,6 +1887,7 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() // Remove previous dependencies m_cleanupJob->removeDependency(QWeakPointer<QAspectJob>()); + const bool dirtyParametersForCurrentFrame = m_dirtyBits.marked & AbstractRenderer::ParameterDirty; const BackendNodeDirtySet dirtyBitsForFrame = m_dirtyBits.marked | m_dirtyBits.remaining; m_dirtyBits.marked = {}; m_dirtyBits.remaining = {}; @@ -1939,7 +1955,7 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() m_updatedDisableSubtreeEnablers.push_back(node->peerId()); } - int idealThreadCount = QThreadPooler::maxThreadCount(); + int idealThreadCount = Qt3DCore::QAspectJobManager::idealThreadCount(); const int fgBranchCount = m_frameGraphLeaves.size(); if (fgBranchCount > 1) { @@ -1995,6 +2011,10 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() m_dirtyBits.remaining = dirtyBitsForFrame & notCleared; + // Dirty Parameters might need 2 frames to react if the parameter references a texture + if (dirtyParametersForCurrentFrame) + m_dirtyBits.remaining |= AbstractRenderer::ParameterDirty; + return renderBinJobs; } diff --git a/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp b/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp index 41aef69a0..99683a6d8 100644 --- a/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp +++ b/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp @@ -41,6 +41,7 @@ #include <Qt3DRender/private/qrenderaspect_p.h> #include <QThread> +#include <Qt3DCore/private/qaspectjobmanager_p.h> QT_BEGIN_NAMESPACE @@ -567,7 +568,7 @@ RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int rende // In some cases having less jobs is better (especially on fast cpus where // splitting just adds more overhead). Ideally, we should try to set the value // depending on the platform/CPU/nbr of cores - m_optimalParallelJobCount = QThread::idealThreadCount(); + m_optimalParallelJobCount = Qt3DCore::QAspectJobManager::idealThreadCount(); } RenderViewInitializerJobPtr RenderViewBuilder::renderViewJob() const @@ -917,22 +918,7 @@ bool RenderViewBuilder::lightCacheNeedsToBeRebuilt() const int RenderViewBuilder::defaultJobCount() { - static int jobCount = 0; - if (jobCount) - return jobCount; - - const QByteArray maxThreadCount = qgetenv("QT3D_MAX_THREAD_COUNT"); - if (!maxThreadCount.isEmpty()) { - bool conversionOK = false; - const int maxThreadCountValue = maxThreadCount.toInt(&conversionOK); - if (conversionOK) { - jobCount = maxThreadCountValue; - return jobCount; - } - } - - jobCount = QThread::idealThreadCount(); - return jobCount; + return Qt3DCore::QAspectJobManager::idealThreadCount(); } int RenderViewBuilder::optimalJobCount() const diff --git a/src/plugins/renderers/opengl/renderer/shaderparameterpack.cpp b/src/plugins/renderers/opengl/renderer/shaderparameterpack.cpp index 43b0b90c1..bf7d5fce6 100644 --- a/src/plugins/renderers/opengl/renderer/shaderparameterpack.cpp +++ b/src/plugins/renderers/opengl/renderer/shaderparameterpack.cpp @@ -100,12 +100,28 @@ void ShaderParameterPack::setImage(const int glslNameId, int uniformArrayIndex, // Contains Uniform Block Index and QNodeId of the ShaderData (UBO) void ShaderParameterPack::setUniformBuffer(BlockToUBO blockToUBO) { - m_uniformBuffers.push_back(std::move(blockToUBO)); + const auto uEnd = m_uniformBuffers.end(); + auto it = std::find_if(m_uniformBuffers.begin(), uEnd, [&] (const BlockToUBO &block) { + return blockToUBO.m_blockIndex == block.m_blockIndex; + }); + + if (it == uEnd) + m_uniformBuffers.push_back(std::move(blockToUBO)); + else + *it = std::move(blockToUBO); } void ShaderParameterPack::setShaderStorageBuffer(BlockToSSBO blockToSSBO) { - m_shaderStorageBuffers.push_back(std::move(blockToSSBO)); + const auto uEnd = m_shaderStorageBuffers.end(); + auto it = std::find_if(m_shaderStorageBuffers.begin(), uEnd, [&] (const BlockToSSBO &block) { + return blockToSSBO.m_blockIndex == block.m_blockIndex; + }); + + if (it == uEnd) + m_shaderStorageBuffers.push_back(std::move(blockToSSBO)); + else + *it = std::move(blockToSSBO); } void ShaderParameterPack::setSubmissionUniformIndex(const int uniformIdx) diff --git a/src/plugins/renderers/rhi/renderer/renderviewbuilder.cpp b/src/plugins/renderers/rhi/renderer/renderviewbuilder.cpp index 387c5ff8d..870eb2cd0 100644 --- a/src/plugins/renderers/rhi/renderer/renderviewbuilder.cpp +++ b/src/plugins/renderers/rhi/renderer/renderviewbuilder.cpp @@ -39,19 +39,13 @@ #include "renderviewbuilder_p.h" #include <Qt3DRender/private/qrenderaspect_p.h> - -#include <QThread> +#include <Qt3DCore/private/qaspectjobmanager_p.h> namespace Qt3DRender { namespace Render { namespace Rhi { -// In some cases having less jobs is better (especially on fast cpus where -// splitting just adds more overhead). Ideally, we should try to set the value -// depending on the platform/CPU/nbr of cores -const int RenderViewBuilder::m_optimalParallelJobCount = QThread::idealThreadCount(); - namespace { int findIdealNumberOfWorkers(int elementCount, int packetSize = 100) @@ -498,6 +492,10 @@ RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int rende m_syncFilterEntityByLayerJob(), m_filterProximityJob(Render::FilterProximityDistanceJobPtr::create()) { + // In some cases having less jobs is better (especially on fast cpus where + // splitting just adds more overhead). Ideally, we should try to set the value + // depending on the platform/CPU/nbr of cores + m_optimalParallelJobCount = Qt3DCore::QAspectJobManager::idealThreadCount(); } RenderViewInitializerJobPtr RenderViewBuilder::renderViewJob() const diff --git a/src/plugins/renderers/rhi/renderer/renderviewbuilder_p.h b/src/plugins/renderers/rhi/renderer/renderviewbuilder_p.h index 4df57b139..974f9e9bb 100644 --- a/src/plugins/renderers/rhi/renderer/renderviewbuilder_p.h +++ b/src/plugins/renderers/rhi/renderer/renderviewbuilder_p.h @@ -139,7 +139,7 @@ private: SynchronizerJobPtr m_syncMaterialGathererJob; FilterProximityDistanceJobPtr m_filterProximityJob; - static const int m_optimalParallelJobCount; + int m_optimalParallelJobCount; }; } // Rhi |