summaryrefslogtreecommitdiffstats
path: root/src/render/backend
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2015-12-10 13:06:33 +0100
committerPaul Lemire <paul.lemire@kdab.com>2016-01-13 16:10:36 +0000
commit412a1d9b1d0b73fcc99c73bd89457cc11ece00fa (patch)
tree0472dcf48168c4903fa6faf148ae08bc1bd3fd13 /src/render/backend
parent9add600584ab87c80d439c0d5571994d72af3477 (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.cpp5
-rw-r--r--src/render/backend/quniformvalue_p.h11
-rw-r--r--src/render/backend/rendercommand_p.h2
-rw-r--r--src/render/backend/renderer.cpp4
-rw-r--r--src/render/backend/renderview.cpp140
-rw-r--r--src/render/backend/renderview_p.h4
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(&parameters, 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,