diff options
Diffstat (limited to 'src/plugins/renderers/rhi/renderer/renderer.cpp')
-rw-r--r-- | src/plugins/renderers/rhi/renderer/renderer.cpp | 145 |
1 files changed, 114 insertions, 31 deletions
diff --git a/src/plugins/renderers/rhi/renderer/renderer.cpp b/src/plugins/renderers/rhi/renderer/renderer.cpp index a17d9b115..03d72e010 100644 --- a/src/plugins/renderers/rhi/renderer/renderer.cpp +++ b/src/plugins/renderers/rhi/renderer/renderer.cpp @@ -706,6 +706,8 @@ void Renderer::doRender(bool swapBuffers) const bool queueIsComplete = m_renderQueue->isFrameQueueComplete(); const bool queueIsEmpty = m_renderQueue->targetRenderViewCount() == 0; + bool mustCleanResources = false; + // When using synchronous rendering (QtQuick) // We are not sure that the frame queue is actually complete // Since a call to render may not be synched with the completions @@ -770,7 +772,7 @@ void Renderer::doRender(bool swapBuffers) submissionData = submitRenderViews(rhiPassesInfo); // Perform any required cleanup of the Graphics resources (Buffers deleted, Shader deleted...) - cleanGraphicsResources(); + mustCleanResources = true; } } @@ -813,6 +815,9 @@ void Renderer::doRender(bool swapBuffers) && surfaceLock.isSurfaceValid() && m_shouldSwapBuffers; m_submissionContext->endDrawing(swapBuffers); + + if (mustCleanResources) + cleanGraphicsResources(); } } @@ -922,10 +927,17 @@ void Renderer::updateGraphicsPipeline(RenderCommand& cmd, RenderView *rv, int re } // Try to retrieve existing pipeline + auto& pipelineManager = *m_RHIResourceManagers->rhiGraphicsPipelineManager(); const GraphicsPipelineIdentifier pipelineKey { cmd.m_geometry, cmd.m_shaderId, renderViewIndex }; - RHIGraphicsPipeline *graphicsPipeline = m_RHIResourceManagers->rhiGraphicsPipelineManager()->getOrCreateResource(pipelineKey); + RHIGraphicsPipeline *graphicsPipeline = pipelineManager.getOrCreateResource(pipelineKey); // TO DO: Ensure we find a way to know when the state is dirty to trigger a rebuild + if (!graphicsPipeline) { + qDebug() << "Warning : could not create a graphics pipeline"; + RHIGraphicsPipeline *graphicsPipeline = m_RHIResourceManagers->rhiGraphicsPipelineManager()->getOrCreateResource(pipelineKey); + return; + } + // Increase score so that we know the pipeline was used for this frame and shouldn't be destroyed graphicsPipeline->increaseScore(); @@ -966,7 +978,7 @@ void Renderer::updateGraphicsPipeline(RenderCommand& cmd, RenderView *rv, int re auto handle = m_RHIResourceManagers->rhiBufferManager()->allocateResource(); RHIBuffer *ubo = m_RHIResourceManagers->rhiBufferManager()->data(handle); Q_ASSERT(ubo); - const QByteArray rawData(block.m_size, '0'); + const QByteArray rawData(block.m_size, '\0'); ubo->allocate(m_submissionContext.data(), rawData, true); ok = ubo->bind(m_submissionContext.data(), RHIBuffer::UniformBuffer); uboBuffers[block.m_binding] = {handle, ubo}; @@ -1139,7 +1151,8 @@ void Renderer::updateGraphicsPipeline(RenderCommand& cmd, RenderView *rv, int re } // Record RHIGraphicsPipeline into command for later use - cmd.pipeline = graphicsPipeline; + if (graphicsPipeline && graphicsPipeline->pipeline()) + cmd.pipeline = graphicsPipeline; } // When this function is called, we must not be processing the commands for frame n+1 @@ -2141,7 +2154,6 @@ bool Renderer::uploadBuffersForCommand(QRhiCommandBuffer *cb, const RenderView * } for (const BlockToUBO& pack : command.m_parameterPack.uniformBuffers()) { - qDebug() << pack.m_bufferID; Buffer *cpuBuffer = nodeManagers()->bufferManager()->lookupResource(pack.m_bufferID); RHIBuffer *ubo = m_submissionContext->rhiBufferForRenderBuffer(cpuBuffer); ubo->bind(&*m_submissionContext, RHIBuffer::UniformBuffer); @@ -2150,6 +2162,77 @@ bool Renderer::uploadBuffersForCommand(QRhiCommandBuffer *cb, const RenderView * return true; } +namespace +{ +void printUpload(const UniformValue& value, + const QShaderDescription::BlockVariable& member) +{ + switch (member.type) + { + case QShaderDescription::VariableType::Int: + qDebug() << "Updating" << member.name << "with int data: " << *value.constData<int>() << " (offset: " << member.offset << ", size: " << member.size << ")"; + break; + case QShaderDescription::VariableType::Float: + qDebug() << "Updating" << member.name << "with float data: " << *value.constData<float>() << " (offset: " << member.offset << ", size: " << member.size << ")"; + break; + case QShaderDescription::VariableType::Vec2: + qDebug() << "Updating" << member.name << "with vec2 data: " + << value.constData<float>()[0] << ", " + << value.constData<float>()[1] << " (offset: " << member.offset << ", size: " << member.size << ")"; + ; + break; + case QShaderDescription::VariableType::Vec3: + qDebug() << "Updating" << member.name << "with vec3 data: " + << value.constData<float>()[0] << ", " + << value.constData<float>()[1] << ", " + << value.constData<float>()[2] << " (offset: " << member.offset << ", size: " << member.size << ")"; + ; + break; + case QShaderDescription::VariableType::Vec4: + qDebug() << "Updating" << member.name << "with vec4 data: " + << value.constData<float>()[0] << ", " + << value.constData<float>()[1] << ", " + << value.constData<float>()[2] << ", " + << value.constData<float>()[3] << " (offset: " << member.offset << ", size: " << member.size << ")"; + ; + break; + default: + qDebug() << "Updating" << member.name << "with data: " << value.constData<char>(); + break; + } +} + +void uploadUniform( + SubmissionContext& submissionContext, + const PackUniformHash &uniforms, + const RHIShader::UBO_Member& uboMember, + const QHash<int, RHIGraphicsPipeline::UBOBuffer>& uboBuffers, + const QString& uniformName, + const QShaderDescription::BlockVariable& member) +{ + const int uniformNameId = StringToInt::lookupId(uniformName); + + if (!uniforms.contains(uniformNameId)) + return; + + const UniformValue value = uniforms.value(uniformNameId); + const ShaderUniformBlock block = uboMember.block; + + // Update UBO with uniform value + Q_ASSERT(uboBuffers.contains(block.m_binding)); + const RHIGraphicsPipeline::UBOBuffer& ubo = uboBuffers[block.m_binding]; + RHIBuffer *buffer = ubo.buffer; + + // TODO we should maybe have this thread_local to not reallocate memory every time + QByteArray rawData; + rawData.resize(member.size); + memcpy(rawData.data(), value.constData<char>(), std::min(value.byteSize(), member.size)); + buffer->update(&submissionContext, rawData, member.offset); + + // printUpload(value, member); +} +} + bool Renderer::uploadUBOsForCommand(QRhiCommandBuffer *cb, const RenderView *rv, const RenderCommand &command) { RHIGraphicsPipeline *pipeline = command.pipeline; @@ -2170,41 +2253,39 @@ bool Renderer::uploadUBOsForCommand(QRhiCommandBuffer *cb, const RenderView *rv, if (!shader) return true; - const QVector<RHIShader::UBO_Member> uboMembers = shader->uboMembers(); - const QHash<int, RHIGraphicsPipeline::UBOBuffer> uboBuffers = pipeline->ubos(); + const QVector<RHIShader::UBO_Member>& uboMembers = shader->uboMembers(); + const QHash<int, RHIGraphicsPipeline::UBOBuffer>& uboBuffers = pipeline->ubos(); const ShaderParameterPack ¶meterPack = command.m_parameterPack; const PackUniformHash &uniforms = parameterPack.uniforms(); // Update Buffer CPU side data based on uniforms being set for (const RHIShader::UBO_Member &uboMember : uboMembers) { - const QVector<QShaderDescription::BlockVariable> members = uboMember.members; - for (const QShaderDescription::BlockVariable &member : members) { - const int uniformNameId = StringToInt::lookupId(member.name); - - - // Check if key is found in one of the custom UBOs - if (uniforms.contains(uniformNameId)) { - const UniformValue value = uniforms.value(uniformNameId); - const ShaderUniformBlock block = uboMember.block; - - // Update UBO with uniform value - Q_ASSERT(uboBuffers.contains(block.m_binding)); - const RHIGraphicsPipeline::UBOBuffer& ubo = uboBuffers[block.m_binding]; - RHIBuffer *buffer = ubo.buffer; - - // TODO we should maybe have this thread_local to not reallocate memory every time - QByteArray rawData; - rawData.resize(member.size); - memcpy(rawData.data(), value.constData<char *>(), std::min(value.byteSize(), member.size)); - buffer->update(m_submissionContext.data(), rawData, member.offset); - qDebug() << "Updating" << member.name << "with" << rawData; + for (const QShaderDescription::BlockVariable &member : qAsConst(uboMember.members)) { + + if (!member.arrayDims.empty()) { + if (!member.structMembers.empty()) { + const int arr0 = member.arrayDims[0]; + for (int i = 0; i < arr0; i++) { + for (const QShaderDescription::BlockVariable& structMember : member.structMembers) { + const QString processedName = member.name + "[" + QString::number(i) + "]." + structMember.name; + uploadUniform(*m_submissionContext, uniforms, uboMember, uboBuffers, processedName, structMember); + } + } + } else { + uploadUniform(*m_submissionContext, uniforms, uboMember, uboBuffers, member.name, member); + } + } + else + { + uploadUniform(*m_submissionContext, uniforms, uboMember, uboBuffers, member.name, member); } } } // Upload changes to GPU Buffer - for (const RHIGraphicsPipeline::UBOBuffer& ubo : uboBuffers) + for (const RHIGraphicsPipeline::UBOBuffer& ubo : uboBuffers) { // Binding triggers the upload ubo.buffer->bind(m_submissionContext.data(), RHIBuffer::UniformBuffer); + } } return true; } @@ -2351,12 +2432,14 @@ void Renderer::cleanGraphicsResources() // Remove unused GraphicsPipeline RHIGraphicsPipelineManager *pipelineManager = m_RHIResourceManagers->rhiGraphicsPipelineManager(); const QVector<HRHIGraphicsPipeline> graphicsPipelinesHandles = pipelineManager->activeHandles(); - for (const HRHIGraphicsPipeline &pipelineHandle : graphicsPipelinesHandles) { + for (HRHIGraphicsPipeline pipelineHandle : graphicsPipelinesHandles) { RHIGraphicsPipeline *pipeline = pipelineManager->data(pipelineHandle); pipeline->decreaseScore(); // Pipeline wasn't used recently, let's destroy it if (pipeline->score() < 0) - pipelineManager->release(pipelineHandle); + { + pipeline->cleanup(); + } } // Clean buffers |