Compare commits
6 Commits
v1.59.5
...
dk/opengl-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff356216d5 | ||
|
|
6fd87cdfef | ||
|
|
8ba001d0ca | ||
|
|
6fd031c611 | ||
|
|
b0e90c48a2 | ||
|
|
149acf4213 |
@@ -49,6 +49,8 @@ option(FILAMENT_SUPPORTS_OSMESA "Enable OSMesa (headless GL context) for Filamen
|
||||
|
||||
option(FILAMENT_ENABLE_FGVIEWER "Enable the frame graph viewer" OFF)
|
||||
|
||||
option(FILAMENT_ENABLE_INIT_GL_WARNINGS_FOR_OPTIMIZED_BUILD "Enable GL error warnings during init in optimized builds" OFF)
|
||||
|
||||
set(FILAMENT_NDK_VERSION "" CACHE STRING
|
||||
"Android NDK version or version prefix to be used when building for Android."
|
||||
)
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.59.5'
|
||||
implementation 'com.google.android.filament:filament-android:1.59.4'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```shell
|
||||
pod 'Filament', '~> 1.59.5'
|
||||
pod 'Filament', '~> 1.59.4'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.59.5
|
||||
VERSION_NAME=1.59.4
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -318,6 +318,13 @@ if (WIN32 AND FILAMENT_SUPPORTS_WEBGPU)
|
||||
target_compile_definitions(${TARGET} PRIVATE "WGPU_IMPLEMENTATION")
|
||||
endif()
|
||||
|
||||
# enable OpenGL init warnings for the optimized build
|
||||
if(FILAMENT_ENABLE_INIT_GL_WARNINGS_FOR_OPTIMIZED_BUILD)
|
||||
target_compile_definitions(${TARGET} PRIVATE "FILAMENT_ENABLE_INIT_GL_WARNINGS_FOR_OPTIMIZED_BUILD")
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
# ==================================================================================================
|
||||
# Expose a header-only target to minimize dependencies.
|
||||
# ==================================================================================================
|
||||
|
||||
@@ -149,13 +149,6 @@ public:
|
||||
* - PlatformEGLAndroid
|
||||
*/
|
||||
bool assertNativeWindowIsValid = false;
|
||||
|
||||
/**
|
||||
* The action to take if a Drawable cannot be acquired. If true, the
|
||||
* frame is aborted instead of panic. This is only supported for:
|
||||
* - PlatformMetal
|
||||
*/
|
||||
bool metalDisablePanicOnDrawableFailure = false;
|
||||
};
|
||||
|
||||
Platform() noexcept;
|
||||
|
||||
@@ -84,7 +84,7 @@ void CommandStream::execute(void* buffer) {
|
||||
|
||||
Profiler profiler;
|
||||
|
||||
if (SYSTRACE_TAG) {
|
||||
if constexpr (SYSTRACE_TAG) {
|
||||
if (UTILS_UNLIKELY(mUsePerformanceCounter)) {
|
||||
// we want to remove all this when tracing is completely disabled
|
||||
profiler.resetEvents(Profiler::EV_CPU_CYCLES | Profiler::EV_BPU_MISSES);
|
||||
@@ -100,7 +100,7 @@ void CommandStream::execute(void* buffer) {
|
||||
}
|
||||
});
|
||||
|
||||
if (SYSTRACE_TAG) {
|
||||
if constexpr (SYSTRACE_TAG) {
|
||||
if (UTILS_UNLIKELY(mUsePerformanceCounter)) {
|
||||
// we want to remove all this when tracing is completely disabled
|
||||
profiler.stop();
|
||||
|
||||
@@ -45,9 +45,6 @@ PlatformMetal::~PlatformMetal() noexcept {
|
||||
}
|
||||
|
||||
Driver* PlatformMetal::createDriver(void* /*sharedContext*/, const Platform::DriverConfig& driverConfig) noexcept {
|
||||
pImpl->mDrawableFailureBehavior = driverConfig.metalDisablePanicOnDrawableFailure
|
||||
? DrawableFailureBehavior::ABORT_FRAME
|
||||
: DrawableFailureBehavior::PANIC;
|
||||
return MetalDriverFactory::create(this, driverConfig);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,14 @@ void assertFramebufferStatus(utils::io::ostream& out, GLenum target, const char*
|
||||
# define CHECK_GL_FRAMEBUFFER_STATUS(out, target) { GLUtils::checkFramebufferStatus(out, target, __func__, __LINE__); }
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
# define CHECK_GL_INIT_ERROR_FOR_OPTIMIZED_BUILD(out) { GLUtils::assertGLError(out, __func__, __LINE__);}
|
||||
#elif defined(FILAMENT_ENABLE_INIT_GL_WARNINGS_FOR_OPTIMIZED_BUILD)
|
||||
# define CHECK_GL_INIT_ERROR_FOR_OPTIMIZED_BUILD(out) { GLUtils::checkGLError(out, __func__, __LINE__);}
|
||||
#else
|
||||
# define CHECK_GL_INIT_ERROR_FOR_OPTIMIZED_BUILD(out)
|
||||
#endif
|
||||
|
||||
constexpr GLuint getComponentCount(ElementType const type) noexcept {
|
||||
using ElementType = ElementType;
|
||||
switch (type) {
|
||||
|
||||
@@ -59,6 +59,9 @@ bool OpenGLContext::queryOpenGLVersion(GLint* major, GLint* minor) noexcept {
|
||||
// OpenGL version
|
||||
glGetIntegerv(GL_MAJOR_VERSION, major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, minor);
|
||||
|
||||
CHECK_GL_INIT_ERROR_FOR_OPTIMIZED_BUILD(utils::slog.e)
|
||||
|
||||
return (glGetError() == GL_NO_ERROR);
|
||||
#endif
|
||||
}
|
||||
@@ -109,6 +112,8 @@ OpenGLContext::OpenGLContext(OpenGLPlatform& platform,
|
||||
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &gets.max_3d_texture_size);
|
||||
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &gets.max_array_texture_layers);
|
||||
|
||||
CHECK_GL_INIT_ERROR_FOR_OPTIMIZED_BUILD(utils::slog.e)
|
||||
|
||||
mFeatureLevel = resolveFeatureLevel(state.major, state.minor, ext, gets, bugs);
|
||||
|
||||
#ifdef BACKEND_OPENGL_VERSION_GLES
|
||||
@@ -149,6 +154,7 @@ OpenGLContext::OpenGLContext(OpenGLPlatform& platform,
|
||||
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
|
||||
&gets.uniform_buffer_offset_alignment);
|
||||
#endif
|
||||
CHECK_GL_INIT_ERROR_FOR_OPTIMIZED_BUILD(utils::slog.e)
|
||||
}
|
||||
|
||||
#ifdef BACKEND_OPENGL_VERSION_GLES
|
||||
@@ -235,6 +241,7 @@ OpenGLContext::OpenGLContext(OpenGLPlatform& platform,
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
CHECK_GL_INIT_ERROR_FOR_OPTIMIZED_BUILD(utils::slog.e)
|
||||
|
||||
// in practice KHR_Debug has never been useful, and actually is confusing. We keep this
|
||||
// only for our own debugging, in case we need it some day.
|
||||
@@ -269,6 +276,7 @@ OpenGLContext::OpenGLContext(OpenGLPlatform& platform,
|
||||
glDebugMessageCallback(cb, nullptr);
|
||||
}
|
||||
#endif
|
||||
CHECK_GL_INIT_ERROR_FOR_OPTIMIZED_BUILD(utils::slog.e)
|
||||
|
||||
mTimerQueryFactory = TimerQueryFactory::init(platform, *this);
|
||||
}
|
||||
@@ -384,6 +392,8 @@ void OpenGLContext::setDefaultState() noexcept {
|
||||
glEnable(GL_CLIP_DISTANCE0);
|
||||
glEnable(GL_CLIP_DISTANCE1);
|
||||
}
|
||||
|
||||
CHECK_GL_INIT_ERROR_FOR_OPTIMIZED_BUILD(utils::slog.e)
|
||||
}
|
||||
|
||||
|
||||
@@ -761,6 +771,8 @@ void OpenGLContext::initExtensionsGLES(Extensions* ext, GLint major, GLint minor
|
||||
ext->EXT_discard_framebuffer = true;
|
||||
ext->OES_vertex_array_object = true;
|
||||
}
|
||||
|
||||
CHECK_GL_INIT_ERROR_FOR_OPTIMIZED_BUILD(utils::slog.e)
|
||||
}
|
||||
|
||||
#endif // BACKEND_OPENGL_VERSION_GLES
|
||||
@@ -831,6 +843,8 @@ void OpenGLContext::initExtensionsGL(Extensions* ext, GLint major, GLint minor)
|
||||
if (major > 4 || (major == 4 && minor >= 5)) {
|
||||
ext->EXT_clip_control = true;
|
||||
}
|
||||
|
||||
CHECK_GL_INIT_ERROR_FOR_OPTIMIZED_BUILD(utils::slog.e)
|
||||
}
|
||||
|
||||
#endif // BACKEND_OPENGL_VERSION_GL
|
||||
|
||||
@@ -152,12 +152,12 @@ static_assert(FVK_ENABLED(FVK_DEBUG_VALIDATION));
|
||||
#elif FVK_ENABLED(FVK_DEBUG_SYSTRACE)
|
||||
|
||||
#include <utils/Systrace.h>
|
||||
|
||||
|
||||
#define FVK_SYSTRACE_CONTEXT() SYSTRACE_CONTEXT()
|
||||
#define FVK_SYSTRACE_START(marker) SYSTRACE_NAME_BEGIN(marker)
|
||||
#define FVK_SYSTRACE_END() SYSTRACE_NAME_END()
|
||||
#define FVK_SYSTRACE_SCOPE() SYSTRACE_NAME(__func__)
|
||||
#define FVK_PROFILE_MARKER(marker) FVK_SYSTRACE_SCOPE()
|
||||
#define FVK_SYSTRACE_SCOPE() SYSTRACE_CALL()
|
||||
#define FVK_PROFILE_MARKER(marker) SYSTRACE_CALL()
|
||||
|
||||
#else
|
||||
#define FVK_SYSTRACE_CONTEXT()
|
||||
|
||||
@@ -317,15 +317,6 @@ public:
|
||||
*/
|
||||
size_t metalUploadBufferSizeBytes = 512 * 1024;
|
||||
|
||||
/**
|
||||
* The action to take if a Drawable cannot be acquired.
|
||||
*
|
||||
* Each frame rendered requires a CAMetalDrawable texture, which is
|
||||
* presented on-screen at the completion of each frame. These are
|
||||
* limited and provided round-robin style by the system.
|
||||
*/
|
||||
bool metalDisablePanicOnDrawableFailure = false;
|
||||
|
||||
/**
|
||||
* Set to `true` to forcibly disable parallel shader compilation in the backend.
|
||||
* Currently only honored by the GL and Metal backends.
|
||||
|
||||
@@ -138,7 +138,6 @@ Engine* FEngine::create(Builder const& builder) {
|
||||
.forceGLES2Context = instance->getConfig().forceGLES2Context,
|
||||
.stereoscopicType = instance->getConfig().stereoscopicType,
|
||||
.assertNativeWindowIsValid = instance->features.backend.opengl.assert_native_window_is_valid,
|
||||
.metalDisablePanicOnDrawableFailure = instance->getConfig().metalDisablePanicOnDrawableFailure,
|
||||
};
|
||||
instance->mDriver = platform->createDriver(sharedContext, driverConfig);
|
||||
|
||||
@@ -734,7 +733,6 @@ int FEngine::loop() {
|
||||
.forceGLES2Context = mConfig.forceGLES2Context,
|
||||
.stereoscopicType = mConfig.stereoscopicType,
|
||||
.assertNativeWindowIsValid = features.backend.opengl.assert_native_window_is_valid,
|
||||
.metalDisablePanicOnDrawableFailure = mConfig.metalDisablePanicOnDrawableFailure,
|
||||
};
|
||||
mDriver = mPlatform->createDriver(mSharedGLContext, driverConfig);
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.59.5"
|
||||
spec.version = "1.59.4"
|
||||
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
|
||||
spec.homepage = "https://google.github.io/filament"
|
||||
spec.authors = "Google LLC."
|
||||
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
|
||||
spec.platform = :ios, "11.0"
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.59.5/filament-v1.59.5-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.59.4/filament-v1.59.4-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/NameComponentManager.h>
|
||||
|
||||
#define SYSTRACE_TAG SYSTRACE_TAG_GLTFIO
|
||||
#include <utils/Systrace.h>
|
||||
|
||||
#include <tsl/robin_map.h>
|
||||
|
||||
@@ -37,7 +37,10 @@
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/JobSystem.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#define SYSTRACE_TAG SYSTRACE_TAG_GLTFIO
|
||||
#include <utils/Systrace.h>
|
||||
|
||||
#include <utils/Path.h>
|
||||
|
||||
#include <cgltf.h>
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "GltfEnums.h"
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
#define SYSTRACE_TAG SYSTRACE_TAG_GLTFIO
|
||||
#include <utils/Systrace.h>
|
||||
|
||||
#define CGLTF_IMPLEMENTATION
|
||||
|
||||
@@ -17,24 +17,23 @@
|
||||
#ifndef TNT_UTILS_SYSTRACE_H
|
||||
#define TNT_UTILS_SYSTRACE_H
|
||||
|
||||
|
||||
#define SYSTRACE_TAG_NEVER (0)
|
||||
#define SYSTRACE_TAG_ALWAYS (1<<0)
|
||||
#define SYSTRACE_TAG_FILAMENT (1<<1) // don't change, used in makefiles
|
||||
#define SYSTRACE_TAG_JOBSYSTEM (1<<2)
|
||||
#define SYSTRACE_TAG_DISABLED (0)
|
||||
#define SYSTRACE_TAG_FILAMENT (2) // don't change used in makefiles
|
||||
#define SYSTRACE_TAG_JOBSYSTEM (3)
|
||||
#define SYSTRACE_TAG_GLTFIO (4)
|
||||
|
||||
/*
|
||||
* The SYSTRACE_ macros use SYSTRACE_TAG as a the TAG, which should be defined
|
||||
* before this file is included. If not, the SYSTRACE_TAG_ALWAYS tag will be used.
|
||||
* The SYSTRACE_ macros use SYSTRACE_TAG as a category, which must be defined
|
||||
* before this file is included.
|
||||
*/
|
||||
|
||||
#ifndef SYSTRACE_TAG
|
||||
#define SYSTRACE_TAG (SYSTRACE_TAG_ALWAYS)
|
||||
# error SYSTRACE_TAG must be set to SYSTRACE_TAG_{DISABLED|FILAMENT|JOBSYSTEM}
|
||||
#endif
|
||||
|
||||
// Systrace on Apple platforms is fragile and adds overhead, should only be enabled in dev builds.
|
||||
#ifndef FILAMENT_APPLE_SYSTRACE
|
||||
#define FILAMENT_APPLE_SYSTRACE 0
|
||||
# define FILAMENT_APPLE_SYSTRACE 0
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
@@ -44,7 +43,6 @@
|
||||
#else
|
||||
|
||||
#define SYSTRACE_ENABLE()
|
||||
#define SYSTRACE_DISABLE()
|
||||
#define SYSTRACE_CONTEXT()
|
||||
#define SYSTRACE_NAME(name)
|
||||
#define SYSTRACE_FRAME_ID(frame)
|
||||
@@ -56,6 +54,6 @@
|
||||
#define SYSTRACE_VALUE32(name, val)
|
||||
#define SYSTRACE_VALUE64(name, val)
|
||||
|
||||
#endif // ANDROID
|
||||
#endif
|
||||
|
||||
#endif // TNT_UTILS_SYSTRACE_H
|
||||
|
||||
@@ -17,226 +17,75 @@
|
||||
#ifndef TNT_UTILS_ANDROID_SYSTRACE_H
|
||||
#define TNT_UTILS_ANDROID_SYSTRACE_H
|
||||
|
||||
#include <atomic>
|
||||
#include <perfetto/perfetto.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE(systrace,
|
||||
perfetto::Category("filament"),
|
||||
perfetto::Category("jobsystem"),
|
||||
perfetto::Category("gltfio"));
|
||||
|
||||
// enable tracing
|
||||
#define SYSTRACE_ENABLE() ::utils::details::Systrace::enable(SYSTRACE_TAG)
|
||||
PERFETTO_USE_CATEGORIES_FROM_NAMESPACE(systrace);
|
||||
|
||||
// disable tracing
|
||||
#define SYSTRACE_DISABLE() ::utils::details::Systrace::disable(SYSTRACE_TAG)
|
||||
#if SYSTRACE_TAG == SYSTRACE_TAG_FILAMENT
|
||||
# define UTILS_PERFETTO_CATEGORY "filament"
|
||||
#elif SYSTRACE_TAG == SYSTRACE_TAG_JOBSYSTEM
|
||||
# define UTILS_PERFETTO_CATEGORY "jobsystem"
|
||||
#elif SYSTRACE_TAG == SYSTRACE_TAG_GLTFIO
|
||||
# define UTILS_PERFETTO_CATEGORY "gltfio"
|
||||
#endif
|
||||
|
||||
#if SYSTRACE_TAG == SYSTRACE_TAG_DISABLED
|
||||
|
||||
/**
|
||||
* Creates a Systrace context in the current scope. needed for calling all other systrace
|
||||
* commands below.
|
||||
*/
|
||||
#define SYSTRACE_CONTEXT() ::utils::details::Systrace ___trctx(SYSTRACE_TAG)
|
||||
#define SYSTRACE_ENABLE()
|
||||
#define SYSTRACE_CONTEXT()
|
||||
#define SYSTRACE_NAME(name)
|
||||
#define SYSTRACE_FRAME_ID(frame)
|
||||
#define SYSTRACE_NAME_BEGIN(name)
|
||||
#define SYSTRACE_NAME_END()
|
||||
#define SYSTRACE_CALL()
|
||||
#define SYSTRACE_ASYNC_BEGIN(name, cookie)
|
||||
#define SYSTRACE_ASYNC_END(name, cookie)
|
||||
#define SYSTRACE_VALUE32(name, val)
|
||||
#define SYSTRACE_VALUE64(name, val)
|
||||
|
||||
#else
|
||||
|
||||
// SYSTRACE_NAME traces the beginning and end of the current scope. To trace
|
||||
// the correct start and end times this macro should be declared first in the
|
||||
// scope body.
|
||||
// It also automatically creates a Systrace context
|
||||
#define SYSTRACE_NAME(name) ::utils::details::ScopedTrace ___tracer(SYSTRACE_TAG, name)
|
||||
#define SYSTRACE_ENABLE()
|
||||
#define SYSTRACE_CONTEXT()
|
||||
|
||||
// Denotes that a new frame has started processing.
|
||||
#define SYSTRACE_FRAME_ID(frame) \
|
||||
{ /* scope for frame id trace */ \
|
||||
char buf[64]; \
|
||||
snprintf(buf, 64, "frame %u", frame); \
|
||||
SYSTRACE_NAME(buf); \
|
||||
}
|
||||
#define SYSTRACE_CALL() \
|
||||
auto constexpr FILAMENT_SYSTRACE_FUNCTION = perfetto::StaticString(__FUNCTION__); \
|
||||
TRACE_EVENT(UTILS_PERFETTO_CATEGORY, FILAMENT_SYSTRACE_FUNCTION)
|
||||
|
||||
// SYSTRACE_CALL is an SYSTRACE_NAME that uses the current function name.
|
||||
#define SYSTRACE_CALL() SYSTRACE_NAME(__FUNCTION__)
|
||||
#define SYSTRACE_NAME(name) TRACE_EVENT(UTILS_PERFETTO_CATEGORY, nullptr, \
|
||||
[&](perfetto::EventContext ctx) { \
|
||||
ctx.event()->set_name(name); \
|
||||
})
|
||||
|
||||
#define SYSTRACE_NAME_BEGIN(name) \
|
||||
___trctx.traceBegin(SYSTRACE_TAG, name)
|
||||
#define SYSTRACE_NAME_BEGIN(name) TRACE_EVENT_BEGIN(UTILS_PERFETTO_CATEGORY, nullptr, \
|
||||
[&](perfetto::EventContext ctx) { \
|
||||
ctx.event()->set_name(name); \
|
||||
})
|
||||
|
||||
#define SYSTRACE_NAME_END() \
|
||||
___trctx.traceEnd(SYSTRACE_TAG)
|
||||
#define SYSTRACE_NAME_END() TRACE_EVENT_END(UTILS_PERFETTO_CATEGORY)
|
||||
|
||||
|
||||
/**
|
||||
* Trace the beginning of an asynchronous event. Unlike ATRACE_BEGIN/ATRACE_END
|
||||
* contexts, asynchronous events do not need to be nested. The name describes
|
||||
* the event, and the cookie provides a unique identifier for distinguishing
|
||||
* simultaneous events. The name and cookie used to begin an event must be
|
||||
* used to end it.
|
||||
*/
|
||||
#define SYSTRACE_ASYNC_BEGIN(name, cookie) \
|
||||
___trctx.asyncBegin(SYSTRACE_TAG, name, cookie)
|
||||
TRACE_EVENT_BEGIN(UTILS_PERFETTO_CATEGORY, name, perfetto::Track(cookie))
|
||||
|
||||
/**
|
||||
* Trace the end of an asynchronous event.
|
||||
* This should have a corresponding SYSTRACE_ASYNC_BEGIN.
|
||||
*/
|
||||
#define SYSTRACE_ASYNC_END(name, cookie) \
|
||||
___trctx.asyncEnd(SYSTRACE_TAG, name, cookie)
|
||||
TRACE_EVENT_END(UTILS_PERFETTO_CATEGORY, perfetto::Track(cookie))
|
||||
|
||||
#define SYSTRACE_FRAME_ID(frame) \
|
||||
TRACE_EVENT_INSTANT(UTILS_PERFETTO_CATEGORY, "frame", "id", frame)
|
||||
|
||||
/**
|
||||
* Traces an integer counter value. name is used to identify the counter.
|
||||
* This can be used to track how a value changes over time.
|
||||
*/
|
||||
#define SYSTRACE_VALUE32(name, val) \
|
||||
___trctx.value(SYSTRACE_TAG, name, int32_t(val))
|
||||
TRACE_COUNTER(UTILS_PERFETTO_CATEGORY, name, val)
|
||||
|
||||
#define SYSTRACE_VALUE64(name, val) \
|
||||
___trctx.value(SYSTRACE_TAG, name, int64_t(val))
|
||||
TRACE_COUNTER(UTILS_PERFETTO_CATEGORY, name, val)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// No user serviceable code below...
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace utils {
|
||||
namespace details {
|
||||
|
||||
class UTILS_PUBLIC Systrace {
|
||||
public:
|
||||
|
||||
enum tags {
|
||||
NEVER = SYSTRACE_TAG_NEVER,
|
||||
ALWAYS = SYSTRACE_TAG_ALWAYS,
|
||||
FILAMENT = SYSTRACE_TAG_FILAMENT,
|
||||
JOBSYSTEM = SYSTRACE_TAG_JOBSYSTEM
|
||||
// we could define more TAGS here, as we need them.
|
||||
};
|
||||
|
||||
explicit Systrace(uint32_t tag) noexcept {
|
||||
if (tag) init(tag);
|
||||
}
|
||||
|
||||
static void enable(uint32_t tags) noexcept;
|
||||
static void disable(uint32_t tags) noexcept;
|
||||
|
||||
|
||||
inline void traceBegin(uint32_t tag, const char* name) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
beginSection(this, name);
|
||||
}
|
||||
}
|
||||
|
||||
inline void traceEnd(uint32_t tag) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
endSection(this);
|
||||
}
|
||||
}
|
||||
|
||||
inline void asyncBegin(uint32_t tag, const char* name, int32_t cookie) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
beginAsyncSection(this, name, cookie);
|
||||
}
|
||||
}
|
||||
|
||||
inline void asyncEnd(uint32_t tag, const char* name, int32_t cookie) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
endAsyncSection(this, name, cookie);
|
||||
}
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int32_t value) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
setCounter(this, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int64_t value) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
setCounter(this, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ScopedTrace;
|
||||
|
||||
// whether tracing is supported at all by the platform
|
||||
|
||||
using ATrace_isEnabled_t = bool (*)();
|
||||
using ATrace_beginSection_t = void (*)(const char* sectionName);
|
||||
using ATrace_endSection_t = void (*)();
|
||||
using ATrace_beginAsyncSection_t = void (*)(const char* sectionName, int32_t cookie);
|
||||
using ATrace_endAsyncSection_t = void (*)(const char* sectionName, int32_t cookie);
|
||||
using ATrace_setCounter_t = void (*)(const char* counterName, int64_t counterValue);
|
||||
|
||||
struct GlobalState {
|
||||
bool isTracingAvailable;
|
||||
std::atomic<uint32_t> isTracingEnabled;
|
||||
int markerFd;
|
||||
|
||||
ATrace_isEnabled_t ATrace_isEnabled;
|
||||
ATrace_beginSection_t ATrace_beginSection;
|
||||
ATrace_endSection_t ATrace_endSection;
|
||||
ATrace_beginAsyncSection_t ATrace_beginAsyncSection;
|
||||
ATrace_endAsyncSection_t ATrace_endAsyncSection;
|
||||
ATrace_setCounter_t ATrace_setCounter;
|
||||
|
||||
void (*beginSection)(Systrace* that, const char* name);
|
||||
void (*endSection)(Systrace* that);
|
||||
void (*beginAsyncSection)(Systrace* that, const char* name, int32_t cookie);
|
||||
void (*endAsyncSection)(Systrace* that, const char* name, int32_t cookie);
|
||||
void (*setCounter)(Systrace* that, const char* name, int64_t value);
|
||||
};
|
||||
|
||||
static GlobalState sGlobalState;
|
||||
|
||||
|
||||
// per-instance versions for better performance
|
||||
ATrace_isEnabled_t ATrace_isEnabled;
|
||||
ATrace_beginSection_t ATrace_beginSection;
|
||||
ATrace_endSection_t ATrace_endSection;
|
||||
ATrace_beginAsyncSection_t ATrace_beginAsyncSection;
|
||||
ATrace_endAsyncSection_t ATrace_endAsyncSection;
|
||||
ATrace_setCounter_t ATrace_setCounter;
|
||||
|
||||
void (*beginSection)(Systrace* that, const char* name);
|
||||
void (*endSection)(Systrace* that);
|
||||
void (*beginAsyncSection)(Systrace* that, const char* name, int32_t cookie);
|
||||
void (*endAsyncSection)(Systrace* that, const char* name, int32_t cookie);
|
||||
void (*setCounter)(Systrace* that, const char* name, int64_t value);
|
||||
|
||||
void init(uint32_t tag) noexcept;
|
||||
|
||||
// cached values for faster access, no need to be initialized
|
||||
bool mIsTracingEnabled;
|
||||
int mMarkerFd = -1;
|
||||
pid_t mPid;
|
||||
|
||||
static void setup() noexcept;
|
||||
static void init_once() noexcept;
|
||||
static bool isTracingEnabled(uint32_t tag) noexcept;
|
||||
|
||||
static void begin_body(int fd, int pid, const char* name) noexcept;
|
||||
static void end_body(int fd, int pid) noexcept;
|
||||
static void async_begin_body(int fd, int pid, const char* name, int32_t cookie) noexcept;
|
||||
static void async_end_body(int fd, int pid, const char* name, int32_t cookie) noexcept;
|
||||
static void int64_body(int fd, int pid, const char* name, int64_t value) noexcept;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
class UTILS_PUBLIC ScopedTrace {
|
||||
public:
|
||||
// we don't inline this because it's relatively heavy due to a global check
|
||||
ScopedTrace(uint32_t tag, const char* name) noexcept: mTrace(tag), mTag(tag) {
|
||||
mTrace.traceBegin(tag, name);
|
||||
}
|
||||
|
||||
inline ~ScopedTrace() noexcept {
|
||||
mTrace.traceEnd(mTag);
|
||||
}
|
||||
|
||||
private:
|
||||
Systrace mTrace;
|
||||
const uint32_t mTag;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace utils
|
||||
#endif // SYSTRACE_TAG == SYSTRACE_TAG_DISABLED
|
||||
|
||||
#endif // TNT_UTILS_ANDROID_SYSTRACE_H
|
||||
|
||||
@@ -29,13 +29,25 @@
|
||||
#include <utils/compiler.h>
|
||||
#include <stack>
|
||||
|
||||
#if SYSTRACE_TAG == SYSTRACE_TAG_DISABLED
|
||||
|
||||
#define SYSTRACE_ENABLE()
|
||||
#define SYSTRACE_CONTEXT()
|
||||
#define SYSTRACE_NAME(name)
|
||||
#define SYSTRACE_FRAME_ID(frame)
|
||||
#define SYSTRACE_NAME_BEGIN(name)
|
||||
#define SYSTRACE_NAME_END()
|
||||
#define SYSTRACE_CALL()
|
||||
#define SYSTRACE_ASYNC_BEGIN(name, cookie)
|
||||
#define SYSTRACE_ASYNC_END(name, cookie)
|
||||
#define SYSTRACE_VALUE32(name, val)
|
||||
#define SYSTRACE_VALUE64(name, val)
|
||||
|
||||
#else
|
||||
|
||||
// enable tracing
|
||||
#define SYSTRACE_ENABLE() ::utils::details::Systrace::enable(SYSTRACE_TAG)
|
||||
|
||||
// disable tracing
|
||||
#define SYSTRACE_DISABLE() ::utils::details::Systrace::disable(SYSTRACE_TAG)
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Systrace context in the current scope. needed for calling all other systrace
|
||||
* commands below.
|
||||
@@ -93,6 +105,8 @@ extern thread_local std::stack<const char*> ___tracerSections;
|
||||
#define SYSTRACE_VALUE64(name, val) \
|
||||
___tracer.value(SYSTRACE_TAG, name, int64_t(val))
|
||||
|
||||
#endif // SYSTRACE_TAG == SYSTRACE_TAG_DISABLED
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// No user serviceable code below...
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -118,50 +132,40 @@ namespace utils {
|
||||
namespace details {
|
||||
|
||||
class Systrace {
|
||||
public:
|
||||
|
||||
enum tags {
|
||||
NEVER = SYSTRACE_TAG_NEVER,
|
||||
ALWAYS = SYSTRACE_TAG_ALWAYS,
|
||||
FILAMENT = SYSTRACE_TAG_FILAMENT,
|
||||
JOBSYSTEM = SYSTRACE_TAG_JOBSYSTEM
|
||||
// we could define more TAGS here, as we need them.
|
||||
};
|
||||
|
||||
public:
|
||||
explicit Systrace(uint32_t tag) noexcept {
|
||||
if (tag) init(tag);
|
||||
}
|
||||
|
||||
static void enable(uint32_t tags) noexcept;
|
||||
static void disable(uint32_t tags) noexcept;
|
||||
static void enable(uint32_t tag) noexcept;
|
||||
|
||||
inline void traceBegin(uint32_t tag, const char* name) noexcept {
|
||||
void traceBegin(uint32_t tag, const char* name) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
APPLE_SIGNPOST_EMIT(sGlobalState.systraceLog, OS_SIGNPOST_INTERVAL_BEGIN,
|
||||
OS_SIGNPOST_ID_EXCLUSIVE, name, name)
|
||||
}
|
||||
}
|
||||
|
||||
inline void traceEnd(uint32_t tag, const char* name) noexcept {
|
||||
void traceEnd(uint32_t tag, const char* name) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
APPLE_SIGNPOST_EMIT(sGlobalState.systraceLog, OS_SIGNPOST_INTERVAL_END,
|
||||
OS_SIGNPOST_ID_EXCLUSIVE, name, "")
|
||||
}
|
||||
}
|
||||
|
||||
inline void asyncBegin(uint32_t tag, const char* name, int32_t cookie) noexcept {
|
||||
void asyncBegin(uint32_t tag, const char* name, int32_t cookie) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
inline void asyncEnd(uint32_t tag, const char* name, int32_t cookie) noexcept {
|
||||
void asyncEnd(uint32_t tag, const char* name, int32_t cookie) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int32_t value) noexcept {
|
||||
void value(uint32_t tag, const char* name, int32_t value) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
char buf[64];
|
||||
snprintf(buf, 64, "%s - %d", name, value);
|
||||
@@ -170,7 +174,7 @@ class Systrace {
|
||||
}
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int64_t value) noexcept {
|
||||
void value(uint32_t tag, const char* name, int64_t value) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
char buf[64];
|
||||
snprintf(buf, 64, "%s - %lld", name, value);
|
||||
@@ -179,16 +183,16 @@ class Systrace {
|
||||
}
|
||||
}
|
||||
|
||||
inline void frameId(uint32_t tag, uint32_t frame) noexcept {
|
||||
void frameId(uint32_t tag, uint32_t frame) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
char buf[64]; \
|
||||
snprintf(buf, 64, "frame %u", frame); \
|
||||
char buf[64];
|
||||
snprintf(buf, 64, "frame %u", frame);
|
||||
APPLE_SIGNPOST_EMIT(sGlobalState.frameIdLog, OS_SIGNPOST_EVENT,
|
||||
OS_SIGNPOST_ID_EXCLUSIVE, "frame", buf)
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
friend class ScopedTrace;
|
||||
|
||||
struct GlobalState {
|
||||
@@ -213,25 +217,25 @@ class Systrace {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
class ScopedTrace {
|
||||
public:
|
||||
public:
|
||||
// we don't inline this because it's relatively heavy due to a global check
|
||||
ScopedTrace(uint32_t tag, const char* name) noexcept : mTrace(tag), mName(name), mTag(tag) {
|
||||
mTrace.traceBegin(tag, name);
|
||||
}
|
||||
|
||||
inline ~ScopedTrace() noexcept {
|
||||
~ScopedTrace() noexcept {
|
||||
mTrace.traceEnd(mTag, mName);
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int32_t v) noexcept {
|
||||
void value(uint32_t tag, const char* name, int32_t v) noexcept {
|
||||
mTrace.value(tag, name, v);
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int64_t v) noexcept {
|
||||
void value(uint32_t tag, const char* name, int64_t v) noexcept {
|
||||
mTrace.value(tag, name, v);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
Systrace mTrace;
|
||||
const char* mName;
|
||||
const uint32_t mTag;
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
*/
|
||||
|
||||
// Note: The overhead of SYSTRACE_TAG_JOBSYSTEM is not negligible especially with parallel_for().
|
||||
#ifndef SYSTRACE_TAG
|
||||
#define SYSTRACE_TAG SYSTRACE_TAG_DISABLED
|
||||
//#define SYSTRACE_TAG SYSTRACE_TAG_JOBSYSTEM
|
||||
#define SYSTRACE_TAG SYSTRACE_TAG_NEVER
|
||||
#endif
|
||||
|
||||
// when SYSTRACE_TAG_JOBSYSTEM is used, enables even heavier systraces
|
||||
#define HEAVY_SYSTRACE 0
|
||||
|
||||
@@ -14,206 +14,26 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <utils/Systrace.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/android/Systrace.h>
|
||||
|
||||
#include <cinttypes>
|
||||
#include <perfetto/perfetto.h>
|
||||
|
||||
#include <string.h>
|
||||
PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE(systrace);
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <dlfcn.h>
|
||||
namespace {
|
||||
|
||||
namespace utils {
|
||||
namespace details {
|
||||
|
||||
static pthread_once_t atrace_once_control = PTHREAD_ONCE_INIT;
|
||||
|
||||
template <typename T>
|
||||
static void loadSymbol(T*& pfn, const char *symbol) noexcept {
|
||||
pfn = (T*)dlsym(RTLD_DEFAULT, symbol);
|
||||
}
|
||||
|
||||
Systrace::GlobalState Systrace::sGlobalState = {};
|
||||
|
||||
void Systrace::init_once() noexcept {
|
||||
GlobalState& s = sGlobalState;
|
||||
|
||||
s.markerFd = -1;
|
||||
|
||||
// API 23
|
||||
loadSymbol(s.ATrace_isEnabled, "ATrace_isEnabled");
|
||||
loadSymbol(s.ATrace_beginSection, "ATrace_beginSection");
|
||||
loadSymbol(s.ATrace_endSection, "ATrace_endSection");
|
||||
// API 29
|
||||
loadSymbol(s.ATrace_beginAsyncSection, "ATrace_beginAsyncSection");
|
||||
loadSymbol(s.ATrace_endAsyncSection, "ATrace_endAsyncSection");
|
||||
loadSymbol(s.ATrace_setCounter, "ATrace_setCounter");
|
||||
|
||||
|
||||
const bool hasBasicAtrace = s.ATrace_isEnabled &&
|
||||
s.ATrace_beginSection &&
|
||||
s.ATrace_endSection;
|
||||
|
||||
const bool hasFullATrace = hasBasicAtrace &&
|
||||
s.ATrace_beginAsyncSection &&
|
||||
s.ATrace_endAsyncSection &&
|
||||
s.ATrace_setCounter;
|
||||
|
||||
if (!hasFullATrace) {
|
||||
s.markerFd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY | O_CLOEXEC);
|
||||
class SystraceStaticInitialization {
|
||||
public:
|
||||
SystraceStaticInitialization() {
|
||||
perfetto::TracingInitArgs args;
|
||||
args.backends |= perfetto::kSystemBackend;
|
||||
perfetto::Tracing::Initialize(args);
|
||||
systrace::TrackEvent::Register();
|
||||
}
|
||||
};
|
||||
|
||||
if (hasBasicAtrace && !hasFullATrace) {
|
||||
// no-op if we don't have all these
|
||||
s.ATrace_beginAsyncSection = [](const char* sectionName, int32_t cookie){};
|
||||
s.ATrace_endAsyncSection = [](const char* sectionName, int32_t cookie){};
|
||||
s.ATrace_setCounter = [](const char* sectionName, int64_t counterValue){};
|
||||
}
|
||||
UTILS_UNUSED SystraceStaticInitialization sSystraceStaticInitialization{};
|
||||
|
||||
const bool hasLegacySystrace = s.markerFd != -1;
|
||||
|
||||
if (hasLegacySystrace && !hasFullATrace) {
|
||||
// use legacy
|
||||
s.beginSection = [](Systrace* that, const char* name) {
|
||||
begin_body(that->mMarkerFd, that->mPid, name);
|
||||
};
|
||||
s.endSection = [](Systrace* that) {
|
||||
end_body(that->mMarkerFd, that->mPid);
|
||||
};
|
||||
s.beginAsyncSection = [](Systrace* that, const char* name, int32_t cookie) {
|
||||
async_begin_body(that->mMarkerFd, that->mPid, name, cookie);
|
||||
};
|
||||
s.endAsyncSection = [](Systrace* that, const char* name, int32_t cookie) {
|
||||
async_end_body(that->mMarkerFd, that->mPid, name, cookie);
|
||||
};
|
||||
s.setCounter = [](Systrace* that, const char* name, int64_t value) {
|
||||
int64_body(that->mMarkerFd, that->mPid, name, value);
|
||||
};
|
||||
} else if (hasBasicAtrace) {
|
||||
// we have at least basic ATrace
|
||||
s.beginSection = [](Systrace* that, const char* name) {
|
||||
that->ATrace_beginSection(name);
|
||||
};
|
||||
s.endSection = [](Systrace* that) {
|
||||
that->ATrace_endSection();
|
||||
};
|
||||
s.beginAsyncSection = [](Systrace* that, const char* name, int32_t cookie) {
|
||||
that->ATrace_beginAsyncSection(name, cookie);
|
||||
};
|
||||
s.endAsyncSection = [](Systrace* that, const char* name, int32_t cookie) {
|
||||
that->ATrace_endAsyncSection(name, cookie);
|
||||
};
|
||||
s.setCounter = [](Systrace* that, const char* name, int64_t value) {
|
||||
that->ATrace_setCounter(name, value);
|
||||
};
|
||||
}
|
||||
|
||||
s.isTracingAvailable = hasLegacySystrace || hasFullATrace || hasBasicAtrace;
|
||||
}
|
||||
|
||||
void Systrace::setup() noexcept {
|
||||
pthread_once(&atrace_once_control, init_once);
|
||||
}
|
||||
|
||||
void Systrace::enable(uint32_t tags) noexcept {
|
||||
setup();
|
||||
if (UTILS_LIKELY(sGlobalState.isTracingAvailable)) {
|
||||
sGlobalState.isTracingEnabled.fetch_or(tags, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
void Systrace::disable(uint32_t tags) noexcept {
|
||||
sGlobalState.isTracingEnabled.fetch_and(~tags, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// unfortunately, this generates quite a bit of code because reading a global is not
|
||||
// trivial. For this reason, we do not inline this method.
|
||||
bool Systrace::isTracingEnabled(uint32_t tag) noexcept {
|
||||
if (tag) {
|
||||
setup();
|
||||
return bool((sGlobalState.isTracingEnabled.load(std::memory_order_relaxed) | SYSTRACE_TAG_ALWAYS) & tag);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void Systrace::init(uint32_t tag) noexcept {
|
||||
// must be called first
|
||||
mIsTracingEnabled = isTracingEnabled(tag);
|
||||
|
||||
// cache static variables for better efficiency
|
||||
GlobalState& s = sGlobalState;
|
||||
ATrace_isEnabled = s.ATrace_isEnabled;
|
||||
ATrace_beginSection = s.ATrace_beginSection;
|
||||
ATrace_endSection = s.ATrace_endSection;
|
||||
ATrace_beginAsyncSection = s.ATrace_beginAsyncSection;
|
||||
ATrace_endAsyncSection = s.ATrace_endAsyncSection;
|
||||
ATrace_setCounter = s.ATrace_setCounter;
|
||||
|
||||
beginSection = s.beginSection;
|
||||
endSection = s.endSection;
|
||||
beginAsyncSection = s.beginAsyncSection;
|
||||
endAsyncSection = s.endAsyncSection;
|
||||
setCounter = s.setCounter;
|
||||
|
||||
mMarkerFd = s.markerFd;
|
||||
|
||||
mPid = getpid();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Maximum size of a message that can be logged to the trace buffer.
|
||||
* Note this message includes a tag, the pid, and the string given as the name.
|
||||
* Names should be kept short to get the most use of the trace buffer.
|
||||
*/
|
||||
#define ATRACE_MESSAGE_LENGTH 512
|
||||
|
||||
#define WRITE_MSG(format_begin, format_end, pid, name, value) { \
|
||||
char buf[ATRACE_MESSAGE_LENGTH]; \
|
||||
int len = snprintf(buf, sizeof(buf), format_begin "%s" format_end, pid, \
|
||||
name, value); \
|
||||
if (len >= (int) sizeof(buf)) { \
|
||||
/* Given the sizeof(buf), and all of the current format buffers, \
|
||||
* it is impossible for name_len to be < 0 if len >= sizeof(buf). */ \
|
||||
int name_len = strlen(name) - (len - sizeof(buf)) - 1; \
|
||||
/* Truncate the name to make the message fit. */ \
|
||||
len = snprintf(buf, sizeof(buf), format_begin "%.*s" format_end, pid, \
|
||||
name_len, name, value); \
|
||||
} \
|
||||
write(fd, buf, len); \
|
||||
}
|
||||
|
||||
void Systrace::begin_body(int fd, int pid, const char* name) noexcept {
|
||||
char buf[ATRACE_MESSAGE_LENGTH];
|
||||
ssize_t len = snprintf(buf, sizeof(buf), "B|%d|%s", pid, name);
|
||||
if (len >= sizeof(buf)) {
|
||||
len = sizeof(buf) - 1;
|
||||
}
|
||||
write(fd, buf, size_t(len));
|
||||
}
|
||||
|
||||
void Systrace::end_body(int fd, int pid) noexcept {
|
||||
const char END_TAG = 'E';
|
||||
write(fd, &END_TAG, 1);
|
||||
}
|
||||
|
||||
void Systrace::async_begin_body(int fd, int pid, const char* name, int32_t cookie) noexcept {
|
||||
WRITE_MSG("S|%d|", "|%" PRId32, pid, name, cookie);
|
||||
}
|
||||
|
||||
void Systrace::async_end_body(int fd, int pid, const char* name, int32_t cookie) noexcept {
|
||||
WRITE_MSG("F|%d|", "|%" PRId32, pid, name, cookie);
|
||||
}
|
||||
|
||||
void Systrace::int64_body(int fd, int pid, const char* name, int64_t value) noexcept {
|
||||
WRITE_MSG("C|%d|", "|%" PRId64, pid, name, value);
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
} // namespace utils
|
||||
|
||||
@@ -14,11 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <utils/Systrace.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/darwin/Systrace.h>
|
||||
|
||||
#ifndef FILAMENT_APPLE_SYSTRACE
|
||||
# define FILAMENT_APPLE_SYSTRACE 0
|
||||
#endif
|
||||
|
||||
#if FILAMENT_APPLE_SYSTRACE
|
||||
|
||||
#include <atomic>
|
||||
#include <stack>
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_once_t atrace_once_control = PTHREAD_ONCE_INIT;
|
||||
@@ -41,21 +47,24 @@ void Systrace::setup() noexcept {
|
||||
pthread_once(&atrace_once_control, init_once);
|
||||
}
|
||||
|
||||
void Systrace::enable(uint32_t tags) noexcept {
|
||||
void Systrace::enable(uint32_t tag) noexcept {
|
||||
setup();
|
||||
sGlobalState.isTracingEnabled.fetch_or(tags, std::memory_order_relaxed);
|
||||
uint32_t const mask = 1 << tag;
|
||||
sGlobalState.isTracingEnabled.fetch_or(mask, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void Systrace::disable(uint32_t tags) noexcept {
|
||||
sGlobalState.isTracingEnabled.fetch_and(~tags, std::memory_order_relaxed);
|
||||
void Systrace::disable(uint32_t tag) noexcept {
|
||||
uint32_t const mask = 1 << tag;
|
||||
sGlobalState.isTracingEnabled.fetch_and(~mask, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// unfortunately, this generates quite a bit of code because reading a global is not
|
||||
// Unfortunately, this generates quite a bit of code because reading a global is not
|
||||
// trivial. For this reason, we do not inline this method.
|
||||
bool Systrace::isTracingEnabled(uint32_t tag) noexcept {
|
||||
if (tag) {
|
||||
setup();
|
||||
return bool((sGlobalState.isTracingEnabled.load(std::memory_order_relaxed) | SYSTRACE_TAG_ALWAYS) & tag);
|
||||
uint32_t const mask = 1 << tag;
|
||||
return bool(sGlobalState.isTracingEnabled.load(std::memory_order_relaxed) & mask);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "filament",
|
||||
"version": "1.59.5",
|
||||
"version": "1.59.4",
|
||||
"description": "Real-time physically based rendering engine",
|
||||
"main": "filament.js",
|
||||
"module": "filament.js",
|
||||
|
||||
Reference in New Issue
Block a user