diff options
Diffstat (limited to 'src/plugins/renderers/rhi')
7 files changed, 148 insertions, 39 deletions
diff --git a/src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp b/src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp index 1f243e37b..eac49f01a 100644 --- a/src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp +++ b/src/plugins/renderers/rhi/graphicshelpers/submissioncontext.cpp @@ -498,6 +498,10 @@ SubmissionContext::SubmissionContext() { static_contexts[m_id] = this; m_contextInfo.m_api = QGraphicsApiFilter::RHI; + + // We set those version numbers because QShaderGenerator wants major > 0 + m_contextInfo.m_major = 1; + m_contextInfo.m_minor = 0; } SubmissionContext::~SubmissionContext() @@ -1630,6 +1634,7 @@ SubmissionContext::ShaderCreationInfo SubmissionContext::createShaderProgram(RHI {QShader::MslShader, QShaderVersion(12)}, }); + b.setGeneratedShaderVariants({QShader::Variant{}, #ifndef QT_NO_OPENGL QShader::Variant{}, @@ -1637,6 +1642,7 @@ SubmissionContext::ShaderCreationInfo SubmissionContext::createShaderProgram(RHI QShader::Variant{}, QShader::Variant{}}); + // TODO handle caching as QShader does not have a built-in mechanism for that QString logs; bool success = true; @@ -1650,7 +1656,7 @@ SubmissionContext::ShaderCreationInfo SubmissionContext::createShaderProgram(RHI b.setSourceString(shaderCode.at(i), rhiStage); QShader bakedShader = b.bake(); if (b.errorMessage() != QString() || !bakedShader.isValid()) { - qDebug() << "Shader Error: " << b.errorMessage(); + qDebug() << "Shader Error: " << b.errorMessage() << shaderCode.at(i).data() << rhiStage; logs += b.errorMessage(); success = false; } diff --git a/src/plugins/renderers/rhi/managers/rhihandle_types_p.h b/src/plugins/renderers/rhi/managers/rhihandle_types_p.h index 946d94a38..2e74131e1 100644 --- a/src/plugins/renderers/rhi/managers/rhihandle_types_p.h +++ b/src/plugins/renderers/rhi/managers/rhihandle_types_p.h @@ -76,9 +76,9 @@ typedef Qt3DCore::QHandle<RHIGraphicsPipeline> HRHIGraphicsPipeline; } // namespace Qt3DRender #if defined(_MSC_VER) -#define RHI_UNIMPLEMENTED do { qDebug() << "Unimplemented: " << __FUNCSIG__; } while (0) +#define RHI_UNIMPLEMENTED // do { qDebug() << "Unimplemented: " << __FUNCSIG__; } while (0) #else -#define RHI_UNIMPLEMENTED do { qDebug() << "Unimplemented: " << __PRETTY_FUNCTION__; } while (0) +#define RHI_UNIMPLEMENTED // do { qDebug() << "Unimplemented: " << __PRETTY_FUNCTION__; } while (0) #endif QT_END_NAMESPACE diff --git a/src/plugins/renderers/rhi/renderer/rendercommand_p.h b/src/plugins/renderers/rhi/renderer/rendercommand_p.h index e848ae593..f4031b711 100644 --- a/src/plugins/renderers/rhi/renderer/rendercommand_p.h +++ b/src/plugins/renderers/rhi/renderer/rendercommand_p.h @@ -68,8 +68,6 @@ QT_BEGIN_NAMESPACE class QRhiGraphicsPipeline; class QRhiShaderResourceBindings; -class QOpenGLVertexArrayObject; - namespace Qt3DRender { namespace Render { @@ -87,11 +85,12 @@ struct CommandUBO float modelMatrix[16]; float inverseModelMatrix[16]; float modelViewMatrix[16]; + float modelNormalMatrix[12]; float inverseModelViewMatrix[16]; float mvp[16]; float inverseModelViewProjectionMatrix[16]; }; -static_assert(sizeof(CommandUBO) == 6 * (16 * sizeof(float)), "UBO doesn't match std140"); +static_assert(sizeof(CommandUBO) == 6 * (16 * sizeof(float)) + 1 * (12 * sizeof(float)), "UBO doesn't match std140"); class Q_AUTOTEST_EXPORT RenderCommand { 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 diff --git a/src/plugins/renderers/rhi/renderer/renderer_p.h b/src/plugins/renderers/rhi/renderer/renderer_p.h index a337f267b..780b23ac2 100644 --- a/src/plugins/renderers/rhi/renderer/renderer_p.h +++ b/src/plugins/renderers/rhi/renderer/renderer_p.h @@ -422,6 +422,7 @@ private: bool uploadBuffersForCommand(QRhiCommandBuffer *cb, const RenderView *rv, RenderCommand &command); bool uploadUBOsForCommand(QRhiCommandBuffer *cb, const RenderView *rv, const RenderCommand &command); bool performDraw(QRhiCommandBuffer *cb, const QRhiViewport& vp, const QRhiScissor* scissor, const RenderCommand &command); + }; } // namespace Rhi diff --git a/src/plugins/renderers/rhi/renderer/renderview.cpp b/src/plugins/renderers/rhi/renderer/renderview.cpp index df6345896..49a7c2d9e 100644 --- a/src/plugins/renderers/rhi/renderer/renderview.cpp +++ b/src/plugins/renderers/rhi/renderer/renderview.cpp @@ -479,6 +479,7 @@ void RenderView::sort() // For RenderCommand with the same shader // We compute the adjacent change cost + /* // Minimize uniform changes int i = 0; const int commandSize = m_commands.size(); @@ -523,6 +524,7 @@ void RenderView::sort() } } } + */ } void RenderView::setRenderer(Renderer *renderer) @@ -864,6 +866,7 @@ void RenderView::updateRenderCommand(EntityRenderCommandData *renderCommandData, // Update CommandUBO (Qt3D standard uniforms) const Matrix4x4 worldTransform = *(entity->worldTransform()); const Matrix4x4 inverseWorldTransform = worldTransform.inverted(); + const QMatrix3x3 modelNormalMatrix = convertToQMatrix4x4(worldTransform).normalMatrix(); const Matrix4x4 modelViewMatrix = m_data.m_viewMatrix * worldTransform; const Matrix4x4 inverseModelViewMatrix = modelViewMatrix.inverted(); const Matrix4x4 mvp = projectionMatrix * modelViewMatrix; @@ -872,6 +875,20 @@ void RenderView::updateRenderCommand(EntityRenderCommandData *renderCommandData, memcpy(&command.m_commandUBO.modelMatrix, &worldTransform, sizeof(Matrix4x4)); memcpy(&command.m_commandUBO.inverseModelMatrix, &inverseWorldTransform, sizeof(Matrix4x4)); memcpy(&command.m_commandUBO.modelViewMatrix, &modelViewMatrix, sizeof(Matrix4x4)); + { + float (& normal)[12] = command.m_commandUBO.modelNormalMatrix; + normal[0] = modelNormalMatrix.constData()[0 * 3 + 0]; + normal[1] = modelNormalMatrix.constData()[0 * 3 + 1]; + normal[2] = modelNormalMatrix.constData()[0 * 3 + 2]; + + normal[4] = modelNormalMatrix.constData()[1 * 3 + 0]; + normal[5] = modelNormalMatrix.constData()[1 * 3 + 1]; + normal[6] = modelNormalMatrix.constData()[1 * 3 + 2]; + + normal[8] = modelNormalMatrix.constData()[2 * 3 + 0]; + normal[9] = modelNormalMatrix.constData()[2 * 3 + 1]; + normal[10] = modelNormalMatrix.constData()[2 * 3 + 2]; + } memcpy(&command.m_commandUBO.inverseModelViewMatrix, &inverseModelViewMatrix, sizeof(Matrix4x4)); memcpy(&command.m_commandUBO.mvp, &mvp, sizeof(Matrix4x4)); memcpy(&command.m_commandUBO.inverseModelViewProjectionMatrix, &inverseModelViewProjection, sizeof(Matrix4x4)); @@ -1148,8 +1165,8 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, } else { // with some drivers, samplers (like the envbox sampler) need to be bound even though // they may not be actually used, otherwise draw calls can fail - static const int irradianceId = StringToInt::lookupId(QLatin1String("envLight.irradiance")); - static const int specularId = StringToInt::lookupId(QLatin1String("envLight.specular")); + static const int irradianceId = StringToInt::lookupId(QLatin1String("envLight_irradiance")); + static const int specularId = StringToInt::lookupId(QLatin1String("envLight_specular")); // setUniformValue(command->m_parameterPack, irradianceId, m_renderer->submissionContext()->maxTextureUnitsCount()); // setUniformValue(command->m_parameterPack, specularId, m_renderer->submissionContext()->maxTextureUnitsCount()); } diff --git a/src/plugins/renderers/rhi/renderer/rhigraphicspipeline.cpp b/src/plugins/renderers/rhi/renderer/rhigraphicspipeline.cpp index 62da8aa12..19fd39d8e 100644 --- a/src/plugins/renderers/rhi/renderer/rhigraphicspipeline.cpp +++ b/src/plugins/renderers/rhi/renderer/rhigraphicspipeline.cpp @@ -68,6 +68,9 @@ void RHIGraphicsPipeline::cleanup() m_rvUbo = nullptr; m_cmdUbo = nullptr; m_pipeline = nullptr; + m_shaderResourceBindings = nullptr; + m_ubos.clear(); + m_attributeNameIdToBindingIndex.clear(); } } // Rhi |