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 <aliasbinman@gmail.com>
This commit is contained in:
aliasbinman
2025-08-20 18:07:00 +00:00
parent 570de5fb86
commit cf0c68cb0c
18 changed files with 144 additions and 6 deletions

View File

@@ -1 +1 @@
f6d5d55b26d9facf3118620de6ff55d908a79f02
4171e09f80920ce55d713060f929fa8ed88a065b

View File

@@ -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')

16
dependencies/premake5_optick.lua vendored Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,7 +1,6 @@
#pragma once
#include <vector>
#include "rive/renderer/render_context.hpp"
struct GLFWwindow;

View File

@@ -11,6 +11,7 @@ std::unique_ptr<FiddleContext> 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 <array>
#include <dxgi1_2.h>
@@ -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<uint8_t>* pixelData = nullptr) override
{
RIVE_PROF_SCOPE()
flushPLSContext(nullptr);
if (pixelData != nullptr)
{

View File

@@ -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 <fstream>
#include <iterator>
@@ -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));
}

View File

@@ -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

View File

@@ -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',

View File

@@ -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 <string_view>
@@ -136,6 +138,7 @@ rcp<RenderBuffer> RenderContext::makeRenderBuffer(RenderBufferType type,
rcp<RenderImage> RenderContext::decodeImage(Span<const uint8_t> encodedBytes)
{
RIVE_PROF_SCOPE()
rcp<Texture> 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<uint16_t>* 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<uint32_t>(
@@ -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<uint32_t>(
@@ -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<uint32_t>(
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<uint32_t>(
@@ -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);

View File

@@ -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> 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;

View File

@@ -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<gpu::Texture> 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<gpu::Texture> 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;

View File

@@ -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 <cmath>
#include <cassert>
@@ -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))

View File

@@ -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 <unordered_map>
#include <chrono>
@@ -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,

View File

@@ -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 <unordered_map>
@@ -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;

View File

@@ -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)

View File

@@ -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;