summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/qt3d/compute-particles/ParticlesScene.qml1
-rw-r--r--examples/qt3d/compute-particles/main.qml21
-rw-r--r--src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp32
-rw-r--r--src/plugins/renderers/rhi/io/rhibuffer.cpp38
-rw-r--r--src/plugins/renderers/rhi/io/rhibuffer_p.h14
-rw-r--r--src/plugins/renderers/rhi/managers/rhihandle_types_p.h2
-rw-r--r--src/plugins/renderers/rhi/managers/rhiresourcemanagers.cpp5
-rw-r--r--src/plugins/renderers/rhi/managers/rhiresourcemanagers_p.h28
-rw-r--r--src/plugins/renderers/rhi/renderer/pipelineuboset_p.h3
-rw-r--r--src/plugins/renderers/rhi/renderer/rendercommand.cpp20
-rw-r--r--src/plugins/renderers/rhi/renderer/rendercommand_p.h32
-rw-r--r--src/plugins/renderers/rhi/renderer/renderer.cpp296
-rw-r--r--src/plugins/renderers/rhi/renderer/renderer_p.h19
-rw-r--r--src/plugins/renderers/rhi/renderer/renderview.cpp6
-rw-r--r--src/plugins/renderers/rhi/renderer/rhigraphicspipeline.cpp24
-rw-r--r--src/plugins/renderers/rhi/renderer/rhigraphicspipeline_p.h71
-rw-r--r--src/plugins/renderers/rhi/renderer/rhishader.cpp60
17 files changed, 494 insertions, 178 deletions
diff --git a/examples/qt3d/compute-particles/ParticlesScene.qml b/examples/qt3d/compute-particles/ParticlesScene.qml
index e63c6cb91..2c74f51b5 100644
--- a/examples/qt3d/compute-particles/ParticlesScene.qml
+++ b/examples/qt3d/compute-particles/ParticlesScene.qml
@@ -117,7 +117,6 @@ Entity {
Buffer {
id: particleBuffer
- type: Buffer.VertexBuffer
// struct ParticleData
// {
// vec3 position; // Aligned to 4 floats
diff --git a/examples/qt3d/compute-particles/main.qml b/examples/qt3d/compute-particles/main.qml
index de5666fad..1375b312a 100644
--- a/examples/qt3d/compute-particles/main.qml
+++ b/examples/qt3d/compute-particles/main.qml
@@ -50,7 +50,7 @@
import QtQuick 2.0
import QtQuick.Scene3D 2.0
-import QtQuick.Controls 1.4
+import QtQuick.Controls 2.0
import QtQuick.Layouts 1.1
Item {
@@ -84,8 +84,8 @@ Item {
height: 35
id: stepSlider
Layout.fillWidth: true
- minimumValue: 0.0
- maximumValue: 2
+ from: 0.0
+ to: 2
value: 0.4
}
}
@@ -98,8 +98,8 @@ Item {
height: 35
id: collisionSlider
Layout.fillWidth: true
- minimumValue: 0.0
- maximumValue: 2
+ from: 0.0
+ to: 2
value: 0.2
}
}
@@ -114,31 +114,32 @@ Item {
text: "Particles Shape:"
color: "white"
}
- ExclusiveGroup {
+ ButtonGroup {
+ exclusive: true
id: particlesTypeGroup
}
CheckBox {
text: "Sphere"
checked: true
- exclusiveGroup: particlesTypeGroup
+ ButtonGroup.group: particlesTypeGroup
onClicked: scene.particlesShape = scene._SPHERE
}
CheckBox
{ text: "Cube"
checked: false
- exclusiveGroup: particlesTypeGroup
+ ButtonGroup.group: particlesTypeGroup
onClicked: scene.particlesShape = scene._CUBE
}
CheckBox {
text: "Cylinder"
checked: false
- exclusiveGroup: particlesTypeGroup
+ ButtonGroup.group: particlesTypeGroup
onClicked: scene.particlesShape = scene._CYLINDER
}
CheckBox {
text: "Torus"
checked: false
- exclusiveGroup: particlesTypeGroup
+ ButtonGroup.group: particlesTypeGroup
onClicked: scene.particlesShape = scene._TORUS
}
}
diff --git a/src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp b/src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp
index 17119e504..15add3310 100644
--- a/src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp
+++ b/src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp
@@ -1665,20 +1665,32 @@ SubmissionContext::ShaderCreationInfo SubmissionContext::createShaderProgram(RHI
// Compile shaders
const auto &shaderCode = shader->shaderCode();
QShaderBaker b;
- b.setGeneratedShaders({
- { QShader::SpirvShader, 100 },
-#ifndef QT_NO_OPENGL
- { QShader::GlslShader, glslVersionForFormat(format()) },
+ QVector<QShaderBaker::GeneratedShader> generatedShaders;
+
+#if QT_FEATURE_vulkan
+ generatedShaders.push_back({ QShader::SpirvShader, 100 });
#endif
- { QShader::HlslShader, QShaderVersion(50) },
- { QShader::MslShader, QShaderVersion(12) },
- });
- b.setGeneratedShaderVariants({ QShader::Variant {},
#ifndef QT_NO_OPENGL
- QShader::Variant {},
+ // GLES2 RHI backend does not seem to support compute
+ //if (shaderCode.at(QShaderProgram::Compute).isEmpty())
+ {
+ generatedShaders.push_back({ QShader::GlslShader, glslVersionForFormat(format()) });
+ }
+#endif
+
+#if Q_OS_WIN
+ generatedShaders.push_back({ QShader::HlslShader, QShaderVersion(50) });
+#endif
+
+#if Q_OS_MACOS
+ generatedShaders.push_back({ QShader::MslShader, QShaderVersion(12) });
#endif
- QShader::Variant {}, QShader::Variant {} });
+
+ QVector<QShader::Variant> generatedShaderVariants(generatedShaders.size());
+
+ b.setGeneratedShaders(generatedShaders);
+ b.setGeneratedShaderVariants(generatedShaderVariants);
// TODO handle caching as QShader does not have a built-in mechanism for that
QString logs;
diff --git a/src/plugins/renderers/rhi/io/rhibuffer.cpp b/src/plugins/renderers/rhi/io/rhibuffer.cpp
index 0f19bf250..fb1dd9f81 100644
--- a/src/plugins/renderers/rhi/io/rhibuffer.cpp
+++ b/src/plugins/renderers/rhi/io/rhibuffer.cpp
@@ -49,19 +49,23 @@ namespace Render {
namespace Rhi {
namespace {
-QRhiBuffer::UsageFlag bufferTypeToRhi(RHIBuffer::Type t)
+QRhiBuffer::UsageFlags bufferTypeToRhi(RHIBuffer::Type t)
{
- switch (t) {
- case RHIBuffer::Type::ArrayBuffer:
- return QRhiBuffer::VertexBuffer;
- case RHIBuffer::Type::IndexBuffer:
- return QRhiBuffer::IndexBuffer;
- case RHIBuffer::Type::UniformBuffer:
- return QRhiBuffer::UniformBuffer;
- default:
- RHI_UNIMPLEMENTED;
- return QRhiBuffer::StorageBuffer;
- }
+ QRhiBuffer::UsageFlags flag{};
+
+ if (t & RHIBuffer::Type::ArrayBuffer)
+ flag |= QRhiBuffer::VertexBuffer;
+
+ if (t & RHIBuffer::Type::IndexBuffer)
+ flag |= QRhiBuffer::IndexBuffer;
+
+ if (t & RHIBuffer::Type::UniformBuffer)
+ flag |= QRhiBuffer::UniformBuffer;
+
+ if (t & RHIBuffer::Type::ShaderStorageBuffer)
+ flag |= QRhiBuffer::StorageBuffer;
+
+ return flag;
}
}
@@ -90,8 +94,11 @@ bool RHIBuffer::bind(SubmissionContext *ctx, Type t)
const auto usage = bufferTypeToRhi(t);
m_rhiBuffer = ctx->rhi()->newBuffer(kind, usage, m_allocSize);
+ assert(m_rhiBuffer);
+
if (!m_rhiBuffer->create())
return false;
+
#if defined(QT_DEBUG)
{
// for debug: we set the buffer to zero
@@ -99,10 +106,15 @@ bool RHIBuffer::bind(SubmissionContext *ctx, Type t)
(ctx->m_currentUpdates->*uploadMethod)(m_rhiBuffer, 0, m_allocSize, ptr);
delete[] ptr;
}
-#endif
}
+#endif
assert(m_rhiBuffer);
+#if defined(QT_DEBUG)
+ // RHI does not seem to support using the same buffer with different types
+ assert(m_rhiBuffer->usage() == bufferTypeToRhi(t));
+#endif
+
for (const std::pair<QByteArray, int> &pair : this->m_datasToUpload) {
const QByteArray &data = pair.first;
int offset = pair.second;
diff --git a/src/plugins/renderers/rhi/io/rhibuffer_p.h b/src/plugins/renderers/rhi/io/rhibuffer_p.h
index 4d13836b7..7d4a3c54f 100644
--- a/src/plugins/renderers/rhi/io/rhibuffer_p.h
+++ b/src/plugins/renderers/rhi/io/rhibuffer_p.h
@@ -70,13 +70,13 @@ public:
RHIBuffer();
enum Type {
- ArrayBuffer = 0,
- UniformBuffer,
- IndexBuffer,
- ShaderStorageBuffer,
- PixelPackBuffer,
- PixelUnpackBuffer,
- DrawIndirectBuffer
+ ArrayBuffer = 1 << 0,
+ UniformBuffer = 1 << 1,
+ IndexBuffer = 1 << 2,
+ ShaderStorageBuffer = 1 << 3,
+ PixelPackBuffer = 1 << 4,
+ PixelUnpackBuffer = 1 << 5,
+ DrawIndirectBuffer = 1 << 6
};
bool bind(SubmissionContext *ctx, Type t);
diff --git a/src/plugins/renderers/rhi/managers/rhihandle_types_p.h b/src/plugins/renderers/rhi/managers/rhihandle_types_p.h
index 3a042a9be..8ae440e6d 100644
--- a/src/plugins/renderers/rhi/managers/rhihandle_types_p.h
+++ b/src/plugins/renderers/rhi/managers/rhihandle_types_p.h
@@ -64,11 +64,13 @@ namespace Rhi {
class RHIBuffer;
class RHITexture;
class RHIGraphicsPipeline;
+class RHIComputePipeline;
struct RHIRenderTarget;
typedef Qt3DCore::QHandle<RHIBuffer> HRHIBuffer;
typedef Qt3DCore::QHandle<RHITexture> HRHITexture;
typedef Qt3DCore::QHandle<RHIGraphicsPipeline> HRHIGraphicsPipeline;
+typedef Qt3DCore::QHandle<RHIComputePipeline> HRHIComputePipeline;
typedef Qt3DCore::QHandle<RHIRenderTarget> HRHIRenderTarget;
} // namespace Rhi
diff --git a/src/plugins/renderers/rhi/managers/rhiresourcemanagers.cpp b/src/plugins/renderers/rhi/managers/rhiresourcemanagers.cpp
index 387464fe4..8fca77247 100644
--- a/src/plugins/renderers/rhi/managers/rhiresourcemanagers.cpp
+++ b/src/plugins/renderers/rhi/managers/rhiresourcemanagers.cpp
@@ -52,7 +52,8 @@ RHIResourceManagers::RHIResourceManagers()
m_rhiShaderManager(new RHIShaderManager()),
m_rhiTextureManager(new RHITextureManager()),
m_rhiRenderTargetManager(new RHIRenderTargetManager()),
- m_rhiGraphicsPipelineManager(new RHIGraphicsPipelineManager())
+ m_rhiGraphicsPipelineManager(new RHIGraphicsPipelineManager()),
+ m_rhiComputePipelineManager(new RHIComputePipelineManager())
{
}
@@ -63,6 +64,7 @@ RHIResourceManagers::~RHIResourceManagers()
delete m_rhiBufferManager;
delete m_rhiRenderTargetManager;
delete m_rhiGraphicsPipelineManager;
+ delete m_rhiComputePipelineManager;
}
void RHIResourceManagers::releaseAllResources()
@@ -82,6 +84,7 @@ void RHIResourceManagers::releaseAllResources()
// releaseAll(m_rhiShaderManager);
releaseAll(m_rhiRenderTargetManager);
releaseAll(m_rhiGraphicsPipelineManager);
+ releaseAll(m_rhiComputePipelineManager);
}
int RHIGraphicsPipelineManager::getIdForAttributeVec(const std::vector<AttributeInfo> &attributesInfo)
diff --git a/src/plugins/renderers/rhi/managers/rhiresourcemanagers_p.h b/src/plugins/renderers/rhi/managers/rhiresourcemanagers_p.h
index 48e9d8300..a323632fb 100644
--- a/src/plugins/renderers/rhi/managers/rhiresourcemanagers_p.h
+++ b/src/plugins/renderers/rhi/managers/rhiresourcemanagers_p.h
@@ -109,6 +109,14 @@ private:
std::vector<AttributeInfoVec> m_attributesInfo;
};
+class Q_AUTOTEST_EXPORT RHIComputePipelineManager
+ : public Qt3DCore::QResourceManager<RHIComputePipeline, ComputePipelineIdentifier,
+ Qt3DCore::NonLockingPolicy>
+{
+public:
+ RHIComputePipelineManager() { }
+};
+
class Q_AUTOTEST_EXPORT RHIResourceManagers
{
public:
@@ -123,6 +131,10 @@ public:
{
return m_rhiGraphicsPipelineManager;
}
+ inline RHIComputePipelineManager *rhiComputePipelineManager() const noexcept
+ {
+ return m_rhiComputePipelineManager;
+ }
void releaseAllResources();
@@ -132,6 +144,7 @@ private:
RHITextureManager *m_rhiTextureManager;
RHIRenderTargetManager *m_rhiRenderTargetManager;
RHIGraphicsPipelineManager *m_rhiGraphicsPipelineManager;
+ RHIComputePipelineManager *m_rhiComputePipelineManager;
};
inline uint qHash(const GraphicsPipelineIdentifier &key, uint seed = 0)
@@ -152,6 +165,20 @@ inline bool operator==(const GraphicsPipelineIdentifier &a, const GraphicsPipeli
a.renderViewIndex == b.renderViewIndex;
}
+inline uint qHash(const ComputePipelineIdentifier &key, uint seed = 0)
+{
+ using QT_PREPEND_NAMESPACE(qHash);
+ seed = qHash(key.shader, seed);
+ seed = qHash(key.renderViewIndex, seed);
+ return seed;
+}
+
+inline bool operator==(const ComputePipelineIdentifier &a, const ComputePipelineIdentifier &b)
+{
+ return a.shader == b.shader &&
+ a.renderViewIndex == b.renderViewIndex;
+}
+
} // Rhi
} // Render
@@ -159,6 +186,7 @@ inline bool operator==(const GraphicsPipelineIdentifier &a, const GraphicsPipeli
} // Qt3DRender
Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::Rhi::RHIGraphicsPipeline, Q_REQUIRES_CLEANUP)
+Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::Rhi::RHIComputePipeline, Q_REQUIRES_CLEANUP)
Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::Rhi::RHITexture, Q_REQUIRES_CLEANUP)
Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::Rhi::RHIBuffer, Q_REQUIRES_CLEANUP)
Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::Rhi::RHIRenderTarget, Q_REQUIRES_CLEANUP)
diff --git a/src/plugins/renderers/rhi/renderer/pipelineuboset_p.h b/src/plugins/renderers/rhi/renderer/pipelineuboset_p.h
index 699ff0602..d56adab12 100644
--- a/src/plugins/renderers/rhi/renderer/pipelineuboset_p.h
+++ b/src/plugins/renderers/rhi/renderer/pipelineuboset_p.h
@@ -110,7 +110,8 @@ private:
std::vector<const RenderCommand *> m_renderCommands;
RHIResourceManagers *m_resourceManagers = nullptr;
- friend class RHIGraphicsPipeline;
+ template<typename Pipeline, typename Key>
+ friend class RHIPipelineBase;
};
diff --git a/src/plugins/renderers/rhi/renderer/rendercommand.cpp b/src/plugins/renderers/rhi/renderer/rendercommand.cpp
index 9e82192f5..06fb3bec0 100644
--- a/src/plugins/renderers/rhi/renderer/rendercommand.cpp
+++ b/src/plugins/renderers/rhi/renderer/rendercommand.cpp
@@ -46,6 +46,22 @@ namespace Qt3DRender {
namespace Render {
namespace Rhi {
+bool RenderCommand::Pipeline::isValid() const noexcept
+{
+ struct {
+ bool operator()(RHIGraphicsPipeline* pipeline) const noexcept {
+ return pipeline && pipeline->pipeline();
+ }
+ bool operator()(RHIComputePipeline* pipeline) const noexcept {
+ return pipeline && pipeline->pipeline();
+ }
+ bool operator()(std::monostate) const noexcept {
+ return false;
+ }
+ } visitor;
+ return this->visit(visitor);
+}
+
RenderCommand::RenderCommand()
: m_rhiShader(nullptr),
m_stateSet(nullptr),
@@ -71,7 +87,7 @@ RenderCommand::RenderCommand()
indexAttribute(nullptr),
indexBuffer(nullptr),
m_commandUBO(),
- pipeline(nullptr)
+ pipeline()
{
m_workGroups[0] = 0;
@@ -81,7 +97,7 @@ RenderCommand::RenderCommand()
bool RenderCommand::isValid() const noexcept
{
- return m_isValid && m_rhiShader && pipeline && pipeline->pipeline();
+ return m_isValid && m_rhiShader && pipeline.isValid();
}
bool operator==(const RenderCommand &a, const RenderCommand &b) noexcept
diff --git a/src/plugins/renderers/rhi/renderer/rendercommand_p.h b/src/plugins/renderers/rhi/renderer/rendercommand_p.h
index 6f0169acf..031b4fca2 100644
--- a/src/plugins/renderers/rhi/renderer/rendercommand_p.h
+++ b/src/plugins/renderers/rhi/renderer/rendercommand_p.h
@@ -64,6 +64,7 @@
#include <QMatrix4x4>
#include <QtGui/private/qrhi_p.h>
#include <Qt3DCore/qattribute.h>
+#include <variant>
QT_BEGIN_NAMESPACE
class QRhiGraphicsPipeline;
@@ -89,6 +90,7 @@ namespace Rhi {
class RHIShader;
class RHIGraphicsPipeline;
+class RHIComputePipeline;
struct CommandUBO
{
@@ -125,7 +127,7 @@ public:
HMaterial m_material; // Purely used to ease sorting (minimize stage changes, binding changes
// ....)
- RHIShader *m_rhiShader; // GL Shader to be used at render time
+ RHIShader *m_rhiShader; // Shader to be used at render time
Qt3DCore::QNodeId m_shaderId; // Shader for given pass and mesh
ShaderParameterPack m_parameterPack; // Might need to be reworked so as to be able to destroy
// the Texture while submission is happening.
@@ -174,9 +176,35 @@ public:
QRhiBuffer *indexBuffer {};
CommandUBO m_commandUBO;
- RHIGraphicsPipeline *pipeline {};
QRhiShaderResourceBindings *shaderResourceBindings = nullptr;
std::vector<QRhiShaderResourceBinding> resourcesBindings;
+
+ struct Pipeline : std::variant<std::monostate, RHIGraphicsPipeline *, RHIComputePipeline*>
+ {
+ using variant::variant;
+
+ bool isValid() const noexcept;
+
+ RHIGraphicsPipeline* graphics() const noexcept
+ {
+ auto ptr = std::get_if<RHIGraphicsPipeline*>(this);
+ return ptr ? *ptr : nullptr;
+ }
+
+ RHIComputePipeline* compute() const noexcept
+ {
+ auto ptr = std::get_if<RHIComputePipeline*>(this);
+ return ptr ? *ptr : nullptr;
+ }
+
+ template<typename F>
+ auto visit(F&& f) const noexcept(noexcept(std::visit(f, (const variant&) *this)))
+ {
+ return std::visit(f, (const variant&) *this);
+ }
+ };
+
+ Pipeline pipeline {};
};
Q_AUTOTEST_EXPORT bool operator==(const RenderCommand &a, const RenderCommand &b) noexcept;
diff --git a/src/plugins/renderers/rhi/renderer/renderer.cpp b/src/plugins/renderers/rhi/renderer/renderer.cpp
index f33626b8f..73d15d51b 100644
--- a/src/plugins/renderers/rhi/renderer/renderer.cpp
+++ b/src/plugins/renderers/rhi/renderer/renderer.cpp
@@ -894,7 +894,7 @@ void Renderer::updateGraphicsPipeline(RenderCommand &cmd, RenderView *rv,
graphicsPipeline->uboSet()->addRenderCommand(cmd);
// Store association between RV and pipeline
- if (auto& pipelines = m_rvToPipelines[rv]; !Qt3DCore::contains(pipelines, graphicsPipeline))
+ if (auto& pipelines = m_rvToGraphicsPipelines[rv]; !Qt3DCore::contains(pipelines, graphicsPipeline))
pipelines.push_back(graphicsPipeline);
// Record RHIGraphicsPipeline into command for later use
@@ -1015,6 +1015,95 @@ void Renderer::buildGraphicsPipelines(RHIGraphicsPipeline *graphicsPipeline,
return onFailure();
}
+void Renderer::updateComputePipeline(RenderCommand &cmd, RenderView *rv, int renderViewIndex)
+{
+ if (!cmd.m_rhiShader) {
+ qDebug() << "Warning: command has no shader";
+ return;
+ }
+
+ // Try to retrieve existing pipeline
+ RHIComputePipelineManager *pipelineManager = m_RHIResourceManagers->rhiComputePipelineManager();
+ const ComputePipelineIdentifier pipelineKey { cmd.m_shaderId, renderViewIndex };
+ RHIComputePipeline *computePipeline = pipelineManager->lookupResource(pipelineKey);
+ if (computePipeline == nullptr) {
+ // Init UBOSet the first time we allocate a new pipeline
+ computePipeline = pipelineManager->getOrCreateResource(pipelineKey);
+ computePipeline->setKey(pipelineKey);
+ computePipeline->uboSet()->setResourceManager(m_RHIResourceManagers);
+ computePipeline->uboSet()->initializeLayout(m_submissionContext.data(), cmd.m_rhiShader);
+ }
+
+ if (!computePipeline) {
+ qDebug() << "Warning : could not create a compute pipeline";
+ return;
+ }
+
+ // Increase score so that we know the pipeline was used for this frame and shouldn't be
+ // destroyed
+ computePipeline->increaseScore();
+
+ // Record command reference in UBOSet
+ computePipeline->uboSet()->addRenderCommand(cmd);
+
+ // Store association between RV and pipeline
+ if (auto& pipelines = m_rvToComputePipelines[rv]; !Qt3DCore::contains(pipelines, computePipeline))
+ pipelines.push_back(computePipeline);
+
+ // Record RHIGraphicsPipeline into command for later use
+ cmd.pipeline = computePipeline;
+
+ // TO DO: Set to true if geometry, shader or render state dirty
+ bool requiredRebuild = false;
+
+ // Note: we can rebuild add/remove things from the QRhiShaderResourceBindings after having
+ // created the pipeline and rebuild it. Changes should be picked up automatically
+
+ // Create pipeline if it doesn't exist or needs to be updated
+ if (computePipeline->pipeline() == nullptr || requiredRebuild)
+ buildComputePipelines(computePipeline, rv, cmd);
+}
+
+void Renderer::buildComputePipelines(RHIComputePipeline *computePipeline,
+ RenderView *rv,
+ const RenderCommand &cmd)
+{
+ const auto bufManager = m_RHIResourceManagers->rhiBufferManager();
+ auto onFailure = [&] { computePipeline->cleanup(); };
+
+ PipelineUBOSet *uboSet = computePipeline->uboSet();
+ RHIShader *shader = cmd.m_rhiShader;
+
+ // Setup shaders
+ const QShader& computeShader = cmd.m_rhiShader->shaderStage(QShader::ComputeStage);
+ if (!computeShader.isValid()) {
+ return onFailure();
+ }
+
+ // Set Resource Bindings
+ const std::vector<QRhiShaderResourceBinding> resourceBindings = uboSet->resourceLayout(shader);
+ QRhiShaderResourceBindings *shaderResourceBindings =
+ m_submissionContext->rhi()->newShaderResourceBindings();
+ computePipeline->setShaderResourceBindings(shaderResourceBindings);
+
+ shaderResourceBindings->setBindings(resourceBindings.cbegin(), resourceBindings.cend());
+ if (!shaderResourceBindings->create()) {
+ return onFailure();
+ }
+
+ // Create pipeline
+ QRhiComputePipeline *pipeline = m_submissionContext->rhi()->newComputePipeline();
+ computePipeline->setPipeline(pipeline);
+
+ pipeline->setShaderStage(QRhiShaderStage{QRhiShaderStage::Compute, computeShader});
+ pipeline->setShaderResourceBindings(shaderResourceBindings);
+
+ // QRhiComputePiple has no render states
+
+ if (!pipeline->create())
+ return onFailure();
+}
+
void Renderer::createRenderTarget(RenderView *rv, RHIRenderTarget *target)
{
// Used in case of failure
@@ -1182,18 +1271,25 @@ Renderer::prepareCommandsSubmission(const std::vector<RenderView *> &renderViews
// -> The number of RenderCommands used by each pipeline
// This will allows us to generate UBOs based on the number of commands/rv we have
- RHIGraphicsPipelineManager *pipelineManager =
- m_RHIResourceManagers->rhiGraphicsPipelineManager();
- const std::vector<HRHIGraphicsPipeline> &graphicsPipelinesHandles = pipelineManager->activeHandles();
+ RHIGraphicsPipelineManager *graphicsPipelineManager = m_RHIResourceManagers->rhiGraphicsPipelineManager();
+ const std::vector<HRHIGraphicsPipeline> &graphicsPipelinesHandles = graphicsPipelineManager->activeHandles();
for (HRHIGraphicsPipeline pipelineHandle : graphicsPipelinesHandles) {
- RHIGraphicsPipeline *pipeline = pipelineManager->data(pipelineHandle);
+ RHIGraphicsPipeline *pipeline = graphicsPipelineManager->data(pipelineHandle);
+ // Reset PipelineUBOSet
+ pipeline->uboSet()->clear();
+ }
+ RHIComputePipelineManager *computePipelineManager = m_RHIResourceManagers->rhiComputePipelineManager();
+ const std::vector<HRHIComputePipeline> &computePipelinesHandles = computePipelineManager->activeHandles();
+ for (HRHIComputePipeline pipelineHandle : computePipelinesHandles) {
+ RHIComputePipeline *pipeline = computePipelineManager->data(pipelineHandle);
// Reset PipelineUBOSet
pipeline->uboSet()->clear();
}
// Clear any reference between RV and Pipelines we had
// as we are about to rebuild these
- m_rvToPipelines.clear();
+ m_rvToGraphicsPipelines.clear();
+ m_rvToComputePipelines.clear();
// We need to have a single RHI RenderPass per RenderTarget
// as creating the pass clears the buffers
@@ -1257,6 +1353,8 @@ Renderer::prepareCommandsSubmission(const std::vector<RenderView *> &renderViews
// By this time shaders have been loaded
RHIShader *shader = command.m_rhiShader;
Q_ASSERT(shader);
+
+ updateComputePipeline(command, rv, i);
}
});
}
@@ -1265,10 +1363,13 @@ Renderer::prepareCommandsSubmission(const std::vector<RenderView *> &renderViews
// has, we can allocate/reallocate UBOs with correct size for each pipelines
for (RenderView *rv : renderViews) {
// Allocate UBOs for pipelines used in current RV
- const std::vector<RHIGraphicsPipeline *> &rvPipelines = m_rvToPipelines[rv];
- for (RHIGraphicsPipeline *pipeline : rvPipelines) {
+ const std::vector<RHIGraphicsPipeline *> &rvGraphicsPipelines = m_rvToGraphicsPipelines[rv];
+ for (RHIGraphicsPipeline *pipeline : rvGraphicsPipelines)
+ pipeline->uboSet()->allocateUBOs(m_submissionContext.data());
+ // Allocate UBOs for pipelines used in current RV
+ const std::vector<RHIComputePipeline *> &rvComputePipelines = m_rvToComputePipelines[rv];
+ for (RHIComputePipeline *pipeline : rvComputePipelines)
pipeline->uboSet()->allocateUBOs(m_submissionContext.data());
- }
}
// Unset dirtiness on Geometry and Attributes
@@ -2234,9 +2335,17 @@ void Renderer::performDraw(RenderCommand *command)
// m_submissionContext->disablePrimitiveRestart();
}
-void Renderer::performCompute(const RenderView *, RenderCommand *command)
+bool Renderer::performCompute(QRhiCommandBuffer *cb, const RenderCommand &command)
{
- RHI_UNIMPLEMENTED;
+ RHIComputePipeline *pipeline = command.pipeline.compute();
+ if (!pipeline)
+ return true;
+ cb->setComputePipeline(pipeline->pipeline());
+ cb->setShaderResources();
+
+ cb->dispatch(command.m_workGroups[0], command.m_workGroups[1], command.m_workGroups[2]);
+
+
Q_UNUSED(command);
//* {
//* RHIShader *shader =
@@ -2251,14 +2360,15 @@ void Renderer::performCompute(const RenderView *, RenderCommand *command)
//* command->m_workGroups[1],
//* command->m_workGroups[2]);
//* }
- //* // HACK: Reset the compute flag to dirty
- //* m_dirtyBits.marked |= AbstractRenderer::ComputeDirty;
+ // HACK: Reset the compute flag to dirty
+ m_dirtyBits.marked |= AbstractRenderer::ComputeDirty;
//* #if defined(QT3D_RENDER_ASPECT_RHI_DEBUG)
//* int err = m_submissionContext->openGLContext()->functions()->glGetError();
//* if (err)
//* qCWarning(Rendering) << "GL error after drawing mesh:" << QString::number(err, 16);
//* #endif
+ return true;
}
static auto rhiIndexFormat(QAttribute::VertexBaseType type)
@@ -2276,12 +2386,48 @@ static auto rhiIndexFormat(QAttribute::VertexBaseType type)
bool Renderer::uploadBuffersForCommand(QRhiCommandBuffer *cb, const RenderView *rv,
RenderCommand &command)
{
- Q_UNUSED(cb);
- Q_UNUSED(rv);
- RHIGraphicsPipeline *graphicsPipeline = command.pipeline;
- if (!graphicsPipeline)
- return true;
+ struct
+ {
+ Renderer &self;
+ RenderCommand &command;
+ bool operator()(RHIGraphicsPipeline* pipeline) const noexcept {
+ if (!pipeline)
+ return true;
+
+ return self.uploadBuffersForCommand(pipeline, command);
+ }
+ bool operator()(RHIComputePipeline* pipeline) const noexcept {
+ if (!pipeline)
+ return true;
+
+ return self.uploadBuffersForCommand(pipeline, command);
+ }
+ bool operator()(std::monostate) {
+ return false;
+ }
+ } vis{*this, command};
+
+ if (!command.pipeline.visit(vis))
+ return false;
+ for (const BlockToUBO &pack : command.m_parameterPack.uniformBuffers()) {
+ Buffer *cpuBuffer = nodeManagers()->bufferManager()->lookupResource(pack.m_bufferID);
+ RHIBuffer *ubo = m_submissionContext->rhiBufferForRenderBuffer(cpuBuffer);
+ if (!ubo->bind(&*m_submissionContext, RHIBuffer::UniformBuffer))
+ return false;
+ }
+ for (const BlockToSSBO &pack : command.m_parameterPack.shaderStorageBuffers()) {
+ Buffer *cpuBuffer = nodeManagers()->bufferManager()->lookupResource(pack.m_bufferID);
+ RHIBuffer *ubo = m_submissionContext->rhiBufferForRenderBuffer(cpuBuffer);
+ if (!ubo->bind(&*m_submissionContext, RHIBuffer::ShaderStorageBuffer))
+ return false;
+ }
+
+ return true;
+}
+
+bool Renderer::uploadBuffersForCommand(RHIGraphicsPipeline* graphicsPipeline, RenderCommand &command)
+{
// Create the vertex input description
// Note: we have to bind the buffers here -> which will trigger the actual
@@ -2297,11 +2443,10 @@ bool Renderer::uploadBuffersForCommand(QRhiCommandBuffer *cb, const RenderView *
// TODO isn't there a more efficient way than doing three hash lookups ?
Attribute *attrib = m_nodesManager->attributeManager()->lookupResource(attribute_id);
Buffer *buffer = m_nodesManager->bufferManager()->lookupResource(attrib->bufferId());
- RHIBuffer *hbuf =
- m_RHIResourceManagers->rhiBufferManager()->lookupResource(buffer->peerId());
+ RHIBuffer *hbuf = m_RHIResourceManagers->rhiBufferManager()->lookupResource(buffer->peerId());
switch (attrib->attributeType()) {
case QAttribute::VertexAttribute: {
- if (!hbuf->bind(&*m_submissionContext, RHIBuffer::Type::ArrayBuffer))
+ if (!hbuf->bind(&*m_submissionContext, RHIBuffer::Type((int)RHIBuffer::Type::ArrayBuffer | (int)RHIBuffer::Type::ShaderStorageBuffer)))
return false;
assert(hbuf->rhiBuffer());
// Find Binding for Attribute
@@ -2328,20 +2473,18 @@ bool Renderer::uploadBuffersForCommand(QRhiCommandBuffer *cb, const RenderView *
}
}
- for (const BlockToUBO &pack : command.m_parameterPack.uniformBuffers()) {
- Buffer *cpuBuffer = nodeManagers()->bufferManager()->lookupResource(pack.m_bufferID);
- RHIBuffer *ubo = m_submissionContext->rhiBufferForRenderBuffer(cpuBuffer);
- if (!ubo->bind(&*m_submissionContext, RHIBuffer::UniformBuffer))
- return false;
- }
+ return true;
+}
+bool Renderer::uploadBuffersForCommand(RHIComputePipeline* computePipeline, RenderCommand &command)
+{
return true;
}
bool Renderer::performDraw(QRhiCommandBuffer *cb, const QRhiViewport &vp,
const QRhiScissor *scissor, RenderCommand &command)
{
- RHIGraphicsPipeline *pipeline = command.pipeline;
+ RHIGraphicsPipeline *pipeline = command.pipeline.graphics();
if (!pipeline)
return true;
@@ -2413,16 +2556,27 @@ bool Renderer::executeCommandsSubmission(const RHIPassInfo &passInfo)
// Render drawing commands
// Upload UBOs for pipelines used in current RV
- const std::vector<RHIGraphicsPipeline *> &rvPipelines = m_rvToPipelines[rv];
- for (RHIGraphicsPipeline *pipeline : rvPipelines) {
+ const std::vector<RHIGraphicsPipeline *> &rvGraphicsPipelines = m_rvToGraphicsPipelines[rv];
+ for (RHIGraphicsPipeline *pipeline : rvGraphicsPipelines)
+ pipeline->uboSet()->uploadUBOs(m_submissionContext.data(), rv);
+
+ const std::vector<RHIComputePipeline *> &rvComputePipelines = m_rvToComputePipelines[rv];
+ for (RHIComputePipeline *pipeline : rvComputePipelines)
pipeline->uboSet()->uploadUBOs(m_submissionContext.data(), rv);
- }
// Upload Buffers for Commands
rv->forEachCommand([&] (RenderCommand &command) {
if (Q_UNLIKELY(!command.isValid()))
return;
+ if (!uploadBuffersForCommand(cb, rv, command)) {
+ // Something went wrong trying to upload buffers
+ // -> likely that frontend buffer has no initial data
+ qCWarning(Backend) << "Failed to upload buffers";
+ // Prevents further processing which could be catastrophic
+ command.m_isValid = false;
+ }
+
if (command.m_type == RenderCommand::Draw) {
if (!uploadBuffersForCommand(cb, rv, command)) {
// Something went wrong trying to upload buffers
@@ -2459,26 +2613,7 @@ bool Renderer::executeCommandsSubmission(const RHIPassInfo &passInfo)
rhiRenderTarget = m_submissionContext->currentSwapChain()->currentFrameRenderTarget();
}
- // TO DO: should be moved elsewhere
- // Perform compute actions
- // cb->beginComputePass(m_submissionContext->m_currentUpdates);
- // for (RenderCommand &command : commands) {
- // if (command.m_type == RenderCommand::Compute) {
- // performCompute(rv, &command);
- // }
- // }
- // cb->endComputePass();
- // m_submissionContext->m_currentUpdates =
- // m_submissionContext->rhi()->nextResourceUpdateBatch();
-
- // Draw the commands
-
- // Begin pass
- cb->beginPass(rhiRenderTarget, clearColor, clearDepthStencil,
- m_submissionContext->m_currentUpdates);
-
- // Per Pass Global States
- for (RenderView *rv : renderViews) {
+ auto executeDrawRenderView = [&] (RenderView* rv) {
// Viewport
QRhiViewport vp;
QRhiScissor scissor;
@@ -2514,13 +2649,64 @@ bool Renderer::executeCommandsSubmission(const RHIPassInfo &passInfo)
if (Q_UNLIKELY(!command.isValid()))
return;
- if (command.m_type == RenderCommand::Draw) {
- performDraw(cb, vp, hasScissor ? &scissor : nullptr, command);
- }
+ Q_ASSERT (command.m_type == RenderCommand::Draw);
+ performDraw(cb, vp, hasScissor ? &scissor : nullptr, command);
+ });
+ };
+
+ auto executeComputeRenderView = [&] (RenderView* rv) {
+ rv->forEachCommand([&] (const RenderCommand &command) {
+ if (Q_UNLIKELY(!command.isValid()))
+ return;
+
+ Q_ASSERT (command.m_type == RenderCommand::Compute);
+ performCompute(cb, command);
});
+ };
+
+ bool inCompute = false;
+ bool inDraw = false;
+
+ // Per Pass Global States
+ for (RenderView *rv : renderViews) {
+ if (rv->isCompute()) {
+ // If we were running draw calls we stop the draw pass
+ if (inDraw) {
+ cb->endPass();
+ m_submissionContext->m_currentUpdates = m_submissionContext->rhi()->nextResourceUpdateBatch();
+ inDraw = false;
+ }
+
+ // There is also the possibility where we weren't either in a compute or draw pass (for the first RV)
+ // hence why these conditions are like this
+ if (!inCompute) {
+ cb->beginComputePass(m_submissionContext->m_currentUpdates);
+ inCompute = true;
+ }
+
+ executeComputeRenderView(rv);
+ } else {
+ // Same logic than above but reversed
+ if (inCompute) {
+ cb->endComputePass();
+ m_submissionContext->m_currentUpdates = m_submissionContext->rhi()->nextResourceUpdateBatch();
+ inCompute = false;
+ }
+
+ if (!inDraw) {
+ cb->beginPass(rhiRenderTarget, clearColor, clearDepthStencil, m_submissionContext->m_currentUpdates);
+ inDraw = true;
+ }
+
+ executeDrawRenderView(rv);
+ }
}
- cb->endPass();
+ if (Q_LIKELY(inDraw))
+ cb->endPass();
+ else if (inCompute)
+ cb->endComputePass();
+
m_submissionContext->m_currentUpdates = m_submissionContext->rhi()->nextResourceUpdateBatch();
return allCommandsIssued;
diff --git a/src/plugins/renderers/rhi/renderer/renderer_p.h b/src/plugins/renderers/rhi/renderer/renderer_p.h
index 5d89670b0..122847bc5 100644
--- a/src/plugins/renderers/rhi/renderer/renderer_p.h
+++ b/src/plugins/renderers/rhi/renderer/renderer_p.h
@@ -158,6 +158,8 @@ struct RHIRenderTarget;
class RHIShader;
class RHIResourceManagers;
class RenderView;
+class RHIGraphicsPipeline;
+class RHIComputePipeline;
class Q_AUTOTEST_EXPORT Renderer : public AbstractRenderer
{
@@ -368,8 +370,6 @@ private:
std::vector<Qt3DCore::QNodeId> m_pendingRenderCaptureSendRequests;
void performDraw(RenderCommand *command);
- void performCompute(const RenderView *rv, RenderCommand *command);
-
SynchronizerJobPtr m_bufferGathererJob;
SynchronizerJobPtr m_textureGathererJob;
SynchronizerPostFramePtr m_introspectShaderJob;
@@ -410,7 +410,8 @@ private:
std::vector<FrameGraphNode *> m_frameGraphLeaves;
QScreen *m_screen = nullptr;
QSharedPointer<ResourceAccessor> m_scene2DResourceAccessor;
- QHash<RenderView *, std::vector<RHIGraphicsPipeline *>> m_rvToPipelines;
+ QHash<RenderView *, std::vector<RHIGraphicsPipeline *>> m_rvToGraphicsPipelines;
+ QHash<RenderView *, std::vector<RHIComputePipeline *>> m_rvToComputePipelines;
RenderDriver m_driver = RenderDriver::Qt3D;
bool m_hasSwapChain = false;
@@ -426,11 +427,17 @@ private:
void updateGraphicsPipeline(RenderCommand &command, RenderView *rv,
int renderViewIndex);
+ void updateComputePipeline(RenderCommand &cmd, RenderView *rv,
+ int renderViewIndex);
void buildGraphicsPipelines(RHIGraphicsPipeline *graphicsPipeline,
RenderView *rv,
const RenderCommand &command);
+ void buildComputePipelines(RHIComputePipeline *computePipeline,
+ RenderView *rv,
+ const RenderCommand &command);
+
void cleanupRenderTarget(const RenderTarget *renderTarget);
void createRenderTarget(RenderView* rv, RHIRenderTarget *);
@@ -438,6 +445,12 @@ private:
bool uploadBuffersForCommand(QRhiCommandBuffer *cb, const RenderView *rv,
RenderCommand &command);
+
+ bool uploadBuffersForCommand(RHIComputePipeline* compute, RenderCommand &command);
+ bool uploadBuffersForCommand(RHIGraphicsPipeline* graphics, RenderCommand &command);
+ bool uploadUBOsForCommand(QRhiCommandBuffer *cb, const RenderView *rv,
+ const RenderCommand &command);
+ bool performCompute(QRhiCommandBuffer *cb, const RenderCommand &command);
bool performDraw(QRhiCommandBuffer *cb, const QRhiViewport &vp, const QRhiScissor *scissor,
RenderCommand &command);
};
diff --git a/src/plugins/renderers/rhi/renderer/renderview.cpp b/src/plugins/renderers/rhi/renderer/renderview.cpp
index c0d6d0214..8c5bbcb9b 100644
--- a/src/plugins/renderers/rhi/renderer/renderview.cpp
+++ b/src/plugins/renderers/rhi/renderer/renderview.cpp
@@ -922,7 +922,7 @@ EntityRenderCommandData RenderView::buildDrawRenderCommands(const Entity **entit
command.m_drawIndirect = (indirectAttribute != nullptr);
command.indexAttribute = nullptr;
command.indexBuffer = nullptr;
- command.pipeline = nullptr;
+ command.pipeline = std::monostate{};
// Update the draw command with all the information required for the drawing
if (command.m_drawIndexed) {
@@ -1385,9 +1385,7 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, ParameterInfoList
// At this point we know whether the command is a valid draw command or not
// We still need to process the uniforms as the command could be a compute command
- command->m_isValid = !command->m_activeAttributes.empty();
-
-
+ command->m_isValid = (!command->m_activeAttributes.empty()) || (command->m_type == RenderCommand::CommandType::Compute);
}
if (shader->hasActiveVariables()) {
diff --git a/src/plugins/renderers/rhi/renderer/rhigraphicspipeline.cpp b/src/plugins/renderers/rhi/renderer/rhigraphicspipeline.cpp
index cc22c8856..824609b7f 100644
--- a/src/plugins/renderers/rhi/renderer/rhigraphicspipeline.cpp
+++ b/src/plugins/renderers/rhi/renderer/rhigraphicspipeline.cpp
@@ -47,30 +47,6 @@ namespace Render {
namespace Rhi {
-RHIGraphicsPipeline::RHIGraphicsPipeline()
- : m_pipeline(nullptr)
- , m_shaderResourceBindings(nullptr)
- , m_score(5)
-{
-}
-
-RHIGraphicsPipeline::~RHIGraphicsPipeline() { }
-
-void RHIGraphicsPipeline::cleanup()
-{
- delete m_shaderResourceBindings;
- if (m_pipeline)
- m_pipeline->destroy();
- delete m_pipeline;
- m_pipeline = nullptr;
- m_shaderResourceBindings = nullptr;
- m_attributeNameIdToBindingIndex.clear();
- m_uboSet.releaseResources();
- m_uboSet.clear();
- m_key = {};
- m_score = 5;
-}
-
} // Rhi
} // Render
diff --git a/src/plugins/renderers/rhi/renderer/rhigraphicspipeline_p.h b/src/plugins/renderers/rhi/renderer/rhigraphicspipeline_p.h
index 68242b525..574b7d342 100644
--- a/src/plugins/renderers/rhi/renderer/rhigraphicspipeline_p.h
+++ b/src/plugins/renderers/rhi/renderer/rhigraphicspipeline_p.h
@@ -76,26 +76,59 @@ struct GraphicsPipelineIdentifier
int renderViewIndex = 0;
};
-class RHIGraphicsPipeline
+struct ComputePipelineIdentifier
+{
+ Qt3DCore::QNodeId shader;
+ int renderViewIndex;
+};
+
+template<typename Pipeline, typename Key>
+class RHIPipelineBase
{
public:
- RHIGraphicsPipeline();
- ~RHIGraphicsPipeline();
+ virtual ~RHIPipelineBase() {}
PipelineUBOSet* uboSet() { return &m_uboSet; }
- QRhiGraphicsPipeline *pipeline() const { return m_pipeline; }
+
+ Pipeline *pipeline() const { return m_pipeline; }
+ void setPipeline(Pipeline *pipeline) { m_pipeline = pipeline; }
+
+ void setKey(const Key &key) { m_key = key; }
+ Key key() const { return m_key; }
+
+ void setShaderResourceBindings(QRhiShaderResourceBindings *shaderResourceBindings) { m_shaderResourceBindings = shaderResourceBindings; }
QRhiShaderResourceBindings *shaderResourceBindings() const { return m_shaderResourceBindings; }
- int score() const { return m_score; }
- void setKey(const GraphicsPipelineIdentifier &key) { m_key = key; }
- GraphicsPipelineIdentifier key() const { return m_key; }
- void setPipeline(QRhiGraphicsPipeline *pipeline) { m_pipeline = pipeline; }
+ int score() const { return m_score; }
+ void increaseScore() { m_score += 2; }
+ void decreaseScore() { --m_score; }
- void setShaderResourceBindings(QRhiShaderResourceBindings *shaderResourceBindings)
+ virtual void cleanup()
{
- m_shaderResourceBindings = shaderResourceBindings;
+ delete m_shaderResourceBindings;
+ delete m_pipeline;
+ m_pipeline = nullptr;
+ m_shaderResourceBindings = nullptr;
+ m_uboSet.releaseResources();
+ m_uboSet.clear();
+ m_key = {};
+ m_score = 5;
}
+protected:
+ RHIPipelineBase() {}
+
+ Pipeline *m_pipeline = nullptr;
+ QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
+ // For user defined uniforms
+ PipelineUBOSet m_uboSet;
+ Key m_key = {};
+ int m_score = 5;
+};
+
+class RHIGraphicsPipeline : public RHIPipelineBase<QRhiGraphicsPipeline, GraphicsPipelineIdentifier>
+{
+public:
void setAttributesToBindingHash(const QHash<int, int> &attributeNameToBinding)
{
m_attributeNameIdToBindingIndex = attributeNameToBinding;
@@ -106,19 +139,19 @@ public:
return m_attributeNameIdToBindingIndex.value(attributeNameId, -1);
}
- void increaseScore() { m_score += 2; }
- void decreaseScore() { --m_score; }
-
- void cleanup();
+ virtual void cleanup()
+ {
+ RHIPipelineBase<QRhiGraphicsPipeline, GraphicsPipelineIdentifier>::cleanup();
+ m_attributeNameIdToBindingIndex.clear();
+ }
private:
- QRhiGraphicsPipeline *m_pipeline;
- QRhiShaderResourceBindings *m_shaderResourceBindings;
// For user defined uniforms
QHash<int, int> m_attributeNameIdToBindingIndex;
- PipelineUBOSet m_uboSet;
- GraphicsPipelineIdentifier m_key;
- int m_score;
+};
+
+class RHIComputePipeline : public RHIPipelineBase<QRhiComputePipeline, ComputePipelineIdentifier>
+{
};
} // Rhi
diff --git a/src/plugins/renderers/rhi/renderer/rhishader.cpp b/src/plugins/renderers/rhi/renderer/rhishader.cpp
index 9d957984f..3281cb640 100644
--- a/src/plugins/renderers/rhi/renderer/rhishader.cpp
+++ b/src/plugins/renderers/rhi/renderer/rhishader.cpp
@@ -408,37 +408,45 @@ void RHIShader::introspect()
std::vector<ShaderAttribute> samplers;
std::vector<ShaderAttribute> images;
- // Introspect shader vertex input
- if (m_stages[QShader::VertexStage].isValid()) {
- const QShaderDescription &vtx = m_stages[QShader::VertexStage].description();
-
- for (const QShaderDescription::InOutVariable &input : vtx.inputVariables()) {
- attributes.push_back(ShaderAttribute { input.name, StringToInt::lookupId(input.name),
- input.type, rhiTypeSize(input.type),
- input.location });
- }
+ if (m_stages[QShader::ComputeStage].isValid()) {
+ const QShaderDescription &comp = m_stages[QShader::ComputeStage].description();
- Qt3DCore::append(rhiUBO, vtx.uniformBlocks());
- Qt3DCore::append(rhiSSBO, vtx.storageBlocks());
+ Qt3DCore::append(rhiUBO, comp.uniformBlocks());
+ Qt3DCore::append(rhiSSBO, comp.storageBlocks());
}
+ else
+ {
+ // Introspect shader vertex input
+ if (m_stages[QShader::VertexStage].isValid()) {
+ const QShaderDescription &vtx = m_stages[QShader::VertexStage].description();
+
+ for (const QShaderDescription::InOutVariable &input : vtx.inputVariables()) {
+ attributes.push_back(ShaderAttribute { input.name, StringToInt::lookupId(input.name),
+ input.type, rhiTypeSize(input.type),
+ input.location });
+ }
- // Introspect shader uniforms
-
- if (m_stages[QShader::FragmentStage].isValid()) {
- const QShaderDescription &frag = m_stages[QShader::FragmentStage].description();
- for (const QShaderDescription::InOutVariable &sampler : frag.combinedImageSamplers()) {
- samplers.push_back(ShaderAttribute { sampler.name, StringToInt::lookupId(sampler.name),
- sampler.type, rhiTypeSize(sampler.type),
- sampler.binding });
- }
- for (const QShaderDescription::InOutVariable &image : frag.storageImages()) {
- images.push_back(ShaderAttribute { image.name, StringToInt::lookupId(image.name),
- image.type, rhiTypeSize(image.type),
- image.binding });
+ Qt3DCore::append(rhiUBO, vtx.uniformBlocks());
+ Qt3DCore::append(rhiSSBO, vtx.storageBlocks());
}
- Qt3DCore::append(rhiUBO, frag.uniformBlocks());
- Qt3DCore::append(rhiSSBO, frag.storageBlocks());
+ // Introspect shader uniforms
+ if (m_stages[QShader::FragmentStage].isValid()) {
+ const QShaderDescription &frag = m_stages[QShader::FragmentStage].description();
+ for (const QShaderDescription::InOutVariable &sampler : frag.combinedImageSamplers()) {
+ samplers.push_back(ShaderAttribute { sampler.name, StringToInt::lookupId(sampler.name),
+ sampler.type, rhiTypeSize(sampler.type),
+ sampler.binding });
+ }
+ for (const QShaderDescription::InOutVariable &image : frag.storageImages()) {
+ images.push_back(ShaderAttribute { image.name, StringToInt::lookupId(image.name),
+ image.type, rhiTypeSize(image.type),
+ image.binding });
+ }
+
+ Qt3DCore::append(rhiUBO, frag.uniformBlocks());
+ Qt3DCore::append(rhiSSBO, frag.storageBlocks());
+ }
}
rhiUBO = stableRemoveDuplicates(rhiUBO,