From cf0c68cb0cd7dd780ac3105391b03c06db00be71 Mon Sep 17 00:00:00 2001 From: aliasbinman Date: Wed, 20 Aug 2025 18:07:00 +0000 Subject: [PATCH] Runtime profiler base (#10391) 4171e09f80 * Add profiling macros and optick profiler * Update premake5_optick.lua * Added more profiling markers * Remove microprofiler option for now as not implemented * Added more markers ro rendering code * Update Optick build premake only for windows builds * More build file changes for optick with windows * Change how optick is built on windows * Update premake5_v2.lua * Update build files to use with_optick option * Added ScopeName macro to appease ASAN * Push to rekick jobs * Delete ProfilerMacros.h * Create profiler_macros.h * Update path_fiddle.cpp * Update fiddle_context.hpp * Update for rename of header * More header changes * Update fiddle_context.hpp * Update profiler_macros.h * Update for clang format * Update fiddle_context.hpp * Update profiler_macros.h * Update profiler_macros.h * Changed premake values on Chris' comments * Removed multiple define fro RIVE_OPTICK and now in rive_build_config.lua * Added Optick URL and Version to rive_build_config Co-authored-by: John White --- .rive_head | 2 +- build/rive_build_config.lua | 7 +++++ dependencies/premake5_optick.lua | 16 ++++++++++ include/rive/profiler/profiler_macros.h | 28 +++++++++++++++++ premake5_v2.lua | 9 ++++++ renderer/path_fiddle/fiddle_context.hpp | 1 - renderer/path_fiddle/fiddle_context_d3d.cpp | 4 +++ renderer/path_fiddle/path_fiddle.cpp | 5 ++++ renderer/premake5.lua | 11 +++++-- renderer/premake5_pls_renderer.lua | 8 +++++ renderer/src/render_context.cpp | 33 ++++++++++++++++++++- renderer/src/rive_render_path.cpp | 3 ++ renderer/src/rive_renderer.cpp | 10 +++++++ src/animation/linear_animation_instance.cpp | 3 ++ src/animation/state_machine_instance.cpp | 2 ++ src/artboard.cpp | 3 ++ src/shapes/paint/shape_paint.cpp | 3 ++ src/static_scene.cpp | 2 ++ 18 files changed, 144 insertions(+), 6 deletions(-) create mode 100644 dependencies/premake5_optick.lua create mode 100644 include/rive/profiler/profiler_macros.h diff --git a/.rive_head b/.rive_head index 044030f4..3ca850f8 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -f6d5d55b26d9facf3118620de6ff55d908a79f02 +4171e09f80920ce55d713060f929fa8ed88a065b diff --git a/build/rive_build_config.lua b/build/rive_build_config.lua index ed930363..05b2dfa3 100644 --- a/build/rive_build_config.lua +++ b/build/rive_build_config.lua @@ -138,6 +138,13 @@ newoption({ description = 'enable UndefinedBehaviorSanitizer', }) +newoption({ trigger = 'with_optick', description = 'use optick profiler' }) +if _OPTIONS['with_optick'] then + defines({ 'RIVE_OPTICK' }) + RIVE_OPTICK_URL = 'bombomby/optick' + RIVE_OPTICK_VERSION = '1.4.0.0' +end + location(RIVE_BUILD_OUT) targetdir(RIVE_BUILD_OUT) objdir(RIVE_BUILD_OUT .. '/obj') diff --git a/dependencies/premake5_optick.lua b/dependencies/premake5_optick.lua new file mode 100644 index 00000000..78dd304d --- /dev/null +++ b/dependencies/premake5_optick.lua @@ -0,0 +1,16 @@ +local dependency = require('dependency') +optick = dependency.github(RIVE_OPTICK_URL, RIVE_OPTICK_VERSION) +project('optick') +do + kind('StaticLib') + language('C++') + cppdialect('C++11') + + files { optick .. "/src/**.cpp" } + -- but exclude this one + removefiles { + optick .. "/src/optick_gpu.vulkan.cpp" + } + + includedirs({ optick .. '/src' }) +end diff --git a/include/rive/profiler/profiler_macros.h b/include/rive/profiler/profiler_macros.h new file mode 100644 index 00000000..b46d4287 --- /dev/null +++ b/include/rive/profiler/profiler_macros.h @@ -0,0 +1,28 @@ +#pragma once + +// RIVE_PROF_FRAME() +// This function should be called at the start of the main loop +// +// RIVE_PROF_SCOPE() +// Add to a function or scope to profile, the function name is +// automatically filled in +// +// RIVE_PROF_SCOPENAME(name) +// Same as above but manually supplied name +// +// RIVE_PROF_THREAD(name) +// Add to new threads + +#if defined(RIVE_OPTICK) // Optick integration +#include "optick_core.h" +#include "optick.h" +#define RIVE_PROF_FRAME() OPTICK_FRAME("RiveFrame") +#define RIVE_PROF_SCOPE() OPTICK_EVENT() +#define RIVE_PROF_SCOPENAME(name) OPTICK_EVENT(name) +#define RIVE_PROF_THREAD(name) OPTICK_THREAD(name) +#else // No profiler selected - fallback to no-op +#define RIVE_PROF_FRAME() +#define RIVE_PROF_SCOPE() +#define RIVE_PROF_SCOPENAME(name) +#define RIVE_PROF_THREAD(name) +#endif diff --git a/premake5_v2.lua b/premake5_v2.lua index 5a2f2ce0..b6af283a 100644 --- a/premake5_v2.lua +++ b/premake5_v2.lua @@ -37,6 +37,11 @@ dofile(path.join(dependencies, 'premake5_harfbuzz_v2.lua')) dofile(path.join(dependencies, 'premake5_sheenbidi_v2.lua')) dofile(path.join(dependencies, 'premake5_miniaudio_v2.lua')) dofile(path.join(dependencies, 'premake5_yoga_v2.lua')) + +if _OPTIONS['with_optick'] then + dofile(path.join(dependencies, 'premake5_optick.lua')) +end + if _OPTIONS['with_rive_scripting'] then luau = require(path.join(path.getabsolute('scripting/'), 'premake5')).luau else @@ -107,6 +112,10 @@ do architecture('x64') defines({ '_USE_MATH_DEFINES' }) end + + if _OPTIONS['with_optick'] then + includedirs({optick .. '/src' }) + end filter('system:macosx or system:ios') do diff --git a/renderer/path_fiddle/fiddle_context.hpp b/renderer/path_fiddle/fiddle_context.hpp index 1a5d9d23..1b3c6564 100644 --- a/renderer/path_fiddle/fiddle_context.hpp +++ b/renderer/path_fiddle/fiddle_context.hpp @@ -1,7 +1,6 @@ #pragma once #include - #include "rive/renderer/render_context.hpp" struct GLFWwindow; diff --git a/renderer/path_fiddle/fiddle_context_d3d.cpp b/renderer/path_fiddle/fiddle_context_d3d.cpp index 0c852f29..9b29ed6f 100644 --- a/renderer/path_fiddle/fiddle_context_d3d.cpp +++ b/renderer/path_fiddle/fiddle_context_d3d.cpp @@ -11,6 +11,7 @@ std::unique_ptr FiddleContext::MakeD3DPLS(FiddleContextOptions) #include "rive/renderer/rive_renderer.hpp" #include "rive/renderer/d3d11/render_context_d3d_impl.hpp" +#include "rive/profiler/profiler_macros.h" #include #include @@ -117,6 +118,8 @@ public: void flushPLSContext(RenderTarget* offscreenRenderTarget) final { + RIVE_PROF_SCOPE() + if (m_renderTarget->targetTexture() == nullptr) { if (m_isHeadless) @@ -143,6 +146,7 @@ public: void end(GLFWwindow*, std::vector* pixelData = nullptr) override { + RIVE_PROF_SCOPE() flushPLSContext(nullptr); if (pixelData != nullptr) { diff --git a/renderer/path_fiddle/path_fiddle.cpp b/renderer/path_fiddle/path_fiddle.cpp index 40d0aca7..f77afa42 100644 --- a/renderer/path_fiddle/path_fiddle.cpp +++ b/renderer/path_fiddle/path_fiddle.cpp @@ -6,6 +6,7 @@ #include "rive/layout.hpp" #include "rive/animation/state_machine_instance.hpp" #include "rive/static_scene.hpp" +#include "rive/profiler/profiler_macros.h" #include #include @@ -770,6 +771,9 @@ static void update_window_title(double fps, void riveMainLoop() { + RIVE_PROF_FRAME() + RIVE_PROF_SCOPE() + #ifdef __EMSCRIPTEN__ { // Fit the canvas to the browser window size. @@ -871,6 +875,7 @@ void riveMainLoop() (j - upRepeat) * spacing)); for (int i = 0; i < horzRepeat * 2 + 1; ++i) { + (*scene++)->draw(renderer.get()); renderer->transform(Mat2D::fromTranslate(spacing, 0)); } diff --git a/renderer/premake5.lua b/renderer/premake5.lua index 5a797275..6f2c3cb4 100644 --- a/renderer/premake5.lua +++ b/renderer/premake5.lua @@ -13,6 +13,7 @@ if not _OPTIONS['with-webgpu'] then project('path_fiddle') do dependson('rive') + kind('ConsoleApp') includedirs({ 'include', @@ -31,7 +32,7 @@ if not _OPTIONS['with-webgpu'] then defines({ 'YOGA_EXPORT=' }) - files({ 'path_fiddle/**.cpp', 'shader_hotload/**.cpp' }) + files({ 'path_fiddle/**.cpp', 'shader_hotload/**.cpp', 'path_fiddle/**.h**', 'shader_hotload/**.h**' }) links({ 'rive', @@ -55,7 +56,7 @@ if not _OPTIONS['with-webgpu'] then if _OPTIONS['with_vulkan'] then dofile('rive_vk_bootstrap/bootstrap_project.lua') end - + filter('action:xcode4') do -- xcode doesnt like angle brackets except for -isystem @@ -87,7 +88,11 @@ if not _OPTIONS['with-webgpu'] then libdirs({ RIVE_RUNTIME_DIR .. '/skia/dependencies/glfw_build/src/Release', }) - links({ 'glfw3', 'opengl32', 'd3d11', 'd3d12', 'dxguid', 'dxgi', 'd3dcompiler' }) + links({ 'glfw3', 'opengl32', 'd3d11', 'd3d12', 'dxguid', 'dxgi', 'd3dcompiler'}) + end + if _OPTIONS['with_optick'] then + links({'optick'}) + externalincludedirs({ optick .. '/src'}) end if _TARGET_OS == 'windows'then diff --git a/renderer/premake5_pls_renderer.lua b/renderer/premake5_pls_renderer.lua index 2a70b17a..f87ea309 100644 --- a/renderer/premake5_pls_renderer.lua +++ b/renderer/premake5_pls_renderer.lua @@ -168,6 +168,10 @@ newoption({ description = 'exclue -ffp-contract=on and -fassociative-math from builoptions', }) +if _OPTIONS['with_optick'] then + optick = dependency.github(RIVE_OPTICK_URL, RIVE_OPTICK_VERSION) +end + project('rive_pls_renderer') do kind('StaticLib') @@ -182,6 +186,10 @@ do files({ 'src/*.cpp', 'renderer/decoding/*.cpp' }) + if _OPTIONS['with_optick'] then + includedirs({optick .. '/src'}) + end + if _OPTIONS['with_vulkan'] then externalincludedirs({ vulkan_headers .. '/include', diff --git a/renderer/src/render_context.cpp b/renderer/src/render_context.cpp index cbc121af..7dcd325e 100644 --- a/renderer/src/render_context.cpp +++ b/renderer/src/render_context.cpp @@ -11,6 +11,8 @@ #include "rive/renderer/draw.hpp" #include "rive/renderer/rive_render_image.hpp" #include "rive/renderer/render_context_impl.hpp" +#include "rive/profiler/profiler_macros.h" + #include "shaders/constants.glsl" #include @@ -136,6 +138,7 @@ rcp RenderContext::makeRenderBuffer(RenderBufferType type, rcp RenderContext::decodeImage(Span encodedBytes) { + RIVE_PROF_SCOPE() rcp texture = m_impl->platformDecodeImageTexture(encodedBytes); #ifdef RIVE_DECODERS if (texture == nullptr) @@ -275,6 +278,7 @@ void RenderContext::LogicalFlush::resetContainers() void RenderContext::beginFrame(const FrameDescriptor& frameDescriptor) { + RIVE_PROF_SCOPE() assert(!m_didBeginFrame); assert(frameDescriptor.renderTargetWidth > 0); assert(frameDescriptor.renderTargetHeight > 0); @@ -389,6 +393,7 @@ bool RenderContext::pushDraws(DrawUniquePtr draws[], size_t drawCount) bool RenderContext::LogicalFlush::pushDraws(DrawUniquePtr draws[], size_t drawCount) { + RIVE_PROF_SCOPE() assert(!m_hasDoneLayout); auto countsVector = m_resourceCounts.toVec(); @@ -464,6 +469,7 @@ bool RenderContext::LogicalFlush::allocateGradient( const Gradient* gradient, gpu::ColorRampLocation* colorRampLocation) { + RIVE_PROF_SCOPE() assert(!m_hasDoneLayout); const float* stops = gradient->stops(); @@ -556,6 +562,8 @@ bool RenderContext::LogicalFlush::allocateAtlasDraw( uint16_t* y, TAABB* paddedRegion) { + RIVE_PROF_SCOPE() + if (m_atlasRectanizer == nullptr) { uint16_t atlasMaxSize = m_ctx->atlasMaxSize(); @@ -607,6 +615,7 @@ bool RenderContext::LogicalFlush::allocateAtlasDraw( size_t RenderContext::LogicalFlush::allocateCoverageBufferRange(size_t length) { + RIVE_PROF_SCOPE() assert(m_ctx->frameInterlockMode() == gpu::InterlockMode::clockwiseAtomic); assert(length % (32 * 32) == 0u); // Allocations must support 32x32 tiles. uint32_t offset = m_coverageBufferLength; @@ -633,6 +642,7 @@ void RenderContext::logicalFlush() void RenderContext::flush(const FlushResources& flushResources) { + RIVE_PROF_SCOPE() assert(m_didBeginFrame); assert(flushResources.renderTarget->width() == m_frameDescriptor.renderTargetWidth); @@ -827,6 +837,7 @@ void RenderContext::LogicalFlush::layoutResources( ResourceCounters* runningFrameResourceCounts, LayoutCounters* runningFrameLayoutCounts) { + RIVE_PROF_SCOPE() assert(!m_hasDoneLayout); const FrameDescriptor& frameDescriptor = m_ctx->frameDescriptor(); @@ -1063,6 +1074,7 @@ void RenderContext::LogicalFlush::layoutResources( void RenderContext::LogicalFlush::writeResources() { + RIVE_PROF_SCOPE() const gpu::PlatformFeatures& platformFeatures = m_ctx->platformFeatures(); assert(m_hasDoneLayout); assert(m_flushDesc.firstPath == m_ctx->m_pathData.elementsWritten()); @@ -1633,6 +1645,7 @@ void RenderContext::LogicalFlush::writeResources() void RenderContext::setResourceSizes(ResourceAllocationCounts allocs, bool forceRealloc) { + RIVE_PROF_SCOPE() #if 0 class Logger { @@ -1877,6 +1890,7 @@ void RenderContext::setResourceSizes(ResourceAllocationCounts allocs, void RenderContext::mapResourceBuffers( const ResourceAllocationCounts& mapCounts) { + RIVE_PROF_SCOPE() if (mapCounts.flushUniformBufferCount > 0) { m_flushUniformData.mapElements( @@ -1958,6 +1972,7 @@ void RenderContext::mapResourceBuffers( void RenderContext::unmapResourceBuffers( const ResourceAllocationCounts& mapCounts) { + RIVE_PROF_SCOPE() if (m_flushUniformData) { m_flushUniformData.unmapElements( @@ -2021,6 +2036,7 @@ void RenderContext::unmapResourceBuffers( uint32_t RenderContext::incrementCoverageBufferPrefix( bool* needsCoverageBufferClear) { + RIVE_PROF_SCOPE() assert(m_didBeginFrame); assert(frameInterlockMode() == gpu::InterlockMode::clockwiseAtomic); do @@ -2058,6 +2074,7 @@ uint32_t RenderContext::LogicalFlush::allocateOuterCubicTessVertices( uint32_t RenderContext::LogicalFlush::pushPath(const PathDraw* draw) { + RIVE_PROF_SCOPE() assert(m_hasDoneLayout); ++m_currentPathID; @@ -2110,6 +2127,7 @@ RenderContext::TessellationWriter::TessellationWriter( m_pathTessLocation(forwardTessLocation), m_pathMirroredTessLocation(mirroredTessLocation) { + RIVE_PROF_SCOPE() RIVE_DEBUG_CODE(m_expectedPathTessEndLocation = m_pathTessLocation + forwardTessVertexCount;) RIVE_DEBUG_CODE(m_expectedPathMirroredTessEndLocation = @@ -2138,6 +2156,7 @@ uint32_t RenderContext::LogicalFlush::pushContour(uint32_t pathID, bool closed, uint32_t vertexIndex0) { + RIVE_PROF_SCOPE() assert(pathID != 0); assert(isStroke || closed); @@ -2160,6 +2179,7 @@ uint32_t RenderContext::TessellationWriter::pushContour( bool closed, uint32_t paddingVertexCount) { + RIVE_PROF_SCOPE() // The first curve of the contour will be pre-padded with // 'paddingVertexCount' tessellation vertices, colocated at T=0. The caller // must use this argument align the end of the contour on a boundary of the @@ -2182,6 +2202,7 @@ void RenderContext::TessellationWriter::pushCubic( uint32_t joinSegmentCount, uint32_t contourIDWithFlags) { + RIVE_PROF_SCOPE() assert(0 <= parametricSegmentCount && parametricSegmentCount <= kMaxParametricSegments); assert(0 <= polarSegmentCount && polarSegmentCount <= kMaxPolarSegments); @@ -2247,6 +2268,7 @@ RIVE_ALWAYS_INLINE void RenderContext::TessellationWriter:: uint32_t joinSegmentCount, uint32_t contourIDWithFlags) { + RIVE_PROF_SCOPE() assert(totalVertexCount > 0); uint32_t y = m_pathTessLocation / kTessTextureWidth; @@ -2385,6 +2407,7 @@ RIVE_ALWAYS_INLINE void RenderContext::TessellationWriter:: void RenderContext::LogicalFlush::pushPaddingVertices(uint32_t count, uint32_t tessLocation) { + RIVE_PROF_SCOPE() assert(m_hasDoneLayout); assert(count > 0); @@ -2410,6 +2433,7 @@ void RenderContext::LogicalFlush::pushMidpointFanDraw( uint32_t tessLocation, gpu::ShaderMiscFlags shaderMiscFlags) { + RIVE_PROF_SCOPE() assert(m_hasDoneLayout); uint32_t baseInstance = math::lossless_numeric_cast( @@ -2431,6 +2455,7 @@ void RenderContext::LogicalFlush::pushOuterCubicsDraw( uint32_t tessLocation, gpu::ShaderMiscFlags shaderMiscFlags) { + RIVE_PROF_SCOPE() assert(m_hasDoneLayout); uint32_t baseInstance = math::lossless_numeric_cast( @@ -2451,6 +2476,7 @@ size_t RenderContext::LogicalFlush::pushInteriorTriangulationDraw( gpu::WindingFaces windingFaces, gpu::ShaderMiscFlags shaderMiscFlags) { + RIVE_PROF_SCOPE() assert(m_hasDoneLayout); assert(pathID != 0); @@ -2475,6 +2501,7 @@ size_t RenderContext::LogicalFlush::pushInteriorTriangulationDraw( void RenderContext::LogicalFlush::pushAtlasBlit(PathDraw* draw, uint32_t pathID) { + RIVE_PROF_SCOPE() auto baseVertex = math::lossless_numeric_cast( m_ctx->m_triangleVertexData.elementsWritten()); auto [l, t, r, b] = AABB(draw->pixelBounds()); @@ -2493,6 +2520,7 @@ void RenderContext::LogicalFlush::pushAtlasBlit(PathDraw* draw, uint32_t pathID) void RenderContext::LogicalFlush::pushImageRectDraw(ImageRectDraw* draw) { + RIVE_PROF_SCOPE() assert(m_hasDoneLayout); // If we support image paints for paths, the client should use pushPath() @@ -2519,7 +2547,7 @@ void RenderContext::LogicalFlush::pushImageRectDraw(ImageRectDraw* draw) void RenderContext::LogicalFlush::pushImageMeshDraw(ImageMeshDraw* draw) { - + RIVE_PROF_SCOPE() assert(m_hasDoneLayout); size_t imageDrawDataOffset = m_ctx->m_imageDrawUniformData.bytesWritten(); @@ -2546,6 +2574,7 @@ void RenderContext::LogicalFlush::pushImageMeshDraw(ImageMeshDraw* draw) void RenderContext::LogicalFlush::pushStencilClipResetDraw( StencilClipReset* draw) { + RIVE_PROF_SCOPE() assert(m_hasDoneLayout); uint32_t baseVertex = math::lossless_numeric_cast( @@ -2576,6 +2605,7 @@ gpu::DrawBatch& RenderContext::LogicalFlush::pushPathDraw( uint32_t vertexCount, uint32_t baseVertex) { + RIVE_PROF_SCOPE() assert(m_hasDoneLayout); DrawBatch& batch = pushDraw(draw, @@ -2666,6 +2696,7 @@ gpu::DrawBatch& RenderContext::LogicalFlush::pushDraw( uint32_t elementCount, uint32_t baseElement) { + RIVE_PROF_SCOPE() assert(m_hasDoneLayout); assert(elementCount > 0); diff --git a/renderer/src/rive_render_path.cpp b/renderer/src/rive_render_path.cpp index 0f8829b8..5c7cfe41 100644 --- a/renderer/src/rive_render_path.cpp +++ b/renderer/src/rive_render_path.cpp @@ -7,6 +7,7 @@ #include "rive/math/bezier_utils.hpp" #include "rive/math/simd.hpp" #include "rive/renderer/gpu.hpp" +#include "rive/profiler/profiler_macros.h" #include "shaders/constants.glsl" namespace rive @@ -161,6 +162,7 @@ static void chop_cubic_at_uniform_rotation(RawPath* path, int numChops, const Mat2D& rotationMatrix) { + RIVE_PROF_SCOPE() math::CubicCoeffs coeffs(p); float2 tangent = simd::load2f(&tangents[0]); float4 rotation = simd::load4f(rotationMatrix.values()); @@ -249,6 +251,7 @@ rcp RiveRenderPath::makeSoftenedCopyForFeathering( float feather, float matrixMaxScale) { + RIVE_PROF_SCOPE() // Since curvature is what breaks 1-dimensional feathering along the normal // vector, chop into segments that rotate no more than a certain threshold. constexpr static int POLAR_JOIN_PRECISION = 2; diff --git a/renderer/src/rive_renderer.cpp b/renderer/src/rive_renderer.cpp index a5a9654f..29dad4cf 100644 --- a/renderer/src/rive_renderer.cpp +++ b/renderer/src/rive_renderer.cpp @@ -9,11 +9,13 @@ #include "rive/math/math_types.hpp" #include "rive/math/simd.hpp" #include "rive/renderer/rive_render_image.hpp" +#include "rive/profiler/profiler_macros.h" namespace rive { bool RiveRenderer::IsAABB(const RawPath& path, AABB* result) { + RIVE_PROF_SCOPE() // Any quadrilateral begins with a move plus 3 lines. constexpr static size_t kAABBVerbCount = 4; constexpr static PathVerb aabbVerbs[kAABBVerbCount] = {PathVerb::move, @@ -108,6 +110,7 @@ void RiveRenderer::transform(const Mat2D& matrix) void RiveRenderer::drawPath(RenderPath* renderPath, RenderPaint* renderPaint) { + RIVE_PROF_SCOPE() LITE_RTTI_CAST_OR_RETURN(path, RiveRenderPath*, renderPath); LITE_RTTI_CAST_OR_RETURN(paint, RiveRenderPaint*, renderPaint); @@ -173,6 +176,7 @@ void RiveRenderer::drawPath(RenderPath* renderPath, RenderPaint* renderPaint) void RiveRenderer::clipPath(RenderPath* renderPath) { + RIVE_PROF_SCOPE() LITE_RTTI_CAST_OR_RETURN(path, RiveRenderPath*, renderPath); if (m_context->frameInterlockMode() == gpu::InterlockMode::clockwiseAtomic) @@ -247,6 +251,7 @@ static bool transform_rect_to_new_space(AABB* rect, void RiveRenderer::clipRectImpl(AABB rect, const RiveRenderPath* originalPath) { + RIVE_PROF_SCOPE() bool hasClipRect = m_stack.back().clipRectInverseMatrix != nullptr; if (rect.isEmptyOrNaN()) { @@ -293,6 +298,7 @@ void RiveRenderer::clipRectImpl(AABB rect, const RiveRenderPath* originalPath) void RiveRenderer::clipPathImpl(const RiveRenderPath* path) { + RIVE_PROF_SCOPE() if (path->getBounds().isEmptyOrNaN()) { m_stack.back().clipIsEmpty = true; @@ -325,6 +331,7 @@ void RiveRenderer::drawImage(const RenderImage* renderImage, BlendMode blendMode, float opacity) { + RIVE_PROF_SCOPE() LITE_RTTI_CAST_OR_RETURN(image, const RiveRenderImage*, renderImage); rcp imageTexture = image->refTexture(); @@ -390,6 +397,7 @@ void RiveRenderer::drawImageMesh(const RenderImage* renderImage, BlendMode blendMode, float opacity) { + RIVE_PROF_SCOPE() LITE_RTTI_CAST_OR_RETURN(image, const RiveRenderImage*, renderImage); rcp imageTexture = image->refTexture(); @@ -425,6 +433,7 @@ void RiveRenderer::drawImageMesh(const RenderImage* renderImage, void RiveRenderer::clipAndPushDraw(gpu::DrawUniquePtr draw) { + RIVE_PROF_SCOPE() assert(!m_stack.back().clipIsEmpty); if (draw.get() == nullptr) { @@ -500,6 +509,7 @@ void RiveRenderer::clipAndPushDraw(gpu::DrawUniquePtr draw) RiveRenderer::ApplyClipResult RiveRenderer::applyClip(gpu::Draw* draw) { + RIVE_PROF_SCOPE() if (m_stack.back().clipIsEmpty) { return ApplyClipResult::clipEmpty; diff --git a/src/animation/linear_animation_instance.cpp b/src/animation/linear_animation_instance.cpp index f7887ba6..acfb7c79 100644 --- a/src/animation/linear_animation_instance.cpp +++ b/src/animation/linear_animation_instance.cpp @@ -2,6 +2,8 @@ #include "rive/animation/linear_animation.hpp" #include "rive/animation/loop.hpp" #include "rive/animation/keyed_callback_reporter.hpp" +#include "rive/profiler/profiler_macros.h" + #include #include @@ -40,6 +42,7 @@ LinearAnimationInstance::~LinearAnimationInstance() {} bool LinearAnimationInstance::advanceAndApply(float seconds) { + RIVE_PROF_SCOPE() bool more = this->advance(seconds, this); this->apply(); if (m_artboardInstance->advance(seconds)) diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp index 39bf8e94..028b8c9e 100644 --- a/src/animation/state_machine_instance.cpp +++ b/src/animation/state_machine_instance.cpp @@ -41,6 +41,7 @@ #include "rive/math/math_types.hpp" #include "rive/audio_event.hpp" #include "rive/dirtyable.hpp" +#include "rive/profiler/profiler_macros.h" #include #include @@ -1874,6 +1875,7 @@ void StateMachineInstance::reset() bool StateMachineInstance::advanceAndApply(float seconds) { + RIVE_PROF_SCOPE() bool keepGoing = this->advance(seconds, true); if (m_artboardInstance->advanceInternal( seconds, diff --git a/src/artboard.cpp b/src/artboard.cpp index 55efc22a..3c373cc5 100644 --- a/src/artboard.cpp +++ b/src/artboard.cpp @@ -34,6 +34,7 @@ #include "rive/event.hpp" #include "rive/assets/audio_asset.hpp" #include "rive/layout/layout_data.hpp" +#include "rive/profiler/profiler_macros.h" #include @@ -1146,6 +1147,8 @@ void Artboard::draw(Renderer* renderer) { draw(renderer, DrawOption::kNormal); } void Artboard::draw(Renderer* renderer, DrawOption option) { + RIVE_PROF_SCOPE() + if (renderOpacity() == 0) { return; diff --git a/src/shapes/paint/shape_paint.cpp b/src/shapes/paint/shape_paint.cpp index d4a6c307..a46fc47c 100644 --- a/src/shapes/paint/shape_paint.cpp +++ b/src/shapes/paint/shape_paint.cpp @@ -4,6 +4,7 @@ #include "rive/artboard.hpp" #include "rive/factory.hpp" #include "rive/shapes/paint/fill.hpp" +#include "rive/profiler/profiler_macros.h" using namespace rive; @@ -59,6 +60,8 @@ void ShapePaint::draw(Renderer* renderer, bool usePathFillRule, RenderPaint* overridePaint) { + RIVE_PROF_SCOPE() + ShapePaintPath* pathToDraw = shapePaintPath; bool saved = false; if (m_feather != nullptr) diff --git a/src/static_scene.cpp b/src/static_scene.cpp index 9f8ecb5e..5ec0b6f3 100644 --- a/src/static_scene.cpp +++ b/src/static_scene.cpp @@ -1,5 +1,6 @@ #include "rive/static_scene.hpp" #include "rive/artboard.hpp" +#include "rive/profiler/profiler_macros.h" using namespace rive; @@ -20,6 +21,7 @@ float StaticScene::durationSeconds() const { return 0; } bool StaticScene::advanceAndApply(float seconds) { + RIVE_PROF_SCOPE() // We ignore the 'seconds' argument because it's not an animated scene m_artboardInstance->advance(0); return true;