summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2016-10-17 17:40:23 +0200
committerPaul Lemire <paul.lemire@kdab.com>2017-01-24 08:40:31 +0000
commite3ecccb973cdfcf8452da71e20f42d5ffdf551e6 (patch)
treed5a9728cfc12f1773f078855db1201f54eed0c5b
parentaa7ba870f3597088fc447f36e3024220ac03680f (diff)
Renderer: now handle indirect draw calls
Change-Id: I8b109425a6a8d49cb7008f9dbed3b6c8cb913235 Reviewed-by: Kevin Ottens <kevin.ottens@kdab.com>
-rw-r--r--src/render/backend/rendercommand.cpp2
-rw-r--r--src/render/backend/rendercommand_p.h4
-rw-r--r--src/render/backend/renderer.cpp150
-rw-r--r--src/render/graphicshelpers/graphicscontext.cpp2
4 files changed, 136 insertions, 22 deletions
diff --git a/src/render/backend/rendercommand.cpp b/src/render/backend/rendercommand.cpp
index eabb2a2d4..044ef035c 100644
--- a/src/render/backend/rendercommand.cpp
+++ b/src/render/backend/rendercommand.cpp
@@ -60,7 +60,9 @@ RenderCommand::RenderCommand()
, m_indexOffset(0)
, m_indexAttributeByteOffset(0)
, m_indexAttributeDataType(GL_UNSIGNED_SHORT)
+ , m_indirectAttributeByteOffset(0)
, m_drawIndexed(false)
+ , m_drawIndirect(false)
, m_primitiveRestartEnabled(false)
, m_isValid(false)
{
diff --git a/src/render/backend/rendercommand_p.h b/src/render/backend/rendercommand_p.h
index 012cdbe9a..4b2966fc6 100644
--- a/src/render/backend/rendercommand_p.h
+++ b/src/render/backend/rendercommand_p.h
@@ -84,6 +84,8 @@ public:
HGeometry m_geometry;
HGeometryRenderer m_geometryRenderer;
+ HBuffer m_indirectDrawBuffer; // Reference to indirect draw buffer (valid only m_drawIndirect == true)
+
// A QAttribute pack might be interesting
// This is a temporary fix in the meantime, to remove the hacked methods in Technique
QVector<int> m_attributes;
@@ -118,7 +120,9 @@ public:
int m_indexOffset;
uint m_indexAttributeByteOffset;
GLint m_indexAttributeDataType;
+ uint m_indirectAttributeByteOffset;
bool m_drawIndexed;
+ bool m_drawIndirect;
bool m_primitiveRestartEnabled;
bool m_isValid;
};
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index 08ee7f428..47759ad4e 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -794,6 +794,75 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
// Prepare the ShaderParameterPack based on the active uniforms of the shader
shader->prepareUniforms(command->m_parameterPack);
+ // TO DO: The step below could be performed by the RenderCommand builder job
+ { // Scoped to show extent
+ command->m_isValid = !command->m_attributes.empty();
+ if (!command->m_isValid)
+ continue;
+
+ // Update the draw command with what's going to be needed for the drawing
+ uint primitiveCount = rGeometryRenderer->vertexCount();
+ uint estimatedCount = 0;
+ Attribute *indexAttribute = nullptr;
+ Attribute *indirectAttribute = nullptr;
+
+ const QVector<Qt3DCore::QNodeId> attributeIds = rGeometry->attributes();
+ for (Qt3DCore::QNodeId attributeId : attributeIds) {
+ Attribute *attribute = m_nodesManager->attributeManager()->lookupResource(attributeId);
+ switch (attribute->attributeType()) {
+ case QAttribute::IndexAttribute:
+ indexAttribute = attribute;
+ break;
+ case QAttribute::DrawIndirectAttribute:
+ indirectAttribute = attribute;
+ break;
+ case QAttribute::VertexAttribute: {
+ if (command->m_attributes.contains(attribute->nameId()))
+ estimatedCount = qMax(attribute->count(), estimatedCount);
+ break;
+ }
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+
+ command->m_drawIndexed = (indexAttribute != nullptr);
+ command->m_drawIndirect = (indirectAttribute != nullptr);
+
+ // Update the draw command with all the information required for the drawing
+ if (command->m_drawIndexed) {
+ command->m_indexAttributeDataType = GraphicsContext::glDataTypeFromAttributeDataType(indexAttribute->vertexBaseType());
+ command->m_indexAttributeByteOffset = indexAttribute->byteOffset();
+ }
+
+ // Note: we only care about the primitiveCount when using direct draw calls
+ // For indirect draw calls it is assumed the buffer was properly set already
+ if (command->m_drawIndirect) {
+ command->m_indirectAttributeByteOffset = indirectAttribute->byteOffset();
+ command->m_indirectDrawBuffer = m_nodesManager->bufferManager()->lookupHandle(indirectAttribute->bufferId());
+ } else {
+ // Use the count specified by the GeometryRender
+ // If not specify use the indexAttribute count if present
+ // Otherwise tries to use the count from the attribute with the highest count
+ if (primitiveCount == 0) {
+ if (indexAttribute)
+ primitiveCount = indexAttribute->count();
+ else
+ primitiveCount = estimatedCount;
+ }
+ }
+
+ command->m_primitiveCount = primitiveCount;
+ command->m_primitiveType = rGeometryRenderer->primitiveType();
+ command->m_primitiveRestartEnabled = rGeometryRenderer->primitiveRestartEnabled();
+ command->m_restartIndexValue = rGeometryRenderer->restartIndexValue();
+ command->m_firstInstance = rGeometryRenderer->firstInstance();
+ command->m_instanceCount = rGeometryRenderer->instanceCount();
+ command->m_firstVertex = rGeometryRenderer->firstVertex();
+ command->m_indexOffset = rGeometryRenderer->indexOffset();
+ command->m_verticesPerPatch = rGeometryRenderer->verticesPerPatch();
+ } // scope
} else if (command->m_type == RenderCommand::Compute) {
Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command->m_shader);
Q_ASSERT(shader);
@@ -1291,29 +1360,66 @@ QAbstractFrameAdvanceService *Renderer::frameAdvanceService() const
// Called by executeCommands
void Renderer::performDraw(RenderCommand *command)
{
- if (command->m_primitiveType == QGeometryRenderer::Patches)
- m_graphicsContext->setVerticesPerPatch(command->m_verticesPerPatch);
+ // Indirect Draw Calls
+ if (command->m_drawIndirect) {
- if (command->m_primitiveRestartEnabled)
- m_graphicsContext->enablePrimitiveRestart(command->m_restartIndexValue);
-
- // TO DO: Add glMulti Draw variants
- if (command->m_drawIndexed) {
- Profiling::GLTimeRecorder recorder(Profiling::DrawElement);
- m_graphicsContext->drawElementsInstancedBaseVertexBaseInstance(command->m_primitiveType,
- command->m_primitiveCount,
- command->m_indexAttributeDataType,
- reinterpret_cast<void*>(quintptr(command->m_indexAttributeByteOffset)),
- command->m_instanceCount,
- command->m_indexOffset,
- command->m_firstVertex);
- } else {
- Profiling::GLTimeRecorder recorder(Profiling::DrawArray);
- m_graphicsContext->drawArraysInstancedBaseInstance(command->m_primitiveType,
- command->m_firstInstance,
- command->m_primitiveCount,
- command->m_instanceCount,
- command->m_firstVertex);
+ // Bind the indirect draw buffer
+ Buffer *indirectDrawBuffer = m_nodesManager->bufferManager()->data(command->m_indirectDrawBuffer);
+ if (Q_UNLIKELY(indirectDrawBuffer == nullptr)) {
+ qWarning() << "Invalid Indirect Draw Buffer - failed to retrieve Buffer";
+ return;
+ }
+
+ // Get GLBuffer from Buffer;
+ GLBuffer *indirectDrawGLBuffer = m_graphicsContext->glBufferForRenderBuffer(indirectDrawBuffer);
+ if (Q_UNLIKELY(indirectDrawGLBuffer == nullptr)) {
+ qWarning() << "Invalid Indirect Draw Buffer - failed to retrieve GLBuffer";
+ return;
+ }
+
+ // Bind GLBuffer
+ const bool successfullyBound = indirectDrawGLBuffer->bind(m_graphicsContext.data(), GLBuffer::DrawIndirectBuffer);
+
+ if (Q_LIKELY(successfullyBound)) {
+ // TO DO: Handle multi draw variants if attribute count > 1
+ if (command->m_drawIndexed) {
+ m_graphicsContext->drawElementsIndirect(command->m_primitiveType,
+ command->m_indexAttributeDataType,
+ reinterpret_cast<void*>(quintptr(command->m_indirectAttributeByteOffset)));
+ } else {
+ m_graphicsContext->drawArraysIndirect(command->m_primitiveType,
+ reinterpret_cast<void*>(quintptr(command->m_indirectAttributeByteOffset)));
+ }
+ } else {
+ qWarning() << "Failed to bind IndirectDrawBuffer";
+ }
+
+ } else { // Direct Draw Calls
+ // TO DO: Add glMulti Draw variants
+ if (command->m_primitiveType == QGeometryRenderer::Patches)
+ m_graphicsContext->setVerticesPerPatch(command->m_verticesPerPatch);
+
+ if (command->m_primitiveRestartEnabled)
+ m_graphicsContext->enablePrimitiveRestart(command->m_restartIndexValue);
+
+ // TO DO: Add glMulti Draw variants
+ if (command->m_drawIndexed) {
+ Profiling::GLTimeRecorder recorder(Profiling::DrawElement);
+ m_graphicsContext->drawElementsInstancedBaseVertexBaseInstance(command->m_primitiveType,
+ command->m_primitiveCount,
+ command->m_indexAttributeDataType,
+ reinterpret_cast<void*>(quintptr(command->m_indexAttributeByteOffset)),
+ command->m_instanceCount,
+ command->m_indexOffset,
+ command->m_firstVertex);
+ } else {
+ Profiling::GLTimeRecorder recorder(Profiling::DrawArray);
+ m_graphicsContext->drawArraysInstancedBaseInstance(command->m_primitiveType,
+ command->m_firstInstance,
+ command->m_primitiveCount,
+ command->m_instanceCount,
+ command->m_firstVertex);
+ }
}
#if defined(QT3D_RENDER_ASPECT_OPENGL_DEBUG)
diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp
index f7ba5c3c4..4214bcb76 100644
--- a/src/render/graphicshelpers/graphicscontext.cpp
+++ b/src/render/graphicshelpers/graphicscontext.cpp
@@ -125,6 +125,8 @@ GLBuffer::Type bufferTypeToGLBufferType(QBuffer::BufferType type)
return GLBuffer::UniformBuffer;
case QBuffer::ShaderStorageBuffer:
return GLBuffer::ShaderStorageBuffer;
+ case QBuffer::DrawIndirectBuffer:
+ return GLBuffer::DrawIndirectBuffer;
default:
Q_UNREACHABLE();
}