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/backend | |
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/backend')
-rw-r--r-- | src/render/backend/quniformvalue.cpp | 5 | ||||
-rw-r--r-- | src/render/backend/quniformvalue_p.h | 11 | ||||
-rw-r--r-- | src/render/backend/rendercommand_p.h | 2 | ||||
-rw-r--r-- | src/render/backend/renderer.cpp | 4 | ||||
-rw-r--r-- | src/render/backend/renderview.cpp | 140 | ||||
-rw-r--r-- | src/render/backend/renderview_p.h | 4 |
6 files changed, 117 insertions, 49 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, |