diff options
Diffstat (limited to 'src/plugins/renderers/rhi/renderer/renderer.cpp')
-rw-r--r-- | src/plugins/renderers/rhi/renderer/renderer.cpp | 178 |
1 files changed, 117 insertions, 61 deletions
diff --git a/src/plugins/renderers/rhi/renderer/renderer.cpp b/src/plugins/renderers/rhi/renderer/renderer.cpp index 45485a6c7..4a25bb464 100644 --- a/src/plugins/renderers/rhi/renderer/renderer.cpp +++ b/src/plugins/renderers/rhi/renderer/renderer.cpp @@ -93,8 +93,6 @@ QT_BEGIN_NAMESPACE -using namespace Qt3DCore; - namespace Qt3DRender { namespace Render { namespace Rhi { @@ -336,7 +334,7 @@ void Renderer::setNodeManagers(NodeManagers *managers) m_computableEntityFilterJob->setManager(m_nodesManager->renderNodesManager()); } -void Renderer::setServices(QServiceLocator *services) +void Renderer::setServices(Qt3DCore::QServiceLocator *services) { m_services = services; @@ -613,12 +611,12 @@ void Renderer::render(bool swapBuffers) // RenderQueue is complete (but that means it may be of size 0) if (!queueIsEmpty) { - QTaskLogger submissionStatsPart1(m_services->systemInformation(), - { JobTypes::FrameSubmissionPart1, 0 }, - QTaskLogger::Submission); - QTaskLogger submissionStatsPart2(m_services->systemInformation(), - { JobTypes::FrameSubmissionPart2, 0 }, - QTaskLogger::Submission); + Qt3DCore::QTaskLogger submissionStatsPart1(m_services->systemInformation(), + { JobTypes::FrameSubmissionPart1, 0 }, + Qt3DCore::QTaskLogger::Submission); + Qt3DCore::QTaskLogger submissionStatsPart2(m_services->systemInformation(), + { JobTypes::FrameSubmissionPart2, 0 }, + Qt3DCore::QTaskLogger::Submission); std::vector<RHIPassInfo> rhiPassesInfo; @@ -759,8 +757,8 @@ QSurfaceFormat Renderer::format() namespace { std::optional<QRhiVertexInputAttribute::Format> rhiAttributeType(Attribute *attr) { switch (attr->vertexBaseType()) { - case QAttribute::Byte: - case QAttribute::UnsignedByte: { + case Qt3DCore::QAttribute::Byte: + case Qt3DCore::QAttribute::UnsignedByte: { if (attr->vertexSize() == 1) return QRhiVertexInputAttribute::UNormByte; if (attr->vertexSize() == 2) @@ -769,7 +767,18 @@ std::optional<QRhiVertexInputAttribute::Format> rhiAttributeType(Attribute *attr return QRhiVertexInputAttribute::UNormByte4; break; } - case QAttribute::UnsignedInt: { + case Qt3DCore::QAttribute::Int: { + if (attr->vertexSize() == 1) + return QRhiVertexInputAttribute::SInt; + if (attr->vertexSize() == 2) + return QRhiVertexInputAttribute::SInt2; + if (attr->vertexSize() == 3) + return QRhiVertexInputAttribute::SInt3; + if (attr->vertexSize() == 4) + return QRhiVertexInputAttribute::SInt4; + break; + } + case Qt3DCore::QAttribute::UnsignedInt: { if (attr->vertexSize() == 1) return QRhiVertexInputAttribute::UInt; if (attr->vertexSize() == 2) @@ -780,7 +789,18 @@ std::optional<QRhiVertexInputAttribute::Format> rhiAttributeType(Attribute *attr return QRhiVertexInputAttribute::UInt4; break; } - case QAttribute::Float: { + case Qt3DCore::QAttribute::HalfFloat: { + if (attr->vertexSize() == 1) + return QRhiVertexInputAttribute::Half; + if (attr->vertexSize() == 2) + return QRhiVertexInputAttribute::Half2; + if (attr->vertexSize() == 3) + return QRhiVertexInputAttribute::Half3; + if (attr->vertexSize() >= 4) + return QRhiVertexInputAttribute::Half4; + break; + } + case Qt3DCore::QAttribute::Float: { if (attr->vertexSize() == 1) return QRhiVertexInputAttribute::Float; if (attr->vertexSize() == 2) @@ -1143,9 +1163,17 @@ void Renderer::createRenderTarget(RenderTarget *target) } }; + RHIRenderTarget::BackBuffer backBuffer = RHIRenderTarget::BackBuffer::None; + // Look up attachments to populate the RT description // Attachments are sorted by attachment point (Color0 is first) for (const Attachment &attachment : pack.attachments()) { + + if (attachment.m_point == QRenderTargetOutput::Left || attachment.m_point == QRenderTargetOutput::Right) { + backBuffer = attachment.m_point == QRenderTargetOutput::Left ? RHIRenderTarget::BackBuffer::Left : RHIRenderTarget::BackBuffer::Right; + break; + } + RHITexture *tex = texman->lookupResource(attachment.m_textureUuid); if (tex && tex->getRhiTexture()) { auto rhiTex = tex->getRhiTexture(); @@ -1185,6 +1213,12 @@ void Renderer::createRenderTarget(RenderTarget *target) } } + rhiTarget->backBuffer = backBuffer; + // If we are targeting one of the back buffers directly, don't create an offscreen RT + if (backBuffer != RHIRenderTarget::BackBuffer::None) + return; + + // Otherwise, create QRhiRenderBuffer and associated resources if (targetSize.width() <= 0 || targetSize.height() <= 0) { cleanAllocatedResources(); return; @@ -1234,6 +1268,12 @@ bool Renderer::setupRenderTarget(RenderView *rv, const auto &managers = *nodeManagers(); auto &renderTargetManager = *managers.renderTargetManager(); + auto useSwapchainForPipeline = [&]() { + Q_ASSERT(swapchain); + rhiPipeline->setRenderPassDescriptor(swapchain->renderPassDescriptor()); + rhiPipeline->setSampleCount(swapchain->sampleCount()); + }; + auto *renderTarget = renderTargetManager.lookupResource(rv->renderTargetId()); if (renderTarget) { // Render to texture @@ -1241,14 +1281,25 @@ bool Renderer::setupRenderTarget(RenderView *rv, RHIRenderTargetManager *rhiRenderTargetManager = m_RHIResourceManagers->rhiRenderTargetManager(); RHIRenderTarget *rhiTarget = rhiRenderTargetManager->lookupResource(renderTargetId); - if (!rhiTarget || !rhiTarget->renderTarget) { + if (!rhiTarget) { qWarning(Backend) << "Invalid RenderTarget " << renderTargetId << " for Pipeline"; return false; } - rhiPipeline->setRenderPassDescriptor(rhiTarget->renderPassDescriptor); - rhiPipeline->setSampleCount(rhiTarget->renderTarget->sampleCount()); + // The RenderTarget we reference might actually be referencing a swapchain back buffer + if (rhiTarget->backBuffer != RHIRenderTarget::BackBuffer::None) { + // Render to the default framebuffer on our swapchain + useSwapchainForPipeline(); + } else { + if (!rhiTarget->renderTarget) { + qWarning(Backend) << "Invalid RenderTarget " << renderTargetId << " for Pipeline"; + return false; + } + rhiPipeline->setRenderPassDescriptor(rhiTarget->renderPassDescriptor); + rhiPipeline->setSampleCount(rhiTarget->renderTarget->sampleCount()); + } return true; + } else if (m_submissionContext->defaultRenderTarget()) { // Use default RenderTarget if set Default FBO set by Scene3D QRhiRenderTarget *defaultTarget = m_submissionContext->defaultRenderTarget();; @@ -1256,10 +1307,8 @@ bool Renderer::setupRenderTarget(RenderView *rv, rhiPipeline->setSampleCount(defaultTarget->sampleCount()); return true; } else { - Q_ASSERT(swapchain); // Render to the default framebuffer on our swapchain - rhiPipeline->setRenderPassDescriptor(swapchain->renderPassDescriptor()); - rhiPipeline->setSampleCount(swapchain->sampleCount()); + useSwapchainForPipeline(); return true; } } @@ -1442,10 +1491,10 @@ void Renderer::lookForDirtyTextures() const std::vector<HTexture> &activeTextureHandles = textureManager->activeHandles(); for (const HTexture &handle : activeTextureHandles) { Texture *texture = textureManager->data(handle); - const QNodeIdVector imageIds = texture->textureImageIds(); + const Qt3DCore::QNodeIdVector imageIds = texture->textureImageIds(); // Does the texture reference any of the dirty texture images? - for (const QNodeId &imageId : imageIds) { + for (const Qt3DCore::QNodeId &imageId : imageIds) { if (dirtyImageIds.contains(imageId)) { texture->addDirtyFlag(Texture::DirtyImageGenerators); break; @@ -1475,7 +1524,7 @@ void Renderer::reloadDirtyShaders() // If api of the renderer matches the one from the technique if (technique->isCompatibleWithRenderer()) { const auto passIds = technique->renderPasses(); - for (const QNodeId &passId : passIds) { + for (const Qt3DCore::QNodeId &passId : passIds) { RenderPass *renderPass = m_nodesManager->renderPassManager()->lookupResource(passId); HShader shaderHandle = @@ -1536,7 +1585,7 @@ void Renderer::sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager) static_cast<decltype(frontend)>(manager->lookupNode(s->peerId())); if (frontend) { QShaderProgramPrivate *dFrontend = - static_cast<decltype(dFrontend)>(QNodePrivate::get(frontend)); + static_cast<decltype(dFrontend)>(Qt3DCore::QNodePrivate::get(frontend)); dFrontend->setStatus(s->status()); dFrontend->setLog(s->log()); s->unsetRequiresFrontendSync(); @@ -1552,7 +1601,7 @@ void Renderer::sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager) continue; QShaderProgramBuilderPrivate *dBuilder = - static_cast<decltype(dBuilder)>(QNodePrivate::get(builder)); + static_cast<decltype(dBuilder)>(Qt3DCore::QNodePrivate::get(builder)); dBuilder->setShaderCode(update.shaderCode, update.shaderType); } m_shaderBuilderUpdates.clear(); @@ -1588,7 +1637,7 @@ void Renderer::sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager) texture->blockNotifications(blocked); QAbstractTexturePrivate *dTexture = - static_cast<QAbstractTexturePrivate *>(QNodePrivate::get(texture)); + static_cast<QAbstractTexturePrivate *>(Qt3DCore::QNodePrivate::get(texture)); dTexture->setStatus(properties.status); dTexture->setHandleType(pair.first.handleType); dTexture->setHandle(pair.first.handle); @@ -1626,7 +1675,7 @@ bool Renderer::prepareGeometryInputBindings(const Geometry *geometry, const RHIS QHash<int, int> &attributeNameToBinding) { // shader requires no attributes - if (shader->attributes().size() == 0) + if (shader->attributes().empty()) return true; // QRhiVertexInputBinding -> specifies the stride of an attribute, @@ -1648,7 +1697,7 @@ bool Renderer::prepareGeometryInputBindings(const Geometry *geometry, const RHIS for (Qt3DCore::QNodeId attribute_id : attributesIds) { Attribute *attrib = m_nodesManager->attributeManager()->lookupResource(attribute_id); - if (attrib->attributeType() != QAttribute::VertexAttribute) + if (attrib->attributeType() != Qt3DCore::QAttribute::VertexAttribute) continue; const int location = locationForAttribute(attrib, shader); // In case the shader doesn't use the attribute, we would get no @@ -1662,20 +1711,20 @@ bool Renderer::prepareGeometryInputBindings(const Geometry *geometry, const RHIS ? QRhiVertexInputBinding::PerInstance : QRhiVertexInputBinding::PerVertex; - auto getAttributeByteSize = [] (const QAttribute::VertexBaseType type) { + auto getAttributeByteSize = [](const Qt3DCore::QAttribute::VertexBaseType type) { switch (type) { - case QAttribute::Byte: - case QAttribute::UnsignedByte: + case Qt3DCore::QAttribute::Byte: + case Qt3DCore::QAttribute::UnsignedByte: return 1; - case QAttribute::Short: - case QAttribute::UnsignedShort: - case QAttribute::HalfFloat: + case Qt3DCore::QAttribute::Short: + case Qt3DCore::QAttribute::UnsignedShort: + case Qt3DCore::QAttribute::HalfFloat: return 2; - case QAttribute::Int: - case QAttribute::UnsignedInt: - case QAttribute::Float: + case Qt3DCore::QAttribute::Int: + case Qt3DCore::QAttribute::UnsignedInt: + case Qt3DCore::QAttribute::Float: return 4; - case QAttribute::Double: + case Qt3DCore::QAttribute::Double: return 8; } return 0; @@ -1842,7 +1891,7 @@ void Renderer::updateResources() // for textures which had not initially specified these information // (TargetAutomatic...) Gather these information and store them to be distributed by // a change next frame - const QNodeIdVector referenceTextureIds = { rhiTextureManager->texNodeIdForRHITexture.value(rhiTexture) }; + const Qt3DCore::QNodeIdVector referenceTextureIds = { rhiTextureManager->texNodeIdForRHITexture.value(rhiTexture) }; // Store properties and referenceTextureIds Texture::TextureUpdateInfo updateInfo; updateInfo.properties = info.properties; @@ -1964,11 +2013,11 @@ void Renderer::updateTexture(Texture *texture) // Will make the texture requestUpload if (dirtyFlags.testFlag(Texture::DirtyImageGenerators)) { - const QNodeIdVector textureImageIds = texture->textureImageIds(); + const Qt3DCore::QNodeIdVector textureImageIds = texture->textureImageIds(); std::vector<RHITexture::Image> images; images.reserve(textureImageIds.size()); // TODO: Move this into RHITexture directly - for (const QNodeId &textureImageId : textureImageIds) { + for (const Qt3DCore::QNodeId &textureImageId : textureImageIds) { const TextureImage *img = m_nodesManager->textureImageManager()->lookupResource(textureImageId); if (img == nullptr) { @@ -2203,7 +2252,7 @@ void Renderer::jobsDone(Qt3DCore::QAspectManager *manager) } // Do we need to notify any texture about property changes? - if (m_updatedTextureProperties.size() > 0) + if (!m_updatedTextureProperties.empty()) sendTextureChangesToFrontend(manager); sendDisablesToFrontend(manager); @@ -2224,7 +2273,7 @@ bool Renderer::processKeyEvent(QObject *object, QKeyEvent *event) } // Jobs we may have to run even if no rendering will happen -std::vector<QAspectJobPtr> Renderer::preRenderingJobs() +std::vector<Qt3DCore::QAspectJobPtr> Renderer::preRenderingJobs() { if (m_sendBufferCaptureJob->hasRequests()) return { m_sendBufferCaptureJob }; @@ -2238,10 +2287,10 @@ std::vector<QAspectJobPtr> Renderer::preRenderingJobs() // for the rendering of the scene std::vector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() { - std::vector<QAspectJobPtr> renderBinJobs; + std::vector<Qt3DCore::QAspectJobPtr> renderBinJobs; // Remove previous dependencies - m_cleanupJob->removeDependency(QWeakPointer<QAspectJob>()); + m_cleanupJob->removeDependency(QWeakPointer<Qt3DCore::QAspectJob>()); const bool dirtyParametersForCurrentFrame = m_dirtyBits.marked & AbstractRenderer::ParameterDirty; const BackendNodeDirtySet dirtyBitsForFrame = m_dirtyBits.marked | m_dirtyBits.remaining; @@ -2315,7 +2364,7 @@ std::vector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() m_updatedDisableSubtreeEnablers.push_back(node->peerId()); } - int idealThreadCount = QAspectJobManager::idealThreadCount(); + int idealThreadCount = Qt3DCore::QAspectJobManager::idealThreadCount(); const size_t fgBranchCount = m_frameGraphLeaves.size(); if (fgBranchCount > 1) { @@ -2379,7 +2428,7 @@ std::vector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() return renderBinJobs; } -QAbstractFrameAdvanceService *Renderer::frameAdvanceService() const +Qt3DCore::QAbstractFrameAdvanceService *Renderer::frameAdvanceService() const { return static_cast<Qt3DCore::QAbstractFrameAdvanceService *>(m_vsyncFrameAdvanceService.data()); } @@ -2404,12 +2453,12 @@ bool Renderer::performCompute(QRhiCommandBuffer *cb, RenderCommand &command) return true; } -static auto rhiIndexFormat(QAttribute::VertexBaseType type) +static auto rhiIndexFormat(Qt3DCore::QAttribute::VertexBaseType type) { switch (type) { - case QAttribute::VertexBaseType ::UnsignedShort: + case Qt3DCore::QAttribute::VertexBaseType ::UnsignedShort: return QRhiCommandBuffer::IndexUInt16; - case QAttribute::VertexBaseType ::UnsignedInt: + case Qt3DCore::QAttribute::VertexBaseType ::UnsignedInt: return QRhiCommandBuffer::IndexUInt32; default: std::abort(); @@ -2481,7 +2530,7 @@ bool Renderer::uploadBuffersForCommand(RHIGraphicsPipeline* graphicsPipeline, Re Buffer *buffer = m_nodesManager->bufferManager()->lookupResource(attrib->bufferId()); RHIBuffer *hbuf = m_RHIResourceManagers->rhiBufferManager()->lookupResource(buffer->peerId()); switch (attrib->attributeType()) { - case QAttribute::VertexAttribute: { + case Qt3DCore::QAttribute::VertexAttribute: { if (!hbuf->bind(&*m_submissionContext, RHIBuffer::Type((int)RHIBuffer::Type::ArrayBuffer | (int)RHIBuffer::Type::ShaderStorageBuffer))) return false; assert(hbuf->rhiBuffer()); @@ -2494,7 +2543,7 @@ bool Renderer::uploadBuffersForCommand(RHIGraphicsPipeline* graphicsPipeline, Re command.vertex_input[bindingIndex] = { hbuf->rhiBuffer(), 0 }; break; } - case QAttribute::IndexAttribute: { + case Qt3DCore::QAttribute::IndexAttribute: { if (!hbuf->bind(&*m_submissionContext, RHIBuffer::Type::IndexBuffer)) return false; assert(hbuf->rhiBuffer()); @@ -2503,7 +2552,7 @@ bool Renderer::uploadBuffersForCommand(RHIGraphicsPipeline* graphicsPipeline, Re command.indexAttribute = attrib; break; } - case QAttribute::DrawIndirectAttribute: + case Qt3DCore::QAttribute::DrawIndirectAttribute: RHI_UNIMPLEMENTED; break; } @@ -2642,12 +2691,19 @@ bool Renderer::executeCommandsSubmission(const RHIPassInfo &passInfo) auto &renderTargetManager = *managers.rhiRenderTargetManager(); auto *renderTarget = renderTargetManager.lookupResource(passInfo.renderTargetId); - if (renderTarget) - rhiRenderTarget = renderTarget->renderTarget; - else if (m_submissionContext->defaultRenderTarget()) + if (renderTarget) { + // Is our RenderTarget targeting offscreen attachments? + if (renderTarget->backBuffer == RHIRenderTarget::BackBuffer::None) + rhiRenderTarget = renderTarget->renderTarget; + else // Or one of the back buffers? + rhiRenderTarget = m_submissionContext->currentSwapChain()->currentFrameRenderTarget(renderTarget->backBuffer == RHIRenderTarget::BackBuffer::Left + ? QRhiSwapChain::LeftBuffer + : QRhiSwapChain::RightBuffer); + } else if (m_submissionContext->defaultRenderTarget()) { rhiRenderTarget = m_submissionContext->defaultRenderTarget(); - else + } else { rhiRenderTarget = m_submissionContext->currentSwapChain()->currentFrameRenderTarget(); + } } auto executeDrawRenderView = [&] (RenderView* rv) { @@ -2707,7 +2763,6 @@ bool Renderer::executeCommandsSubmission(const RHIPassInfo &passInfo) // All the RVs in the current passinfo target the same RenderTarget // A single beginPass should take place, unless Computes RVs are intermingled - QRhiResourceUpdateBatch *inPassUpdates = nullptr; static const bool supportsCompute = m_submissionContext->rhi()->isFeatureSupported(QRhi::Compute); // Per Pass Global States @@ -2725,6 +2780,7 @@ bool Renderer::executeCommandsSubmission(const RHIPassInfo &passInfo) if (supportsCompute) { if (!inCompute) { cb->beginComputePass(m_submissionContext->m_currentUpdates); + m_submissionContext->m_currentUpdates = m_submissionContext->rhi()->nextResourceUpdateBatch(); inCompute = true; } executeComputeRenderView(rv); @@ -2746,6 +2802,7 @@ bool Renderer::executeCommandsSubmission(const RHIPassInfo &passInfo) continue; } cb->beginPass(rhiRenderTarget, clearColor, clearDepthStencil, m_submissionContext->m_currentUpdates); + m_submissionContext->m_currentUpdates = m_submissionContext->rhi()->nextResourceUpdateBatch(); inDraw = true; } @@ -2794,8 +2851,7 @@ bool Renderer::executeCommandsSubmission(const RHIPassInfo &passInfo) const QRhiColorAttachment *color0Att = desc.colorAttachmentAt(0); readbackDesc.setTexture(color0Att->texture()); } - inPassUpdates = m_submissionContext->rhi()->nextResourceUpdateBatch(); - inPassUpdates->readBackTexture(readbackDesc, readBackResult); + m_submissionContext->m_currentUpdates->readBackTexture(readbackDesc, readBackResult); } else { qCWarning(Backend) << "Requested capture rectangle is outside framebuffer"; } @@ -2807,9 +2863,9 @@ bool Renderer::executeCommandsSubmission(const RHIPassInfo &passInfo) } if (Q_LIKELY(inDraw)) - cb->endPass(inPassUpdates); + cb->endPass(m_submissionContext->m_currentUpdates); else if (inCompute) - cb->endComputePass(); + cb->endComputePass(m_submissionContext->m_currentUpdates); m_submissionContext->m_currentUpdates = m_submissionContext->rhi()->nextResourceUpdateBatch(); |