diff options
author | android-build-prod (mdb) <android-build-team-robot@google.com> | 2019-05-28 21:17:01 +0000 |
---|---|---|
committer | android-build-prod (mdb) <android-build-team-robot@google.com> | 2019-05-28 21:17:01 +0000 |
commit | 3a1c6b83eb6d9f3ba346881ae5d09c5943adbadc (patch) | |
tree | b2a5b6aee1396f7229e5296020fcd6fd6a94834b | |
parent | 1ad1d11d2970e003d4042aaa987186505592190f (diff) | |
parent | 67dafc58012c2e9b0af1733004bf123363ce2522 (diff) | |
download | gamesdk-simpleperf-release.tar.gz |
Snap for 5611316 from 67dafc58012c2e9b0af1733004bf123363ce2522 to simpleperf-releasesimpleperf-release
Change-Id: I5171c62fd96ae253ce7655e74740a802012fe374
25 files changed, 420 insertions, 192 deletions
diff --git a/build.gradle b/build.gradle index eb6698e2..5e1ac788 100644 --- a/build.gradle +++ b/build.gradle @@ -394,9 +394,9 @@ task swappyUnityBuild(type: BuildTask) { ext.packageName = 'swappyUnity' ext.flattenLibs = true ext.withTuningFork = false - ext.withSharedLibs = true + ext.withSharedLibs = false ext.withStaticLibs = true - ext.withFullBuildKey = false + ext.withFullBuildKey = true ext.nativeBuild = { tf -> unityNativeBuild(tf) } } @@ -406,9 +406,9 @@ task unityBuild(type: BuildTask) { ext.packageName = 'unity' ext.flattenLibs = true ext.withTuningFork = true - ext.withSharedLibs = true - ext.withStaticLibs = false - ext.withFullBuildKey = false + ext.withSharedLibs = false + ext.withStaticLibs = true + ext.withFullBuildKey = true ext.nativeBuild = { tf -> unityNativeBuild(tf) } } diff --git a/include/swappy/swappyGL.h b/include/swappy/swappyGL.h index bb6c1136..edc324fe 100644 --- a/include/swappy/swappyGL.h +++ b/include/swappy/swappyGL.h @@ -29,8 +29,16 @@ extern "C" { #endif +// Internal init function. Do not call directly. +void SwappyGL_init_internal(JNIEnv *env, jobject jactivity); + // Initialize Swappy, getting the required Android parameters from the display subsystem via JNI -void SwappyGL_init(JNIEnv *env, jobject jactivity); +static inline void SwappyGL_init(JNIEnv *env, jobject jactivity) { + // This call ensures that the header and the linked library are from the same version + // (if not, a linker error will be triggered because of an undefined symbolP). + SWAPPY_VERSION_SYMBOL(); + return SwappyGL_init_internal(env, jactivity); +} // Returns true if Swappy was successfully initialized. // Returns false if either the 'swappy.disable' system property is not 'false' diff --git a/include/swappy/swappyVk.h b/include/swappy/swappyVk.h index 189af625..f8c285b6 100644 --- a/include/swappy/swappyVk.h +++ b/include/swappy/swappyVk.h @@ -20,6 +20,8 @@ #include "swappy_common.h" +#include "jni.h" + #if (defined ANDROID) && (defined SWAPPYVK_USE_WRAPPER) #include <vulkan_wrapper.h> #else @@ -99,9 +101,23 @@ void SwappyVk_setQueueFamilyIndex( // applications don't re-create swapchains. Is this long-term sufficient? /** + * Internal init function. Do not call directly. + * See SwappyVk_initAndGetRefreshCycleDuration instead. + */ +bool SwappyVk_initAndGetRefreshCycleDuration_internal( + JNIEnv* env, + jobject jactivity, + VkPhysicalDevice physicalDevice, + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t* pRefreshDuration); + +/** * Initialize SwappyVk for a given device and swapchain, and obtain the * approximate time duration between vertical-blanking periods. * + * Uses JNI to query AppVsyncOffset and PresentationDeadline. + * * If your application presents to more than one swapchain at a time, you must * call this for each swapchain before calling swappyVkSetSwapInterval() for it. * @@ -116,6 +132,8 @@ void SwappyVk_setQueueFamilyIndex( * * Parameters: * + * (IN) env - JNIEnv that is assumed to be from AttachCurrentThread function + * (IN) jactivity - NativeActivity object handle, used for JNI * (IN) physicalDevice - The VkPhysicalDevice associated with the swapchain * (IN) device - The VkDevice associated with the swapchain * (IN) swapchain - The VkSwapchainKHR the application wants Swappy to swap @@ -126,11 +144,18 @@ void SwappyVk_setQueueFamilyIndex( * bool - true if the value returned by pRefreshDuration is valid, * otherwise false if an error. */ -bool SwappyVk_initAndGetRefreshCycleDuration( +static inline bool SwappyVk_initAndGetRefreshCycleDuration( + JNIEnv* env, + jobject jactivity, VkPhysicalDevice physicalDevice, VkDevice device, VkSwapchainKHR swapchain, - uint64_t* pRefreshDuration); + uint64_t* pRefreshDuration) { + // This call ensures that the header and the linked library are from the same version + // (if not, a linker error will be triggered because of an undefined symbol). + SWAPPY_VERSION_SYMBOL(); + return SwappyVk_initAndGetRefreshCycleDuration_internal(env, jactivity, physicalDevice, device, swapchain, pRefreshDuration); +} /** @@ -190,6 +215,31 @@ void SwappyVk_destroySwapchain( VkDevice device, VkSwapchainKHR swapchain); +/** + * Enables Auto-Swap-Interval feature for all instances. + * + * By default this feature is enabled. Changing it is completely + * optional for fine-tuning swappy behaviour. + * + * Parameters: + * + * (IN) enabled - True means enable, false means disable + */ +void SwappyVk_setAutoSwapInterval(bool enabled); + + +/** + * Enables Auto-Pipeline-Mode feature for all instances. + * + * By default this feature is enabled. Changing it is completely + * optional for fine-tuning swappy behaviour. + * + * Parameters: + * + * (IN) enabled - True means enable, false means disable + */ +void SwappyVk_setAutoPipelineMode(bool enabled); + #ifdef __cplusplus } // extern "C" #endif diff --git a/include/swappy/swappy_common.h b/include/swappy/swappy_common.h index 61b96587..c126c24e 100644 --- a/include/swappy/swappy_common.h +++ b/include/swappy/swappy_common.h @@ -21,4 +21,29 @@ // swap interval constant helpers #define SWAPPY_SWAP_60FPS (16666667L) #define SWAPPY_SWAP_30FPS (33333333L) -#define SWAPPY_SWAP_20FPS (50000000L)
\ No newline at end of file +#define SWAPPY_SWAP_20FPS (50000000L) + +#define SWAPPY_SYSTEM_PROP_KEY_DISABLE "swappy.disable" + +// Internal macros to track Swappy version, do not use directly. +#define SWAPPY_MAJOR_VERSION 0 +#define SWAPPY_MINOR_VERSION 1 +#define SWAPPY_PACKED_VERSION ((SWAPPY_MAJOR_VERSION<<16)|(SWAPPY_MINOR_VERSION)) + +// Internal macros to generate a symbol to track Swappy version, do not use directly. +#define SWAPPY_VERSION_CONCAT_NX(PREFIX, MAJOR, MINOR) PREFIX ## _ ## MAJOR ## _ ## MINOR +#define SWAPPY_VERSION_CONCAT(PREFIX, MAJOR, MINOR) SWAPPY_VERSION_CONCAT_NX(PREFIX, MAJOR, MINOR) +#define SWAPPY_VERSION_SYMBOL SWAPPY_VERSION_CONCAT(Swappy_version, SWAPPY_MAJOR_VERSION, SWAPPY_MINOR_VERSION) + +#ifdef __cplusplus +extern "C" { +#endif + +// Internal function to track Swappy version bundled in a binary. Do not call directly. +// If you are getting linker errors related to Swappy_version_x_y, you probably have a +// mismatch between the header used at compilation and the actually library used by the linker. +void SWAPPY_VERSION_SYMBOL(); + +#ifdef __cplusplus +} // extern "C" +#endif
\ No newline at end of file diff --git a/include/tuningfork/tuningfork.h b/include/tuningfork/tuningfork.h index c1e6bd7e..18fec072 100644 --- a/include/tuningfork/tuningfork.h +++ b/include/tuningfork/tuningfork.h @@ -23,6 +23,11 @@ #define TUNINGFORK_MINOR_VERSION 2 #define TUNINGFORK_PACKED_VERSION ((TUNINGFORK_MAJOR_VERSION<<16)|(TUNINGFORK_MINOR_VERSION)) +// Internal macros to generate a symbol to track TuningFork version, do not use directly. +#define TUNINGFORK_VERSION_CONCAT_NX(PREFIX, MAJOR, MINOR) PREFIX ## _ ## MAJOR ## _ ## MINOR +#define TUNINGFORK_VERSION_CONCAT(PREFIX, MAJOR, MINOR) TUNINGFORK_VERSION_CONCAT_NX(PREFIX, MAJOR, MINOR) +#define TUNINGFORK_VERSION_SYMBOL TUNINGFORK_VERSION_CONCAT(TuningFork_version, TUNINGFORK_MAJOR_VERSION, TUNINGFORK_MINOR_VERSION) + // Instrument keys 64000-65535 are reserved enum { TFTICK_USERDEFINED_BASE = 0, @@ -105,11 +110,24 @@ inline void TFSettings_Free(TFSettings* settings) { if(settings->dealloc) settings->dealloc(settings); } +// Internal init function. Do not call directly. +TFErrorCode TuningFork_init_internal(const TFSettings *settings, JNIEnv* env, jobject context); + +// Internal function to track TuningFork version bundled in a binary. Do not call directly. +// If you are getting linker errors related to TuningFork_version_x_y, you probably have a +// mismatch between the header used at compilation and the actually library used by the linker. +void TUNINGFORK_VERSION_SYMBOL(); + // TuningFork_init must be called before any other functions. // If 'settings' is a null pointer, settings are extracted from the app. // Ownership of 'settings' remains with the caller. // Returns TFERROR_OK if successful, TFERROR_NO_SETTINGS if no settings could be found. -TFErrorCode TuningFork_init(const TFSettings *settings, JNIEnv* env, jobject context); +static inline TFErrorCode TuningFork_init(const TFSettings *settings, JNIEnv* env, jobject context) { + // This call ensures that the header and the linked library are from the same version + // (if not, a linker error will be triggered because of an undefined symbol). + TUNINGFORK_VERSION_SYMBOL(); + return TuningFork_init_internal(settings, env, context); +} // Blocking call to get fidelity parameters from the server. // Note that once fidelity parameters are downloaded, any timing information is recorded diff --git a/src/swappy/CMakeLists.txt b/src/swappy/CMakeLists.txt index 7ab71342..08f3a58d 100644 --- a/src/swappy/CMakeLists.txt +++ b/src/swappy/CMakeLists.txt @@ -37,6 +37,7 @@ add_library( swappy_static ${SOURCE_LOCATION_COMMON}/Settings.cpp ${SOURCE_LOCATION_COMMON}/Thread.cpp ${SOURCE_LOCATION_COMMON}/SwappyCommon.cpp + ${SOURCE_LOCATION_COMMON}/swappy_c.cpp ${SOURCE_LOCATION_OPENGL}/EGL.cpp ${SOURCE_LOCATION_OPENGL}/swappyGL_c.cpp ${SOURCE_LOCATION_OPENGL}/SwappyGL.cpp diff --git a/src/swappy/common/SwappyCommon.cpp b/src/swappy/common/SwappyCommon.cpp index 5b233c83..a9a4954c 100644 --- a/src/swappy/common/SwappyCommon.cpp +++ b/src/swappy/common/SwappyCommon.cpp @@ -36,26 +36,92 @@ using std::chrono::nanoseconds; constexpr std::chrono::nanoseconds SwappyCommon::FrameDuration::MAX_DURATION; constexpr std::chrono::nanoseconds SwappyCommon::FRAME_HYSTERESIS; -SwappyCommon::SwappyCommon(JavaVM* vm, - std::chrono::nanoseconds refreshPeriod, - std::chrono::nanoseconds appOffset, - std::chrono::nanoseconds sfOffset) - : mChoreographerFilter(std::make_unique<ChoreographerFilter>(refreshPeriod, - sfOffset - appOffset, - [this]() { return wakeClient(); })), - mChoreographerThread(ChoreographerThread::createChoreographerThread( - ChoreographerThread::Type::Swappy, - vm, - [this]{ mChoreographerFilter->onChoreographer(); })), - mSwapDuration(std::chrono::nanoseconds(0)), - mRefreshPeriod(refreshPeriod), +SwappyCommon::SwappyCommon(JNIEnv *env, jobject jactivity) + : mSwapDuration(std::chrono::nanoseconds(0)), mSwapInterval(1), - mAutoSwapInterval(1) -{ + mAutoSwapInterval(1), + mValid(false) { + jclass activityClass = env->FindClass("android/app/NativeActivity"); + jclass windowManagerClass = env->FindClass("android/view/WindowManager"); + jclass displayClass = env->FindClass("android/view/Display"); + + jmethodID getWindowManager = env->GetMethodID( + activityClass, + "getWindowManager", + "()Landroid/view/WindowManager;"); + + jmethodID getDefaultDisplay = env->GetMethodID( + windowManagerClass, + "getDefaultDisplay", + "()Landroid/view/Display;"); + + jobject wm = env->CallObjectMethod(jactivity, getWindowManager); + jobject display = env->CallObjectMethod(wm, getDefaultDisplay); + + jmethodID getRefreshRate = env->GetMethodID( + displayClass, + "getRefreshRate", + "()F"); + + const float refreshRateHz = env->CallFloatMethod(display, getRefreshRate); + + jmethodID getAppVsyncOffsetNanos = env->GetMethodID( + displayClass, + "getAppVsyncOffsetNanos", "()J"); + + // getAppVsyncOffsetNanos was only added in API 21. + // Return gracefully if this device doesn't support it. + if (getAppVsyncOffsetNanos == 0 || env->ExceptionOccurred()) { + ALOGE("Error while getting method: getAppVsyncOffsetNanos"); + env->ExceptionClear(); + return; + } + const long appVsyncOffsetNanos = env->CallLongMethod(display, getAppVsyncOffsetNanos); + + jmethodID getPresentationDeadlineNanos = env->GetMethodID( + displayClass, + "getPresentationDeadlineNanos", + "()J"); + + + if (getPresentationDeadlineNanos == 0 || env->ExceptionOccurred()) { + ALOGE("Error while getting method: getPresentationDeadlineNanos"); + return; + } + + const long vsyncPresentationDeadlineNanos = env->CallLongMethod( + display, getPresentationDeadlineNanos); + + const long ONE_MS_IN_NS = 1000 * 1000; + const long ONE_S_IN_NS = ONE_MS_IN_NS * 1000; + + const long vsyncPeriodNanos = static_cast<long>(ONE_S_IN_NS / refreshRateHz); + const long sfVsyncOffsetNanos = + vsyncPeriodNanos - (vsyncPresentationDeadlineNanos - ONE_MS_IN_NS); + + JavaVM* vm; + env->GetJavaVM(&vm); + + using std::chrono::nanoseconds; + mRefreshPeriod = nanoseconds(vsyncPeriodNanos); + mAppVsyncOffset = nanoseconds(appVsyncOffsetNanos); + mSfVsyncOffset = nanoseconds(sfVsyncOffsetNanos); + + mChoreographerFilter = std::make_unique<ChoreographerFilter>(mRefreshPeriod, + mSfVsyncOffset - mAppVsyncOffset, + [this]() { return wakeClient(); }); + + mChoreographerThread = ChoreographerThread::createChoreographerThread( + ChoreographerThread::Type::Swappy, + vm, + [this]{ mChoreographerFilter->onChoreographer(); }); + Settings::getInstance()->addListener([this]() { onSettingsChanged(); }); mAutoSwapIntervalThreshold = (1e9f / mRefreshPeriod.count()) / 20; // 20FPS mFrameDurations.reserve(mFrameDurationSamples); + + mValid = true; } SwappyCommon::~SwappyCommon() { @@ -416,5 +482,4 @@ void SwappyCommon::waitOneFrame() { mWaitingCondition.wait(lock, [&]() { return mCurrentFrame >= target; }); } - } // namespace swappy diff --git a/src/swappy/common/SwappyCommon.h b/src/swappy/common/SwappyCommon.h index 5d2448f4..27150b63 100644 --- a/src/swappy/common/SwappyCommon.h +++ b/src/swappy/common/SwappyCommon.h @@ -43,11 +43,7 @@ public: std::function<std::chrono::nanoseconds()> getPrevFrameGpuTime; }; - SwappyCommon(JavaVM *vm, - std::chrono::nanoseconds refreshPeriod, - std::chrono::nanoseconds appOffset, - std::chrono::nanoseconds sfOffset); - + SwappyCommon(JNIEnv *env, jobject jactivity); ~SwappyCommon(); uint64_t getSwapIntervalNS(); @@ -67,8 +63,12 @@ public: void setAutoSwapInterval(bool enabled); void setAutoPipelineMode(bool enabled); - std::chrono::nanoseconds getRefreshPeriod() { return mRefreshPeriod; } std::chrono::steady_clock::time_point getPresentationTime() { return mPresentationTime; } + std::chrono::nanoseconds getRefreshPeriod() { return mRefreshPeriod; } + std::chrono::nanoseconds getAppVsyncOffset() { return mAppVsyncOffset; } + std::chrono::nanoseconds getSfVsyncOffset() { return mSfVsyncOffset; } + + bool isValid() { return mValid; } private: class FrameDuration { @@ -154,7 +154,12 @@ private: std::chrono::steady_clock::time_point mCurrentFrameTimestamp = std::chrono::steady_clock::now(); int32_t mCurrentFrame = 0; std::atomic<std::chrono::nanoseconds> mSwapDuration; - const std::chrono::nanoseconds mRefreshPeriod; + + std::chrono::steady_clock::time_point mSwapTime; + + std::chrono::nanoseconds mRefreshPeriod; + std::chrono::nanoseconds mAppVsyncOffset; + std::chrono::nanoseconds mSfVsyncOffset; std::mutex mFrameDurationsMutex; std::vector<FrameDuration> mFrameDurations GUARDED_BY(mFrameDurationsMutex); @@ -186,7 +191,7 @@ private: bool mPresentationTimeNeeded; bool mPipelineMode = false; - std::chrono::steady_clock::time_point mSwapTime; + bool mValid; }; } //namespace swappy
\ No newline at end of file diff --git a/src/swappy/common/swappy_c.cpp b/src/swappy/common/swappy_c.cpp new file mode 100644 index 00000000..3ab3d059 --- /dev/null +++ b/src/swappy/common/swappy_c.cpp @@ -0,0 +1,30 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// API entry points for both OpenGL and Vulkan + +#include "swappy/swappy_common.h" + +extern "C" { + +void SWAPPY_VERSION_SYMBOL() { + // Intentionally empty: this function is used to ensure that the proper + // version of the library is linked against the proper headers. + // In case of mismatch, a linker error will be triggered because of an + // undefined symbol, as the name of the function depends on the version. +} + +} // extern "C"
\ No newline at end of file diff --git a/src/swappy/opengl/SwappyGL.cpp b/src/swappy/opengl/SwappyGL.cpp index 9a565cbb..6793dc8a 100644 --- a/src/swappy/opengl/SwappyGL.cpp +++ b/src/swappy/opengl/SwappyGL.cpp @@ -38,79 +38,12 @@ std::mutex SwappyGL::sInstanceMutex; std::unique_ptr<SwappyGL> SwappyGL::sInstance; void SwappyGL::init(JNIEnv *env, jobject jactivity) { - jclass activityClass = env->FindClass("android/app/NativeActivity"); - jclass windowManagerClass = env->FindClass("android/view/WindowManager"); - jclass displayClass = env->FindClass("android/view/Display"); - - jmethodID getWindowManager = env->GetMethodID( - activityClass, - "getWindowManager", - "()Landroid/view/WindowManager;"); - - jmethodID getDefaultDisplay = env->GetMethodID( - windowManagerClass, - "getDefaultDisplay", - "()Landroid/view/Display;"); - - jobject wm = env->CallObjectMethod(jactivity, getWindowManager); - jobject display = env->CallObjectMethod(wm, getDefaultDisplay); - - jmethodID getRefreshRate = env->GetMethodID( - displayClass, - "getRefreshRate", - "()F"); - - const float refreshRateHz = env->CallFloatMethod(display, getRefreshRate); - - jmethodID getAppVsyncOffsetNanos = env->GetMethodID( - displayClass, - "getAppVsyncOffsetNanos", "()J"); - - // getAppVsyncOffsetNanos was only added in API 21. - // Return gracefully if this device doesn't support it. - if (getAppVsyncOffsetNanos == 0 || env->ExceptionOccurred()) { - env->ExceptionClear(); - return; - } - const long appVsyncOffsetNanos = env->CallLongMethod(display, getAppVsyncOffsetNanos); - - jmethodID getPresentationDeadlineNanos = env->GetMethodID( - displayClass, - "getPresentationDeadlineNanos", - "()J"); - - const long vsyncPresentationDeadlineNanos = env->CallLongMethod( - display, - getPresentationDeadlineNanos); - - const long ONE_MS_IN_NS = 1000000; - const long ONE_S_IN_NS = ONE_MS_IN_NS * 1000; - - const long vsyncPeriodNanos = static_cast<long>(ONE_S_IN_NS / refreshRateHz); - const long sfVsyncOffsetNanos = - vsyncPeriodNanos - (vsyncPresentationDeadlineNanos - ONE_MS_IN_NS); - - using std::chrono::nanoseconds; - JavaVM *vm; - env->GetJavaVM(&vm); - SwappyGL::init( - vm, - nanoseconds(vsyncPeriodNanos), - nanoseconds(appVsyncOffsetNanos), - nanoseconds(sfVsyncOffsetNanos)); -} - -void SwappyGL::init(JavaVM *vm, - nanoseconds refreshPeriod, - nanoseconds appOffset, - nanoseconds sfOffset) { std::lock_guard<std::mutex> lock(sInstanceMutex); if (sInstance) { ALOGE("Attempted to initialize SwappyGL twice"); return; } - sInstance = - std::make_unique<SwappyGL>(vm, refreshPeriod, appOffset, sfOffset, ConstructorTag{}); + sInstance = std::make_unique<SwappyGL>(env, jactivity, ConstructorTag{}); } void SwappyGL::onChoreographer(int64_t frameTimeNanos) { @@ -269,7 +202,9 @@ SwappyGL *SwappyGL::getInstance() { bool SwappyGL::isEnabled() { SwappyGL *swappy = getInstance(); if (!swappy) { - ALOGE("Failed to get SwappyGL instance in getStats"); + // This is a case of error. + // We do not log anything here, so that we do not spam + // the user when this function is called each frame. return false; } return swappy->enabled(); @@ -289,32 +224,35 @@ EGL *SwappyGL::getEgl() { return egl; } -SwappyGL::SwappyGL(JavaVM *vm, - nanoseconds refreshPeriod, - nanoseconds appOffset, - nanoseconds sfOffset, - ConstructorTag) +SwappyGL::SwappyGL(JNIEnv *env, jobject jactivity, ConstructorTag) : mFrameStatistics(nullptr), - mSfOffset(sfOffset), - mCommonBase(vm, refreshPeriod, appOffset, sfOffset) + mCommonBase(env, jactivity) { - mDisableSwappy = getSystemPropViaGetAsBool("swappy.disable", false); + if (!mCommonBase.isValid()) { + ALOGE("SwappyCommon could not initialize correctly."); + mEnableSwappy = false; + return; + } + + mEnableSwappy = !getSystemPropViaGetAsBool(SWAPPY_SYSTEM_PROP_KEY_DISABLE, false); if (!enabled()) { ALOGI("Swappy is disabled"); return; } std::lock_guard<std::mutex> lock(mEglMutex); - mEgl = EGL::create(refreshPeriod); + mEgl = EGL::create(mCommonBase.getRefreshPeriod()); if (!mEgl) { ALOGE("Failed to load EGL functions"); - mDisableSwappy = true; + mEnableSwappy = false; return; } - ALOGI("Initialized Swappy with refreshPeriod=%lld, appOffset=%lld, sfOffset=%lld" , - (long long)refreshPeriod.count(), (long long)appOffset.count(), - (long long)sfOffset.count()); + ALOGI("Initialized Swappy with vsyncPeriod=%lld, appOffset=%lld, sfOffset=%lld", + (long long)mCommonBase.getRefreshPeriod().count(), + (long long)mCommonBase.getAppVsyncOffset().count(), + (long long)mCommonBase.getSfVsyncOffset().count() + ); } void SwappyGL::resetSyncFence(EGLDisplay display) { @@ -326,7 +264,7 @@ bool SwappyGL::setPresentationTime(EGLDisplay display, EGLSurface surface) { // if we are too close to the vsync, there is no need to set presentation time if ((mCommonBase.getPresentationTime() - std::chrono::steady_clock::now()) < - (mCommonBase.getRefreshPeriod() - mSfOffset)) { + (mCommonBase.getRefreshPeriod() - mCommonBase.getSfVsyncOffset())) { return EGL_TRUE; } diff --git a/src/swappy/opengl/SwappyGL.h b/src/swappy/opengl/SwappyGL.h index 6e00922c..77bc0283 100644 --- a/src/swappy/opengl/SwappyGL.h +++ b/src/swappy/opengl/SwappyGL.h @@ -40,12 +40,7 @@ class SwappyGL { // outside of the class since no one else can construct a ConstructorTag struct ConstructorTag {}; public: - SwappyGL(JavaVM *vm, - std::chrono::nanoseconds refreshPeriod, - std::chrono::nanoseconds appOffset, - std::chrono::nanoseconds sfOffset, - ConstructorTag); - + SwappyGL(JNIEnv *env, jobject jactivity, ConstructorTag); static void init(JNIEnv *env, jobject jactivity); static void onChoreographer(int64_t frameTimeNanos); @@ -68,14 +63,9 @@ class SwappyGL { static void destroyInstance(); private: - static void init(JavaVM *vm, - std::chrono::nanoseconds refreshPeriod, - std::chrono::nanoseconds appOffset, - std::chrono::nanoseconds sfOffset); - static SwappyGL *getInstance(); - bool enabled() const { return !mDisableSwappy; } + bool enabled() const { return mEnableSwappy; } EGL *getEgl(); @@ -90,7 +80,7 @@ private: // using eglPresentationTimeANDROID bool setPresentationTime(EGLDisplay display, EGLSurface surface); - bool mDisableSwappy = false; + bool mEnableSwappy = true; static std::mutex sInstanceMutex; static std::unique_ptr<SwappyGL> sInstance; @@ -100,8 +90,6 @@ private: std::unique_ptr<FrameStatistics> mFrameStatistics; - const std::chrono::nanoseconds mSfOffset; - SwappyCommon mCommonBase; }; diff --git a/src/swappy/opengl/swappyGL_c.cpp b/src/swappy/opengl/swappyGL_c.cpp index b025d690..473fa43a 100644 --- a/src/swappy/opengl/swappyGL_c.cpp +++ b/src/swappy/opengl/swappyGL_c.cpp @@ -28,7 +28,7 @@ using namespace swappy; extern "C" { -void SwappyGL_init(JNIEnv *env, jobject jactivity) { +void SwappyGL_init_internal(JNIEnv *env, jobject jactivity) { SwappyGL::init(env, jactivity); } diff --git a/src/swappy/vulkan/SwappyVk.cpp b/src/swappy/vulkan/SwappyVk.cpp index cbee274c..e4863f9f 100644 --- a/src/swappy/vulkan/SwappyVk.cpp +++ b/src/swappy/vulkan/SwappyVk.cpp @@ -51,8 +51,8 @@ void SwappyVk::swappyVkDetermineDeviceExtensions( } void SwappyVk::SetQueueFamilyIndex(VkDevice device, - VkQueue queue, - uint32_t queueFamilyIndex) + VkQueue queue, + uint32_t queueFamilyIndex) { perQueueFamilyIndex[queue] = {device, queueFamilyIndex}; } @@ -61,7 +61,9 @@ void SwappyVk::SetQueueFamilyIndex(VkDevice device, /** * Generic/Singleton implementation of swappyVkGetRefreshCycleDuration. */ -bool SwappyVk::GetRefreshCycleDuration(VkPhysicalDevice physicalDevice, +bool SwappyVk::GetRefreshCycleDuration(JNIEnv *env, + jobject jactivity, + VkPhysicalDevice physicalDevice, VkDevice device, VkSwapchainKHR swapchain, uint64_t* pRefreshDuration) @@ -84,11 +86,11 @@ bool SwappyVk::GetRefreshCycleDuration(VkPhysicalDevice physicalDevice, // determine which derived class to use to implement the rest of the API if (doesPhysicalDeviceHaveGoogleDisplayTiming[physicalDevice]) { pImplementation = std::make_shared<SwappyVkGoogleDisplayTiming> - (physicalDevice, device, mLibVulkan); + (env, jactivity, physicalDevice, device, mLibVulkan); ALOGV("SwappyVk initialized for VkDevice %p using VK_GOOGLE_display_timing on Android", device); } else { pImplementation = std::make_shared<SwappyVkFallback> - (physicalDevice, device, mLibVulkan); + (env, jactivity, physicalDevice, device, mLibVulkan); ALOGV("SwappyVk initialized for VkDevice %p using Android fallback", device); } @@ -103,7 +105,8 @@ bool SwappyVk::GetRefreshCycleDuration(VkPhysicalDevice physicalDevice, perSwapchainImplementation[swapchain] = pImplementation; // Now, call that derived class to get the refresh duration to return - return pImplementation->doGetRefreshCycleDuration(swapchain, pRefreshDuration); + return pImplementation->doGetRefreshCycleDuration(swapchain, + pRefreshDuration); } @@ -169,4 +172,16 @@ void SwappyVk::DestroySwapchain(VkDevice device, perSwapchainImplementation[swapchain] = nullptr; } +void SwappyVk::SetAutoSwapInterval(bool enabled) { + for (auto i : perSwapchainImplementation) { + i.second->setAutoSwapInterval(enabled); + } +} + +void SwappyVk::SetAutoPipelineMode(bool enabled) { + for (auto i : perSwapchainImplementation) { + i.second->setAutoPipelineMode(enabled); + } +} + } // namespace swappy
\ No newline at end of file diff --git a/src/swappy/vulkan/SwappyVk.h b/src/swappy/vulkan/SwappyVk.h index 216f2717..79a74b03 100644 --- a/src/swappy/vulkan/SwappyVk.h +++ b/src/swappy/vulkan/SwappyVk.h @@ -61,7 +61,9 @@ public: void SetQueueFamilyIndex(VkDevice device, VkQueue queue, uint32_t queueFamilyIndex); - bool GetRefreshCycleDuration(VkPhysicalDevice physicalDevice, + bool GetRefreshCycleDuration(JNIEnv *env, + jobject jactivity, + VkPhysicalDevice physicalDevice, VkDevice device, VkSwapchainKHR swapchain, uint64_t* pRefreshDuration); @@ -73,6 +75,9 @@ public: void DestroySwapchain(VkDevice device, VkSwapchainKHR swapchain); + void SetAutoSwapInterval(bool enabled); + void SetAutoPipelineMode(bool enabled); + private: std::map<VkPhysicalDevice, bool> doesPhysicalDeviceHaveGoogleDisplayTiming; std::map<VkDevice, std::shared_ptr<SwappyVkBase>> perDeviceImplementation; diff --git a/src/swappy/vulkan/SwappyVkBase.cpp b/src/swappy/vulkan/SwappyVkBase.cpp index abf84a8a..3bfb7b73 100644 --- a/src/swappy/vulkan/SwappyVkBase.cpp +++ b/src/swappy/vulkan/SwappyVkBase.cpp @@ -16,18 +16,29 @@ #include "SwappyVkBase.h" +#include "SystemProperties.h" + #define LOG_TAG "SwappyVkBase" namespace swappy { -SwappyVkBase::SwappyVkBase(VkPhysicalDevice physicalDevice, +SwappyVkBase::SwappyVkBase(JNIEnv *env, + jobject jactivity, + VkPhysicalDevice physicalDevice, VkDevice device, void *libVulkan) : + mCommonBase(env, jactivity), mPhysicalDevice(physicalDevice), mDevice(device), mLibVulkan(libVulkan), - mInitialized(false) + mInitialized(false), + mEnabled(false) { + if (!mCommonBase.isValid()) { + ALOGE("SwappyCommon could not initialize correctly."); + return; + } + InitVulkan(); mpfnGetDeviceProcAddr = @@ -38,6 +49,8 @@ SwappyVkBase::SwappyVkBase(VkPhysicalDevice physicalDevice, mpfnGetDeviceProcAddr(mDevice, "vkQueuePresentKHR")); initGoogExtension(); + + mEnabled = !getSystemPropViaGetAsBool(SWAPPY_SYSTEM_PROP_KEY_DISABLE, false); } void SwappyVkBase::initGoogExtension() { @@ -204,8 +217,8 @@ bool SwappyVkBase::lastFrameIsCompleted(VkQueue queue) { } VkResult SwappyVkBase::injectFence(VkQueue queue, - const VkPresentInfoKHR* pPresentInfo, - VkSemaphore* pSemaphore) { + const VkPresentInfoKHR* pPresentInfo, + VkSemaphore* pSemaphore) { // If we cross the swap interval threshold, we don't pace at all. // In this case we might not have a free fence, so just don't use the fence. if (mFreeSync[queue].size() == 0) { @@ -239,6 +252,14 @@ VkResult SwappyVkBase::injectFence(VkQueue queue, return res; } +void SwappyVkBase::setAutoSwapInterval(bool enabled) { + mCommonBase.setAutoSwapInterval(enabled); +} + +void SwappyVkBase::setAutoPipelineMode(bool enabled) { + mCommonBase.setAutoPipelineMode(enabled); +} + void SwappyVkBase::waitForFenceThreadMain(VkQueue queue) { ThreadContext& thread = *mThreads[queue]; diff --git a/src/swappy/vulkan/SwappyVkBase.h b/src/swappy/vulkan/SwappyVkBase.h index 07f33aa6..5509137f 100644 --- a/src/swappy/vulkan/SwappyVkBase.h +++ b/src/swappy/vulkan/SwappyVkBase.h @@ -94,7 +94,9 @@ using PFN_AChoreographer_postFrameCallbackDelayed = void (*)(AChoreographer* cho class SwappyVkBase { public: - SwappyVkBase(VkPhysicalDevice physicalDevice, + SwappyVkBase(JNIEnv *env, + jobject jactivity, + VkPhysicalDevice physicalDevice, VkDevice device, void *libVulkan); @@ -108,9 +110,15 @@ public: void doSetSwapInterval(VkSwapchainKHR swapchain, uint64_t swap_ns); - VkResult injectFence(VkQueue queue, - const VkPresentInfoKHR* pPresentInfo, - VkSemaphore* pSemaphore); + VkResult injectFence(VkQueue queue, + const VkPresentInfoKHR* pPresentInfo, + VkSemaphore* pSemaphore); + + bool isEnabled() { return mEnabled; } + + void setAutoSwapInterval(bool enabled); + void setAutoPipelineMode(bool enabled); + protected: struct VkSync { VkFence fence; @@ -131,10 +139,12 @@ protected: std::condition_variable_any condition; }; + SwappyCommon mCommonBase; VkPhysicalDevice mPhysicalDevice; VkDevice mDevice; void* mLibVulkan; bool mInitialized; + bool mEnabled; uint32_t mNextPresentID = 0; uint32_t mNextPresentIDToCheck = 2; @@ -149,8 +159,6 @@ protected: std::map<VkQueue, VkCommandPool> mCommandPool; std::map<VkQueue, std::unique_ptr<ThreadContext>> mThreads; - std::unique_ptr<SwappyCommon> mCommonBase; - static constexpr int MAX_PENDING_FENCES = 1; void initGoogExtension(); diff --git a/src/swappy/vulkan/SwappyVkFallback.cpp b/src/swappy/vulkan/SwappyVkFallback.cpp index 0aebcf8d..8b677776 100644 --- a/src/swappy/vulkan/SwappyVkFallback.cpp +++ b/src/swappy/vulkan/SwappyVkFallback.cpp @@ -20,21 +20,24 @@ namespace swappy { -SwappyVkFallback::SwappyVkFallback(VkPhysicalDevice physicalDevice, +SwappyVkFallback::SwappyVkFallback(JNIEnv *env, + jobject jactivity, + VkPhysicalDevice physicalDevice, VkDevice device, void *libVulkan) : - SwappyVkBase(physicalDevice, device, libVulkan) {} + SwappyVkBase(env, jactivity, physicalDevice, device, libVulkan) {} bool SwappyVkFallback::doGetRefreshCycleDuration(VkSwapchainKHR swapchain, uint64_t* pRefreshDuration) { - // TODO(adyabr): get the app/sf offsets - // TODO(adyabr): how to get the refresh duration here ? - mCommonBase = std::make_unique<SwappyCommon>(nullptr, 16600000ns, 0ns, 0ns); + if (!isEnabled()) { + ALOGE("Swappy is disabled."); + return false; + } // Since we don't have presentation timing, we cannot achieve pipelining. - mCommonBase->setAutoPipelineMode(false); + mCommonBase.setAutoPipelineMode(false); - *pRefreshDuration = mCommonBase->getRefreshPeriod().count(); + *pRefreshDuration = mCommonBase.getRefreshPeriod().count(); double refreshRate = 1000000000.0 / *pRefreshDuration; ALOGI("Returning refresh duration of %" PRIu64 " nsec (approx %f Hz)", @@ -46,6 +49,11 @@ bool SwappyVkFallback::doGetRefreshCycleDuration(VkSwapchainKHR swapchain, VkResult SwappyVkFallback::doQueuePresent(VkQueue queue, uint32_t queueFamilyIndex, const VkPresentInfoKHR* pPresentInfo) { + if (!isEnabled()) { + ALOGE("Swappy is disabled."); + return VK_ERROR_INITIALIZATION_FAILED; + } + VkResult result = initializeVkSyncObjects(queue, queueFamilyIndex); if (result) { return result; @@ -65,7 +73,7 @@ VkResult SwappyVkFallback::doQueuePresent(VkQueue queue, return result; } - mCommonBase->onPreSwap(handlers); + mCommonBase.onPreSwap(handlers); VkPresentInfoKHR replacementPresentInfo = { pPresentInfo->sType, @@ -80,7 +88,7 @@ VkResult SwappyVkFallback::doQueuePresent(VkQueue queue, result = mpfnQueuePresentKHR(queue, pPresentInfo); - mCommonBase->onPostSwap(handlers); + mCommonBase.onPostSwap(handlers); return result; } diff --git a/src/swappy/vulkan/SwappyVkFallback.h b/src/swappy/vulkan/SwappyVkFallback.h index 86b8631e..3e27744d 100644 --- a/src/swappy/vulkan/SwappyVkFallback.h +++ b/src/swappy/vulkan/SwappyVkFallback.h @@ -30,7 +30,9 @@ namespace swappy { class SwappyVkFallback : public SwappyVkBase { public: - SwappyVkFallback(VkPhysicalDevice physicalDevice, + SwappyVkFallback(JNIEnv *env, + jobject jactivity, + VkPhysicalDevice physicalDevice, VkDevice device, void *libVulkan); diff --git a/src/swappy/vulkan/SwappyVkGoogleDisplayTiming.cpp b/src/swappy/vulkan/SwappyVkGoogleDisplayTiming.cpp index e4f78f87..321e4519 100644 --- a/src/swappy/vulkan/SwappyVkGoogleDisplayTiming.cpp +++ b/src/swappy/vulkan/SwappyVkGoogleDisplayTiming.cpp @@ -22,17 +22,24 @@ using std::chrono::nanoseconds; namespace swappy { -SwappyVkGoogleDisplayTiming::SwappyVkGoogleDisplayTiming(VkPhysicalDevice physicalDevice, +SwappyVkGoogleDisplayTiming::SwappyVkGoogleDisplayTiming(JNIEnv *env, + jobject jactivity, + VkPhysicalDevice physicalDevice, VkDevice device, void *libVulkan) : - SwappyVkBase(physicalDevice, device, libVulkan) {} + SwappyVkBase(env, jactivity, physicalDevice, device, libVulkan) {} SwappyVkGoogleDisplayTiming::~SwappyVkGoogleDisplayTiming() { destroyVkSyncObjects(); } bool SwappyVkGoogleDisplayTiming::doGetRefreshCycleDuration(VkSwapchainKHR swapchain, - uint64_t* pRefreshDuration) { + uint64_t* pRefreshDuration) { + if (!isEnabled()) { + ALOGE("Swappy is disabled."); + return false; + } + VkRefreshCycleDurationGOOGLE refreshCycleDuration; VkResult res = mpfnGetRefreshCycleDurationGOOGLE(mDevice, swapchain, &refreshCycleDuration); if (res != VK_SUCCESS) { @@ -40,13 +47,7 @@ bool SwappyVkGoogleDisplayTiming::doGetRefreshCycleDuration(VkSwapchainKHR swapc return false; } - // TODO(adyabr): get appOffset and sfOffset - mCommonBase = std::make_unique<SwappyCommon>(nullptr, - nanoseconds(refreshCycleDuration.refreshDuration), - 0ns, - 0ns); - - *pRefreshDuration = mCommonBase->getRefreshPeriod().count(); + *pRefreshDuration = mCommonBase.getRefreshPeriod().count(); double refreshRate = 1000000000.0 / *pRefreshDuration; ALOGI("Returning refresh duration of %" PRIu64 " nsec (approx %f Hz)", @@ -58,6 +59,11 @@ bool SwappyVkGoogleDisplayTiming::doGetRefreshCycleDuration(VkSwapchainKHR swapc VkResult SwappyVkGoogleDisplayTiming::doQueuePresent(VkQueue queue, uint32_t queueFamilyIndex, const VkPresentInfoKHR* pPresentInfo) { + if (!isEnabled()) { + ALOGE("Swappy is disabled."); + return VK_ERROR_INITIALIZATION_FAILED; + } + VkResult res = initializeVkSyncObjects(queue, queueFamilyIndex); if (res) { return res; @@ -69,7 +75,7 @@ VkResult SwappyVkGoogleDisplayTiming::doQueuePresent(VkQueue que .getPrevFrameGpuTime = std::bind(&SwappyVkGoogleDisplayTiming::getLastFenceTime, this, queue), }; - mCommonBase->onPreSwap(handlers); + mCommonBase.onPreSwap(handlers); VkSemaphore semaphore; res = injectFence(queue, pPresentInfo, &semaphore); @@ -81,11 +87,11 @@ VkResult SwappyVkGoogleDisplayTiming::doQueuePresent(VkQueue que VkPresentTimeGOOGLE pPresentTimes[pPresentInfo->swapchainCount]; VkPresentInfoKHR replacementPresentInfo; VkPresentTimesInfoGOOGLE presentTimesInfo; - if (mCommonBase->needToSetPresentationTime()) { + if (mCommonBase.needToSetPresentationTime()) { // Setup the new structures to pass: for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { pPresentTimes[i].presentID = mNextPresentID; - pPresentTimes[i].desiredPresentTime = mCommonBase->getPresentationTime().time_since_epoch().count(); + pPresentTimes[i].desiredPresentTime = mCommonBase.getPresentationTime().time_since_epoch().count(); } presentTimesInfo = { @@ -121,7 +127,7 @@ VkResult SwappyVkGoogleDisplayTiming::doQueuePresent(VkQueue que mNextPresentID++; res = mpfnQueuePresentKHR(queue, &replacementPresentInfo); - mCommonBase->onPostSwap(handlers); + mCommonBase.onPostSwap(handlers); return res; } diff --git a/src/swappy/vulkan/SwappyVkGoogleDisplayTiming.h b/src/swappy/vulkan/SwappyVkGoogleDisplayTiming.h index 587ac3c5..784962ba 100644 --- a/src/swappy/vulkan/SwappyVkGoogleDisplayTiming.h +++ b/src/swappy/vulkan/SwappyVkGoogleDisplayTiming.h @@ -60,7 +60,9 @@ namespace swappy { class SwappyVkGoogleDisplayTiming : public SwappyVkBase { public: - SwappyVkGoogleDisplayTiming(VkPhysicalDevice physicalDevice, + SwappyVkGoogleDisplayTiming(JNIEnv *env, + jobject jactivity, + VkPhysicalDevice physicalDevice, VkDevice device, void *libVulkan); diff --git a/src/swappy/vulkan/swappyVk_c.cpp b/src/swappy/vulkan/swappyVk_c.cpp index 91593f0c..575066f7 100644 --- a/src/swappy/vulkan/swappyVk_c.cpp +++ b/src/swappy/vulkan/swappyVk_c.cpp @@ -20,8 +20,6 @@ #include "SwappyVk.h" -using namespace swappy; - extern "C" { void SwappyVk_determineDeviceExtensions( @@ -48,7 +46,9 @@ void SwappyVk_setQueueFamilyIndex( swappy.SetQueueFamilyIndex(device, queue, queueFamilyIndex); } -bool SwappyVk_initAndGetRefreshCycleDuration( +bool SwappyVk_initAndGetRefreshCycleDuration_internal( + JNIEnv *env, + jobject jactivity, VkPhysicalDevice physicalDevice, VkDevice device, VkSwapchainKHR swapchain, @@ -56,7 +56,9 @@ bool SwappyVk_initAndGetRefreshCycleDuration( { TRACE_CALL(); swappy::SwappyVk& swappy = swappy::SwappyVk::getInstance(); - return swappy.GetRefreshCycleDuration(physicalDevice, device, swapchain, pRefreshDuration); + return swappy.GetRefreshCycleDuration(env, jactivity, + physicalDevice, device, swapchain, + pRefreshDuration); } void SwappyVk_setSwapIntervalNS( @@ -87,4 +89,16 @@ void SwappyVk_destroySwapchain( swappy.DestroySwapchain(device, swapchain); } +void SwappyVk_setAutoSwapInterval(bool enabled) { + TRACE_CALL(); + swappy::SwappyVk& swappy = swappy::SwappyVk::getInstance(); + swappy.SetAutoSwapInterval(enabled); +} + +void SwappyVk_setAutoPipelineMode(bool enabled) { + TRACE_CALL(); + swappy::SwappyVk& swappy = swappy::SwappyVk::getInstance(); + swappy.SetAutoPipelineMode(enabled); +} + } // extern "C"
\ No newline at end of file diff --git a/src/tuningfork/CMakeLists.txt b/src/tuningfork/CMakeLists.txt index 0fbf099b..0ce4907b 100644 --- a/src/tuningfork/CMakeLists.txt +++ b/src/tuningfork/CMakeLists.txt @@ -4,6 +4,12 @@ include("../protobuf/protobuf.cmake") set( MODPB64_DIR "${EXTERNAL_ROOT}/modp_b64") set( JSON11_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/json11") +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Werror -Wthread-safety" ) +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -O3 -fPIC" ) +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions" ) +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti" ) +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections" ) + if (${CMAKE_BUILD_TYPE} STREQUAL "Release") set( CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections,-s") endif (${CMAKE_BUILD_TYPE} STREQUAL "Release") diff --git a/src/tuningfork/clearcut_backend.cpp b/src/tuningfork/clearcut_backend.cpp index 24993260..60b0b60b 100644 --- a/src/tuningfork/clearcut_backend.cpp +++ b/src/tuningfork/clearcut_backend.cpp @@ -94,15 +94,9 @@ TFErrorCode ClearcutBackend::Init(JNIEnv *env, jobject context, ProtoPrint* prot return TFERROR_JNI_BAD_JVM; } - try { - bool inited = InitWithClearcut(env, context, false); - ALOGI("Clearcut status: %s available", inited ? "" : "not"); - return inited ? TFERROR_OK : TFERROR_NO_CLEARCUT; - } catch (const std::exception& e) { - ALOGI("Clearcut status: not available"); - return TFERROR_NO_CLEARCUT; - } - + bool inited = InitWithClearcut(env, context, false); + ALOGI("Clearcut status: %s available", inited ? "" : "not"); + return inited ? TFERROR_OK : TFERROR_NO_CLEARCUT; } bool ClearcutBackend::IsGooglePlayServiceAvailable(JNIEnv* env, jobject context) { diff --git a/src/tuningfork/tuningfork_c.cpp b/src/tuningfork/tuningfork_c.cpp index b4e9fc40..7c295be1 100644 --- a/src/tuningfork/tuningfork_c.cpp +++ b/src/tuningfork/tuningfork_c.cpp @@ -40,8 +40,7 @@ void ToCProtobufSerialization(const tuningfork::ProtobufSerialization& pbs, extern "C" { -// TuningFork_init must be called before any other functions -TFErrorCode TuningFork_init(const TFSettings *settings, JNIEnv* env, jobject context) { +TFErrorCode TuningFork_init_internal(const TFSettings *settings, JNIEnv* env, jobject context) { if (settings) { return tuningfork::Init(*settings, env, context); } else { @@ -107,4 +106,11 @@ TFErrorCode TuningFork_flush() { return tuningfork::Flush(); } +void TUNINGFORK_VERSION_SYMBOL() { + // Intentionally empty: this function is used to ensure that the proper + // version of the library is linked against the proper headers. + // In case of mismatch, a linker error will be triggered because of an + // undefined symbol, as the name of the function depends on the version. +} + } // extern "C" { diff --git a/third_party/cube/app/src/main/cpp/cube.c b/third_party/cube/app/src/main/cpp/cube.c index d9f2537c..514967fe 100644 --- a/third_party/cube/app/src/main/cpp/cube.c +++ b/third_party/cube/app/src/main/cpp/cube.c @@ -524,6 +524,11 @@ struct demo { uint32_t current_buffer; uint32_t queue_family_count; + + struct { + JavaVM* vm; + jobject jactivity; + } swappy_init_data; }; VKAPI_ATTR VkBool32 VKAPI_CALL debug_messenger_callback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, @@ -1478,8 +1483,14 @@ static void demo_prepare_buffers(struct demo *demo) { demo->next_present_id = 1; } - assert(SwappyVk_initAndGetRefreshCycleDuration(demo->gpu, demo->device, demo->swapchain, - &demo->refresh_duration)); + JavaVM* vm = demo->swappy_init_data.vm; + assert(vm); + JNIEnv *env; + (*vm)->AttachCurrentThread(vm, &env, NULL); + assert(SwappyVk_initAndGetRefreshCycleDuration(env, + demo->swappy_init_data.jactivity, + demo->gpu, demo->device, demo->swapchain, + &demo->refresh_duration)); // Refresh rate of this demo is locked to 30 FPS. SwappyVk_setSwapIntervalNS(demo->device, demo->swapchain, SWAPPY_SWAP_30FPS); @@ -4001,6 +4012,8 @@ static void processCommand(struct android_app *app, int32_t cmd) { for (int i = 0; i < argc; i++) __android_log_print(ANDROID_LOG_INFO, appTag, "argv[%i] = %s", i, argv[i]); demo_init(&demo, argc, argv); + demo.swappy_init_data.vm = app->activity->vm; + demo.swappy_init_data.jactivity = app->activity->clazz; // Free the argv malloc'd by get_args for (int i = 0; i < argc; i++) free(argv[i]); |