From 3bc1b227c2564b27527e97bbf76e546878ccb4bd Mon Sep 17 00:00:00 2001 From: Razakhel Date: Thu, 7 Mar 2024 21:23:19 +0100 Subject: [PATCH] [Render] Instrumented rendering features for profiling purposes - Moved the geometry pass' execution to a dedicated RenderGraph::executeGeometryPass() function - Moved the input callbacks processing to a dedicated Window::processInputs() function --- include/RaZ/Render/RenderGraph.hpp | 5 +- include/RaZ/Render/Window.hpp | 4 ++ src/RaZ/Render/Camera.cpp | 26 +++++++++++ src/RaZ/Render/Cubemap.cpp | 10 ++++ src/RaZ/Render/Framebuffer.cpp | 14 ++++++ src/RaZ/Render/Material.cpp | 4 ++ src/RaZ/Render/MeshRenderer.cpp | 12 ++++- src/RaZ/Render/Overlay.cpp | 11 ++++- src/RaZ/Render/RenderGraph.cpp | 45 ++++++++++++------ src/RaZ/Render/RenderPass.cpp | 4 ++ src/RaZ/Render/RenderSystem.cpp | 20 ++++++++ src/RaZ/Render/Shader.cpp | 6 +++ src/RaZ/Render/ShaderProgram.cpp | 42 +++++++++++++++++ src/RaZ/Render/SubmeshRenderer.cpp | 12 +++++ src/RaZ/Render/Texture.cpp | 36 +++++++++++++++ src/RaZ/Render/Window.cpp | 74 ++++++++++++++++++++---------- 16 files changed, 285 insertions(+), 40 deletions(-) diff --git a/include/RaZ/Render/RenderGraph.hpp b/include/RaZ/Render/RenderGraph.hpp index 7f9a7efd..079b7fda 100644 --- a/include/RaZ/Render/RenderGraph.hpp +++ b/include/RaZ/Render/RenderGraph.hpp @@ -42,9 +42,12 @@ class RenderGraph : public Graph { /// Executes the render graph, executing all passes starting with the geometry's. /// \param renderSystem Render system executing the render graph. void execute(RenderSystem& renderSystem); + /// Executes the geometry pass. + /// \param renderSystem Render system executing the render graph. + void executeGeometryPass(RenderSystem& renderSystem) const; /// Executes a render pass, which in turn recursively executes its parents if they have not already been in the current frame. /// \param renderPass Render pass to be executed. - void execute(const RenderPass& renderPass); + void executePass(const RenderPass& renderPass); RenderPass m_geometryPass {}; std::vector> m_renderProcesses {}; diff --git a/include/RaZ/Render/Window.hpp b/include/RaZ/Render/Window.hpp index f71f3b0b..d1726cc2 100644 --- a/include/RaZ/Render/Window.hpp +++ b/include/RaZ/Render/Window.hpp @@ -174,6 +174,10 @@ class Window { ~Window() { close(); } private: + /// Processes actions corresponding to keyboard & mouse inputs. + /// \param deltaTime Amount of time elapsed since the last frame. + void processInputs(float deltaTime); + static inline int s_refCounter = 0; OwnerValue m_windowHandle {}; diff --git a/src/RaZ/Render/Camera.cpp b/src/RaZ/Render/Camera.cpp index eace5d31..c0e8dc89 100644 --- a/src/RaZ/Render/Camera.cpp +++ b/src/RaZ/Render/Camera.cpp @@ -1,6 +1,8 @@ #include "RaZ/Math/Transform.hpp" #include "RaZ/Render/Camera.hpp" +#include "tracy/Tracy.hpp" + namespace Raz { Camera::Camera(unsigned int frameWidth, unsigned int frameHeight, @@ -10,11 +12,15 @@ Camera::Camera(unsigned int frameWidth, unsigned int frameHeight, m_fieldOfView{ fieldOfView }, m_nearPlane{ nearPlane }, m_farPlane{ farPlane }, m_projType{ projType } { + ZoneScopedN("Camera::Camera"); + computeProjectionMatrix(); computeInverseProjectionMatrix(); } void Camera::setFieldOfView(Radiansf fieldOfView) { + ZoneScopedN("Camera::setFieldOfView"); + m_fieldOfView = fieldOfView; if (m_projType == ProjectionType::PERSPECTIVE) { @@ -24,6 +30,8 @@ void Camera::setFieldOfView(Radiansf fieldOfView) { } void Camera::setOrthographicBound(float bound) { + ZoneScopedN("Camera::setOrthographicBound"); + m_orthoBound = bound; if (m_projType == ProjectionType::ORTHOGRAPHIC) { @@ -33,6 +41,8 @@ void Camera::setOrthographicBound(float bound) { } void Camera::setProjectionType(ProjectionType projType) { + ZoneScopedN("Camera::setProjectionType"); + if (projType == m_projType) return; // No need to recompute the projection matrix @@ -43,12 +53,16 @@ void Camera::setProjectionType(ProjectionType projType) { } const Mat4f& Camera::computeViewMatrix(const Transform& cameraTransform) { + ZoneScopedN("Camera::computeViewMatrix"); + // TODO: the rotation quaternion being supposedly a unit one, the inversion could be replaced by a conjugation m_viewMat = cameraTransform.getRotation().inverse().computeMatrix() * cameraTransform.computeTranslationMatrix(true); return m_viewMat; } const Mat4f& Camera::computeLookAt(const Vec3f& position) { + ZoneScopedN("Camera::computeLookAt"); + const Vec3f zAxis = (position - m_target).normalize(); const Vec3f xAxis = m_upAxis.cross(zAxis).normalize(); const Vec3f yAxis = zAxis.cross(xAxis); @@ -62,11 +76,15 @@ const Mat4f& Camera::computeLookAt(const Vec3f& position) { } const Mat4f& Camera::computeInverseViewMatrix() { + ZoneScopedN("Camera::computeInverseViewMatrix"); + m_invViewMat = m_viewMat.inverse(); return m_invViewMat; } const Mat4f& Camera::computePerspectiveMatrix() { + ZoneScopedN("Camera::computePerspectiveMatrix"); + const float halfFovTangent = std::tan(m_fieldOfView.value * 0.5f); const float fovRatio = m_frameRatio * halfFovTangent; const float planeMult = m_farPlane * m_nearPlane; @@ -81,6 +99,8 @@ const Mat4f& Camera::computePerspectiveMatrix() { } const Mat4f& Camera::computeOrthographicMatrix(float minX, float maxX, float minY, float maxY, float minZ, float maxZ) { + ZoneScopedN("Camera::computeOrthographicMatrix"); + const float invDistX = 1.f / (maxX - minX); const float invDistY = 1.f / (maxY - minY); const float invDistZ = 1.f / (maxZ - minZ); @@ -99,6 +119,8 @@ const Mat4f& Camera::computeOrthographicMatrix() { } const Mat4f& Camera::computeProjectionMatrix() { + ZoneScopedN("Camera::computeProjectionMatrix"); + if (m_projType == ProjectionType::ORTHOGRAPHIC) return computeOrthographicMatrix(); @@ -106,11 +128,15 @@ const Mat4f& Camera::computeProjectionMatrix() { } const Mat4f& Camera::computeInverseProjectionMatrix() { + ZoneScopedN("Camera::computeInverseProjectionMatrix"); + m_invProjMat = m_projMat.inverse(); return m_invProjMat; } void Camera::resizeViewport(unsigned int frameWidth, unsigned int frameHeight) { + ZoneScopedN("Camera::resizeViewport"); + const float newRatio = static_cast(frameWidth) / static_cast(frameHeight); if (newRatio == m_frameRatio) diff --git a/src/RaZ/Render/Cubemap.cpp b/src/RaZ/Render/Cubemap.cpp index 6ff37cc7..797c9e5b 100644 --- a/src/RaZ/Render/Cubemap.cpp +++ b/src/RaZ/Render/Cubemap.cpp @@ -5,6 +5,8 @@ #include "RaZ/Render/Renderer.hpp" #include "RaZ/Utils/Logger.hpp" +#include "tracy/Tracy.hpp" + namespace Raz { namespace { @@ -145,6 +147,8 @@ TextureInternalFormat recoverInternalFormat(ImageColorspace colorspace, ImageDat } // namespace Cubemap::Cubemap() { + ZoneScopedN("Cubemap::Cubemap"); + Logger::debug("[Cubemap] Creating..."); Renderer::generateTexture(m_index); Logger::debug("[Cubemap] Created (ID: " + std::to_string(m_index) + ')'); @@ -155,6 +159,8 @@ const RenderShaderProgram& Cubemap::getProgram() const { } void Cubemap::load(const Image& right, const Image& left, const Image& top, const Image& bottom, const Image& front, const Image& back) const { + ZoneScopedN("Cubemap::load"); + bind(); constexpr auto mapImage = [] (const Image& img, TextureType type) { @@ -220,6 +226,8 @@ void Cubemap::unbind() const { } void Cubemap::draw() const { + ZoneScopedN("Cubemap::draw"); + Renderer::setDepthFunction(DepthStencilFunction::LESS_EQUAL); const MeshRenderer& displayCube = getDisplayCube(); @@ -235,6 +243,8 @@ void Cubemap::draw() const { } Cubemap::~Cubemap() { + ZoneScopedN("Cubemap::~Cubemap"); + if (!m_index.isValid()) return; diff --git a/src/RaZ/Render/Framebuffer.cpp b/src/RaZ/Render/Framebuffer.cpp index 71fd79fc..5cccecb5 100644 --- a/src/RaZ/Render/Framebuffer.cpp +++ b/src/RaZ/Render/Framebuffer.cpp @@ -6,11 +6,15 @@ #include "RaZ/Render/Texture.hpp" #include "RaZ/Utils/Logger.hpp" +#include "tracy/Tracy.hpp" + namespace Raz { namespace { inline void drawDisplaySurface() { + ZoneScopedN("[Framebuffer]::drawDisplaySurface"); + // Creating a triangle large enough to cover the whole render frame: // // 3 | \ 3 | \ @@ -54,6 +58,8 @@ inline void drawDisplaySurface() { } // namespace Framebuffer::Framebuffer() { + ZoneScopedN("Framebuffer::Framebuffer"); + Logger::debug("[Framebuffer] Creating..."); Renderer::generateFramebuffer(m_index); Logger::debug("[Framebuffer] Created (ID: " + std::to_string(m_index) + ')'); @@ -118,6 +124,8 @@ void Framebuffer::clearTextureBuffers() { } void Framebuffer::resizeBuffers(unsigned int width, unsigned int height) { + ZoneScopedN("Framebuffer::resizeBuffers"); + if (m_depthBuffer) m_depthBuffer->resize(width, height); @@ -126,6 +134,8 @@ void Framebuffer::resizeBuffers(unsigned int width, unsigned int height) { } void Framebuffer::mapBuffers() const { + ZoneScopedN("Framebuffer::mapBuffers"); + Logger::debug("[Framebuffer] Mapping buffers (ID: " + std::to_string(m_index) + ")..."); Renderer::bindFramebuffer(m_index); @@ -168,11 +178,15 @@ void Framebuffer::unbind() const { } void Framebuffer::display() const { + ZoneScopedN("Framebuffer::display"); + Renderer::clear(MaskType::COLOR); drawDisplaySurface(); } Framebuffer::~Framebuffer() { + ZoneScopedN("Framebuffer::~Framebuffer"); + if (!m_index.isValid()) return; diff --git a/src/RaZ/Render/Material.cpp b/src/RaZ/Render/Material.cpp index 90fb7864..5bb69e4d 100644 --- a/src/RaZ/Render/Material.cpp +++ b/src/RaZ/Render/Material.cpp @@ -2,6 +2,8 @@ #include "RaZ/Render/Material.hpp" #include "RaZ/Render/Renderer.hpp" +#include "tracy/Tracy.hpp" + namespace Raz { namespace { @@ -29,6 +31,8 @@ constexpr std::string_view singleTexture3DShaderSource = { } // namespace void Material::loadType(MaterialType type) { + ZoneScopedN("Material::loadType"); + switch (type) { case MaterialType::COOK_TORRANCE: m_program.setShaders(VertexShader::loadFromSource(vertShaderSource), FragmentShader::loadFromSource(cookTorranceShaderSource)); diff --git a/src/RaZ/Render/MeshRenderer.cpp b/src/RaZ/Render/MeshRenderer.cpp index 44850757..177f03e2 100644 --- a/src/RaZ/Render/MeshRenderer.cpp +++ b/src/RaZ/Render/MeshRenderer.cpp @@ -2,6 +2,8 @@ #include "RaZ/Render/MeshRenderer.hpp" #include "RaZ/Utils/Logger.hpp" +#include "tracy/Tracy.hpp" + namespace Raz { void MeshRenderer::setRenderMode(RenderMode renderMode, const Mesh& mesh) { @@ -10,6 +12,8 @@ void MeshRenderer::setRenderMode(RenderMode renderMode, const Mesh& mesh) { } Material& MeshRenderer::setMaterial(Material&& material) { + ZoneScopedN("MeshRenderer::setMaterial"); + m_materials.clear(); Material& newMaterial = m_materials.emplace_back(std::move(material)); @@ -26,7 +30,7 @@ Material& MeshRenderer::setMaterial(Material&& material) { } void MeshRenderer::removeMaterial(std::size_t materialIndex) { - assert("Error: Cannot remove a material that doesn't exist." && materialIndex < m_materials.size()); + assert("Error: Cannot remove a material that does not exist." && materialIndex < m_materials.size()); m_materials.erase(m_materials.begin() + static_cast(materialIndex)); @@ -58,6 +62,8 @@ MeshRenderer MeshRenderer::clone() const { } void MeshRenderer::load(const Mesh& mesh, RenderMode renderMode) { + ZoneScopedN("MeshRenderer::load"); + if (mesh.getSubmeshes().empty()) { Logger::error("[MeshRenderer] Cannot load an empty mesh."); return; @@ -78,6 +84,8 @@ void MeshRenderer::load(const Mesh& mesh, RenderMode renderMode) { } void MeshRenderer::loadMaterials() const { + ZoneScopedN("MeshRenderer::loadMaterials"); + for (const Material& material : m_materials) { material.getProgram().sendAttributes(); material.getProgram().initTextures(); @@ -88,6 +96,8 @@ void MeshRenderer::loadMaterials() const { } void MeshRenderer::draw() const { + ZoneScopedN("MeshRenderer::draw"); + for (const SubmeshRenderer& submeshRenderer : m_submeshRenderers) { if (submeshRenderer.getMaterialIndex() != std::numeric_limits::max()) { assert("Error: The material index does not reference any existing material." && (submeshRenderer.getMaterialIndex() < m_materials.size())); diff --git a/src/RaZ/Render/Overlay.cpp b/src/RaZ/Render/Overlay.cpp index f0f2e72e..2afefdf0 100644 --- a/src/RaZ/Render/Overlay.cpp +++ b/src/RaZ/Render/Overlay.cpp @@ -3,13 +3,14 @@ #include "RaZ/Render/Texture.hpp" #include "RaZ/Utils/Logger.hpp" -#include "GLFW/glfw3.h" #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" #include "misc/cpp/imgui_stdlib.h" #include "implot.h" +#include "tracy/Tracy.hpp" + namespace Raz { OverlayWindow& Overlay::addWindow(std::string title, const Vec2f& initSize, const Vec2f& initPos) { @@ -25,6 +26,8 @@ bool Overlay::hasMouseFocus() const { } void Overlay::render() const { + ZoneScopedN("Overlay::render"); + #if !defined(USE_OPENGL_ES) && defined(RAZ_CONFIG_DEBUG) if (Renderer::checkVersion(4, 3)) Renderer::pushDebugGroup("Overlay pass"); @@ -47,6 +50,8 @@ void Overlay::render() const { } void Overlay::initialize(GLFWwindow* windowHandle) { + ZoneScopedN("Overlay::initialize"); + if (ImGui::GetCurrentContext() != nullptr) return; // The overlay has already been initialized @@ -71,6 +76,8 @@ void Overlay::initialize(GLFWwindow* windowHandle) { } void Overlay::destroy() { + ZoneScopedN("Overlay::destroy"); + if (ImGui::GetCurrentContext() == nullptr) return; // The overlay has already been destroyed @@ -244,6 +251,8 @@ OverlayFpsCounter& OverlayWindow::addFpsCounter(std::string formattedLabel) { } void OverlayWindow::render() const { + ZoneScopedN("OverlayWindow::render"); + if (!m_enabled) return; diff --git a/src/RaZ/Render/RenderGraph.cpp b/src/RaZ/Render/RenderGraph.cpp index 3a7b4790..f47cc919 100644 --- a/src/RaZ/Render/RenderGraph.cpp +++ b/src/RaZ/Render/RenderGraph.cpp @@ -4,6 +4,8 @@ #include "RaZ/Render/RenderGraph.hpp" #include "RaZ/Render/RenderSystem.hpp" +#include "tracy/Tracy.hpp" + namespace Raz { bool RenderGraph::isValid() const { @@ -16,16 +18,20 @@ bool RenderGraph::isValid() const { } void RenderGraph::resizeViewport(unsigned int width, unsigned int height) { + ZoneScopedN("RenderGraph::resizeViewport"); + m_geometryPass.resizeWriteBuffers(width, height); - for (std::unique_ptr& renderPass : m_nodes) + for (const std::unique_ptr& renderPass : m_nodes) renderPass->resizeWriteBuffers(width, height); // TODO: resizing all write buffers will only work if they have all been created with equal dimensions - for (std::unique_ptr& renderProcess : m_renderProcesses) + for (const std::unique_ptr& renderProcess : m_renderProcesses) renderProcess->resizeBuffers(width, height); } void RenderGraph::updateShaders() const { + ZoneScopedN("RenderGraph::updateShaders"); + for (const std::unique_ptr& renderPass : m_nodes) renderPass->getProgram().updateShaders(); } @@ -34,9 +40,26 @@ void RenderGraph::execute(RenderSystem& renderSystem) { assert("Error: The render system needs a camera for the render graph to be executed." && (renderSystem.m_cameraEntity != nullptr)); assert("Error: The camera referenced by the render system needs a transform component." && renderSystem.m_cameraEntity->hasComponent()); - Renderer::clear(MaskType::COLOR | MaskType::DEPTH | MaskType::STENCIL); + ZoneScopedN("RenderGraph::execute"); - const Framebuffer& geometryFramebuffer = m_geometryPass.m_writeFramebuffer; + { + ZoneScopedN("Renderer::clear"); + Renderer::clear(MaskType::COLOR | MaskType::DEPTH | MaskType::STENCIL); + } + + executeGeometryPass(renderSystem); + + m_executedPasses.reserve(m_nodes.size() + 1); + m_executedPasses.emplace(&m_geometryPass); + + for (const std::unique_ptr& renderPass : m_nodes) + executePass(*renderPass); + + m_executedPasses.clear(); +} + +void RenderGraph::executeGeometryPass(RenderSystem& renderSystem) const { + ZoneScopedN("RenderGraph::executeGeometryPass"); #if !defined(USE_OPENGL_ES) m_geometryPass.m_timer.start(); @@ -47,6 +70,8 @@ void RenderGraph::execute(RenderSystem& renderSystem) { #endif #endif + const Framebuffer& geometryFramebuffer = m_geometryPass.m_writeFramebuffer; + if (!geometryFramebuffer.isEmpty()) geometryFramebuffer.bind(); @@ -102,22 +127,14 @@ void RenderGraph::execute(RenderSystem& renderSystem) { Renderer::popDebugGroup(); #endif #endif - - m_executedPasses.reserve(m_nodes.size() + 1); - m_executedPasses.emplace(&m_geometryPass); - - for (const std::unique_ptr& renderPass : m_nodes) - execute(*renderPass); - - m_executedPasses.clear(); } -void RenderGraph::execute(const RenderPass& renderPass) { +void RenderGraph::executePass(const RenderPass& renderPass) { if (m_executedPasses.find(&renderPass) != m_executedPasses.cend()) return; for (const RenderPass* parentPass : renderPass.m_parents) - execute(*parentPass); + executePass(*parentPass); renderPass.execute(); diff --git a/src/RaZ/Render/RenderPass.cpp b/src/RaZ/Render/RenderPass.cpp index e1616ec0..6d844dc3 100644 --- a/src/RaZ/Render/RenderPass.cpp +++ b/src/RaZ/Render/RenderPass.cpp @@ -2,6 +2,8 @@ #include "RaZ/Render/RenderPass.hpp" #include "RaZ/Render/Texture.hpp" +#include "tracy/Tracy.hpp" + namespace Raz { bool RenderPass::isValid() const { @@ -35,6 +37,8 @@ void RenderPass::addReadTexture(TexturePtr texture, const std::string& uniformNa } void RenderPass::execute() const { + ZoneScopedN("RenderPass::execute"); + if (!m_enabled) return; diff --git a/src/RaZ/Render/RenderSystem.cpp b/src/RaZ/Render/RenderSystem.cpp index b2472efe..5d1aaa07 100644 --- a/src/RaZ/Render/RenderSystem.cpp +++ b/src/RaZ/Render/RenderSystem.cpp @@ -8,6 +8,8 @@ #include "RaZ/Render/Renderer.hpp" #include "RaZ/Render/RenderSystem.hpp" +#include "tracy/Tracy.hpp" + namespace Raz { void RenderSystem::setCubemap(Cubemap&& cubemap) { @@ -16,6 +18,8 @@ void RenderSystem::setCubemap(Cubemap&& cubemap) { } void RenderSystem::resizeViewport(unsigned int width, unsigned int height) { + ZoneScopedN("RenderSystem::resizeViewport"); + m_sceneWidth = width; m_sceneHeight = height; @@ -28,6 +32,8 @@ void RenderSystem::resizeViewport(unsigned int width, unsigned int height) { } bool RenderSystem::update(const FrameTimeInfo& timeInfo) { + ZoneScopedN("RenderSystem::update"); + m_cameraUbo.bindBase(0); m_lightsUbo.bindBase(1); m_timeUbo.bindBase(2); @@ -75,6 +81,8 @@ void RenderSystem::sendCameraMatrices() const { } void RenderSystem::updateLights() const { + ZoneScopedN("RenderSystem::updateLights"); + unsigned int lightCount = 0; m_lightsUbo.bind(); @@ -91,6 +99,8 @@ void RenderSystem::updateLights() const { } void RenderSystem::updateShaders() const { + ZoneScopedN("RenderSystem::updateShaders"); + m_renderGraph.updateShaders(); for (std::size_t i = 0; i < m_renderGraph.getNodeCount(); ++i) { @@ -114,6 +124,8 @@ void RenderSystem::updateShaders() const { } void RenderSystem::updateMaterials(const MeshRenderer& meshRenderer) const { + ZoneScopedN("RenderSystem::updateMaterials(MeshRenderer)"); + for (const Material& material : meshRenderer.getMaterials()) { const RenderShaderProgram& materialProgram = material.getProgram(); @@ -131,6 +143,8 @@ void RenderSystem::updateMaterials(const MeshRenderer& meshRenderer) const { } void RenderSystem::updateMaterials() const { + ZoneScopedN("RenderSystem::updateMaterials"); + for (const Entity* entity : m_entities) { if (entity->hasComponent()) updateMaterials(entity->getComponent()); @@ -138,6 +152,8 @@ void RenderSystem::updateMaterials() const { } void RenderSystem::saveToImage(const FilePath& filePath, TextureFormat format, PixelDataType dataType) const { + ZoneScopedN("RenderSystem::saveToImage"); + ImageColorspace colorspace = ImageColorspace::RGB; switch (format) { @@ -169,6 +185,8 @@ void RenderSystem::destroy() { } void RenderSystem::linkEntity(const EntityPtr& entity) { + ZoneScopedN("RenderSystem::linkEntity"); + System::linkEntity(entity); if (entity->hasComponent()) @@ -182,6 +200,8 @@ void RenderSystem::linkEntity(const EntityPtr& entity) { } void RenderSystem::initialize() { + ZoneScopedN("RenderSystem::initialize"); + registerComponents(); // TODO: this Renderer initialization is technically useless; the RenderSystem needs to have it initialized before construction diff --git a/src/RaZ/Render/Shader.cpp b/src/RaZ/Render/Shader.cpp index a5a0aa98..e3cc7a99 100644 --- a/src/RaZ/Render/Shader.cpp +++ b/src/RaZ/Render/Shader.cpp @@ -4,6 +4,8 @@ #include "RaZ/Utils/Logger.hpp" #include "RaZ/Utils/StrUtils.hpp" +#include "tracy/Tracy.hpp" + namespace Raz { void Shader::import(FilePath filePath) { @@ -31,6 +33,8 @@ bool Shader::isCompiled() const noexcept { } void Shader::loadSource(const std::string& source) const { + ZoneScopedN("Shader::loadSource"); + Logger::debug("[Shader] Loading source (ID: " + std::to_string(m_index) + ")..."); // Removing spaces in front so that we can directly check the header tags @@ -56,6 +60,8 @@ void Shader::loadSource(const std::string& source) const { } void Shader::destroy() { + ZoneScopedN("Shader::destroy"); + if (!m_index.isValid()) return; diff --git a/src/RaZ/Render/ShaderProgram.cpp b/src/RaZ/Render/ShaderProgram.cpp index 17443f25..2f63e667 100644 --- a/src/RaZ/Render/ShaderProgram.cpp +++ b/src/RaZ/Render/ShaderProgram.cpp @@ -2,6 +2,8 @@ #include "RaZ/Render/ShaderProgram.hpp" #include "RaZ/Utils/Logger.hpp" +#include "tracy/Tracy.hpp" + namespace Raz { namespace { @@ -152,6 +154,8 @@ void ShaderProgram::setImageTexture(TexturePtr texture, const std::string& unifo #endif void ShaderProgram::link() { + ZoneScopedN("ShaderProgram::link"); + Logger::debug("[ShaderProgram] Linking (ID: " + std::to_string(m_index) + ")..."); Renderer::linkProgram(m_index); @@ -165,6 +169,8 @@ bool ShaderProgram::isLinked() const { } void ShaderProgram::updateShaders() { + ZoneScopedN("ShaderProgram::updateShaders"); + Logger::debug("[ShaderProgram] Updating shaders..."); loadShaders(); @@ -188,6 +194,8 @@ bool ShaderProgram::isUsed() const { } void ShaderProgram::sendAttributes() const { + ZoneScopedN("ShaderProgram::sendAttributes"); + if (m_attributes.empty()) return; @@ -211,6 +219,8 @@ void ShaderProgram::removeAttribute(const std::string& uniformName) { } void ShaderProgram::initTextures() const { + ZoneScopedN("ShaderProgram::initTextures"); + if (m_textures.empty()) return; @@ -224,6 +234,8 @@ void ShaderProgram::initTextures() const { } void ShaderProgram::bindTextures() const { + ZoneScopedN("ShaderProgram::bindTextures"); + use(); unsigned int textureIndex = 0; @@ -252,6 +264,8 @@ void ShaderProgram::removeTexture(const std::string& uniformName) { #if !defined(USE_WEBGL) void ShaderProgram::initImageTextures() const { + ZoneScopedN("ShaderProgram::initImageTextures"); + if (m_imageTextures.empty()) return; @@ -265,6 +279,8 @@ void ShaderProgram::initImageTextures() const { } void ShaderProgram::bindImageTextures() const { + ZoneScopedN("ShaderProgram::bindImageTextures"); + use(); unsigned int bindingIndex = 0; @@ -385,6 +401,8 @@ void ShaderProgram::sendUniform(int index, const Mat4f& mat) const { } ShaderProgram::~ShaderProgram() { + ZoneScopedN("ShaderProgram::~ShaderProgram"); + if (!m_index.isValid()) return; @@ -394,6 +412,8 @@ ShaderProgram::~ShaderProgram() { } void ShaderProgram::updateAttributesLocations() { + ZoneScopedN("ShaderProgram::updateAttributesLocations"); + for (auto& [name, attrib] : m_attributes) attrib.location = recoverUniformLocation(name); } @@ -528,6 +548,8 @@ RenderShaderProgram RenderShaderProgram::clone() const { } void RenderShaderProgram::loadShaders() const { + ZoneScopedN("RenderShaderProgram::loadShaders"); + Logger::debug("[RenderShaderProgram] Loading shaders..."); m_vertShader.load(); @@ -542,6 +564,8 @@ void RenderShaderProgram::loadShaders() const { } void RenderShaderProgram::compileShaders() const { + ZoneScopedN("RenderShaderProgram::compileShaders"); + Logger::debug("[RenderShaderProgram] Compiling shaders..."); m_vertShader.compile(); @@ -556,12 +580,16 @@ void RenderShaderProgram::compileShaders() const { } void RenderShaderProgram::destroyVertexShader() { + ZoneScopedN("RenderShaderProgram::destroyVertexShader"); + Renderer::detachShader(m_index, m_vertShader.getIndex()); m_vertShader.destroy(); } #if !defined(USE_OPENGL_ES) void RenderShaderProgram::destroyTessellationControlShader() { + ZoneScopedN("RenderShaderProgram::destroyTessellationControlShader"); + if (!m_tessCtrlShader) return; @@ -571,6 +599,8 @@ void RenderShaderProgram::destroyTessellationControlShader() { } void RenderShaderProgram::destroyTessellationEvaluationShader() { + ZoneScopedN("RenderShaderProgram::destroyTessellationEvaluationShader"); + if (!m_tessEvalShader) return; @@ -580,6 +610,8 @@ void RenderShaderProgram::destroyTessellationEvaluationShader() { } void RenderShaderProgram::destroyGeometryShader() { + ZoneScopedN("RenderShaderProgram::destroyGeometryShader"); + if (!m_geomShader) return; @@ -590,6 +622,8 @@ void RenderShaderProgram::destroyGeometryShader() { #endif void RenderShaderProgram::destroyFragmentShader() { + ZoneScopedN("RenderShaderProgram::destroyFragmentShader"); + Renderer::detachShader(m_index, m_fragShader.getIndex()); m_fragShader.destroy(); } @@ -626,24 +660,32 @@ ComputeShaderProgram ComputeShaderProgram::clone() const { } void ComputeShaderProgram::loadShaders() const { + ZoneScopedN("ComputeShaderProgram::loadShaders"); + Logger::debug("[ComputeShaderProgram] Loading shader..."); m_compShader.load(); Logger::debug("[ComputeShaderProgram] Loaded shader"); } void ComputeShaderProgram::compileShaders() const { + ZoneScopedN("ComputeShaderProgram::compileShaders"); + Logger::debug("[ComputeShaderProgram] Compiling shader..."); m_compShader.compile(); Logger::debug("[ComputeShaderProgram] Compiled shader"); } void ComputeShaderProgram::execute(unsigned int groupCountX, unsigned int groupCountY, unsigned int groupCountZ) const { + ZoneScopedN("ComputeShaderProgram::execute"); + bindImageTextures(); Renderer::dispatchCompute(groupCountX, groupCountY, groupCountZ); Renderer::setMemoryBarrier(BarrierType::ALL); } void ComputeShaderProgram::destroyShader() { + ZoneScopedN("ComputeShaderProgram::destroyShader"); + Renderer::detachShader(m_index, m_compShader.getIndex()); m_compShader.destroy(); } diff --git a/src/RaZ/Render/SubmeshRenderer.cpp b/src/RaZ/Render/SubmeshRenderer.cpp index a478f32e..5e30b93d 100644 --- a/src/RaZ/Render/SubmeshRenderer.cpp +++ b/src/RaZ/Render/SubmeshRenderer.cpp @@ -2,9 +2,13 @@ #include "RaZ/Render/SubmeshRenderer.hpp" #include "RaZ/Utils/Logger.hpp" +#include "tracy/Tracy.hpp" + namespace Raz { void SubmeshRenderer::setRenderMode(RenderMode renderMode, const Submesh& submesh) { + ZoneScopedN("SubmeshRenderer::setRenderMode"); + m_renderMode = renderMode; switch (m_renderMode) { @@ -52,11 +56,15 @@ SubmeshRenderer SubmeshRenderer::clone() const { } void SubmeshRenderer::load(const Submesh& submesh, RenderMode renderMode) { + ZoneScopedN("SubmeshRenderer::load"); + loadVertices(submesh); setRenderMode(renderMode, submesh); } void SubmeshRenderer::draw() const { + ZoneScopedN("SubmeshRenderer::draw"); + m_vao.bind(); m_ibo.bind(); @@ -64,6 +72,8 @@ void SubmeshRenderer::draw() const { } void SubmeshRenderer::loadVertices(const Submesh& submesh) { + ZoneScopedN("SubmeshRenderer::loadVertices"); + Logger::debug("[SubmeshRenderer] Loading submesh vertices..."); m_vao.bind(); @@ -114,6 +124,8 @@ void SubmeshRenderer::loadVertices(const Submesh& submesh) { } void SubmeshRenderer::loadIndices(const Submesh& submesh) { + ZoneScopedN("SubmeshRenderer::loadIndices"); + Logger::debug("[SubmeshRenderer] Loading submesh indices..."); m_vao.bind(); diff --git a/src/RaZ/Render/Texture.cpp b/src/RaZ/Render/Texture.cpp index 21e4146a..ac0508e3 100644 --- a/src/RaZ/Render/Texture.cpp +++ b/src/RaZ/Render/Texture.cpp @@ -7,6 +7,8 @@ #include "RaZ/Render/Texture.hpp" #include "RaZ/Utils/Logger.hpp" +#include "tracy/Tracy.hpp" + namespace Raz { namespace { @@ -118,6 +120,8 @@ void Texture::unbind() const { } void Texture::setFilter(TextureFilter minify, TextureFilter magnify) const { + ZoneScopedN("Texture::setFilter"); + bind(); Renderer::setTextureParameter(m_type, TextureParam::MINIFY_FILTER, recoverParam(minify)); Renderer::setTextureParameter(m_type, TextureParam::MAGNIFY_FILTER, recoverParam(magnify)); @@ -125,6 +129,8 @@ void Texture::setFilter(TextureFilter minify, TextureFilter magnify) const { } void Texture::setFilter(TextureFilter minify, TextureFilter mipmapMinify, TextureFilter magnify) const { + ZoneScopedN("Texture::setFilter"); + bind(); Renderer::setTextureParameter(m_type, TextureParam::MINIFY_FILTER, recoverParam(minify, mipmapMinify)); Renderer::setTextureParameter(m_type, TextureParam::MAGNIFY_FILTER, recoverParam(magnify)); @@ -132,6 +138,8 @@ void Texture::setFilter(TextureFilter minify, TextureFilter mipmapMinify, Textur } void Texture::setWrapping(TextureWrapping wrapping) const { + ZoneScopedN("Texture::setWrapping"); + const TextureParamValue value = recoverParam(wrapping); bind(); @@ -150,6 +158,8 @@ void Texture::setColorspace(TextureColorspace colorspace, TextureDataType dataTy && (colorspace != TextureColorspace::DEPTH || dataType == TextureDataType::FLOAT32)); assert("Error: A depth texture cannot be three-dimensional." && (colorspace != TextureColorspace::DEPTH || m_type != TextureType::TEXTURE_3D)); + ZoneScopedN("Texture::setColorspace"); + m_colorspace = colorspace; m_dataType = dataType; @@ -160,6 +170,8 @@ void Texture::setColorspace(TextureColorspace colorspace, TextureDataType dataTy } Texture::~Texture() { + ZoneScopedN("Texture::~Texture"); + if (!m_index.isValid()) return; @@ -169,6 +181,8 @@ Texture::~Texture() { } Texture::Texture(TextureType type) : m_type{ type } { + ZoneScopedN("Texture::Texture"); + Logger::debug("[Texture] Creating..."); Renderer::generateTexture(m_index); Logger::debug("[Texture] Created (ID: " + std::to_string(m_index) + ')'); @@ -178,6 +192,8 @@ Texture::Texture(TextureType type) : m_type{ type } { } void Texture::setLoadedParameters(bool createMipmaps) const { + ZoneScopedN("Texture::setLoadedParameters"); + if (m_colorspace == TextureColorspace::GRAY || m_colorspace == TextureColorspace::RG) { Renderer::setTextureParameter(m_type, TextureParam::SWIZZLE_R, static_cast(TextureFormat::RED)); Renderer::setTextureParameter(m_type, TextureParam::SWIZZLE_G, static_cast(TextureFormat::RED)); @@ -196,6 +212,8 @@ void Texture::setLoadedParameters(bool createMipmaps) const { } void Texture::generateMipmaps() const { + ZoneScopedN("Texture::generateMipmaps"); + bind(); Renderer::generateMipmap(m_type); unbind(); @@ -221,6 +239,8 @@ void Texture1D::resize(unsigned int width) { } void Texture1D::fill(const Color& color) { + ZoneScopedN("Texture1D::fill"); + m_colorspace = TextureColorspace::RGB; m_dataType = TextureDataType::BYTE; @@ -238,6 +258,8 @@ void Texture1D::fill(const Color& color) { } void Texture1D::load() const { + ZoneScopedN("Texture1D::load"); + if (m_colorspace == TextureColorspace::INVALID) return; // No colorspace has been set yet, the texture can't be loaded @@ -274,6 +296,8 @@ void Texture2D::resize(unsigned int width, unsigned int height) { } void Texture2D::load(const Image& image, bool createMipmaps) { + ZoneScopedN("Texture2D::load(Image)"); + if (image.isEmpty()) { // Image not found, defaulting texture to pure white fill(ColorPreset::White); @@ -307,6 +331,8 @@ void Texture2D::load(const Image& image, bool createMipmaps) { } void Texture2D::fill(const Color& color) { + ZoneScopedN("Texture2D::fill"); + m_colorspace = TextureColorspace::RGB; m_dataType = TextureDataType::BYTE; @@ -325,6 +351,8 @@ void Texture2D::fill(const Color& color) { } Image Texture2D::recoverImage() const { + ZoneScopedN("Texture2D::recoverImage"); + Image img(m_width, m_height, static_cast(m_colorspace), (m_dataType == TextureDataType::BYTE ? ImageDataType::BYTE : ImageDataType::FLOAT)); const PixelDataType pixelDataType = (m_dataType == TextureDataType::BYTE ? PixelDataType::UBYTE : PixelDataType::FLOAT); @@ -350,6 +378,8 @@ Image Texture2D::recoverImage() const { } void Texture2D::load() const { + ZoneScopedN("Texture2D::load"); + if (m_colorspace == TextureColorspace::INVALID) return; // No colorspace has been set yet, the texture can't be loaded @@ -388,6 +418,8 @@ void Texture3D::resize(unsigned int width, unsigned int height, unsigned int dep } void Texture3D::load(const std::vector& imageSlices, bool createMipmaps) { + ZoneScopedN("Texture3D::load(std::vector)"); + if (imageSlices.empty() || imageSlices.front().isEmpty()) { // Images not found, defaulting texture to pure white fill(ColorPreset::White); @@ -440,6 +472,8 @@ void Texture3D::load(const std::vector& imageSlices, bool createMipmaps) } void Texture3D::fill(const Color& color) { + ZoneScopedN("Texture3D::fill"); + m_colorspace = TextureColorspace::RGB; m_dataType = TextureDataType::BYTE; @@ -459,6 +493,8 @@ void Texture3D::fill(const Color& color) { } void Texture3D::load() const { + ZoneScopedN("Texture3D::load"); + if (m_colorspace == TextureColorspace::INVALID) return; // No colorspace has been set yet, the texture can't be loaded diff --git a/src/RaZ/Render/Window.cpp b/src/RaZ/Render/Window.cpp index dc39cbff..2f5117e7 100644 --- a/src/RaZ/Render/Window.cpp +++ b/src/RaZ/Render/Window.cpp @@ -19,6 +19,8 @@ #include "imgui_impl_glfw.h" #endif +#include "tracy/Tracy.hpp" + #if defined(RAZ_PLATFORM_EMSCRIPTEN) #include #endif @@ -30,6 +32,8 @@ Window::Window(RenderSystem& renderSystem, const std::string& title, WindowSetting settings, uint8_t antiAliasingSampleCount) : m_renderSystem{ &renderSystem }, m_width{ static_cast(width) }, m_height{ static_cast(height) } { + ZoneScopedN("Window::Window"); + Logger::debug("[Window] Initializing..."); glfwSetErrorCallback([] (int errorCode, const char* description) { @@ -184,6 +188,8 @@ void Window::enableFaceCulling(bool value) const { } bool Window::recoverVerticalSyncState() const { + ZoneScopedN("Window::recoverVerticalSyncState"); + #if defined(RAZ_PLATFORM_WINDOWS) if (wglGetExtensionsStringEXT()) return static_cast(wglGetSwapIntervalEXT()); @@ -207,6 +213,8 @@ bool Window::recoverVerticalSyncState() const { } void Window::enableVerticalSync([[maybe_unused]] bool value) const { + ZoneScopedN("Window::enableVerticalSync"); + #if defined(RAZ_PLATFORM_WINDOWS) if (wglGetExtensionsStringEXT()) { wglSwapIntervalEXT(static_cast(value)); @@ -262,6 +270,8 @@ void Window::setCloseCallback(std::function func) { } void Window::updateCallbacks() const { + ZoneScopedN("Window::updateCallbacks"); + #if !defined(RAZ_NO_OVERLAY) // Monitor events glfwSetMonitorCallback([] (GLFWmonitor* monitorHandle, int event) { @@ -391,37 +401,22 @@ void Window::updateCallbacks() const { } bool Window::run(float deltaTime) { + ZoneScopedN("Window::run"); + if (glfwWindowShouldClose(m_windowHandle)) return false; - glfwPollEvents(); - - // Process actions belonging to pressed keys & mouse buttons - auto& actions = std::get<4>(m_callbacks); - auto actionIter = actions.cbegin(); - - while (actionIter != actions.cend()) { - const auto& action = actionIter->second; - - // An action consists of two parts: - // - a callback associated to the triggered key or button - // - a value indicating if it should be executed only once or every frame - - action.first(deltaTime); - - // Removing the current action if ONCE is given, or simply increment the iterator - if (action.second == Input::ONCE) - actionIter = actions.erase(actionIter); // std::unordered_map::erase(iter) returns an iterator on the next element - else - ++actionIter; - } + processInputs(deltaTime); #if !defined(RAZ_NO_OVERLAY) if (m_isOverlayEnabled && !m_overlay.isEmpty()) m_overlay.render(); #endif - glfwSwapBuffers(m_windowHandle); + { + ZoneScopedN("glfwSwapBuffers"); + glfwSwapBuffers(m_windowHandle); + } #if defined(RAZ_PLATFORM_EMSCRIPTEN) emscripten_webgl_commit_frame(); @@ -443,6 +438,8 @@ void Window::setShouldClose() const { } void Window::close() { + ZoneScopedN("Window::close"); + if (!m_windowHandle.isValid()) return; @@ -455,11 +452,42 @@ void Window::close() { Overlay::destroy(); #endif - glfwTerminate(); + { + ZoneScopedN("glfwTerminate"); + glfwTerminate(); + } m_windowHandle = nullptr; } Logger::debug("[Window] Closed"); } +void Window::processInputs(float deltaTime) { + ZoneScopedN("Window::processInputs"); + + { + ZoneScopedN("glfwPollEvents"); + glfwPollEvents(); + } + + auto& actions = std::get(m_callbacks); + auto actionIter = actions.cbegin(); + + while (actionIter != actions.cend()) { + const auto& action = actionIter->second; + + // An action consists of two parts: + // - A callback associated to the triggered key or button + // - A value indicating if it should be executed only once or every frame + + action.first(deltaTime); + + // Removing the current action if ONCE is given, or simply increment the iterator + if (action.second == Input::ONCE) + actionIter = actions.erase(actionIter); // std::unordered_map::erase(iter) returns an iterator on the next element + else + ++actionIter; + } +} + } // namespace Raz