aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-prod (mdb) <android-build-team-robot@google.com>2019-05-28 21:17:01 +0000
committerandroid-build-prod (mdb) <android-build-team-robot@google.com>2019-05-28 21:17:01 +0000
commit3a1c6b83eb6d9f3ba346881ae5d09c5943adbadc (patch)
treeb2a5b6aee1396f7229e5296020fcd6fd6a94834b
parent1ad1d11d2970e003d4042aaa987186505592190f (diff)
parent67dafc58012c2e9b0af1733004bf123363ce2522 (diff)
downloadgamesdk-simpleperf-release.tar.gz
Snap for 5611316 from 67dafc58012c2e9b0af1733004bf123363ce2522 to simpleperf-releasesimpleperf-release
Change-Id: I5171c62fd96ae253ce7655e74740a802012fe374
-rw-r--r--build.gradle10
-rw-r--r--include/swappy/swappyGL.h10
-rw-r--r--include/swappy/swappyVk.h54
-rw-r--r--include/swappy/swappy_common.h27
-rw-r--r--include/tuningfork/tuningfork.h20
-rw-r--r--src/swappy/CMakeLists.txt1
-rw-r--r--src/swappy/common/SwappyCommon.cpp97
-rw-r--r--src/swappy/common/SwappyCommon.h21
-rw-r--r--src/swappy/common/swappy_c.cpp30
-rw-r--r--src/swappy/opengl/SwappyGL.cpp104
-rw-r--r--src/swappy/opengl/SwappyGL.h18
-rw-r--r--src/swappy/opengl/swappyGL_c.cpp2
-rw-r--r--src/swappy/vulkan/SwappyVk.cpp27
-rw-r--r--src/swappy/vulkan/SwappyVk.h7
-rw-r--r--src/swappy/vulkan/SwappyVkBase.cpp29
-rw-r--r--src/swappy/vulkan/SwappyVkBase.h20
-rw-r--r--src/swappy/vulkan/SwappyVkFallback.cpp26
-rw-r--r--src/swappy/vulkan/SwappyVkFallback.h4
-rw-r--r--src/swappy/vulkan/SwappyVkGoogleDisplayTiming.cpp34
-rw-r--r--src/swappy/vulkan/SwappyVkGoogleDisplayTiming.h4
-rw-r--r--src/swappy/vulkan/swappyVk_c.cpp22
-rw-r--r--src/tuningfork/CMakeLists.txt6
-rw-r--r--src/tuningfork/clearcut_backend.cpp12
-rw-r--r--src/tuningfork/tuningfork_c.cpp10
-rw-r--r--third_party/cube/app/src/main/cpp/cube.c17
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]);