diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2015-12-10 13:06:33 +0100 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2016-01-13 16:10:36 +0000 |
commit | 412a1d9b1d0b73fcc99c73bd89457cc11ece00fa (patch) | |
tree | 0472dcf48168c4903fa6faf148ae08bc1bd3fd13 /src/render | |
parent | 9add600584ab87c80d439c0d5571994d72af3477 (diff) |
RenderView/GraphicsContext: support SSBO/UBO with buffer used as Parameters
Change-Id: I347aa5deea6521b43b9033e2200ab2f8b272f671
Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
Diffstat (limited to 'src/render')
22 files changed, 231 insertions, 115 deletions
diff --git a/src/render/backend/quniformvalue.cpp b/src/render/backend/quniformvalue.cpp index 511720ea1..eb5c9a682 100644 --- a/src/render/backend/quniformvalue.cpp +++ b/src/render/backend/quniformvalue.cpp @@ -108,6 +108,11 @@ void ShaderParameterPack::setUniformBuffer(const BlockToUBO &blockToUBO) m_uniformBuffers.append(blockToUBO); } +void ShaderParameterPack::setShaderStorageBuffer(const BlockToSSBO &blockToSSBO) +{ + m_shaderStorageBuffers.push_back(blockToSSBO); +} + void TextureUniform::apply(GraphicsContext *ctx, const ShaderUniform &description) const { // We assume that the texture has been successfully bound and attache to a texture unit diff --git a/src/render/backend/quniformvalue_p.h b/src/render/backend/quniformvalue_p.h index 35a9cca0f..6d8681edf 100644 --- a/src/render/backend/quniformvalue_p.h +++ b/src/render/backend/quniformvalue_p.h @@ -137,11 +137,16 @@ private: struct BlockToUBO { int m_blockIndex; - Qt3DCore::QNodeId m_shaderDataID; + Qt3DCore::QNodeId m_bufferID; bool m_needsUpdate; QHash<QString, QVariant> m_updatedProperties; }; +struct BlockToSSBO { + int m_blockIndex; + Qt3DCore::QNodeId m_bufferID; +}; + class ShaderParameterPack { public: @@ -150,6 +155,7 @@ public: void setUniform(const QString &glslName, const QUniformValue *val); void setTexture(const QString &glslName, const Qt3DCore::QNodeId &id); void setUniformBuffer(const BlockToUBO &blockToUBO); + void setShaderStorageBuffer(const BlockToSSBO &blockToSSBO); inline const QHash<QString, const QUniformValue* > &uniforms() const { return m_uniforms; } const QUniformValue *uniform(const QString &glslName) const { return m_uniforms.value(glslName); } @@ -168,12 +174,13 @@ public: inline QVector<NamedTexture> textures() const { return m_textures; } inline QVector<BlockToUBO> uniformBuffers() const { return m_uniformBuffers; } - + inline QVector<BlockToSSBO> shaderStorageBuffers() const { return m_shaderStorageBuffers; } private: QHash<QString, const QUniformValue* > m_uniforms; QVector<NamedTexture> m_textures; QVector<BlockToUBO> m_uniformBuffers; + QVector<BlockToSSBO> m_shaderStorageBuffers; friend class RenderView; }; diff --git a/src/render/backend/rendercommand_p.h b/src/render/backend/rendercommand_p.h index 6813a6ad7..52afd8da9 100644 --- a/src/render/backend/rendercommand_p.h +++ b/src/render/backend/rendercommand_p.h @@ -73,7 +73,7 @@ public: HVao m_vao; // VAO used during the submission step to store all states and VBOs HShader m_shader; // Shader for given pass and mesh - ShaderParameterPack m_uniforms; // Might need to be reworked so as to be able to destroy the + ShaderParameterPack m_parameterPack; // Might need to be reworked so as to be able to destroy the // Texture while submission is happening. GLint m_instancesCount; // Number of instances of the mesh, if 0 regular draw otherwise glDrawArraysInstanced or glDrawElementsInstanced RenderStateSet *m_stateSet; diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index 98110061d..8140eb7c6 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -809,7 +809,7 @@ void Renderer::executeCommands(const QVector<RenderCommand *> &commands) if (shader == Q_NULLPTR) { shader = m_defaultRenderShader; command->m_parameterAttributeToShaderNames = m_defaultParameterToGLSLAttributeNames; - command->m_uniforms = m_defaultUniformPack; + command->m_parameterPack = m_defaultUniformPack; } // The VAO should be created only once for a QGeometry and a ShaderProgram @@ -868,7 +868,7 @@ void Renderer::executeCommands(const QVector<RenderCommand *> &commands) } //// Update program uniforms - m_graphicsContext->setUniforms(command->m_uniforms); + m_graphicsContext->setParameters(command->m_parameterPack); //// Bind SSBO Buffers // Note: how does that behave regarding VAO diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp index 44b7ca1a3..93802754c 100644 --- a/src/render/backend/renderview.cpp +++ b/src/render/backend/renderview.cpp @@ -60,6 +60,7 @@ #include <Qt3DRender/private/renderstateset_p.h> #include <Qt3DRender/private/techniquefilternode_p.h> #include <Qt3DRender/private/viewportnode_p.h> +#include <Qt3DRender/private/buffermanager_p.h> #include <Qt3DRender/qparametermapping.h> @@ -291,7 +292,7 @@ RenderView::~RenderView() Q_FOREACH (RenderCommand *command, m_commands) { // Deallocate all uniform values of the QUniformPack of each RenderCommand - const QHash<QString, const QUniformValue* > uniforms = command->m_uniforms.uniforms(); + const QHash<QString, const QUniformValue* > uniforms = command->m_parameterPack.uniforms(); const QHash<QString, const QUniformValue* >::const_iterator end = uniforms.constEnd(); QHash<QString, const QUniformValue* >::const_iterator it = uniforms.constBegin(); @@ -352,10 +353,10 @@ void RenderView::sort() ++i; if (i - j > 0) { // Several commands have the same shader, so we minimize uniform changes - QHash<QString, const QUniformValue *> cachedUniforms = m_commands[j++]->m_uniforms.uniforms(); + QHash<QString, const QUniformValue *> cachedUniforms = m_commands[j++]->m_parameterPack.uniforms(); while (j < i) { - QHash<QString, const QUniformValue *> &uniforms = m_commands[j]->m_uniforms.m_uniforms; + QHash<QString, const QUniformValue *> &uniforms = m_commands[j]->m_parameterPack.m_uniforms; QHash<QString, const QUniformValue *>::iterator it = uniforms.begin(); while (it != uniforms.end()) { @@ -608,12 +609,27 @@ void RenderView::setStandardUniformValue(ShaderParameterPack &uniformPack, const uniformPack.setUniform(glslName, (this->*ms_standardUniformSetters[name])(worldTransform)); } -void RenderView::setUniformBlockValue(ShaderParameterPack &uniformPack, Shader *shader, const ShaderUniformBlock &block, const QVariant &value) +void RenderView::setUniformBlockValue(ShaderParameterPack &uniformPack, + Shader *shader, + const ShaderUniformBlock &block, + const QVariant &value) { - ShaderData *shaderData = Q_NULLPTR; + Q_UNUSED(shader) - if (static_cast<QMetaType::Type>(value.type()) == qNodeIdTypeId && - (shaderData = m_manager->shaderDataManager()->lookupResource(value.value<Qt3DCore::QNodeId>())) != Q_NULLPTR) { + if (static_cast<QMetaType::Type>(value.type()) == qNodeIdTypeId) { + + Buffer *buffer = Q_NULLPTR; + if ((buffer = m_manager->bufferManager()->lookupResource(value.value<Qt3DCore::QNodeId>())) != Q_NULLPTR) { + BlockToUBO uniformBlockUBO; + uniformBlockUBO.m_blockIndex = block.m_index; + uniformBlockUBO.m_bufferID = buffer->peerUuid(); + uniformPack.setUniformBuffer(uniformBlockUBO); + // Buffer update to GL buffer will be done at render time + } + + + //ShaderData *shaderData = Q_NULLPTR; + // if ((shaderData = m_manager->shaderDataManager()->lookupResource(value.value<Qt3DCore::QNodeId>())) != Q_NULLPTR) { // UBO are indexed by <ShaderId, ShaderDataId> so that a same QShaderData can be used among different shaders // while still making sure that if they have a different layout everything will still work // If two shaders define the same block with the exact same layout, in that case the UBO could be shared @@ -659,6 +675,25 @@ void RenderView::setUniformBlockValue(ShaderParameterPack &uniformPack, Shader * // uniformBlockUBO.m_needsUpdate = uboNeedsUpdate; // uniformPack.setUniformBuffer(uniformBlockUBO); + // } + } +} + +void RenderView::setShaderStorageValue(ShaderParameterPack &uniformPack, + Shader *shader, + const ShaderStorageBlock &block, + const QVariant &value) +{ + Q_UNUSED(shader) + if (static_cast<QMetaType::Type>(value.type()) == qNodeIdTypeId) { + Buffer *buffer = Q_NULLPTR; + if ((buffer = m_manager->bufferManager()->lookupResource(value.value<Qt3DCore::QNodeId>())) != Q_NULLPTR) { + BlockToSSBO shaderStorageBlock; + shaderStorageBlock.m_blockIndex = block.m_index; + shaderStorageBlock.m_bufferID = buffer->peerUuid(); + uniformPack.setShaderStorageBuffer(shaderStorageBlock); + // Buffer update to GL buffer will be done at render time + } } } @@ -755,7 +790,7 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, RenderPass *rPass, // Set default standard uniforms without bindings Q_FOREACH (const QString &uniformName, uniformNames) { if (ms_standardUniformSetters.contains(uniformName)) - setStandardUniformValue(command->m_uniforms, uniformName, uniformName, worldTransform); + setStandardUniformValue(command->m_parameterPack, uniformName, uniformName, worldTransform); } // Set default attributes @@ -767,23 +802,46 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, RenderPass *rPass, // Set uniforms and attributes explicitly binded Q_FOREACH (const ParameterMapping &binding, rPass->bindings()) { ParameterInfoList::iterator it = findParamInfo(¶meters, binding.parameterName()); + if (it == parameters.end()) { - if (binding.bindingType() == QParameterMapping::Attribute - && attributeNames.contains(binding.shaderVariableName())) { - command->m_parameterAttributeToShaderNames.insert(binding.parameterName(), binding.shaderVariableName()); - } else if (binding.bindingType() == QParameterMapping::StandardUniform - && uniformNames.contains(binding.shaderVariableName()) - && ms_standardUniformSetters.contains(binding.parameterName())) { - setStandardUniformValue(command->m_uniforms, binding.shaderVariableName(), binding.parameterName(), worldTransform); - } else if (binding.bindingType() == QParameterMapping::FragmentOutput - && fragOutputs.contains(binding.parameterName())) { - fragOutputs.insert(binding.shaderVariableName(), fragOutputs.take(binding.parameterName())); - } else { + // A Parameters wasn't found with the name binding.parameterName + // -> we need to use the binding.shaderVariableName + switch (binding.bindingType()) { + + case QParameterMapping::Attribute: + if (attributeNames.contains(binding.shaderVariableName())) { + command->m_parameterAttributeToShaderNames.insert(binding.parameterName(), binding.shaderVariableName()); + break; + } + case QParameterMapping::StandardUniform: + if (uniformNames.contains(binding.shaderVariableName()) + && ms_standardUniformSetters.contains(binding.parameterName())) { + setStandardUniformValue(command->m_parameterPack, binding.shaderVariableName(), binding.parameterName(), worldTransform); + break; + } + + case QParameterMapping::FragmentOutput: + if (fragOutputs.contains(binding.parameterName())) { + fragOutputs.insert(binding.shaderVariableName(), fragOutputs.take(binding.parameterName())); + break; + } + + case QParameterMapping::UniformBufferObject: + if (uniformBlockNames.contains(binding.parameterName())) { + setUniformBlockValue(command->m_parameterPack, shader, shader->uniformBlock(it->name), it->value); + break; + } + + case QParameterMapping::ShaderStorageBufferObject: + if (shaderStorageBlockNames.contains(binding.parameterName())) { + setShaderStorageValue(command->m_parameterPack, shader, shader->storageBlock(it->name), it->value); + break; + } + + default: qCWarning(Render::Backend) << Q_FUNC_INFO << "Trying to bind a Parameter that hasn't been defined " << binding.parameterName(); + break; } - } else { - setUniformValue(command->m_uniforms, binding.shaderVariableName(), it->value); - parameters.erase(it); } } @@ -791,35 +849,29 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, RenderPass *rPass, // -> uniform scalar / vector // -> uniform struct / arrays // -> uniform block / array (4.3) + // -> ssbo block / array (4.3) if ((!uniformNames.isEmpty() || !uniformBlockNames.isEmpty()) && !parameters.isEmpty()) { ParameterInfoList::iterator it = parameters.begin(); - while (it != parameters.end()) { + const ParameterInfoList::iterator parametersEnd = parameters.end(); + while (it != parametersEnd) { if (uniformNames.contains(it->name)) { // Parameter is a regular uniform - setUniformValue(command->m_uniforms, it->name, it->value); - it = parameters.erase(it); + setUniformValue(command->m_parameterPack, it->name, it->value); } else if (uniformBlockNames.indexOf(it->name) != -1) { // Parameter is a uniform block - const ShaderUniformBlock &block = shader->uniformBlock(it->name); - setUniformBlockValue(command->m_uniforms, shader, block, it->value); - it = parameters.erase(it); + setUniformBlockValue(command->m_parameterPack, shader, shader->uniformBlock(it->name), it->value); } else if (shaderStorageBlockNames.indexOf(it->name) != -1) { // Parameters is a SSBO - const ShaderStorageBlock block = shader->storageBlock(it->name); - // TO DO: Do whatever is needed - Q_UNUSED(block) - it = parameters.erase(it); + setShaderStorageValue(command->m_parameterPack, shader, shader->storageBlock(it->name), it->value); } else { // Parameter is a struct const QVariant &v = it->value; ShaderData *shaderData = Q_NULLPTR; if (static_cast<QMetaType::Type>(v.type()) == qNodeIdTypeId && (shaderData = m_manager->shaderDataManager()->lookupResource(v.value<Qt3DCore::QNodeId>())) != Q_NULLPTR) { // Try to check if we have a struct or array matching a QShaderData parameter - setDefaultUniformBlockShaderDataValue(command->m_uniforms, shader, shaderData, it->name); - it = parameters.erase(it); - } else { - // Else param unused by current shader - ++it; + setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, it->name); } + // Otherwise: param unused by current shader } + ++it; } } @@ -837,20 +889,20 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, RenderPass *rPass, if (lightIdx == MAX_LIGHTS) break; const QString structName = QStringLiteral("lights[") + QString::number(lightIdx) + QLatin1Char(']'); - setUniformValue(command->m_uniforms, structName + LIGHT_POSITION_NAME, worldPos); - setDefaultUniformBlockShaderDataValue(command->m_uniforms, shader, light, structName); + setUniformValue(command->m_parameterPack, structName + LIGHT_POSITION_NAME, worldPos); + setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, light, structName); ++lightIdx; } } if (uniformNames.contains(LIGHT_COUNT_NAME)) - setUniformValue(command->m_uniforms, LIGHT_COUNT_NAME, qMax(1, lightIdx)); + setUniformValue(command->m_parameterPack, LIGHT_COUNT_NAME, qMax(1, lightIdx)); if (activeLightSources.isEmpty()) { - setUniformValue(command->m_uniforms, QStringLiteral("lights[0].type"), int(QLight::DirectionalLight)); - setUniformValue(command->m_uniforms, QStringLiteral("lights[0].direction"), QVector3D(0.0f, -1.0f, -1.0f)); - setUniformValue(command->m_uniforms, QStringLiteral("lights[0].color"), QVector3D(1.0f, 1.0f, 1.0f)); - setUniformValue(command->m_uniforms, QStringLiteral("lights[0].intensity"), 1.0f); + setUniformValue(command->m_parameterPack, QStringLiteral("lights[0].type"), int(QLight::PointLight)); + setUniformValue(command->m_parameterPack, QStringLiteral("lights[0].position"), QVector3D(10.0f, 10.0f, 0.0f)); + setUniformValue(command->m_parameterPack, QStringLiteral("lights[0].color"), QVector3D(1.0f, 1.0f, 1.0f)); + setUniformValue(command->m_parameterPack, QStringLiteral("lights[0].intensity"), QVector3D(0.5f, 0.5f, 0.5f)); } } // Set frag outputs in the shaders if hash not empty diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h index 6246a32d1..fc63bcf4e 100644 --- a/src/render/backend/renderview_p.h +++ b/src/render/backend/renderview_p.h @@ -318,6 +318,10 @@ private: Shader *shader, const ShaderUniformBlock &block, const QVariant &value); + void setShaderStorageValue(ShaderParameterPack &uniformPack, + Shader *shader, + const ShaderStorageBlock &block, + const QVariant &value); void setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, Shader *shader, ShaderData *shaderData, diff --git a/src/render/geometry/qbuffer.h b/src/render/geometry/qbuffer.h index 8b91a3efd..3f64007f3 100644 --- a/src/render/geometry/qbuffer.h +++ b/src/render/geometry/qbuffer.h @@ -62,7 +62,9 @@ public: VertexBuffer = 0x8892, // GL_ARRAY_BUFFER IndexBuffer = 0x8893, // GL_ELEMENT_ARRAY_BUFFER PixelPackBuffer = 0x88EB, // GL_PIXEL_PACK_BUFFER - PixelUnpackBuffer = 0x88EC // GL_PIXEL_UNPACK_BUFFER + PixelUnpackBuffer = 0x88EC, // GL_PIXEL_UNPACK_BUFFER + UniformBuffer = 0x8A11, // GL_UNIFORM_BUFFER + ShaderStorageBuffer = 0x90D2 // GL_SHADER_STORAGE_BUFFER }; Q_ENUM(BufferType) diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index b91692adc..5279fb191 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -51,6 +51,7 @@ #include <Qt3DRender/private/graphicshelperinterface_p.h> #include <Qt3DRender/private/renderer_p.h> #include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DRender/private/buffermanager_p.h> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/attachmentpack_p.h> #include <QOpenGLShaderProgram> @@ -91,6 +92,10 @@ GLBuffer::Type bufferTypeToGLBufferType(QBuffer::BufferType type) return GLBuffer::PixelPackBuffer; case QBuffer::PixelUnpackBuffer: return GLBuffer::PixelUnpackBuffer; + case QBuffer::UniformBuffer: + return GLBuffer::UniformBuffer; + case QBuffer::ShaderStorageBuffer: + return GLBuffer::ShaderStorageBuffer; default: Q_UNREACHABLE(); } @@ -720,6 +725,11 @@ void GraphicsContext::bindUniformBlock(GLuint programId, GLuint uniformBlockInde m_glHelper->bindUniformBlock(programId, uniformBlockIndex, uniformBlockBinding); } +void GraphicsContext::bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) +{ + m_glHelper->bindShaderStorageBlock(programId, shaderStorageBlockIndex, shaderStorageBlockBinding); +} + void GraphicsContext::bindBufferBase(GLenum target, GLuint bindingIndex, GLuint buffer) { m_glHelper->bindBufferBase(target, bindingIndex, buffer); @@ -844,7 +854,7 @@ void GraphicsContext::setRenderer(Renderer *renderer) // It will be easier if the QGraphicContext applies the QUniformPack // than the other way around -void GraphicsContext::setUniforms(ShaderParameterPack &uniforms) +void GraphicsContext::setParameters(ShaderParameterPack ¶meterPack) { // Activate textures and update TextureUniform in the pack // with the correct textureUnit @@ -855,9 +865,9 @@ void GraphicsContext::setUniforms(ShaderParameterPack &uniforms) deactivateTexturesWithScope(TextureScopeMaterial); // Update the uniforms with the correct texture unit id's - const QHash<QString, const QUniformValue *> &uniformValues = uniforms.uniforms(); - for (int i = 0; i < uniforms.textures().size(); ++i) { - const ShaderParameterPack::NamedTexture &namedTex = uniforms.textures().at(i); + const QHash<QString, const QUniformValue *> &uniformValues = parameterPack.uniforms(); + for (int i = 0; i < parameterPack.textures().size(); ++i) { + const ShaderParameterPack::NamedTexture &namedTex = parameterPack.textures().at(i); Texture *t = manager->lookupResource<Texture, TextureManager>(namedTex.texId); const TextureUniform *texUniform = Q_NULLPTR; // TO DO : Rework the way textures are loaded @@ -871,66 +881,52 @@ void GraphicsContext::setUniforms(ShaderParameterPack &uniforms) } } - // Bind UniformBlocks to UBO and update UBO from ShaderData - const QVector<BlockToUBO> &blockToUbos = uniforms.uniformBuffers(); - GLBuffer *ubo = Q_NULLPTR; - bool needsToUnbindUBO = false; - - // TEMPORARLY Disabled - - // for (int i = 0; i < blockToUbos.length(); ++i) { - // const ShaderUniformBlock &block = m_activeShader->uniformBlock(blockToUbos[i].m_blockIndex); - // if (block.m_index != -1 && block.m_size > 0) { - // ubo = manager->lookupResource<GLBuffer, GLBufferManager>(BufferShaderKey(blockToUbos[i].m_shaderDataID, - // m_activeShader->peerUuid())); - // // bind Uniform Block of index ubos[i].m_index to binding point i - // bindUniformBlock(m_activeShader->getOrCreateProgram(this)->programId(), block.m_index, i); - // // bind the UBO to the binding point i - // // Specs specify that there are at least 14 binding points - - // // Allocate ubo if not allocated previously - // if (!ubo->isCreated()) { - // ubo->create(this); - // ubo->bind(this, GLBuffer::UniformBuffer); - // ubo->allocate(this, block.m_size); - // } - - // // update the ubo if needed - - // // TO DO: Maybe QShaderData should act as a QBuffer data provider - // // and internally update a QBuffer which we would then reupload - // // and the ShaderData updates could then be done in some jobs - // // rather than at render time ? - // if (blockToUbos[i].m_needsUpdate) { - // if (!ubo->isBound()) - // ubo->bind(this, GLBuffer::UniformBuffer); - // needsToUnbindUBO |= true; - // const QHash<QString, ShaderUniform> &activeUniformsInBlock = m_activeShader->activeUniformsForUniformBlock(block.m_index); - // const QHash<QString, ShaderUniform>::const_iterator uniformsEnd = activeUniformsInBlock.end(); - // QHash<QString, ShaderUniform>::const_iterator uniformsIt = activeUniformsInBlock.begin(); - - // while (uniformsIt != uniformsEnd) { - // if (blockToUbos[i].m_updatedProperties.contains(uniformsIt.key())) { - // buildUniformBuffer(blockToUbos[i].m_updatedProperties.value(uniformsIt.key()), - // uniformsIt.value(), - // m_uboTempArray); - // ubo->update(this, m_uboTempArray.constData() + uniformsIt.value().m_offset, - // uniformsIt.value().m_rawByteSize, - // uniformsIt.value().m_offset); - // } - // ++uniformsIt; - // } - // } - // // bind UBO to binding point - // ubo->bindToUniformBlock(this, i); - // } - // } - - if (needsToUnbindUBO) - ubo->release(this); + QOpenGLShaderProgram *shader = m_activeShader->getOrCreateProgram(this); + + // TO DO: We could cache the binding points somehow and only do the binding when necessary + // for SSBO and UBO + + // Bind Shader Storage block to SSBO and update SSBO + const QVector<BlockToSSBO> blockToSSBOs = parameterPack.shaderStorageBuffers(); + int ssboIndex = 0; + Q_FOREACH (const BlockToSSBO b, blockToSSBOs) { + Buffer *cpuBuffer = m_renderer->nodeManagers()->bufferManager()->lookupResource(b.m_bufferID); + GLBuffer *ssbo = glBufferForRenderBuffer(cpuBuffer); + bindShaderStorageBlock(shader->programId(), b.m_blockIndex, ssboIndex); + // Needed to avoid conflict where the buffer would already + // be bound as a VertexArray + ssbo->bind(this, GLBuffer::ShaderStorageBuffer); + ssbo->bindBufferBase(this, ssboIndex++, GLBuffer::ShaderStorageBuffer); + // Perform update if required + if (cpuBuffer->isDirty()) { + uploadDataToGLBuffer(cpuBuffer, ssbo); + cpuBuffer->unsetDirty(); + } + // TO DO: Make sure that there's enough binding points + } + + // Bind UniformBlocks to UBO and update UBO from Buffer + // TO DO: Convert ShaderData to Buffer so that we can use that generic process + const QVector<BlockToUBO> blockToUBOs = parameterPack.uniformBuffers(); + int uboIndex = 0; + Q_FOREACH (const BlockToUBO b, blockToUBOs) { + Buffer *cpuBuffer = m_renderer->nodeManagers()->bufferManager()->lookupResource(b.m_bufferID); + GLBuffer *ubo = glBufferForRenderBuffer(cpuBuffer); + bindUniformBlock(shader->programId(), b.m_blockIndex, uboIndex); + // Needed to avoid conflict where the buffer would already + // be bound as a VertexArray + ubo->bind(this, GLBuffer::UniformBuffer); + ubo->bindBufferBase(this, uboIndex++, GLBuffer::UniformBuffer); + if (cpuBuffer->isDirty()) { + // Perform update if required + uploadDataToGLBuffer(cpuBuffer, ubo); + cpuBuffer->unsetDirty(); + } + // TO DO: Make sure that there's enough binding points + } // Update uniforms in the Default Uniform Block - m_activeShader->updateUniforms(this, uniforms); + m_activeShader->updateUniforms(this, parameterPack); } void GraphicsContext::specifyAttribute(const Attribute *attribute, Buffer *buffer, const QString &shaderName) diff --git a/src/render/graphicshelpers/graphicscontext_p.h b/src/render/graphicshelpers/graphicscontext_p.h index 3a4150ea9..bbc93c43d 100644 --- a/src/render/graphicshelpers/graphicscontext_p.h +++ b/src/render/graphicshelpers/graphicscontext_p.h @@ -144,7 +144,7 @@ public: void specifyIndices(Buffer *buffer); void updateBuffer(Buffer *buffer); - void setUniforms(ShaderParameterPack &uniforms); + void setParameters(ShaderParameterPack ¶meterPack); /** * @brief glBufferFor - given a client-side (CPU) buffer, provide the @@ -176,6 +176,7 @@ public: void bindUniform(const QVariant &v, const ShaderUniform &description); void blendEquation(GLenum mode); void blendFunci(GLuint buf, GLenum sfactor, GLenum dfactor); + void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding); GLuint boundFrameBufferObject(); void buildUniformBuffer(const QVariant &v, const ShaderUniform &description, QByteArray &buffer); void clearColor(const QColor &color); diff --git a/src/render/graphicshelpers/graphicshelperes2.cpp b/src/render/graphicshelpers/graphicshelperes2.cpp index 1e1e1710a..29fe849d7 100644 --- a/src/render/graphicshelpers/graphicshelperes2.cpp +++ b/src/render/graphicshelpers/graphicshelperes2.cpp @@ -460,6 +460,14 @@ void GraphicsHelperES2::bindUniformBlock(GLuint programId, GLuint uniformBlockIn qWarning() << "UBO are not supported by ES 2.0 (since ES 3.0)"; } +void GraphicsHelperES2::bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) +{ + Q_UNUSED(programId); + Q_UNUSED(shaderStorageBlockIndex); + Q_UNUSED(shaderStorageBlockBinding); + qWarning() << "SSBO are not supported by ES 2.0 (since ES 3.1)"; +} + void GraphicsHelperES2::bindBufferBase(GLenum target, GLuint index, GLuint buffer) { Q_UNUSED(target); diff --git a/src/render/graphicshelpers/graphicshelperes2_p.h b/src/render/graphicshelpers/graphicshelperes2_p.h index 5211bb3ac..01d4f59c4 100644 --- a/src/render/graphicshelpers/graphicshelperes2_p.h +++ b/src/render/graphicshelpers/graphicshelperes2_p.h @@ -69,6 +69,7 @@ public: void bindFragDataLocation(GLuint shader, const QHash<QString, int> &outputs) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferObject(GLuint frameBufferId) Q_DECL_OVERRIDE; + void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) Q_DECL_OVERRIDE; void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) Q_DECL_OVERRIDE; void bindUniform(const QVariant &v, const ShaderUniform &description) Q_DECL_OVERRIDE; void blendEquation(GLenum mode) Q_DECL_OVERRIDE; diff --git a/src/render/graphicshelpers/graphicshelpergl2.cpp b/src/render/graphicshelpers/graphicshelpergl2.cpp index 28283928a..55676a6bf 100644 --- a/src/render/graphicshelpers/graphicshelpergl2.cpp +++ b/src/render/graphicshelpers/graphicshelpergl2.cpp @@ -453,6 +453,14 @@ void GraphicsHelperGL2::bindUniformBlock(GLuint programId, GLuint uniformBlockIn qWarning() << "UBO are not supported by OpenGL 2.0 (since OpenGL 3.1)"; } +void GraphicsHelperGL2::bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) +{ + Q_UNUSED(programId); + Q_UNUSED(shaderStorageBlockIndex); + Q_UNUSED(shaderStorageBlockBinding); + qWarning() << "SSBO are not supported by OpenGL 2.0 (since OpenGL 4.3)"; +} + void GraphicsHelperGL2::bindBufferBase(GLenum target, GLuint index, GLuint buffer) { Q_UNUSED(target); diff --git a/src/render/graphicshelpers/graphicshelpergl2_p.h b/src/render/graphicshelpers/graphicshelpergl2_p.h index 0ad6a39d8..cb7596f4a 100644 --- a/src/render/graphicshelpers/graphicshelpergl2_p.h +++ b/src/render/graphicshelpers/graphicshelpergl2_p.h @@ -71,6 +71,7 @@ public: void bindFragDataLocation(GLuint shader, const QHash<QString, int> &outputs) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferObject(GLuint frameBufferId) Q_DECL_OVERRIDE; + void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) Q_DECL_OVERRIDE; void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) Q_DECL_OVERRIDE; void bindUniform(const QVariant &v, const ShaderUniform &description) Q_DECL_OVERRIDE; void blendEquation(GLenum mode) Q_DECL_OVERRIDE; diff --git a/src/render/graphicshelpers/graphicshelpergl3.cpp b/src/render/graphicshelpers/graphicshelpergl3.cpp index 91339da74..64c0c1b03 100644 --- a/src/render/graphicshelpers/graphicshelpergl3.cpp +++ b/src/render/graphicshelpers/graphicshelpergl3.cpp @@ -571,6 +571,14 @@ void GraphicsHelperGL3::bindUniformBlock(GLuint programId, GLuint uniformBlockIn m_funcs->glUniformBlockBinding(programId, uniformBlockIndex, uniformBlockBinding); } +void GraphicsHelperGL3::bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) +{ + Q_UNUSED(programId); + Q_UNUSED(shaderStorageBlockIndex); + Q_UNUSED(shaderStorageBlockBinding); + qWarning() << "SSBO are not supported by OpenGL 3.0 (since OpenGL 4.3)"; +} + void GraphicsHelperGL3::bindBufferBase(GLenum target, GLuint index, GLuint buffer) { m_funcs->glBindBufferBase(target, index, buffer); diff --git a/src/render/graphicshelpers/graphicshelpergl3_3.cpp b/src/render/graphicshelpers/graphicshelpergl3_3.cpp index 4e916755a..e74968db9 100644 --- a/src/render/graphicshelpers/graphicshelpergl3_3.cpp +++ b/src/render/graphicshelpers/graphicshelpergl3_3.cpp @@ -568,6 +568,14 @@ void GraphicsHelperGL3_3::bindUniformBlock(GLuint programId, GLuint uniformBlock m_funcs->glUniformBlockBinding(programId, uniformBlockIndex, uniformBlockBinding); } +void GraphicsHelperGL3_3::bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) +{ + Q_UNUSED(programId); + Q_UNUSED(shaderStorageBlockIndex); + Q_UNUSED(shaderStorageBlockBinding); + qWarning() << "SSBO are not supported by OpenGL 3.3 (since OpenGL 4.3)"; +} + void GraphicsHelperGL3_3::bindBufferBase(GLenum target, GLuint index, GLuint buffer) { m_funcs->glBindBufferBase(target, index, buffer); diff --git a/src/render/graphicshelpers/graphicshelpergl3_3_p.h b/src/render/graphicshelpers/graphicshelpergl3_3_p.h index bce7efdd7..837a61673 100644 --- a/src/render/graphicshelpers/graphicshelpergl3_3_p.h +++ b/src/render/graphicshelpers/graphicshelpergl3_3_p.h @@ -72,6 +72,7 @@ public: void bindFragDataLocation(GLuint shader, const QHash<QString, int> &outputs) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferObject(GLuint frameBufferId) Q_DECL_OVERRIDE; + void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) Q_DECL_OVERRIDE; void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) Q_DECL_OVERRIDE; void bindUniform(const QVariant &v, const ShaderUniform &description) Q_DECL_OVERRIDE; void blendEquation(GLenum mode) Q_DECL_OVERRIDE; diff --git a/src/render/graphicshelpers/graphicshelpergl3_p.h b/src/render/graphicshelpers/graphicshelpergl3_p.h index 56bce6f07..11d5c567c 100644 --- a/src/render/graphicshelpers/graphicshelpergl3_p.h +++ b/src/render/graphicshelpers/graphicshelpergl3_p.h @@ -72,6 +72,7 @@ public: void bindFragDataLocation(GLuint shader, const QHash<QString, int> &outputs) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferObject(GLuint frameBufferId) Q_DECL_OVERRIDE; + void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) Q_DECL_OVERRIDE; void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) Q_DECL_OVERRIDE; void bindUniform(const QVariant &v, const ShaderUniform &description) Q_DECL_OVERRIDE; void blendEquation(GLenum mode) Q_DECL_OVERRIDE; diff --git a/src/render/graphicshelpers/graphicshelpergl4.cpp b/src/render/graphicshelpers/graphicshelpergl4.cpp index df9a2f839..86b17e7f3 100644 --- a/src/render/graphicshelpers/graphicshelpergl4.cpp +++ b/src/render/graphicshelpers/graphicshelpergl4.cpp @@ -566,6 +566,11 @@ void GraphicsHelperGL4::bindUniformBlock(GLuint programId, GLuint uniformBlockIn m_funcs->glUniformBlockBinding(programId, uniformBlockIndex, uniformBlockBinding); } +void GraphicsHelperGL4::bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) +{ + m_funcs->glShaderStorageBlockBinding(programId, shaderStorageBlockIndex, shaderStorageBlockBinding); +} + void GraphicsHelperGL4::bindBufferBase(GLenum target, GLuint index, GLuint buffer) { m_funcs->glBindBufferBase(target, index, buffer); diff --git a/src/render/graphicshelpers/graphicshelpergl4_p.h b/src/render/graphicshelpers/graphicshelpergl4_p.h index aaf840d10..4077a7828 100644 --- a/src/render/graphicshelpers/graphicshelpergl4_p.h +++ b/src/render/graphicshelpers/graphicshelpergl4_p.h @@ -71,6 +71,7 @@ public: void bindFragDataLocation(GLuint shader, const QHash<QString, int> &outputs) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferObject(GLuint frameBufferId) Q_DECL_OVERRIDE; + void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) Q_DECL_OVERRIDE; void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) Q_DECL_OVERRIDE; void bindUniform(const QVariant &v, const ShaderUniform &description) Q_DECL_OVERRIDE; void blendEquation(GLenum mode) Q_DECL_OVERRIDE; diff --git a/src/render/graphicshelpers/graphicshelperinterface_p.h b/src/render/graphicshelpers/graphicshelperinterface_p.h index 95264dc49..caeb8f0c0 100644 --- a/src/render/graphicshelpers/graphicshelperinterface_p.h +++ b/src/render/graphicshelpers/graphicshelperinterface_p.h @@ -80,6 +80,7 @@ public: virtual void bindFragDataLocation(GLuint shader, const QHash<QString, int> &outputs) = 0; virtual void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) = 0; virtual void bindFrameBufferObject(GLuint frameBufferId) = 0; + virtual void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) = 0; virtual void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0; virtual void bindUniform(const QVariant &v, const ShaderUniform &description) = 0; virtual void blendEquation(GLenum mode) = 0; diff --git a/src/render/io/glbuffer.cpp b/src/render/io/glbuffer.cpp index 8e7636964..d059949db 100644 --- a/src/render/io/glbuffer.cpp +++ b/src/render/io/glbuffer.cpp @@ -133,7 +133,12 @@ void GLBuffer::update(GraphicsContext *ctx, const void *data, uint size, int off ctx->openGLContext()->functions()->glBufferSubData(m_lastTarget, offset, size, data); } -void GLBuffer::bindToUniformBlock(GraphicsContext *ctx, int bindingPoint) +void GLBuffer::bindBufferBase(GraphicsContext *ctx, int bindingPoint, GLBuffer::Type t) +{ + ctx->bindBufferBase(glBufferTypes[t], bindingPoint, m_bufferId); +} + +void GLBuffer::bindBufferBase(GraphicsContext *ctx, int bindingPoint) { ctx->bindBufferBase(m_lastTarget, bindingPoint, m_bufferId); } diff --git a/src/render/io/glbuffer_p.h b/src/render/io/glbuffer_p.h index 1dc8adb3c..4eeae9624 100644 --- a/src/render/io/glbuffer_p.h +++ b/src/render/io/glbuffer_p.h @@ -81,7 +81,8 @@ public: void allocate(GraphicsContext *ctx, uint size, bool dynamic = true); void allocate(GraphicsContext *ctx, const void *data, uint size, bool dynamic = true); void update(GraphicsContext *ctx, const void *data, uint size, int offset = 0); - void bindToUniformBlock(GraphicsContext *ctx, int bindingPoint); + void bindBufferBase(GraphicsContext *ctx, int bindingPoint, Type t); + void bindBufferBase(GraphicsContext *ctx, int bindingPoint); inline GLuint bufferId() const { return m_bufferId; } inline bool isCreated() const { return m_isCreated; } |