Compare commits
1 Commits
GetMappedR
...
MapAsyncEx
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f14ebba87 |
@@ -6,3 +6,7 @@
|
||||
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
|
||||
|
||||
## Release notes for next branch cut
|
||||
|
||||
- engine: add `View::getLastDynamicResolutionScale()` (b/457753622)
|
||||
|
||||
- materials: Make Material Instances' UBO descriptor use dynamic offsets. [⚠️ **Recompile Materials**]
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.67.1'
|
||||
implementation 'com.google.android.filament:filament-android:1.67.0'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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.67.1'
|
||||
pod 'Filament', '~> 1.67.0'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -7,12 +7,6 @@ A new header is inserted each time a *tag* is created.
|
||||
Instead, if you are authoring a PR for the main branch, add your release note to
|
||||
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
|
||||
|
||||
## v1.68.0
|
||||
|
||||
- engine: add `View::getLastDynamicResolutionScale()` (b/457753622)
|
||||
- Metal: report GPU errors to the platform via `debugUpdateStat` (b/431665753).
|
||||
- materials: Make Material Instances' UBO descriptor use dynamic offsets. [⚠️ **Recompile Materials**]
|
||||
|
||||
## v1.67.1
|
||||
|
||||
- Metal: Add support for the `SwapChain::CONFIG_MSAA_4_SAMPLES` flag.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.67.1
|
||||
VERSION_NAME=1.67.0
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ important for <code>matc</code> (material compiler).</p>
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.67.1'
|
||||
implementation 'com.google.android.filament:filament-android:1.66.2'
|
||||
}
|
||||
</code></pre>
|
||||
<p>Here are all the libraries available in the group <code>com.google.android.filament</code>:</p>
|
||||
@@ -196,7 +196,7 @@ dependencies {
|
||||
</div>
|
||||
<h3 id="ios"><a class="header" href="#ios">iOS</a></h3>
|
||||
<p>iOS projects can use CocoaPods to install the latest release:</p>
|
||||
<pre><code class="language-shell">pod 'Filament', '~> 1.67.1'
|
||||
<pre><code class="language-shell">pod 'Filament', '~> 1.66.2'
|
||||
</code></pre>
|
||||
<h2 id="documentation"><a class="header" href="#documentation">Documentation</a></h2>
|
||||
<ul>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -316,8 +316,6 @@ if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
src/webgpu/WebGPURenderPrimitive.h
|
||||
src/webgpu/WebGPURenderTarget.cpp
|
||||
src/webgpu/WebGPURenderTarget.h
|
||||
src/webgpu/WebGPUStagePool.cpp
|
||||
src/webgpu/WebGPUStagePool.h
|
||||
src/webgpu/WebGPUStrings.h
|
||||
src/webgpu/WebGPUSwapChain.cpp
|
||||
src/webgpu/WebGPUSwapChain.h
|
||||
|
||||
@@ -19,17 +19,13 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PLATFORM_H
|
||||
#define TNT_FILAMENT_BACKEND_PLATFORM_H
|
||||
|
||||
#include <utils/CString.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Invocable.h>
|
||||
#include <utils/Mutex.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -512,22 +508,13 @@ public:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Debugging APIs
|
||||
|
||||
using DebugUpdateStatFunc = utils::Invocable<void(const char* UTILS_NONNULL key,
|
||||
uint64_t intValue, utils::CString stringValue)>;
|
||||
using DebugUpdateStatFunc = utils::Invocable<void(const char* UTILS_NONNULL key, uint64_t value)>;
|
||||
|
||||
/**
|
||||
* Sets the callback function that the backend can use to update backend-specific statistics
|
||||
* to aid with debugging. This callback is guaranteed to be called on the Filament driver
|
||||
* thread.
|
||||
*
|
||||
* The callback signature is (key, intValue, stringValue). Note that for any given call,
|
||||
* only one of the value parameters (intValue or stringValue) will be meaningful, depending on
|
||||
* the specific key.
|
||||
*
|
||||
* IMPORTANT_NOTE: because the callback is called on the driver thread, only quick, non-blocking
|
||||
* work should be done inside it. Furthermore, no graphics API calls (such as GL calls) should
|
||||
* be made, which could interfere with Filament's driver state.
|
||||
*
|
||||
* @param debugUpdateStat an Invocable that updates debug statistics
|
||||
*/
|
||||
void setDebugUpdateStatFunc(DebugUpdateStatFunc&& debugUpdateStat) noexcept;
|
||||
@@ -546,32 +533,15 @@ public:
|
||||
* This function is guaranteed to be called only on a single thread, the Filament driver
|
||||
* thread.
|
||||
*
|
||||
* @param key a null-terminated C-string with the key of the debug statistic
|
||||
* @param intValue the updated integer value of key (the string value passed to the
|
||||
* callback will be empty)
|
||||
* @param key a null-terminated C-string with the key of the debug statistic
|
||||
* @param value the updated value of key
|
||||
*/
|
||||
void debugUpdateStat(const char* UTILS_NONNULL key, uint64_t intValue);
|
||||
|
||||
/**
|
||||
* To track backend-specific statistics, the backend implementation can call the
|
||||
* application-provided callback function debugUpdateStatFunc to associate or update a value
|
||||
* with a given key. It is possible for this function to be called multiple times with the
|
||||
* same key, in which case newer values should overwrite older values.
|
||||
*
|
||||
* This function is guaranteed to be called only on a single thread, the Filament driver
|
||||
* thread.
|
||||
*
|
||||
* @param key a null-terminated C-string with the key of the debug statistic
|
||||
* @param stringValue the updated string value of key (the integer value passed to the
|
||||
* callback will be 0)
|
||||
*/
|
||||
void debugUpdateStat(const char* UTILS_NONNULL key, utils::CString stringValue);
|
||||
void debugUpdateStat(const char* UTILS_NONNULL key, uint64_t value);
|
||||
|
||||
private:
|
||||
std::shared_ptr<InsertBlobFunc> mInsertBlob;
|
||||
std::shared_ptr<RetrieveBlobFunc> mRetrieveBlob;
|
||||
std::shared_ptr<DebugUpdateStatFunc> mDebugUpdateStat;
|
||||
mutable utils::Mutex mMutex;
|
||||
InsertBlobFunc mInsertBlob;
|
||||
RetrieveBlobFunc mRetrieveBlob;
|
||||
DebugUpdateStatFunc mDebugUpdateStat;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
|
||||
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
|
||||
|
||||
#include "AndroidSwapChainHelper.h"
|
||||
#include "AndroidFrameCallback.h"
|
||||
#include "AndroidNdk.h"
|
||||
|
||||
#include <backend/AcquiredImage.h>
|
||||
@@ -169,10 +171,19 @@ protected:
|
||||
SwapChain* drawSwapChain,
|
||||
SwapChain* readSwapChain) override;
|
||||
|
||||
private:
|
||||
struct SwapChainEGLAndroid;
|
||||
struct AndroidDetails;
|
||||
struct SwapChainEGLAndroid : public SwapChainEGL {
|
||||
SwapChainEGLAndroid(PlatformEGLAndroid const& platform,
|
||||
void* nativeWindow, uint64_t flags);
|
||||
SwapChainEGLAndroid(PlatformEGLAndroid const& platform,
|
||||
uint32_t width, uint32_t height, uint64_t flags);
|
||||
void terminate(PlatformEGLAndroid& platform);
|
||||
bool setPresentFrameId(uint64_t frameId) const noexcept;
|
||||
uint64_t getFrameId(uint64_t frameId) const noexcept;
|
||||
private:
|
||||
AndroidSwapChainHelper mImpl{};
|
||||
};
|
||||
|
||||
private:
|
||||
// prevent derived classes' implementations to call through
|
||||
[[nodiscard]] SwapChain* createSwapChain(void* nativeWindow, uint64_t flags) override;
|
||||
[[nodiscard]] SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) override;
|
||||
@@ -192,14 +203,17 @@ private:
|
||||
|
||||
int mOSVersion;
|
||||
ExternalStreamManagerAndroid& mExternalStreamManager;
|
||||
AndroidDetails& mAndroidDetails;
|
||||
InitializeJvmForPerformanceManagerIfNeeded const mInitializeJvmForPerformanceManagerIfNeeded;
|
||||
utils::PerformanceHintManager mPerformanceHintManager;
|
||||
utils::PerformanceHintManager::Session mPerformanceHintSession;
|
||||
SwapChainEGLAndroid* mCurrentDrawSwapChain{};
|
||||
|
||||
using clock = std::chrono::high_resolution_clock;
|
||||
clock::time_point mStartTimeOfActualWork;
|
||||
SwapChainEGLAndroid* mCurrentDrawSwapChain{};
|
||||
AndroidProducerThrottling mProducerThrottling;
|
||||
bool mAssertNativeWindowIsValid = false;
|
||||
|
||||
AndroidFrameCallback mAndroidFrameCallback;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -17,13 +17,12 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PLATFORMS_VULKAN_PLATFORM_ANDROID_H
|
||||
#define TNT_FILAMENT_BACKEND_PLATFORMS_VULKAN_PLATFORM_ANDROID_H
|
||||
|
||||
#include "AndroidFrameCallback.h"
|
||||
#include "AndroidNdk.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/platforms/VulkanPlatform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <android/hardware_buffer.h>
|
||||
|
||||
namespace filament::backend {
|
||||
@@ -92,8 +91,6 @@ protected:
|
||||
VkExternalFenceHandleTypeFlagBits getFenceExportFlags() const noexcept override;
|
||||
|
||||
private:
|
||||
struct AndroidDetails;
|
||||
|
||||
struct ExternalImageVulkanAndroid : public ExternalImage {
|
||||
AHardwareBuffer* aHardwareBuffer = nullptr;
|
||||
bool sRGB = false;
|
||||
@@ -102,7 +99,7 @@ private:
|
||||
~ExternalImageVulkanAndroid() override;
|
||||
};
|
||||
|
||||
AndroidDetails& mAndroidDetails;
|
||||
AndroidFrameCallback mAndroidFrameCallback;
|
||||
int mOSVersion{};
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <backend/platforms/AndroidNdk.h>
|
||||
#include "AndroidNdk.h"
|
||||
|
||||
#include <android/hardware_buffer.h>
|
||||
|
||||
|
||||
@@ -139,73 +139,42 @@ bool Platform::queryFrameTimestamps(SwapChain const*, uint64_t, FrameTimestamps*
|
||||
}
|
||||
|
||||
void Platform::setBlobFunc(InsertBlobFunc&& insertBlob, RetrieveBlobFunc&& retrieveBlob) noexcept {
|
||||
std::lock_guard<decltype(mMutex)> lock(mMutex);
|
||||
mInsertBlob = std::make_shared<InsertBlobFunc>(std::move(insertBlob));
|
||||
mRetrieveBlob = std::make_shared<RetrieveBlobFunc>(std::move(retrieveBlob));
|
||||
mInsertBlob = std::move(insertBlob);
|
||||
mRetrieveBlob = std::move(retrieveBlob);
|
||||
}
|
||||
|
||||
bool Platform::hasInsertBlobFunc() const noexcept {
|
||||
std::lock_guard<decltype(mMutex)> lock(mMutex);
|
||||
return bool(mInsertBlob);
|
||||
}
|
||||
|
||||
bool Platform::hasRetrieveBlobFunc() const noexcept {
|
||||
std::lock_guard<decltype(mMutex)> lock(mMutex);
|
||||
return bool(mRetrieveBlob);
|
||||
}
|
||||
|
||||
void Platform::insertBlob(void const* key, size_t keySize, void const* value, size_t valueSize) {
|
||||
std::shared_ptr<InsertBlobFunc> callback;
|
||||
{
|
||||
std::unique_lock<decltype(mMutex)> lock(mMutex);
|
||||
callback = mInsertBlob;
|
||||
}
|
||||
if (callback) {
|
||||
(*callback)(key, keySize, value, valueSize);
|
||||
if (mInsertBlob) {
|
||||
mInsertBlob(key, keySize, value, valueSize);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Platform::retrieveBlob(void const* key, size_t keySize, void* value, size_t valueSize) {
|
||||
std::shared_ptr<RetrieveBlobFunc> callback;
|
||||
{
|
||||
std::unique_lock<decltype(mMutex)> lock(mMutex);
|
||||
callback = mRetrieveBlob;
|
||||
}
|
||||
if (callback) {
|
||||
return (*callback)(key, keySize, value, valueSize);
|
||||
if (mRetrieveBlob) {
|
||||
return mRetrieveBlob(key, keySize, value, valueSize);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Platform::setDebugUpdateStatFunc(DebugUpdateStatFunc&& debugUpdateStat) noexcept {
|
||||
std::lock_guard<decltype(mMutex)> lock(mMutex);
|
||||
mDebugUpdateStat = std::make_shared<DebugUpdateStatFunc>(std::move(debugUpdateStat));
|
||||
mDebugUpdateStat = std::move(debugUpdateStat);
|
||||
}
|
||||
|
||||
bool Platform::hasDebugUpdateStatFunc() const noexcept {
|
||||
std::lock_guard<decltype(mMutex)> lock(mMutex);
|
||||
return mDebugUpdateStat != nullptr;
|
||||
return bool(mDebugUpdateStat);
|
||||
}
|
||||
|
||||
void Platform::debugUpdateStat(const char* key, uint64_t intValue) {
|
||||
std::shared_ptr<DebugUpdateStatFunc> callback;
|
||||
{
|
||||
std::unique_lock<decltype(mMutex)> lock(mMutex);
|
||||
callback = mDebugUpdateStat;
|
||||
}
|
||||
if (callback) {
|
||||
(*callback)(key, intValue, "");
|
||||
}
|
||||
}
|
||||
|
||||
void Platform::debugUpdateStat(const char* key, utils::CString stringValue) {
|
||||
std::shared_ptr<DebugUpdateStatFunc> callback;
|
||||
{
|
||||
std::unique_lock<decltype(mMutex)> lock(mMutex);
|
||||
callback = mDebugUpdateStat;
|
||||
}
|
||||
if (callback) {
|
||||
(*callback)(key, 0, stringValue);
|
||||
void Platform::debugUpdateStat(const char* key, uint64_t value) {
|
||||
if (mDebugUpdateStat) {
|
||||
mDebugUpdateStat(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#ifndef TNT_METALCONTEXT_H
|
||||
#define TNT_METALCONTEXT_H
|
||||
|
||||
#include "MetalErrorQueue.h"
|
||||
#include "MetalResourceTracker.h"
|
||||
#include "MetalShaderCompiler.h"
|
||||
#include "MetalState.h"
|
||||
@@ -130,7 +129,6 @@ struct MetalContext {
|
||||
id<MTLCommandBuffer> pendingCommandBuffer = nil;
|
||||
id<MTLRenderCommandEncoder> currentRenderPassEncoder = nil;
|
||||
uint32_t currentFrame = 0;
|
||||
MetalErrorQueue commandBufferErrors;
|
||||
|
||||
std::atomic<bool> memorylessLimitsReached = false;
|
||||
|
||||
|
||||
@@ -153,7 +153,6 @@ id<MTLCommandBuffer> getPendingCommandBuffer(MetalContext* context) {
|
||||
|
||||
if (UTILS_UNLIKELY(errorCode != MTLCommandBufferErrorNone)) {
|
||||
logMTLCommandBufferError(errorCode);
|
||||
context->commandBufferErrors.push(buffer.error);
|
||||
}
|
||||
}];
|
||||
FILAMENT_CHECK_POSTCONDITION(context->pendingCommandBuffer)
|
||||
|
||||
@@ -254,18 +254,6 @@ MetalDriver::~MetalDriver() noexcept {
|
||||
void MetalDriver::tick(int) {
|
||||
executeTickOps();
|
||||
executeDeferredOps();
|
||||
|
||||
// Notify platform of GPU errors.
|
||||
auto& platform = mPlatform;
|
||||
if (UTILS_UNLIKELY(!mContext->commandBufferErrors.isEmpty())) {
|
||||
mContext->commandBufferErrors.flush([&platform](NSError* error) {
|
||||
if (UTILS_VERY_UNLIKELY(!error)) {
|
||||
return;
|
||||
}
|
||||
const utils::CString errorString(error.localizedDescription.UTF8String);
|
||||
platform.debugUpdateStat("filament.metal.command_buffer_error", errorString);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void MetalDriver::beginFrame(int64_t monotonic_clock_ns,
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_DRIVER_METALERRORQUEUE_H
|
||||
#define TNT_FILAMENT_DRIVER_METALERRORQUEUE_H
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
class MetalErrorQueue {
|
||||
public:
|
||||
bool isEmpty() const {
|
||||
return !mHasErrors.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void push(NSError* error) {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mErrors.push_back(error);
|
||||
mHasErrors.store(true, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void flush(const std::function<void(NSError*)>& callback) {
|
||||
if (UTILS_LIKELY(isEmpty())) {
|
||||
return;
|
||||
}
|
||||
std::vector<NSError*> errors;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
std::swap(mErrors, errors);
|
||||
mHasErrors.store(false, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
for (const auto& error: errors) {
|
||||
callback(error);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<NSError*> mErrors;
|
||||
std::mutex mMutex;
|
||||
|
||||
// Optimization to avoid locking the mutex at each call to flush.
|
||||
std::atomic<bool> mHasErrors;
|
||||
};
|
||||
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_METALERRORQUEUE_H
|
||||
@@ -28,13 +28,14 @@
|
||||
#include <private/backend/VirtualMachineEnv.h>
|
||||
|
||||
#include "AndroidNativeWindow.h"
|
||||
#include "AndroidFrameCallback.h"
|
||||
#include "AndroidSwapChainHelper.h"
|
||||
#include "ExternalStreamManagerAndroid.h"
|
||||
|
||||
#include <android/api-level.h>
|
||||
#include <android/native_window.h>
|
||||
#include <android/hardware_buffer.h>
|
||||
#include <android/choreographer.h>
|
||||
#include <android/looper.h>
|
||||
|
||||
#include <utils/android/PerformanceHintManager.h>
|
||||
#include <utils/compiler.h>
|
||||
@@ -98,25 +99,6 @@ using namespace glext;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
struct PlatformEGLAndroid::SwapChainEGLAndroid : public SwapChainEGL {
|
||||
SwapChainEGLAndroid(PlatformEGLAndroid const& platform,
|
||||
void* nativeWindow, uint64_t flags);
|
||||
SwapChainEGLAndroid(PlatformEGLAndroid const& platform,
|
||||
uint32_t width, uint32_t height, uint64_t flags);
|
||||
void terminate(PlatformEGLAndroid& platform);
|
||||
bool setPresentFrameId(uint64_t frameId) const noexcept;
|
||||
uint64_t getFrameId(uint64_t frameId) const noexcept;
|
||||
private:
|
||||
AndroidSwapChainHelper mImpl{};
|
||||
};
|
||||
|
||||
struct PlatformEGLAndroid::AndroidDetails {
|
||||
AndroidProducerThrottling producerThrottling;
|
||||
AndroidFrameCallback androidFrameCallback;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
PlatformEGLAndroid::InitializeJvmForPerformanceManagerIfNeeded::InitializeJvmForPerformanceManagerIfNeeded() {
|
||||
// PerformanceHintManager() needs the calling thread to be a Java thread; so we need
|
||||
// to attach this thread to the JVM before we initialize PerformanceHintManager.
|
||||
@@ -130,20 +112,17 @@ PlatformEGLAndroid::InitializeJvmForPerformanceManagerIfNeeded::InitializeJvmFor
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
PlatformEGLAndroid::PlatformEGLAndroid() noexcept
|
||||
: mExternalStreamManager(ExternalStreamManagerAndroid::create()),
|
||||
mAndroidDetails(*(new(std::nothrow) AndroidDetails{})) {
|
||||
: mExternalStreamManager(ExternalStreamManagerAndroid::create()) {
|
||||
mOSVersion = android_get_device_api_level();
|
||||
if (mOSVersion < 0) {
|
||||
mOSVersion = __ANDROID_API_FUTURE__;
|
||||
}
|
||||
}
|
||||
|
||||
PlatformEGLAndroid::~PlatformEGLAndroid() noexcept {
|
||||
delete &mAndroidDetails;
|
||||
}
|
||||
PlatformEGLAndroid::~PlatformEGLAndroid() noexcept = default;
|
||||
|
||||
void PlatformEGLAndroid::terminate() noexcept {
|
||||
mAndroidDetails.androidFrameCallback.terminate();
|
||||
mAndroidFrameCallback.terminate();
|
||||
ExternalStreamManagerAndroid::destroy(&mExternalStreamManager);
|
||||
PlatformEGL::terminate();
|
||||
}
|
||||
@@ -261,7 +240,7 @@ Driver* PlatformEGLAndroid::createDriver(void* sharedContext,
|
||||
|
||||
mAssertNativeWindowIsValid = driverConfig.assertNativeWindowIsValid;
|
||||
|
||||
mAndroidDetails.androidFrameCallback.init();
|
||||
mAndroidFrameCallback.init();
|
||||
|
||||
return driver;
|
||||
}
|
||||
@@ -285,7 +264,7 @@ bool PlatformEGLAndroid::queryCompositorTiming(SwapChain const* swapchain,
|
||||
}
|
||||
|
||||
AndroidFrameCallback::Timeline const preferredTimeline{
|
||||
mAndroidDetails.androidFrameCallback.getPreferredTimeline() };
|
||||
mAndroidFrameCallback.getPreferredTimeline() };
|
||||
outCompositorTiming->frameTime = preferredTimeline.frameTime;
|
||||
outCompositorTiming->expectedPresentTime = preferredTimeline.expectedPresentTime;
|
||||
outCompositorTiming->frameTimelineDeadline = preferredTimeline.frameTimelineDeadline;
|
||||
@@ -696,12 +675,12 @@ AcquiredImage PlatformEGLAndroid::transformAcquiredImage(AcquiredImage const sou
|
||||
|
||||
|
||||
bool PlatformEGLAndroid::isProducerThrottlingControlSupported() const {
|
||||
return mAndroidDetails.producerThrottling.isSupported();
|
||||
return mProducerThrottling.isSupported();
|
||||
}
|
||||
|
||||
int32_t PlatformEGLAndroid::setProducerThrottlingEnabled(
|
||||
EGLNativeWindowType const nativeWindow, bool const enabled) const {
|
||||
return mAndroidDetails.producerThrottling.setProducerThrottlingEnabled(nativeWindow, enabled);
|
||||
return mProducerThrottling.setProducerThrottlingEnabled(nativeWindow, enabled);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -921,6 +921,14 @@ void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
// on Android, disable producer throttling
|
||||
if (mProducerThrottling.isSupported()) {
|
||||
mProducerThrottling.setProducerThrottlingEnabled(
|
||||
static_cast<ANativeWindow*>(nativeWindow), false);
|
||||
}
|
||||
#endif
|
||||
|
||||
auto swapChain = resource_ptr<VulkanSwapChain>::make(&mResourceManager, sch, mPlatform,
|
||||
mContext, &mResourceManager, mAllocator, &mCommands, mStagePool, nativeWindow, flags);
|
||||
swapChain.inc();
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
#include <utils/Allocator.h>
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include "AndroidNativeWindow.h"
|
||||
#endif
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class VulkanPlatform;
|
||||
@@ -202,6 +206,9 @@ private:
|
||||
bool const mIsSRGBSwapChainSupported;
|
||||
bool const mIsMSAASwapChainSupported;
|
||||
backend::StereoscopicType const mStereoscopicType;
|
||||
#if defined(__ANDROID__)
|
||||
AndroidProducerThrottling mProducerThrottling;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <backend/platforms/VulkanPlatformAndroid.h>
|
||||
|
||||
#include "vulkan/VulkanConstants.h"
|
||||
@@ -21,8 +20,6 @@
|
||||
#include "vulkan/platform/VulkanPlatformSwapChainImpl.h"
|
||||
#include "vulkan/utils/Image.h"
|
||||
|
||||
#include "AndroidFrameCallback.h"
|
||||
|
||||
#include <private/backend/BackendUtilsAndroid.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
@@ -35,7 +32,6 @@
|
||||
#include <android/hardware_buffer.h>
|
||||
#include <android/native_window.h>
|
||||
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
using namespace bluevk;
|
||||
@@ -204,14 +200,6 @@ uint32_t selectMemoryTypeForExternalImage(VkPhysicalDevice physicalDevice, VkDev
|
||||
|
||||
} // namespace
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
struct VulkanPlatformAndroid::AndroidDetails {
|
||||
AndroidFrameCallback androidFrameCallback;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
VulkanPlatformAndroid::ExternalImageVulkanAndroid::~ExternalImageVulkanAndroid() {
|
||||
if (__builtin_available(android 26, *)) {
|
||||
if (aHardwareBuffer) {
|
||||
@@ -220,19 +208,14 @@ VulkanPlatformAndroid::ExternalImageVulkanAndroid::~ExternalImageVulkanAndroid()
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
VulkanPlatformAndroid::VulkanPlatformAndroid() :
|
||||
mAndroidDetails(*(new(std::nothrow) AndroidDetails{})) {
|
||||
VulkanPlatformAndroid::VulkanPlatformAndroid() {
|
||||
mOSVersion = android_get_device_api_level();
|
||||
if (mOSVersion < 0) {
|
||||
mOSVersion = __ANDROID_API_FUTURE__;
|
||||
}
|
||||
}
|
||||
|
||||
VulkanPlatformAndroid::~VulkanPlatformAndroid() noexcept {
|
||||
delete &mAndroidDetails;
|
||||
}
|
||||
VulkanPlatformAndroid::~VulkanPlatformAndroid() noexcept = default;
|
||||
|
||||
Platform::ExternalImageHandle VulkanPlatformAndroid::createExternalImage(
|
||||
AHardwareBuffer const* buffer, bool sRGB) noexcept {
|
||||
@@ -514,14 +497,14 @@ int VulkanPlatformAndroid::getOSVersion() const noexcept {
|
||||
}
|
||||
|
||||
void VulkanPlatformAndroid::terminate() {
|
||||
mAndroidDetails.androidFrameCallback.terminate();
|
||||
mAndroidFrameCallback.terminate();
|
||||
VulkanPlatform::terminate();
|
||||
}
|
||||
|
||||
Driver* VulkanPlatformAndroid::createDriver(void* sharedContext, DriverConfig const& driverConfig) {
|
||||
Driver* driver = VulkanPlatform::createDriver(sharedContext, driverConfig);
|
||||
if (driver) {
|
||||
mAndroidDetails.androidFrameCallback.init();
|
||||
mAndroidFrameCallback.init();
|
||||
}
|
||||
return driver;
|
||||
}
|
||||
@@ -537,7 +520,7 @@ bool VulkanPlatformAndroid::queryCompositorTiming(SwapChain const* swapchain,
|
||||
}
|
||||
|
||||
AndroidFrameCallback::Timeline const preferredTimeline{
|
||||
mAndroidDetails.androidFrameCallback.getPreferredTimeline() };
|
||||
mAndroidFrameCallback.getPreferredTimeline() };
|
||||
outCompositorTiming->frameTime = preferredTimeline.frameTime;
|
||||
outCompositorTiming->expectedPresentTime = preferredTimeline.expectedPresentTime;
|
||||
outCompositorTiming->frameTimelineDeadline = preferredTimeline.frameTimelineDeadline;
|
||||
|
||||
@@ -165,11 +165,6 @@ VulkanPlatformSurfaceSwapChain::~VulkanPlatformSurfaceSwapChain() {
|
||||
VkResult VulkanPlatformSurfaceSwapChain::create() {
|
||||
#ifdef __ANDROID__
|
||||
NativeWindow::enableFrameTimestamps(static_cast<ANativeWindow*>(mNativeWindow), true);
|
||||
// on Android, disable producer throttling
|
||||
if (mProducerThrottling.isSupported()) {
|
||||
mProducerThrottling.setProducerThrottlingEnabled(
|
||||
static_cast<ANativeWindow*>(mNativeWindow), false);
|
||||
}
|
||||
#endif
|
||||
|
||||
VkSurfaceFormatKHR surfaceFormat = {};
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "AndroidSwapChainHelper.h"
|
||||
#include "AndroidNativeWindow.h"
|
||||
#include <AndroidSwapChainHelper.h>
|
||||
#endif
|
||||
|
||||
#include <unordered_map>
|
||||
@@ -123,7 +122,6 @@ private:
|
||||
|
||||
#ifdef __ANDROID__
|
||||
AndroidSwapChainHelper mImpl{};
|
||||
AndroidProducerThrottling mProducerThrottling;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
#include "WebGPUConstants.h"
|
||||
#include "WebGPUQueueManager.h"
|
||||
#include "WebGPUStagePool.h"
|
||||
|
||||
#include "DriverBase.h"
|
||||
#include <backend/BufferDescriptor.h>
|
||||
@@ -30,7 +29,6 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -65,9 +63,9 @@ WebGPUBufferBase::WebGPUBufferBase(wgpu::Device const& device, const wgpu::Buffe
|
||||
// WebGPU requires that the size of the data copied from the staging buffer to the GPU buffer is a
|
||||
// multiple of 4. This function handles cases where the buffer descriptor's size is not a multiple
|
||||
// of 4 by padding with zeros.
|
||||
void WebGPUBufferBase::updateGPUBuffer(BufferDescriptor const& bufferDescriptor,
|
||||
void WebGPUBufferBase::updateGPUBuffer(BufferDescriptor&& bufferDescriptor,
|
||||
const uint32_t byteOffset, wgpu::Device const& device,
|
||||
WebGPUQueueManager* const webGPUQueueManager, WebGPUStagePool* const webGPUStagePool) {
|
||||
WebGPUQueueManager* const webGPUQueueManager) {
|
||||
FILAMENT_CHECK_PRECONDITION(bufferDescriptor.buffer)
|
||||
<< "updateGPUBuffer called with a null buffer";
|
||||
FILAMENT_CHECK_PRECONDITION(bufferDescriptor.size + byteOffset <= mBuffer.GetSize())
|
||||
@@ -81,67 +79,56 @@ void WebGPUBufferBase::updateGPUBuffer(BufferDescriptor const& bufferDescriptor,
|
||||
// This may have some performance implications. That should be investigated later.
|
||||
assert_invariant(mBuffer.GetUsage() & wgpu::BufferUsage::CopyDst);
|
||||
|
||||
// // Calculate some alignment related sizes
|
||||
// Calculate some alignment related sizes
|
||||
const size_t remainder = bufferDescriptor.size % FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS;
|
||||
const size_t mainBulk = bufferDescriptor.size - remainder;
|
||||
const size_t stagingBufferSize =
|
||||
remainder == 0 ? bufferDescriptor.size : mainBulk + FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS;
|
||||
//
|
||||
// // create a staging buffer
|
||||
// wgpu::BufferDescriptor descriptor{
|
||||
// .label = "Filament WebGPU Staging Buffer",
|
||||
// .usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc,
|
||||
// .size = stagingBufferSize,
|
||||
// .mappedAtCreation = true };
|
||||
// wgpu::Buffer stagingBuffer = device.CreateBuffer(&descriptor);
|
||||
MappedStage mappedStage = webGPUStagePool->acquireBuffer(stagingBufferSize);
|
||||
|
||||
std::string mappedRangeIsNull = mappedStage.mappedRange
|
||||
? "no"
|
||||
: "yes";
|
||||
std::cout << "Run Yu: got mapped range on the staging buffer with size "
|
||||
<< mappedStage.buffer.GetSize() << " and it is null? " << mappedRangeIsNull << std::endl;
|
||||
memcpy(mappedStage.mappedRange, bufferDescriptor.buffer, bufferDescriptor.size);
|
||||
|
||||
// Make sure the padded memory is set to 0 to have deterministic behaviors
|
||||
// if (remainder != 0) {
|
||||
// uint8_t* paddingStart = static_cast<uint8_t*>(mappedRange) + bufferDescriptor.size;
|
||||
// memset(paddingStart, 0, FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS - remainder);
|
||||
// }
|
||||
// size_t stagingBufferSize = stagingBuffer.GetSize();
|
||||
// if (stagingBufferSize != bufferDescriptor.size) {
|
||||
// assert(stagingBufferSize > bufferDescriptor.size);
|
||||
// assert(stagingBufferSize % FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS == 0);
|
||||
// uint8_t* paddingStart = static_cast<uint8_t*>(mappedRange) + bufferDescriptor.size;
|
||||
// memset(paddingStart, 0, FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS - (stagingBuffer.GetSize() - bufferDescriptor.size));
|
||||
// }
|
||||
|
||||
mappedStage.buffer.Unmap();
|
||||
|
||||
std::cout << "Run Yu: about to issue copy command with actual staging buffer of size "
|
||||
<< mappedStage.buffer.GetSize() << ", and computed size of " << stagingBufferSize
|
||||
<< ". The mBuffer size is " << mBuffer.GetSize() << std::endl;
|
||||
// Copy the staging buffer contents to the destination buffer.
|
||||
webGPUQueueManager->getCommandEncoder().CopyBufferToBuffer(mappedStage.buffer, 0, mBuffer,
|
||||
byteOffset,
|
||||
remainder == 0 ? bufferDescriptor.size
|
||||
: mainBulk + FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS);
|
||||
webGPUQueueManager->flush();
|
||||
// create a staging buffer
|
||||
wgpu::BufferDescriptor descriptor{
|
||||
.label = "Filament WebGPU Staging Buffer",
|
||||
.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc,
|
||||
.size = stagingBufferSize};
|
||||
wgpu::Buffer stagingBuffer = device.CreateBuffer(&descriptor);
|
||||
|
||||
struct UserData final {
|
||||
uint32_t byteOffset;
|
||||
size_t stagingBufferSize;
|
||||
size_t remainder;
|
||||
BufferDescriptor srcBufferDescriptor;
|
||||
wgpu::Buffer stagingBuffer;
|
||||
WebGPUStagePool* webGPUStagePool;
|
||||
WebGPUQueueManager* const webGPUQueueManager;
|
||||
wgpu::Buffer dstBuffer;
|
||||
};
|
||||
auto userData = std::make_unique<UserData>(
|
||||
UserData{ .stagingBuffer = mappedStage.buffer, .webGPUStagePool = webGPUStagePool });
|
||||
mappedStage.buffer.MapAsync(
|
||||
wgpu::MapMode::Write, 0, stagingBufferSize, wgpu::CallbackMode::AllowSpontaneous,
|
||||
[](wgpu::MapAsyncStatus status, const char* message, UserData* userData) {
|
||||
auto userData = std::make_unique<UserData>(UserData{
|
||||
.byteOffset = byteOffset,
|
||||
.stagingBufferSize = stagingBufferSize,
|
||||
.remainder = remainder,
|
||||
.srcBufferDescriptor = std::move(bufferDescriptor),
|
||||
.stagingBuffer = stagingBuffer,
|
||||
.webGPUQueueManager = webGPUQueueManager,
|
||||
.dstBuffer = mBuffer});
|
||||
stagingBuffer.MapAsync(
|
||||
wgpu::MapMode::Write, 0, stagingBufferSize, wgpu::CallbackMode::AllowProcessEvents,
|
||||
[](wgpu::MapAsyncStatus status, const char* message, UserData* userdata) {
|
||||
std::unique_ptr<UserData> data(static_cast<UserData*>(userdata));
|
||||
if (UTILS_LIKELY(status == wgpu::MapAsyncStatus::Success)) {
|
||||
std::unique_ptr<UserData> data(static_cast<UserData*>(userData));
|
||||
userData->webGPUStagePool->addBufferToPool(userData->stagingBuffer);
|
||||
void* mappedRange = data->stagingBuffer.GetMappedRange();
|
||||
memcpy(mappedRange, data->srcBufferDescriptor.buffer,
|
||||
data->srcBufferDescriptor.size);
|
||||
if (data->remainder != 0) {
|
||||
uint8_t* paddingStart =
|
||||
static_cast<uint8_t*>(mappedRange) + data->srcBufferDescriptor.size;
|
||||
memset(paddingStart, 0,
|
||||
FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS - data->remainder);
|
||||
}
|
||||
data->stagingBuffer.Unmap();
|
||||
data->webGPUQueueManager->getCommandEncoder().CopyBufferToBuffer(
|
||||
data->stagingBuffer, 0, data->dstBuffer, data->byteOffset,
|
||||
data->stagingBufferSize);
|
||||
} else {
|
||||
std::cout << "Run Yu: MAPPING UNSUCCESSFUL!!\n";
|
||||
FWGPU_LOGE << "Failed to map staging buffer for readPixels: " << message;
|
||||
}
|
||||
},
|
||||
userData.release());
|
||||
|
||||
@@ -25,7 +25,6 @@ namespace filament::backend {
|
||||
|
||||
class BufferDescriptor;
|
||||
class WebGPUQueueManager;
|
||||
class WebGPUStagePool;
|
||||
|
||||
/**
|
||||
* A base class for WebGPU buffer objects, providing common functionality for creating and
|
||||
@@ -40,8 +39,8 @@ public:
|
||||
* happen after draw commands encoded in the encoder. Submitting any commands up to this point
|
||||
* ensures the calls happen in the expected sequence.
|
||||
*/
|
||||
void updateGPUBuffer(BufferDescriptor const&, uint32_t byteOffset, wgpu::Device const& device,
|
||||
WebGPUQueueManager* const webGPUQueueManager, WebGPUStagePool* const webGPUStagePool);
|
||||
void updateGPUBuffer(BufferDescriptor&&, uint32_t byteOffset, wgpu::Device const& device,
|
||||
WebGPUQueueManager* const webGPUQueueManager);
|
||||
|
||||
[[nodiscard]] wgpu::Buffer const& getBuffer() const { return mBuffer; }
|
||||
|
||||
|
||||
@@ -107,7 +107,6 @@ WebGPUDriver::WebGPUDriver(WebGPUPlatform& platform,
|
||||
mAdapter{ mPlatform.requestAdapter(nullptr) },
|
||||
mDevice{ mPlatform.requestDevice(mAdapter) },
|
||||
mQueueManager{ mDevice },
|
||||
mStagePool{ mDevice },
|
||||
mPipelineLayoutCache{ mDevice },
|
||||
mPipelineCache{ mDevice },
|
||||
mRenderPassMipmapGenerator{ mDevice, &mQueueManager },
|
||||
@@ -857,7 +856,7 @@ void WebGPUDriver::updateIndexBuffer(Handle<HwIndexBuffer> indexBufferHandle,
|
||||
// draw calls are made.
|
||||
flush();
|
||||
handleCast<WebGPUIndexBuffer>(indexBufferHandle)
|
||||
->updateGPUBuffer(bufferDescriptor, byteOffset, mDevice, &mQueueManager, &mStagePool);
|
||||
->updateGPUBuffer(std::move(bufferDescriptor), byteOffset, mDevice, &mQueueManager);
|
||||
scheduleDestroy(std::move(bufferDescriptor));
|
||||
}
|
||||
|
||||
@@ -868,14 +867,14 @@ void WebGPUDriver::updateBufferObject(Handle<HwBufferObject> bufferObjectHandle,
|
||||
// draw calls are made.
|
||||
flush();
|
||||
handleCast<WebGPUBufferObject>(bufferObjectHandle)
|
||||
->updateGPUBuffer(bufferDescriptor, byteOffset, mDevice, &mQueueManager, &mStagePool);
|
||||
->updateGPUBuffer(std::move(bufferDescriptor), byteOffset, mDevice, &mQueueManager);
|
||||
scheduleDestroy(std::move(bufferDescriptor));
|
||||
}
|
||||
|
||||
void WebGPUDriver::updateBufferObjectUnsynchronized(Handle<HwBufferObject> bufferObjectHandle,
|
||||
BufferDescriptor&& bufferDescriptor, const uint32_t byteOffset) {
|
||||
handleCast<WebGPUBufferObject>(bufferObjectHandle)
|
||||
->updateGPUBuffer(bufferDescriptor, byteOffset, mDevice, &mQueueManager, &mStagePool);
|
||||
->updateGPUBuffer(std::move(bufferDescriptor), byteOffset, mDevice, &mQueueManager);
|
||||
scheduleDestroy(std::move(bufferDescriptor));
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "webgpu/WebGPUPipelineLayoutCache.h"
|
||||
#include "webgpu/WebGPURenderPassMipmapGenerator.h"
|
||||
#include "webgpu/WebGPUQueueManager.h"
|
||||
#include "webgpu/WebGPUStagePool.h"
|
||||
#include "webgpu/utils/AsyncTaskCounter.h"
|
||||
#include <backend/platforms/WebGPUPlatform.h>
|
||||
|
||||
@@ -82,7 +81,6 @@ private:
|
||||
wgpu::Device mDevice = nullptr;
|
||||
wgpu::Limits mDeviceLimits = {};
|
||||
WebGPUQueueManager mQueueManager;
|
||||
WebGPUStagePool mStagePool;
|
||||
void* mNativeWindow = nullptr;
|
||||
WebGPUSwapChain* mSwapChain = nullptr;
|
||||
uint64_t mNextFakeHandle = 1;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -58,6 +59,7 @@ WebGPUQueueManager::WebGPUQueueManager(wgpu::Device const& device)
|
||||
WebGPUQueueManager::~WebGPUQueueManager() = default;
|
||||
|
||||
wgpu::CommandEncoder WebGPUQueueManager::getCommandEncoder() {
|
||||
// std::unique_lock<std::mutex> lock(mLock);
|
||||
if (!mCommandEncoder) {
|
||||
wgpu::CommandEncoderDescriptor commandEncoderDescriptor = {
|
||||
.label = "Filament Command Encoder",
|
||||
@@ -90,7 +92,9 @@ std::shared_ptr<WebGPUSubmissionState> WebGPUQueueManager::getLatestSubmissionSt
|
||||
}
|
||||
|
||||
void WebGPUQueueManager::submit() {
|
||||
// std::unique_lock<std::mutex> lock(mLock);
|
||||
if (!mCommandEncoder) {
|
||||
std::cout << "Run Yu: no mCommandEncoder found!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ private:
|
||||
wgpu::Queue mQueue;
|
||||
wgpu::CommandEncoder mCommandEncoder;
|
||||
std::shared_ptr<WebGPUSubmissionState> mLatestSubmissionState;
|
||||
std::mutex mLock;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.
|
||||
*/
|
||||
|
||||
#include "WebGPUStagePool.h"
|
||||
|
||||
#include "WebGPUConstants.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
WebGPUStagePool::WebGPUStagePool(wgpu::Device const& device) : mDevice(device) {}
|
||||
|
||||
WebGPUStagePool::~WebGPUStagePool() = default;
|
||||
|
||||
MappedStage WebGPUStagePool::acquireBuffer(size_t requiredSize) {
|
||||
std::cout << "Run Yu: required size in acquireBuffer: " << requiredSize << std::endl;
|
||||
std::cout << "Run Yu: the pool size is " << mBuffers.size() << std::endl;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
auto iter = mBuffers.lower_bound(requiredSize);
|
||||
if (iter != mBuffers.end()) {
|
||||
std::cout << "Run Yu: found buffer in the pool with size " << iter->second.GetSize()
|
||||
<< std::endl;
|
||||
if (iter->second.GetMapState() != wgpu::BufferMapState::Mapped) {
|
||||
std::cout << "Run Yu: before GetMappedRange the buffer state is not mapped!\n";
|
||||
}
|
||||
MappedStage mappedStage = { .buffer = iter->second,
|
||||
.mappedRange = iter->second.GetMappedRange() };
|
||||
if (!mappedStage.mappedRange) {
|
||||
std::cout << "Run Yu: mapped range is null in acquireBuffer!\n";
|
||||
}
|
||||
if (mappedStage.buffer.GetMapState() != wgpu::BufferMapState::Mapped) {
|
||||
std::cout << "Run Yu: after GetMappedRange the buffer state is not mapped!\n";
|
||||
}
|
||||
mBuffers.erase(iter);
|
||||
return mappedStage;
|
||||
}
|
||||
}
|
||||
wgpu::Buffer newBuffer = createNewBuffer(requiredSize);
|
||||
return { .buffer = newBuffer, .mappedRange = newBuffer.GetMappedRange() };
|
||||
}
|
||||
|
||||
void WebGPUStagePool::addBufferToPool(wgpu::Buffer buffer) {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
std::cout << "Run Yu: adding buffer to the pool with size " << buffer.GetSize() << std::endl;
|
||||
mBuffers.insert({buffer.GetSize(), buffer});
|
||||
std::cout << "Run Yu: added buffer to the pool with size " << buffer.GetSize() << std::endl;
|
||||
|
||||
bool allMapped = true;
|
||||
for (const auto& pair : mBuffers) {
|
||||
auto state = pair.second.GetMapState();
|
||||
if (state != wgpu::BufferMapState::Mapped) {
|
||||
allMapped = false;
|
||||
std::cout << "Run Yu: the buffer with size " << pair.second.GetSize()
|
||||
<< " is not mapped but somehow was added to the pool, its state is "
|
||||
<< static_cast<int>(state) << std::endl;
|
||||
}
|
||||
}
|
||||
if (!allMapped) {
|
||||
std::cout << "Run Yu: found buffers that are not mapped\n";
|
||||
}
|
||||
}
|
||||
|
||||
wgpu::Buffer WebGPUStagePool::createNewBuffer(size_t bufferSize) {
|
||||
std::cout << "Run Yu: creating new buffer with size " << bufferSize << std::endl;
|
||||
wgpu::BufferDescriptor descriptor{
|
||||
.label = "Filament WebGPU Staging Buffer",
|
||||
.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc,
|
||||
.size = bufferSize,
|
||||
.mappedAtCreation = true };
|
||||
return mDevice.CreateBuffer(&descriptor);
|
||||
}
|
||||
|
||||
} // namespace filament::backend
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_WEBGPUSTAGEPOOL_H
|
||||
#define TNT_FILAMENT_BACKEND_WEBGPUSTAGEPOOL_H
|
||||
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
struct MappedStage {
|
||||
wgpu::Buffer buffer;
|
||||
void* mappedRange;
|
||||
};
|
||||
|
||||
class WebGPUStagePool {
|
||||
public:
|
||||
WebGPUStagePool(wgpu::Device const& device);
|
||||
~WebGPUStagePool();
|
||||
|
||||
MappedStage acquireBuffer(size_t requiredSize);
|
||||
void addBufferToPool(wgpu::Buffer buffer);
|
||||
private:
|
||||
wgpu::Buffer createNewBuffer(size_t bufferSize);
|
||||
std::multimap<uint32_t, wgpu::Buffer> mBuffers;
|
||||
mutable std::mutex mMutex;
|
||||
|
||||
wgpu::Device mDevice;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_WEBGPUSTAGEPOOL_H
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#include "details/BufferAllocator.h"
|
||||
|
||||
#include <private/utils/Tracing.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
@@ -170,7 +169,6 @@ void BufferAllocator::releaseGpu(AllocationId id) {
|
||||
}
|
||||
|
||||
void BufferAllocator::releaseFreeSlots() {
|
||||
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
||||
if (!mHasPendingFrees) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -718,7 +718,8 @@ void FEngine::prepare() {
|
||||
|
||||
if (useUboBatching) {
|
||||
assert_invariant(mUboManager != nullptr);
|
||||
mUboManager->beginFrame(driver);
|
||||
|
||||
mUboManager->beginFrame(driver, mMaterialInstances);
|
||||
}
|
||||
|
||||
UboManager* uboManager = mUboManager;
|
||||
@@ -757,7 +758,7 @@ void FEngine::gc() {
|
||||
void FEngine::submitFrame() {
|
||||
if (isUboBatchingEnabled()) {
|
||||
DriverApi& driver = getDriverApi();
|
||||
getUboManager()->endFrame(driver);
|
||||
getUboManager()->endFrame(driver, getMaterialInstanceResourceList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1284,6 +1285,11 @@ UTILS_NOINLINE
|
||||
bool FEngine::destroy(const FMaterialInstance* p) {
|
||||
if (p == nullptr) return true;
|
||||
|
||||
if (p->isUsingUboBatching()) {
|
||||
assert_invariant(isUboBatchingEnabled());
|
||||
mUboManager->retireSlot(p->getAllocationId());
|
||||
}
|
||||
|
||||
// Check that the material instance we're destroying is not in use in the RenderableManager
|
||||
// To do this, we currently need to inspect all render primitives in the RenderableManager
|
||||
EntityManager const& em = mEntityManager;
|
||||
|
||||
@@ -95,7 +95,6 @@ FMaterialInstance::FMaterialInstance(FEngine& engine, FMaterial const* material,
|
||||
|
||||
if (mUseUboBatching) {
|
||||
mUboData = BufferAllocator::UNALLOCATED;
|
||||
engine.getUboManager()->manageMaterialInstance(this);
|
||||
} else {
|
||||
mUboData = driver.createBufferObject(mUniforms.getSize(), BufferObjectBinding::UNIFORM,
|
||||
BufferUsage::STATIC, ImmutableCString{ material->getName().c_str_safe() });
|
||||
@@ -168,7 +167,6 @@ FMaterialInstance::FMaterialInstance(FEngine& engine,
|
||||
|
||||
if (mUseUboBatching) {
|
||||
mUboData = BufferAllocator::UNALLOCATED;
|
||||
engine.getUboManager()->manageMaterialInstance(this);
|
||||
} else {
|
||||
mUboData = driver.createBufferObject(mUniforms.getSize(), BufferObjectBinding::UNIFORM,
|
||||
BufferUsage::DYNAMIC, ImmutableCString{ material->getName().c_str_safe() });
|
||||
@@ -213,10 +211,6 @@ FMaterialInstance::~FMaterialInstance() noexcept = default;
|
||||
void FMaterialInstance::terminate(FEngine& engine) {
|
||||
FEngine::DriverApi& driver = engine.getDriverApi();
|
||||
mDescriptorSet.terminate(driver);
|
||||
if (mUseUboBatching) {
|
||||
engine.getUboManager()->unmanageMaterialInstance(this);
|
||||
}
|
||||
|
||||
auto* ubHandle = std::get_if<Handle<HwBufferObject>>(&mUboData);
|
||||
if (ubHandle){
|
||||
driver.destroyBufferObject(*ubHandle);
|
||||
|
||||
@@ -48,7 +48,6 @@ void UboManager::FenceManager::track(DriverApi& driver, std::unordered_set<Alloc
|
||||
|
||||
void UboManager::FenceManager::reclaimCompletedResources(DriverApi& driver,
|
||||
std::function<void(AllocationId)> const& onReclaimed) {
|
||||
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
||||
uint32_t signaledCount = 0;
|
||||
bool seenSignaledFence = false;
|
||||
|
||||
@@ -116,7 +115,8 @@ UboManager::UboManager(DriverApi& driver, allocation_size_t defaultSlotSizeInByt
|
||||
reallocate(driver, defaultTotalSizeInBytes);
|
||||
}
|
||||
|
||||
void UboManager::beginFrame(DriverApi& driver) {
|
||||
void UboManager::beginFrame(DriverApi& driver,
|
||||
const std::unordered_map<const FMaterial*, ResourceList<FMaterialInstance>>& materialInstances) {
|
||||
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
||||
// Check finished frames and decrement GPU count accordingly.
|
||||
mFenceManager.reclaimCompletedResources(driver,
|
||||
@@ -126,7 +126,7 @@ void UboManager::beginFrame(DriverApi& driver) {
|
||||
mAllocator.releaseFreeSlots();
|
||||
|
||||
// Traverse all MIs and see which of them need slot allocation.
|
||||
if (allocateOnDemand() == SUCCESS) {
|
||||
if (allocateOnDemand(materialInstances) == SUCCESS) {
|
||||
// No need to grow the buffer, so we can just map the buffer for writing and return.
|
||||
mMemoryMappedBufferHandle = driver.mapBuffer(mUbHandle, 0, mUboSize, MapBufferAccessFlags::WRITE_BIT,
|
||||
"UboManager");
|
||||
@@ -135,19 +135,25 @@ void UboManager::beginFrame(DriverApi& driver) {
|
||||
}
|
||||
|
||||
// Calculate the required size and grow the Ubo.
|
||||
const allocation_size_t requiredSize = calculateRequiredSize();
|
||||
const allocation_size_t requiredSize = calculateRequiredSize(materialInstances);
|
||||
reallocate(driver, requiredSize);
|
||||
|
||||
// Allocate slots for each MI on the new Ubo.
|
||||
allocateAllInstances();
|
||||
allocateAllInstances(materialInstances);
|
||||
|
||||
// Map the buffer so that we can write to it
|
||||
mMemoryMappedBufferHandle =
|
||||
driver.mapBuffer(mUbHandle, 0, mUboSize, MapBufferAccessFlags::WRITE_BIT, "UboManager");
|
||||
|
||||
// Invalidate the migrated MIs, so that next commit() call must be triggered.
|
||||
for (const auto* mi : mManagedInstances) {
|
||||
mi->getUniformBuffer().invalidate();
|
||||
for (const auto& materialInstance : materialInstances) {
|
||||
materialInstance.second.forEach([](const FMaterialInstance* mi) {
|
||||
if (!mi->isUsingUboBatching()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mi->getUniformBuffer().invalidate();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,16 +164,24 @@ void UboManager::finishBeginFrame(DriverApi& driver) {
|
||||
}
|
||||
}
|
||||
|
||||
void UboManager::endFrame(DriverApi& driver) {
|
||||
void UboManager::endFrame(DriverApi& driver,
|
||||
const std::unordered_map<const FMaterial*, ResourceList<FMaterialInstance>>& materialInstances) {
|
||||
BufferAllocator& allocator = mAllocator;
|
||||
std::unordered_set<AllocationId> allocationIds;
|
||||
for (const auto* mi : mManagedInstances) {
|
||||
const AllocationId id = mi->getAllocationId();
|
||||
if (UTILS_UNLIKELY(!BufferAllocator::isValid(id))) {
|
||||
continue;
|
||||
}
|
||||
for (const auto& materialInstance : materialInstances) {
|
||||
materialInstance.second.forEach([&allocator, &allocationIds](const FMaterialInstance* mi) {
|
||||
if (!mi->isUsingUboBatching()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mAllocator.acquireGpu(id);
|
||||
allocationIds.insert(id);
|
||||
const AllocationId id = mi->getAllocationId();
|
||||
if (!BufferAllocator::isValid(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
allocator.acquireGpu(id);
|
||||
allocationIds.insert(id);
|
||||
});
|
||||
}
|
||||
|
||||
mFenceManager.track(driver, std::move(allocationIds));
|
||||
@@ -180,90 +194,76 @@ void UboManager::terminate(DriverApi& driver) {
|
||||
|
||||
void UboManager::updateSlot(DriverApi& driver, AllocationId id,
|
||||
BufferDescriptor bufferDescriptor) const {
|
||||
if (!mMemoryMappedBufferHandle) {
|
||||
if (!mMemoryMappedBufferHandle)
|
||||
return;
|
||||
}
|
||||
|
||||
const allocation_size_t offset = mAllocator.getAllocationOffset(id);
|
||||
driver.copyToMemoryMappedBuffer(mMemoryMappedBufferHandle, offset, std::move(bufferDescriptor));
|
||||
}
|
||||
|
||||
void UboManager::manageMaterialInstance(FMaterialInstance* instance) {
|
||||
mPendingInstances.insert(instance);
|
||||
void UboManager::retireSlot(BufferAllocator::AllocationId id) {
|
||||
if (!BufferAllocator::isValid(id))
|
||||
return;
|
||||
mAllocator.retire(id);
|
||||
}
|
||||
|
||||
void UboManager::unmanageMaterialInstance(FMaterialInstance* materialInstance) {
|
||||
AllocationId id = materialInstance->getAllocationId();
|
||||
mPendingInstances.erase(materialInstance);
|
||||
mManagedInstances.erase(materialInstance);
|
||||
|
||||
if (!BufferAllocator::isValid(id)) {
|
||||
return;
|
||||
UboManager::AllocationResult UboManager::allocateOnDemand(
|
||||
const std::unordered_map<const FMaterial*, ResourceList<FMaterialInstance>>&
|
||||
materialInstances) {
|
||||
// Collect all MIs that need allocation into two groups.
|
||||
std::vector<FMaterialInstance*> newInstances;
|
||||
std::vector<FMaterialInstance*> existingInstances;
|
||||
for (const auto& [_, miList] : materialInstances) {
|
||||
miList.forEach([&](FMaterialInstance* mi) {
|
||||
if (!mi->isUsingUboBatching()) {
|
||||
return;
|
||||
}
|
||||
if (BufferAllocator::isValid(mi->getAllocationId())) {
|
||||
existingInstances.push_back(mi);
|
||||
} else {
|
||||
newInstances.push_back(mi);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
mAllocator.retire(id);
|
||||
materialInstance->assignUboAllocation(mUbHandle, BufferAllocator::UNALLOCATED, 0);
|
||||
}
|
||||
|
||||
UboManager::AllocationResult UboManager::allocateOnDemand() {
|
||||
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
||||
bool reallocationNeeded = false;
|
||||
|
||||
// Pass 1: Allocate slots for new material instances (that don't have a slot yet).
|
||||
for (auto* mi : mPendingInstances) {
|
||||
mManagedInstances.insert(mi);
|
||||
for (FMaterialInstance* mi : newInstances) {
|
||||
auto [newId, newOffset] = mAllocator.allocate(mi->getUniformBuffer().getSize());
|
||||
|
||||
// Even if the newId is not valid, we assign it to the MI so that the following process knows
|
||||
// this material instance was not allocated successfully. Then we can calculate the new
|
||||
// required UBO size properly.
|
||||
mi->assignUboAllocation(mUbHandle, newId, newOffset);
|
||||
|
||||
if (!BufferAllocator::isValid(newId)) {
|
||||
reallocationNeeded = true;
|
||||
}
|
||||
}
|
||||
mPendingInstances.clear();
|
||||
|
||||
// Pass 2: Allocate slots for existing material instances that need to be orphaned.
|
||||
for (auto* mi: mManagedInstances) {
|
||||
if (!BufferAllocator::isValid(mi->getAllocationId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// This instance doesn't need orphaning.
|
||||
if (!mi->getUniformBuffer().isDirty() || !mAllocator.isLockedByGpu(mi->getAllocationId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mAllocator.retire(mi->getAllocationId());
|
||||
|
||||
// If the space is already not sufficient, we don't need to give another try on allocation.
|
||||
if (reallocationNeeded) {
|
||||
mi->assignUboAllocation(mUbHandle, REALLOCATION_REQUIRED, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto [newId, newOffset] = mAllocator.allocate(mi->getUniformBuffer().getSize());
|
||||
|
||||
// Even if the newId is not valid, we assign it to the MI so that the following process knows
|
||||
// this material instance was not allocated successfully. Then we can calculate the new
|
||||
// required UBO size properly.
|
||||
mi->assignUboAllocation(mUbHandle, newId, newOffset);
|
||||
|
||||
if (!BufferAllocator::isValid(newId)) {
|
||||
reallocationNeeded = true;
|
||||
for (FMaterialInstance* mi : existingInstances) {
|
||||
if (mi->getUniformBuffer().isDirty() && mAllocator.isLockedByGpu(mi->getAllocationId())) {
|
||||
mAllocator.retire(mi->getAllocationId());
|
||||
auto [newId, newOffset] = mAllocator.allocate(mi->getUniformBuffer().getSize());
|
||||
mi->assignUboAllocation(mUbHandle, newId, newOffset);
|
||||
if (!BufferAllocator::isValid(newId)) {
|
||||
reallocationNeeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return reallocationNeeded ? REALLOCATION_REQUIRED : SUCCESS;
|
||||
}
|
||||
|
||||
void UboManager::allocateAllInstances() {
|
||||
for (auto* mi: mManagedInstances) {
|
||||
auto [newId, newOffset] = mAllocator.allocate(mi->getUniformBuffer().getSize());
|
||||
assert_invariant(BufferAllocator::isValid(newId));
|
||||
mi->assignUboAllocation(mUbHandle, newId, newOffset);
|
||||
void UboManager::allocateAllInstances(
|
||||
const std::unordered_map<const FMaterial*, ResourceList<FMaterialInstance>>&
|
||||
materialInstances) {
|
||||
for (const auto& [_, miList] : materialInstances) {
|
||||
miList.forEach([this](FMaterialInstance* mi) {
|
||||
if (!mi->isUsingUboBatching()) {
|
||||
return;
|
||||
}
|
||||
auto [newId, newOffset] = mAllocator.allocate(mi->getUniformBuffer().getSize());
|
||||
assert_invariant(BufferAllocator::isValid(newId));
|
||||
mi->assignUboAllocation(mUbHandle, newId, newOffset);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,19 +288,28 @@ void UboManager::reallocate(DriverApi& driver, allocation_size_t requiredSize) {
|
||||
BufferUsage::DYNAMIC | BufferUsage::SHARED_WRITE_BIT);
|
||||
}
|
||||
|
||||
allocation_size_t UboManager::calculateRequiredSize() {
|
||||
allocation_size_t UboManager::calculateRequiredSize(
|
||||
const std::unordered_map<const FMaterial*, ResourceList<FMaterialInstance>>&
|
||||
materialInstances) {
|
||||
BufferAllocator& allocator = mAllocator;
|
||||
allocation_size_t newBufferSize = 0;
|
||||
for (const auto* mi: mManagedInstances) {
|
||||
const AllocationId allocationId = mi->getAllocationId();
|
||||
if (allocationId == BufferAllocator::REALLOCATION_REQUIRED) {
|
||||
// For MIs whose parameters have been updated, aside from the slot it is being
|
||||
// occupied by the GPU, we need to preserve an additional slot for it.
|
||||
newBufferSize += 2 * mAllocator.alignUp(mi->getUniformBuffer().getSize());
|
||||
} else {
|
||||
newBufferSize += mAllocator.alignUp(mi->getUniformBuffer().getSize());
|
||||
}
|
||||
for (const auto& materialInstance: materialInstances) {
|
||||
materialInstance.second.forEach([&newBufferSize, &allocator](const FMaterialInstance* mi) {
|
||||
if (!mi->isUsingUboBatching()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const AllocationId allocationId = mi->getAllocationId();
|
||||
if (allocationId == BufferAllocator::REALLOCATION_REQUIRED) {
|
||||
// For MIs whose parameters have been updated, aside from the slot it is being
|
||||
// occupied by the GPU, we need to preserve an additional slot for it.
|
||||
newBufferSize += 2 * allocator.alignUp(mi->getUniformBuffer().getSize());
|
||||
} else {
|
||||
newBufferSize += allocator.alignUp(mi->getUniformBuffer().getSize());
|
||||
}
|
||||
});
|
||||
}
|
||||
return mAllocator.alignUp(newBufferSize * BUFFER_SIZE_GROWTH_MULTIPLIER);
|
||||
return allocator.alignUp(newBufferSize * BUFFER_SIZE_GROWTH_MULTIPLIER);
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#ifndef TNT_FILAMENT_DETAILS_UBOMANAGER_H
|
||||
#define TNT_FILAMENT_DETAILS_UBOMANAGER_H
|
||||
|
||||
#include "ResourceList.h"
|
||||
#include "backend/DriverApiForward.h"
|
||||
|
||||
#include "details/BufferAllocator.h"
|
||||
@@ -28,8 +29,6 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
class UboManagerTest;
|
||||
|
||||
namespace filament {
|
||||
|
||||
class FMaterial;
|
||||
@@ -97,8 +96,9 @@ public:
|
||||
// instances with modified uniforms).
|
||||
// 3. Reallocating a larger shared UBO if the current one is insufficient.
|
||||
// 4. Mapping the shared UBO into CPU-accessible memory to prepare for uniform data writes.
|
||||
// Note that it must happen before committing all MIs.
|
||||
void beginFrame(backend::DriverApi& driver);
|
||||
void beginFrame(backend::DriverApi& driver,
|
||||
const std::unordered_map<const FMaterial*, ResourceList<FMaterialInstance>>&
|
||||
materialInstances);
|
||||
|
||||
// Unmap the buffer here
|
||||
void finishBeginFrame(backend::DriverApi& driver);
|
||||
@@ -106,31 +106,23 @@ public:
|
||||
// Create a fence and associate it with a set of allocation ids.
|
||||
// The gpuUseCount of these allocations will be incremented, and they will be decremented
|
||||
// After the corresponding frame has been done.
|
||||
void endFrame(backend::DriverApi& driver);
|
||||
void endFrame(backend::DriverApi& driver,
|
||||
const std::unordered_map<const FMaterial*, ResourceList<FMaterialInstance>>&
|
||||
materialInstances);
|
||||
|
||||
void terminate(backend::DriverApi& driver);
|
||||
|
||||
void updateSlot(backend::DriverApi& driver, BufferAllocator::AllocationId id,
|
||||
backend::BufferDescriptor bufferDescriptor) const;
|
||||
|
||||
// Call this to register a new material instance to UboManager.
|
||||
void manageMaterialInstance(FMaterialInstance* instance);
|
||||
|
||||
// Call this when a material instance is destroyed.
|
||||
void unmanageMaterialInstance(FMaterialInstance* materialInstance);
|
||||
// Call this when a material instance is no longer holding a slot. e.g. it is destroyed.
|
||||
void retireSlot(BufferAllocator::AllocationId id);
|
||||
|
||||
// Returns the size of the actual UBO. Note that when there's allocation failed, it will be
|
||||
// reallocated to a bigger size at the next frame.
|
||||
[[nodiscard]] BufferAllocator::allocation_size_t getTotalSize() const noexcept;
|
||||
|
||||
// For testing
|
||||
[[nodiscard]] backend::MemoryMappedBufferHandle getMemoryMappedBufferHandle() const noexcept {
|
||||
return mMemoryMappedBufferHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ::UboManagerTest;
|
||||
|
||||
constexpr static float BUFFER_SIZE_GROWTH_MULTIPLIER = 1.5f;
|
||||
|
||||
enum AllocationResult {
|
||||
@@ -142,19 +134,23 @@ private:
|
||||
[[nodiscard]] BufferAllocator::allocation_size_t getAllocationOffset(
|
||||
BufferAllocator::AllocationId id) const;
|
||||
|
||||
AllocationResult allocateOnDemand();
|
||||
AllocationResult allocateOnDemand(
|
||||
const std::unordered_map<const FMaterial*, ResourceList<FMaterialInstance>>&
|
||||
materialInstances);
|
||||
|
||||
void allocateAllInstances();
|
||||
void allocateAllInstances(
|
||||
const std::unordered_map<const FMaterial*, ResourceList<FMaterialInstance>>&
|
||||
materialInstances);
|
||||
|
||||
void reallocate(backend::DriverApi& driver, BufferAllocator::allocation_size_t requiredSize);
|
||||
|
||||
BufferAllocator::allocation_size_t calculateRequiredSize();
|
||||
BufferAllocator::allocation_size_t calculateRequiredSize(
|
||||
const std::unordered_map<const FMaterial*, ResourceList<FMaterialInstance>>&
|
||||
materialInstances);
|
||||
|
||||
backend::Handle<backend::HwBufferObject> mUbHandle;
|
||||
backend::MemoryMappedBufferHandle mMemoryMappedBufferHandle;
|
||||
BufferAllocator::allocation_size_t mUboSize{};
|
||||
std::unordered_set<FMaterialInstance*> mPendingInstances;
|
||||
std::unordered_set<FMaterialInstance*> mManagedInstances;
|
||||
|
||||
FenceManager mFenceManager;
|
||||
BufferAllocator mAllocator;
|
||||
|
||||
@@ -285,45 +285,53 @@ FVertexBuffer::FVertexBuffer(FEngine& engine, const Builder& builder)
|
||||
|
||||
// calculate buffer sizes
|
||||
size_t bufferSizes[MAX_VERTEX_BUFFER_COUNT] = {};
|
||||
|
||||
auto shouldCreateBuffer = [this](size_t attributeIndex) {
|
||||
const uint8_t slot = mAttributes[attributeIndex].buffer;
|
||||
return mDeclaredAttributes[attributeIndex] && slot != Attribute::BUFFER_UNUSED &&
|
||||
!mBufferObjects[slot];
|
||||
};
|
||||
auto updateBufferSize = [&bufferSizes, this](size_t attributeIndex) {
|
||||
const uint32_t offset = mAttributes[attributeIndex].offset;
|
||||
const uint8_t stride = mAttributes[attributeIndex].stride;
|
||||
const uint8_t slot = mAttributes[attributeIndex].buffer;
|
||||
const size_t end = offset + mVertexCount * stride;
|
||||
assert_invariant(slot < MAX_VERTEX_BUFFER_COUNT);
|
||||
bufferSizes[slot] = std::max(bufferSizes[slot], end);
|
||||
};
|
||||
|
||||
if (!mBufferObjectsEnabled) {
|
||||
#pragma nounroll
|
||||
for (size_t i = 0, n = mAttributes.size(); i < n; ++i) {
|
||||
if (shouldCreateBuffer(i)) {
|
||||
updateBufferSize(i);
|
||||
#pragma nounroll
|
||||
for (size_t i = 0, n = mAttributes.size(); i < n; ++i) {
|
||||
if (mDeclaredAttributes[i]) {
|
||||
const uint32_t offset = mAttributes[i].offset;
|
||||
const uint8_t stride = mAttributes[i].stride;
|
||||
const uint8_t slot = mAttributes[i].buffer;
|
||||
const size_t end = offset + mVertexCount * stride;
|
||||
if (slot != Attribute::BUFFER_UNUSED) {
|
||||
assert_invariant(slot < MAX_VERTEX_BUFFER_COUNT);
|
||||
bufferSizes[slot] = std::max(bufferSizes[slot], end);
|
||||
}
|
||||
}
|
||||
} else if (mAdvancedSkinningEnabled) {
|
||||
// For advanced skinning mode, only relevant buffers (BONE_INDICES & BONE_WEIGHTS) are
|
||||
// created. We manually populated the relevant attributes for those buffers above.
|
||||
updateBufferSize(BONE_INDICES);
|
||||
updateBufferSize(BONE_WEIGHTS);
|
||||
}
|
||||
|
||||
// create buffers
|
||||
for (size_t i = 0; i < MAX_VERTEX_BUFFER_COUNT; ++i) {
|
||||
if (bufferSizes[i] == 0 || mBufferObjects[i]) {
|
||||
continue;
|
||||
if (!mBufferObjectsEnabled) {
|
||||
// If buffer objects are not enabled at the API level, then we create them internally.
|
||||
#pragma nounroll
|
||||
for (size_t index = 0; index < MAX_VERTEX_ATTRIBUTE_COUNT; ++index) {
|
||||
size_t const i = mAttributes[index].buffer;
|
||||
if (i != Attribute::BUFFER_UNUSED) {
|
||||
assert_invariant(bufferSizes[i] > 0);
|
||||
if (!mBufferObjects[i]) {
|
||||
BufferObjectHandle const bo = driver.createBufferObject(bufferSizes[i],
|
||||
BufferObjectBinding::VERTEX, BufferUsage::STATIC,
|
||||
utils::ImmutableCString{ builder.getName() });
|
||||
driver.setVertexBufferObject(mHandle, i, bo);
|
||||
mBufferObjects[i] = bo;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// in advanced skinning mode, we manage the BONE_INDICES and BONE_WEIGHTS arrays ourselves,
|
||||
// so we have to set the corresponding buffer objects.
|
||||
if (mAdvancedSkinningEnabled) {
|
||||
for (auto const index : { BONE_INDICES, BONE_WEIGHTS }) {
|
||||
size_t const i = mAttributes[index].buffer;
|
||||
assert_invariant(i != Attribute::BUFFER_UNUSED);
|
||||
assert_invariant(bufferSizes[i] > 0);
|
||||
if (!mBufferObjects[i]) {
|
||||
BufferObjectHandle const bo = driver.createBufferObject(bufferSizes[i],
|
||||
BufferObjectBinding::VERTEX, BufferUsage::STATIC,
|
||||
utils::ImmutableCString{ builder.getName() });
|
||||
driver.setVertexBufferObject(mHandle, i, bo);
|
||||
mBufferObjects[i] = bo;
|
||||
}
|
||||
}
|
||||
}
|
||||
BufferObjectHandle const bo = driver.createBufferObject(bufferSizes[i],
|
||||
BufferObjectBinding::VERTEX, BufferUsage::STATIC,
|
||||
utils::ImmutableCString{ builder.getName() });
|
||||
driver.setVertexBufferObject(mHandle, i, bo);
|
||||
mBufferObjects[i] = bo;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,17 +50,14 @@ if (TNT_DEV)
|
||||
test_BufferAllocatorStress.cpp
|
||||
test_CircularQueue.cpp
|
||||
test_FenceManager.cpp
|
||||
test_UboManager.cpp
|
||||
filament_test_exposure.cpp
|
||||
filament_rendering_test.cpp
|
||||
filament_bimap_test.cpp
|
||||
filament_framegraph_test.cpp
|
||||
filament_test.cpp
|
||||
${RESGEN_SOURCE})
|
||||
filament_test.cpp)
|
||||
|
||||
target_link_libraries(test_${TARGET} PRIVATE filament gtest)
|
||||
target_compile_options(test_${TARGET} PRIVATE ${COMPILER_FLAGS})
|
||||
target_include_directories(test_${TARGET} PRIVATE ${RESOURCE_DIR})
|
||||
set_target_properties(test_${TARGET} PROPERTIES FOLDER Tests)
|
||||
|
||||
add_executable(test_depth depth_test.cpp)
|
||||
|
||||
@@ -1,366 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.
|
||||
*/
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "MockDriver.h"
|
||||
#include "details/MaterialInstance.h"
|
||||
#include "details/UboManager.h"
|
||||
|
||||
#include <private/backend/CommandBufferQueue.h>
|
||||
#include <private/backend/CommandStream.h>
|
||||
#include <private/backend/Driver.h>
|
||||
|
||||
#include "filament_test_resources.h"
|
||||
|
||||
namespace {
|
||||
using namespace filament;
|
||||
using namespace backend;
|
||||
|
||||
using ::testing::NiceMock;
|
||||
|
||||
using AllocationId = BufferAllocator::AllocationId;
|
||||
using allocation_size_t = BufferAllocator::allocation_size_t;
|
||||
} // anonymous namespace
|
||||
|
||||
class UboManagerTest : public ::testing::Test {
|
||||
protected:
|
||||
static constexpr size_t MIN_COMMAND_BUFFERS_SIZE = 1 * 1024 * 1024;
|
||||
static constexpr size_t COMMAND_BUFFERS_SIZE = 3 * MIN_COMMAND_BUFFERS_SIZE;
|
||||
static constexpr BufferAllocator::allocation_size_t DEFAULT_SLOT_SIZE = 64;
|
||||
static constexpr BufferAllocator::allocation_size_t DEFAULT_TOTAL_SIZE = 1024;
|
||||
|
||||
UboManagerTest()
|
||||
: mCommandBufferQueue(MIN_COMMAND_BUFFERS_SIZE, COMMAND_BUFFERS_SIZE, false),
|
||||
mCommandStream(mMockDriver, mCommandBufferQueue.getCircularBuffer()),
|
||||
|
||||
mDriverApi(mCommandStream),
|
||||
// The constructor will call reallocate, which calls createBufferObject.
|
||||
// MockDriver's default ...S() implementation returns an incrementing handle.
|
||||
// So, the first handle will be 1.
|
||||
mUboManager(mDriverApi, DEFAULT_SLOT_SIZE, DEFAULT_TOTAL_SIZE),
|
||||
mPendingInstances(mUboManager.mPendingInstances),
|
||||
mManagedInstances(mUboManager.mManagedInstances),
|
||||
mUbHandle(mUboManager.mUbHandle),
|
||||
mAllocator(mUboManager.mAllocator) {
|
||||
mEngine = Engine::Builder()
|
||||
.feature("material.enable_material_instance_uniform_batching", true)
|
||||
.backend(Backend::NOOP)
|
||||
.build();
|
||||
|
||||
mMaterial = Material::Builder()
|
||||
.package(FILAMENT_TEST_RESOURCES_TEST_MATERIAL_DATA,
|
||||
FILAMENT_TEST_RESOURCES_TEST_MATERIAL_SIZE)
|
||||
.build(*mEngine);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
mEngine->destroy(mMaterial);
|
||||
Engine::destroy(&mEngine);
|
||||
}
|
||||
|
||||
// The engine is only for creating materials/material instances, we're not using the UboManager
|
||||
// inside for testing.
|
||||
Engine* mEngine = nullptr;
|
||||
NiceMock<MockDriver> mMockDriver;
|
||||
CommandBufferQueue mCommandBufferQueue;
|
||||
CommandStream mCommandStream;
|
||||
DriverApi& mDriverApi;
|
||||
UboManager mUboManager;
|
||||
Material const* mMaterial;
|
||||
std::unordered_set<FMaterialInstance*>& mPendingInstances;
|
||||
std::unordered_set<FMaterialInstance*>& mManagedInstances;
|
||||
Handle<HwBufferObject>& mUbHandle;
|
||||
BufferAllocator& mAllocator;
|
||||
};
|
||||
|
||||
TEST_F(UboManagerTest, InitialState) {
|
||||
EXPECT_EQ(mUboManager.getTotalSize(), DEFAULT_TOTAL_SIZE);
|
||||
EXPECT_EQ(mMockDriver.nextFakeHandle, 2);
|
||||
EXPECT_NE(mUbHandle.getId(), HandleBase::nullid);
|
||||
}
|
||||
|
||||
TEST_F(UboManagerTest, BeginFrameWithoutReallocate) {
|
||||
BufferAllocator::allocation_size_t originalBufferSize = mUboManager.getTotalSize();
|
||||
auto mi1 = static_cast<FMaterialInstance*>(mMaterial->createInstance());
|
||||
EXPECT_EQ(mi1->getAllocationId(), BufferAllocator::UNALLOCATED);
|
||||
ASSERT_TRUE(mi1->isUsingUboBatching());
|
||||
|
||||
// The mi1 should be put in the pending list.
|
||||
mUboManager.manageMaterialInstance(mi1);
|
||||
EXPECT_TRUE(mPendingInstances.contains(mi1));
|
||||
EXPECT_FALSE(mManagedInstances.contains(mi1));
|
||||
|
||||
mUboManager.beginFrame(mDriverApi);
|
||||
|
||||
// The mi1 should be moved to managed list after beginFrame.
|
||||
EXPECT_FALSE(mPendingInstances.contains(mi1));
|
||||
EXPECT_TRUE(mManagedInstances.contains(mi1));
|
||||
// Should have allocation after beginFrame.
|
||||
EXPECT_TRUE(BufferAllocator::isValid(mi1->getAllocationId()));
|
||||
|
||||
// Reallocation is not triggered under this case.
|
||||
EXPECT_EQ(mUboManager.getTotalSize(), originalBufferSize);
|
||||
EXPECT_NE(mUboManager.getMemoryMappedBufferHandle().getId(), HandleBase::nullid);
|
||||
|
||||
mUboManager.finishBeginFrame(mDriverApi);
|
||||
EXPECT_EQ(mUboManager.getMemoryMappedBufferHandle().getId(), HandleBase::nullid);
|
||||
|
||||
mUboManager.endFrame(mDriverApi);
|
||||
EXPECT_TRUE(mAllocator.isLockedByGpu(mi1->getAllocationId()));
|
||||
|
||||
// We're not using the UboManager inside mEngine, so we need to unmanage the material instance
|
||||
// by ourselves.
|
||||
mUboManager.unmanageMaterialInstance(mi1);
|
||||
EXPECT_FALSE(mPendingInstances.contains(mi1));
|
||||
EXPECT_FALSE(mManagedInstances.contains(mi1));
|
||||
|
||||
mUboManager.terminate(mDriverApi);
|
||||
mEngine->destroy(mi1);
|
||||
}
|
||||
|
||||
TEST_F(UboManagerTest, BeginFrameWithReallocate) {
|
||||
const allocation_size_t originalBufferSize = mUboManager.getTotalSize();
|
||||
const Handle<HwBufferObject> originalBufferHandle = mUbHandle;
|
||||
|
||||
// Create enough material instances to trigger a reallocation.
|
||||
constexpr size_t numInstances = (DEFAULT_TOTAL_SIZE / DEFAULT_SLOT_SIZE) + 1;
|
||||
std::vector<FMaterialInstance*> instances;
|
||||
instances.reserve(numInstances);
|
||||
|
||||
for (size_t i = 0; i < numInstances; ++i) {
|
||||
auto mi = static_cast<FMaterialInstance*>(mMaterial->createInstance());
|
||||
instances.push_back(mi);
|
||||
mUboManager.manageMaterialInstance(mi);
|
||||
}
|
||||
|
||||
// Before beginFrame, all instances should be pending.
|
||||
EXPECT_EQ(mPendingInstances.size(), numInstances);
|
||||
EXPECT_TRUE(mManagedInstances.empty());
|
||||
|
||||
mUboManager.beginFrame(mDriverApi);
|
||||
|
||||
// After beginFrame, reallocation should have occurred.
|
||||
EXPECT_NE(mUbHandle.getId(), originalBufferHandle.getId());
|
||||
EXPECT_GT(mUboManager.getTotalSize(), originalBufferSize);
|
||||
|
||||
// All instances should now be managed and have valid allocations.
|
||||
EXPECT_TRUE(mPendingInstances.empty());
|
||||
EXPECT_EQ(mManagedInstances.size(), numInstances);
|
||||
for (const auto* mi: instances) {
|
||||
EXPECT_TRUE(mManagedInstances.contains(const_cast<FMaterialInstance*>(mi)));
|
||||
EXPECT_TRUE(BufferAllocator::isValid(mi->getAllocationId()));
|
||||
}
|
||||
|
||||
mUboManager.finishBeginFrame(mDriverApi);
|
||||
mUboManager.terminate(mDriverApi);
|
||||
|
||||
for (auto* mi: instances) {
|
||||
// We're not using the UboManager inside mEngine, so we need to unmanage the material instance
|
||||
// by ourselves.
|
||||
mUboManager.unmanageMaterialInstance(mi);
|
||||
mEngine->destroy(mi);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(UboManagerTest, RecycleSlot) {
|
||||
auto mi1 = static_cast<FMaterialInstance*>(mMaterial->createInstance());
|
||||
mUboManager.manageMaterialInstance(mi1);
|
||||
|
||||
// Frame 1: mi1 gets an allocation.
|
||||
mUboManager.beginFrame(mDriverApi);
|
||||
const AllocationId mi1AllocationId = mi1->getAllocationId();
|
||||
const allocation_size_t mi1AllocationOffset =
|
||||
mAllocator.getAllocationOffset(mi1AllocationId);
|
||||
EXPECT_TRUE(BufferAllocator::isValid(mi1AllocationId));
|
||||
mUboManager.finishBeginFrame(mDriverApi);
|
||||
mUboManager.endFrame(mDriverApi); // Locks mi1's allocation.
|
||||
|
||||
// Now, unmanage mi1. The slot should be retired but not yet released.
|
||||
mUboManager.unmanageMaterialInstance(mi1);
|
||||
EXPECT_TRUE(mAllocator.isLockedByGpu(mi1AllocationId));
|
||||
|
||||
// Frame 2: The slot for mi1 is still locked by the GPU.
|
||||
// We expect getFenceStatus to be called for the fence from frame 1.
|
||||
// We'll mock it to return TIMEOUT_EXPIRED, so the resource is not reclaimed.
|
||||
EXPECT_CALL(mMockDriver, getFenceStatus(_)).WillOnce(Return(FenceStatus::TIMEOUT_EXPIRED));
|
||||
mUboManager.beginFrame(mDriverApi);
|
||||
mUboManager.finishBeginFrame(mDriverApi);
|
||||
mUboManager.endFrame(mDriverApi);
|
||||
|
||||
// Frame 3: Now, we'll simulate that the fence from frame 1 has signaled.
|
||||
// The resource for mi1 should be reclaimed.
|
||||
EXPECT_CALL(mMockDriver, getFenceStatus(_)).WillOnce(Return(FenceStatus::CONDITION_SATISFIED));
|
||||
|
||||
auto mi2 = static_cast<FMaterialInstance*>(mMaterial->createInstance());
|
||||
mUboManager.manageMaterialInstance(mi2);
|
||||
|
||||
mUboManager.beginFrame(mDriverApi);
|
||||
|
||||
// mi2 should now have a valid allocation, and it should reuse the slot from mi1.
|
||||
EXPECT_TRUE(BufferAllocator::isValid(mi2->getAllocationId()));
|
||||
EXPECT_EQ(mAllocator.getAllocationOffset(mi2->getAllocationId()), mi1AllocationOffset);
|
||||
|
||||
mUboManager.finishBeginFrame(mDriverApi);
|
||||
mUboManager.unmanageMaterialInstance(mi2);
|
||||
mUboManager.terminate(mDriverApi);
|
||||
|
||||
mEngine->destroy(mi1);
|
||||
mEngine->destroy(mi2);
|
||||
}
|
||||
|
||||
TEST_F(UboManagerTest, OrphanSlot) {
|
||||
auto mi1 = static_cast<FMaterialInstance*>(mMaterial->createInstance());
|
||||
mUboManager.manageMaterialInstance(mi1);
|
||||
|
||||
// Frame 1: mi1 gets an allocation.
|
||||
mUboManager.beginFrame(mDriverApi);
|
||||
const AllocationId alloc1 = mi1->getAllocationId();
|
||||
EXPECT_TRUE(BufferAllocator::isValid(alloc1));
|
||||
mUboManager.finishBeginFrame(mDriverApi);
|
||||
mUboManager.endFrame(mDriverApi); // Locks alloc1.
|
||||
|
||||
// Frame 2: Mark the instance as dirty and begin a new frame.
|
||||
// This should trigger orphaning.
|
||||
mi1->getUniformBuffer().invalidate();
|
||||
EXPECT_CALL(mMockDriver, getFenceStatus(_)).WillOnce(Return(FenceStatus::TIMEOUT_EXPIRED));
|
||||
mUboManager.beginFrame(mDriverApi);
|
||||
|
||||
const AllocationId alloc2 = mi1->getAllocationId();
|
||||
EXPECT_TRUE(BufferAllocator::isValid(alloc2));
|
||||
EXPECT_NE(alloc1, alloc2); // Should have a new allocation.
|
||||
|
||||
mUboManager.finishBeginFrame(mDriverApi);
|
||||
mUboManager.endFrame(mDriverApi); // Locks alloc2.
|
||||
|
||||
// Frame 3: The fence for alloc1 should now be signaled.
|
||||
EXPECT_CALL(mMockDriver, getFenceStatus(_))
|
||||
.WillOnce(Return(FenceStatus::TIMEOUT_EXPIRED)) // For alloc2's fence
|
||||
.WillOnce(Return(FenceStatus::CONDITION_SATISFIED)); // For alloc1's fence
|
||||
mUboManager.beginFrame(mDriverApi);
|
||||
mUboManager.finishBeginFrame(mDriverApi);
|
||||
mUboManager.unmanageMaterialInstance(mi1);
|
||||
mUboManager.terminate(mDriverApi);
|
||||
|
||||
mEngine->destroy(mi1);
|
||||
}
|
||||
|
||||
TEST_F(UboManagerTest, DoubleManage) {
|
||||
auto mi1 = static_cast<FMaterialInstance*>(mMaterial->createInstance());
|
||||
mUboManager.manageMaterialInstance(mi1);
|
||||
EXPECT_EQ(mPendingInstances.size(), 1);
|
||||
|
||||
// Managing the same instance again should be a no-op.
|
||||
mUboManager.manageMaterialInstance(mi1);
|
||||
EXPECT_EQ(mPendingInstances.size(), 1);
|
||||
|
||||
mUboManager.terminate(mDriverApi);
|
||||
mEngine->destroy(mi1);
|
||||
}
|
||||
|
||||
TEST_F(UboManagerTest, ManageAndUnmanageBeforeBeginFrame) {
|
||||
auto mi1 = static_cast<FMaterialInstance*>(mMaterial->createInstance());
|
||||
mUboManager.manageMaterialInstance(mi1);
|
||||
EXPECT_TRUE(mPendingInstances.contains(mi1));
|
||||
|
||||
mUboManager.unmanageMaterialInstance(mi1);
|
||||
EXPECT_FALSE(mPendingInstances.contains(mi1));
|
||||
|
||||
// After beginFrame, the instance should not be in any list.
|
||||
mUboManager.beginFrame(mDriverApi);
|
||||
EXPECT_FALSE(mPendingInstances.contains(mi1));
|
||||
EXPECT_FALSE(mManagedInstances.contains(mi1));
|
||||
EXPECT_EQ(mi1->getAllocationId(), BufferAllocator::UNALLOCATED);
|
||||
|
||||
mUboManager.terminate(mDriverApi);
|
||||
mEngine->destroy(mi1);
|
||||
}
|
||||
|
||||
TEST_F(UboManagerTest, UnmanageUnmanaged) {
|
||||
auto mi1 = static_cast<FMaterialInstance*>(mMaterial->createInstance());
|
||||
|
||||
// Unmanaging an instance that was never managed should not cause any issues.
|
||||
mUboManager.unmanageMaterialInstance(mi1);
|
||||
EXPECT_FALSE(mPendingInstances.contains(mi1));
|
||||
EXPECT_FALSE(mManagedInstances.contains(mi1));
|
||||
|
||||
mUboManager.terminate(mDriverApi);
|
||||
mEngine->destroy(mi1);
|
||||
}
|
||||
|
||||
TEST_F(UboManagerTest, AllAllocationsLockedAfterEndFrame) {
|
||||
constexpr size_t numInstances = 5;
|
||||
std::vector<FMaterialInstance*> instances;
|
||||
instances.reserve(numInstances);
|
||||
|
||||
for (size_t i = 0; i < numInstances; ++i) {
|
||||
auto mi = static_cast<FMaterialInstance*>(mMaterial->createInstance());
|
||||
instances.push_back(mi);
|
||||
mUboManager.manageMaterialInstance(mi);
|
||||
}
|
||||
|
||||
mUboManager.beginFrame(mDriverApi);
|
||||
mUboManager.finishBeginFrame(mDriverApi);
|
||||
mUboManager.endFrame(mDriverApi);
|
||||
|
||||
for (const auto* mi: instances) {
|
||||
EXPECT_TRUE(mAllocator.isLockedByGpu(mi->getAllocationId()));
|
||||
}
|
||||
|
||||
mUboManager.terminate(mDriverApi);
|
||||
for (auto* mi: instances) {
|
||||
// We're not using the UboManager inside mEngine, so we need to unmanage the material instance
|
||||
// by ourselves.
|
||||
mUboManager.unmanageMaterialInstance(mi);
|
||||
mEngine->destroy(mi);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(UboManagerTest, AllAllocationsLockedAfterEndFrameWithInvalidIdInBetween) {
|
||||
constexpr size_t numInstances = 5;
|
||||
std::vector<FMaterialInstance*> instances;
|
||||
instances.reserve(numInstances);
|
||||
|
||||
for (size_t i = 0; i < numInstances; ++i) {
|
||||
auto mi = static_cast<FMaterialInstance*>(mMaterial->createInstance());
|
||||
instances.push_back(mi);
|
||||
mUboManager.manageMaterialInstance(mi);
|
||||
}
|
||||
|
||||
mUboManager.beginFrame(mDriverApi);
|
||||
mUboManager.finishBeginFrame(mDriverApi);
|
||||
|
||||
// It should rarely happen, but we want to make sure all other instances are locked properly.
|
||||
instances[2]->assignUboAllocation(mUbHandle, BufferAllocator::REALLOCATION_REQUIRED, 0);
|
||||
mUboManager.endFrame(mDriverApi);
|
||||
|
||||
for (const auto* mi: instances) {
|
||||
if (BufferAllocator::isValid(mi->getAllocationId())) {
|
||||
EXPECT_TRUE(mAllocator.isLockedByGpu(mi->getAllocationId()));
|
||||
}
|
||||
}
|
||||
|
||||
mUboManager.terminate(mDriverApi);
|
||||
for (auto* mi: instances) {
|
||||
// We're not using the UboManager inside mEngine, so we need to unmanage the material instance
|
||||
// by ourselves.
|
||||
mUboManager.unmanageMaterialInstance(mi);
|
||||
mEngine->destroy(mi);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add more tests for the beginFrame flow
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.67.1"
|
||||
spec.version = "1.67.0"
|
||||
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.67.1/filament-v1.67.1-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.67.0/filament-v1.67.0-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -302,16 +302,14 @@ vec4 evaluateLights(const MaterialInputs material) {
|
||||
return vec4(color, computeDiffuseAlpha(material.baseColor.a));
|
||||
}
|
||||
|
||||
vec3 emissive(const MaterialInputs material, float alpha) {
|
||||
void addEmissive(const MaterialInputs material, inout vec4 color) {
|
||||
#if defined(MATERIAL_HAS_EMISSIVE)
|
||||
highp vec4 emissive = material.emissive;
|
||||
highp float attenuation = mix(1.0, getExposure(), emissive.w);
|
||||
#if defined(BLEND_MODE_TRANSPARENT) || defined(BLEND_MODE_FADE)
|
||||
attenuation *= alpha;
|
||||
attenuation *= color.a;
|
||||
#endif
|
||||
return emissive.rgb * attenuation;
|
||||
#else
|
||||
return vec3(0.0);
|
||||
color.rgb += emissive.rgb * attenuation;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -323,7 +321,7 @@ vec3 emissive(const MaterialInputs material, float alpha) {
|
||||
*/
|
||||
vec4 evaluateMaterial(const MaterialInputs material) {
|
||||
vec4 color = evaluateLights(material);
|
||||
color.rgb += emissive(material, color.a);
|
||||
addEmissive(material, color);
|
||||
// kill +inf generated by strong highlights
|
||||
color.rgb = min(color.rgb, MEDIUMP_FLT_MAX);
|
||||
return color;
|
||||
|
||||
2
third_party/benchmark/.clang-format
vendored
2
third_party/benchmark/.clang-format
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
PointerAlignment: Left
|
||||
...
|
||||
|
||||
|
||||
37
third_party/benchmark/.clang-tidy
vendored
37
third_party/benchmark/.clang-tidy
vendored
@@ -1,37 +0,0 @@
|
||||
---
|
||||
Checks: >
|
||||
abseil-*,
|
||||
bugprone-*,
|
||||
clang-analyzer-*,
|
||||
cppcoreguidelines-*,
|
||||
google-*,
|
||||
misc-*,
|
||||
performance-*,
|
||||
readability-*,
|
||||
-clang-analyzer-deadcode*,
|
||||
-clang-analyzer-optin*,
|
||||
-readability-identifier-length
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: ''
|
||||
FormatStyle: none
|
||||
CheckOptions:
|
||||
llvm-else-after-return.WarnOnConditionVariables: 'false'
|
||||
modernize-loop-convert.MinConfidence: reasonable
|
||||
modernize-replace-auto-ptr.IncludeStyle: llvm
|
||||
cert-str34-c.DiagnoseSignedUnsignedCharComparisons: 'false'
|
||||
google-readability-namespace-comments.ShortNamespaceLines: '10'
|
||||
cert-err33-c.CheckedFunctions: '::aligned_alloc;::asctime_s;::at_quick_exit;::atexit;::bsearch;::bsearch_s;::btowc;::c16rtomb;::c32rtomb;::calloc;::clock;::cnd_broadcast;::cnd_init;::cnd_signal;::cnd_timedwait;::cnd_wait;::ctime_s;::fclose;::fflush;::fgetc;::fgetpos;::fgets;::fgetwc;::fopen;::fopen_s;::fprintf;::fprintf_s;::fputc;::fputs;::fputwc;::fputws;::fread;::freopen;::freopen_s;::fscanf;::fscanf_s;::fseek;::fsetpos;::ftell;::fwprintf;::fwprintf_s;::fwrite;::fwscanf;::fwscanf_s;::getc;::getchar;::getenv;::getenv_s;::gets_s;::getwc;::getwchar;::gmtime;::gmtime_s;::localtime;::localtime_s;::malloc;::mbrtoc16;::mbrtoc32;::mbsrtowcs;::mbsrtowcs_s;::mbstowcs;::mbstowcs_s;::memchr;::mktime;::mtx_init;::mtx_lock;::mtx_timedlock;::mtx_trylock;::mtx_unlock;::printf_s;::putc;::putwc;::raise;::realloc;::remove;::rename;::scanf;::scanf_s;::setlocale;::setvbuf;::signal;::snprintf;::snprintf_s;::sprintf;::sprintf_s;::sscanf;::sscanf_s;::strchr;::strerror_s;::strftime;::strpbrk;::strrchr;::strstr;::strtod;::strtof;::strtoimax;::strtok;::strtok_s;::strtol;::strtold;::strtoll;::strtoul;::strtoull;::strtoumax;::strxfrm;::swprintf;::swprintf_s;::swscanf;::swscanf_s;::thrd_create;::thrd_detach;::thrd_join;::thrd_sleep;::time;::timespec_get;::tmpfile;::tmpfile_s;::tmpnam;::tmpnam_s;::tss_create;::tss_get;::tss_set;::ungetc;::ungetwc;::vfprintf;::vfprintf_s;::vfscanf;::vfscanf_s;::vfwprintf;::vfwprintf_s;::vfwscanf;::vfwscanf_s;::vprintf_s;::vscanf;::vscanf_s;::vsnprintf;::vsnprintf_s;::vsprintf;::vsprintf_s;::vsscanf;::vsscanf_s;::vswprintf;::vswprintf_s;::vswscanf;::vswscanf_s;::vwprintf_s;::vwscanf;::vwscanf_s;::wcrtomb;::wcschr;::wcsftime;::wcspbrk;::wcsrchr;::wcsrtombs;::wcsrtombs_s;::wcsstr;::wcstod;::wcstof;::wcstoimax;::wcstok;::wcstok_s;::wcstol;::wcstold;::wcstoll;::wcstombs;::wcstombs_s;::wcstoul;::wcstoull;::wcstoumax;::wcsxfrm;::wctob;::wctrans;::wctype;::wmemchr;::wprintf_s;::wscanf;::wscanf_s;'
|
||||
cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField: 'false'
|
||||
cert-dcl16-c.NewSuffixes: 'L;LL;LU;LLU'
|
||||
google-readability-braces-around-statements.ShortStatementLines: '1'
|
||||
cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'true'
|
||||
google-readability-namespace-comments.SpacesBeforeComments: '2'
|
||||
modernize-loop-convert.MaxCopySize: '16'
|
||||
modernize-pass-by-value.IncludeStyle: llvm
|
||||
modernize-use-nullptr.NullMacros: 'NULL'
|
||||
llvm-qualified-auto.AddConstToQualified: 'false'
|
||||
modernize-loop-convert.NamingStyle: CamelCase
|
||||
llvm-else-after-return.WarnOnUnfixable: 'false'
|
||||
google-readability-function-size.StatementThreshold: '800'
|
||||
...
|
||||
|
||||
1
third_party/benchmark/.clang-tidy.ignore
vendored
1
third_party/benchmark/.clang-tidy.ignore
vendored
@@ -1 +0,0 @@
|
||||
.*third_party/.*
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG]"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**System**
|
||||
Which OS, compiler, and compiler version are you using:
|
||||
- OS:
|
||||
- Compiler and version:
|
||||
|
||||
**To reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. sync to commit ...
|
||||
2. cmake/bazel...
|
||||
3. make ...
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[FR]"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
12
third_party/benchmark/.github/install_bazel.sh
vendored
12
third_party/benchmark/.github/install_bazel.sh
vendored
@@ -1,12 +0,0 @@
|
||||
if ! bazel version; then
|
||||
arch=$(uname -m)
|
||||
if [ "$arch" == "aarch64" ]; then
|
||||
arch="arm64"
|
||||
fi
|
||||
echo "Downloading $arch Bazel binary from GitHub releases."
|
||||
curl -L -o $HOME/bin/bazel --create-dirs "https://github.com/bazelbuild/bazel/releases/download/8.2.0/bazel-8.2.0-linux-$arch"
|
||||
chmod +x $HOME/bin/bazel
|
||||
else
|
||||
# Bazel is installed for the correct architecture
|
||||
exit 0
|
||||
fi
|
||||
35
third_party/benchmark/.github/libcxx-setup.sh
vendored
35
third_party/benchmark/.github/libcxx-setup.sh
vendored
@@ -1,35 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
# Checkout LLVM sources
|
||||
git clone --filter=blob:none --depth=1 --branch llvmorg-19.1.6 --no-checkout https://github.com/llvm/llvm-project.git llvm-project
|
||||
cd llvm-project
|
||||
git sparse-checkout set --cone
|
||||
git checkout llvmorg-19.1.6
|
||||
git sparse-checkout set cmake llvm/cmake runtimes libcxx libcxxabi
|
||||
cd ..
|
||||
|
||||
## Setup libc++ options
|
||||
if [ -z "$BUILD_32_BITS" ]; then
|
||||
export BUILD_32_BITS=OFF && echo disabling 32 bit build
|
||||
fi
|
||||
|
||||
## Build and install libc++ (Use unstable ABI for better sanitizer coverage)
|
||||
mkdir llvm-build && cd llvm-build
|
||||
cmake -GNinja \
|
||||
-DCMAKE_C_COMPILER=${CC} \
|
||||
-DCMAKE_CXX_COMPILER=${CXX} \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DLIBCXX_ABI_UNSTABLE=OFF \
|
||||
-DLLVM_USE_SANITIZER=${LIBCXX_SANITIZER} \
|
||||
-DLLVM_BUILD_32_BITS=${BUILD_32_BITS} \
|
||||
-DLIBCXXABI_USE_LLVM_UNWINDER=OFF \
|
||||
-DLLVM_INCLUDE_TESTS=OFF \
|
||||
-DLIBCXX_INCLUDE_TESTS=OFF \
|
||||
-DLIBCXX_INCLUDE_BENCHMARKS=OFF \
|
||||
-DLLVM_ENABLE_RUNTIMES='libcxx;libcxxabi' \
|
||||
../llvm-project/runtimes/
|
||||
cmake --build . -- cxx cxxabi
|
||||
cd ..
|
||||
@@ -1,37 +0,0 @@
|
||||
name: bazel
|
||||
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
build_and_test_default:
|
||||
name: bazel.${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: mount bazel cache
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
cache-name: bazel-cache
|
||||
with:
|
||||
path: "~/.cache/bazel"
|
||||
key: ${{ env.cache-name }}-${{ matrix.os }}-${{ github.ref }}
|
||||
restore-keys: |
|
||||
${{ env.cache-name }}-${{ matrix.os }}-main
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
bazel build //:benchmark //:benchmark_main //test/...
|
||||
|
||||
- name: test
|
||||
run: |
|
||||
bazel test --test_output=all //test/...
|
||||
@@ -1,49 +0,0 @@
|
||||
name: build-and-test-min-cmake
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
job:
|
||||
name: ${{ matrix.os }}.min-cmake
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: 3.13.0
|
||||
|
||||
- name: create build environment
|
||||
run: cmake -E make_directory ${{ runner.workspace }}/_build
|
||||
|
||||
- name: setup cmake initial cache
|
||||
run: touch compiler-cache.cmake
|
||||
|
||||
- name: configure cmake
|
||||
env:
|
||||
CXX: ${{ matrix.compiler }}
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: >
|
||||
cmake -C ${{ github.workspace }}/compiler-cache.cmake
|
||||
$GITHUB_WORKSPACE
|
||||
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
-DCMAKE_CXX_VISIBILITY_PRESET=hidden
|
||||
-DCMAKE_VISIBILITY_INLINES_HIDDEN=ON
|
||||
|
||||
- name: build
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: cmake --build .
|
||||
@@ -1,54 +0,0 @@
|
||||
name: build-and-test-perfcounters
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
job:
|
||||
# TODO(dominic): Extend this to include compiler and set through env: CC/CXX.
|
||||
name: ${{ matrix.os }}.${{ matrix.build_type }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
build_type: ['Release', 'Debug']
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: install libpfm
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt -y install libpfm4-dev
|
||||
|
||||
- name: create build environment
|
||||
run: cmake -E make_directory ${{ runner.workspace }}/_build
|
||||
|
||||
- name: configure cmake
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: >
|
||||
cmake $GITHUB_WORKSPACE
|
||||
-DBENCHMARK_ENABLE_LIBPFM=1
|
||||
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||
|
||||
- name: build
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: cmake --build . --config ${{ matrix.build_type }}
|
||||
|
||||
# Skip testing, for now. It seems perf_event_open does not succeed on the
|
||||
# hosting machine, very likely a permissions issue.
|
||||
# TODO(mtrofin): Enable test.
|
||||
# - name: test
|
||||
# shell: bash
|
||||
# working-directory: ${{ runner.workspace }}/_build
|
||||
# run: ctest -C ${{ matrix.build_type }} --rerun-failed --output-on-failure
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
name: build-and-test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
# TODO: add 32-bit builds (g++ and clang++) for ubuntu
|
||||
# (requires g++-multilib and libc6:i386)
|
||||
# TODO: add coverage build (requires lcov)
|
||||
# TODO: add clang + libc++ builds for ubuntu
|
||||
job:
|
||||
name: ${{ matrix.os }}.${{ matrix.build_type }}.${{ matrix.lib }}.${{ matrix.compiler }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-24.04, ubuntu-22.04, ubuntu-24.04-arm, macos-latest]
|
||||
build_type: ['Release', 'Debug']
|
||||
compiler: ['g++', 'clang++']
|
||||
lib: ['shared', 'static']
|
||||
|
||||
steps:
|
||||
- name: Install dependencies (macos)
|
||||
if: runner.os == 'macOS'
|
||||
run: brew install ninja
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: build
|
||||
uses: threeal/cmake-action@v2.1.0
|
||||
with:
|
||||
build-dir: ${{ runner.workspace }}/_build
|
||||
cxx-compiler: ${{ matrix.compiler }}
|
||||
options: |
|
||||
BENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
BUILD_SHARED_LIBS=${{ matrix.lib == 'shared' }}
|
||||
CMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||
CMAKE_CXX_COMPILER=${{ matrix.compiler }}
|
||||
CMAKE_CXX_VISIBILITY_PRESET=hidden
|
||||
CMAKE_VISIBILITY_INLINES_HIDDEN=ON
|
||||
|
||||
- name: test
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: ctest -C ${{ matrix.build_type }} -VV
|
||||
|
||||
msvc:
|
||||
name: ${{ matrix.os }}.${{ matrix.build_type }}.${{ matrix.lib }}.${{ matrix.msvc }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: powershell
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
msvc:
|
||||
- VS-16-2019
|
||||
- VS-17-2022
|
||||
build_type:
|
||||
- Debug
|
||||
- Release
|
||||
lib:
|
||||
- shared
|
||||
- static
|
||||
include:
|
||||
- msvc: VS-16-2019
|
||||
os: windows-2019
|
||||
generator: 'Visual Studio 16 2019'
|
||||
- msvc: VS-17-2022
|
||||
os: windows-2022
|
||||
generator: 'Visual Studio 17 2022'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: lukka/get-cmake@latest
|
||||
|
||||
- name: configure cmake
|
||||
run: >
|
||||
cmake -S . -B ${{ runner.workspace }}/_build/
|
||||
-G "${{ matrix.generator }}"
|
||||
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.lib == 'shared' }}
|
||||
|
||||
- name: build
|
||||
run: cmake --build ${{ runner.workspace }}/_build/ --config ${{ matrix.build_type }}
|
||||
|
||||
- name: test
|
||||
run: ctest --test-dir ${{ runner.workspace }}/_build/ -C ${{ matrix.build_type }} -VV
|
||||
|
||||
msys2:
|
||||
name: ${{ matrix.os }}.${{ matrix.build_type }}.${{ matrix.lib }}.${{ matrix.msys2.msystem }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ windows-latest ]
|
||||
msys2:
|
||||
- { msystem: MINGW64, arch: x86_64, family: GNU, compiler: g++ }
|
||||
- { msystem: CLANG64, arch: x86_64, family: LLVM, compiler: clang++ }
|
||||
- { msystem: UCRT64, arch: x86_64, family: GNU, compiler: g++ }
|
||||
build_type:
|
||||
- Debug
|
||||
- Release
|
||||
lib:
|
||||
- shared
|
||||
- static
|
||||
|
||||
steps:
|
||||
- name: setup msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
cache: false
|
||||
msystem: ${{ matrix.msys2.msystem }}
|
||||
update: true
|
||||
install: >-
|
||||
git
|
||||
base-devel
|
||||
pacboy: >-
|
||||
gcc:p
|
||||
clang:p
|
||||
cmake:p
|
||||
ninja:p
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# NOTE: we can't use cmake actions here as we need to do everything in msys2 shell.
|
||||
- name: configure cmake
|
||||
env:
|
||||
CXX: ${{ matrix.msys2.compiler }}
|
||||
run: >
|
||||
cmake -S . -B _build/
|
||||
-GNinja
|
||||
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.lib == 'shared' }}
|
||||
|
||||
- name: build
|
||||
run: cmake --build _build/ --config ${{ matrix.build_type }}
|
||||
|
||||
- name: test
|
||||
working-directory: _build
|
||||
run: ctest -C ${{ matrix.build_type }} -VV
|
||||
@@ -1,19 +0,0 @@
|
||||
name: clang-format-lint
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
job:
|
||||
name: check-clang-format
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: DoozyX/clang-format-lint-action@v0.18.2
|
||||
with:
|
||||
source: './include/benchmark ./src ./test'
|
||||
clangFormatVersion: 18
|
||||
@@ -1,41 +0,0 @@
|
||||
name: clang-tidy
|
||||
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
job:
|
||||
name: run-clang-tidy
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: install clang-tidy
|
||||
run: sudo apt update && sudo apt -y install clang-tidy
|
||||
|
||||
- name: create build environment
|
||||
run: cmake -E make_directory ${{ github.workspace }}/_build
|
||||
|
||||
- name: configure cmake
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/_build
|
||||
run: >
|
||||
cmake $GITHUB_WORKSPACE
|
||||
-DBENCHMARK_ENABLE_ASSEMBLY_TESTS=OFF
|
||||
-DBENCHMARK_ENABLE_LIBPFM=OFF
|
||||
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
-DCMAKE_C_COMPILER=clang
|
||||
-DCMAKE_CXX_COMPILER=clang++
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
-DGTEST_COMPILE_COMMANDS=OFF
|
||||
|
||||
- name: run
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/_build
|
||||
run: run-clang-tidy -config-file=$GITHUB_WORKSPACE/.clang-tidy
|
||||
@@ -1,31 +0,0 @@
|
||||
name: doxygen
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
name: Build HTML documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Fetching sources
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Installing build dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install doxygen gcc git
|
||||
|
||||
- name: Creating build directory
|
||||
run: mkdir build
|
||||
|
||||
- name: Building HTML documentation with Doxygen
|
||||
run: |
|
||||
cmake -S . -B build -DBENCHMARK_ENABLE_TESTING:BOOL=OFF -DBENCHMARK_ENABLE_DOXYGEN:BOOL=ON -DBENCHMARK_INSTALL_DOCS:BOOL=ON
|
||||
cmake --build build --target benchmark_doxygen
|
||||
@@ -1,41 +0,0 @@
|
||||
name: python + Bazel pre-commit checks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
pre-commit:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
MYPY_CACHE_DIR: "${{ github.workspace }}/.cache/mypy"
|
||||
RUFF_CACHE_DIR: "${{ github.workspace }}/.cache/ruff"
|
||||
PRE_COMMIT_HOME: "${{ github.workspace }}/.cache/pre-commit"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.11
|
||||
cache: pip
|
||||
cache-dependency-path: pyproject.toml
|
||||
- name: Install dependencies
|
||||
run: python -m pip install ".[dev]"
|
||||
- name: Cache pre-commit tools
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
${{ env.MYPY_CACHE_DIR }}
|
||||
${{ env.RUFF_CACHE_DIR }}
|
||||
${{ env.PRE_COMMIT_HOME }}
|
||||
key: ${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }}-linter-cache
|
||||
- name: Run pre-commit checks
|
||||
run: pre-commit run --all-files --verbose --show-diff-on-failure
|
||||
@@ -1,97 +0,0 @@
|
||||
name: sanitizer
|
||||
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
UBSAN_OPTIONS: "print_stacktrace=1"
|
||||
|
||||
jobs:
|
||||
job:
|
||||
name: ${{ matrix.sanitizer }}.${{ matrix.build_type }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build_type: ['Debug', 'RelWithDebInfo']
|
||||
sanitizer: ['asan', 'ubsan', 'tsan', 'msan']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: configure msan env
|
||||
if: matrix.sanitizer == 'msan'
|
||||
run: |
|
||||
echo "EXTRA_FLAGS=-g -O2 -fno-omit-frame-pointer -fsanitize=memory -fsanitize-memory-track-origins" >> $GITHUB_ENV
|
||||
echo "LIBCXX_SANITIZER=MemoryWithOrigins" >> $GITHUB_ENV
|
||||
|
||||
- name: configure ubsan env
|
||||
if: matrix.sanitizer == 'ubsan'
|
||||
run: |
|
||||
echo "EXTRA_FLAGS=-g -O2 -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=all" >> $GITHUB_ENV
|
||||
echo "LIBCXX_SANITIZER=Undefined" >> $GITHUB_ENV
|
||||
|
||||
- name: configure asan env
|
||||
if: matrix.sanitizer == 'asan'
|
||||
run: |
|
||||
echo "EXTRA_FLAGS=-g -O2 -fno-omit-frame-pointer -fsanitize=address -fno-sanitize-recover=all" >> $GITHUB_ENV
|
||||
echo "LIBCXX_SANITIZER=Address" >> $GITHUB_ENV
|
||||
|
||||
- name: configure tsan env
|
||||
if: matrix.sanitizer == 'tsan'
|
||||
run: |
|
||||
echo "EXTRA_FLAGS=-g -O2 -fno-omit-frame-pointer -fsanitize=thread -fno-sanitize-recover=all" >> $GITHUB_ENV
|
||||
echo "LIBCXX_SANITIZER=Thread" >> $GITHUB_ENV
|
||||
|
||||
- name: fine-tune asan options
|
||||
# in asan we get an error from std::regex. ignore it.
|
||||
if: matrix.sanitizer == 'asan'
|
||||
run: |
|
||||
echo "ASAN_OPTIONS=alloc_dealloc_mismatch=0" >> $GITHUB_ENV
|
||||
|
||||
- name: setup clang
|
||||
uses: egor-tensin/setup-clang@v1
|
||||
with:
|
||||
version: latest
|
||||
platform: x64
|
||||
|
||||
- name: configure clang
|
||||
run: |
|
||||
echo "CC=cc" >> $GITHUB_ENV
|
||||
echo "CXX=c++" >> $GITHUB_ENV
|
||||
|
||||
- name: build libc++ (non-asan)
|
||||
if: matrix.sanitizer != 'asan'
|
||||
run: |
|
||||
"${GITHUB_WORKSPACE}/.github/libcxx-setup.sh"
|
||||
echo "EXTRA_CXX_FLAGS=-stdlib=libc++ -L${GITHUB_WORKSPACE}/llvm-build/lib -lc++abi -I${GITHUB_WORKSPACE}/llvm-build/include/c++/v1 -Isystem${GITHUB_WORKSPACE}/llvm-build/include/c++/v1 -Wl,-rpath,${GITHUB_WORKSPACE}/llvm-build/lib" >> $GITHUB_ENV
|
||||
|
||||
- name: create build environment
|
||||
run: cmake -E make_directory ${{ runner.workspace }}/_build
|
||||
|
||||
- name: configure cmake
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: >
|
||||
VERBOSE=1
|
||||
cmake -GNinja $GITHUB_WORKSPACE
|
||||
-DBENCHMARK_ENABLE_ASSEMBLY_TESTS=OFF
|
||||
-DBENCHMARK_ENABLE_LIBPFM=OFF
|
||||
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
|
||||
-DCMAKE_C_COMPILER=${{ env.CC }}
|
||||
-DCMAKE_CXX_COMPILER=${{ env.CXX }}
|
||||
-DCMAKE_C_FLAGS="${{ env.EXTRA_FLAGS }}"
|
||||
-DCMAKE_CXX_FLAGS="${{ env.EXTRA_FLAGS }} ${{ env.EXTRA_CXX_FLAGS }}"
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||
|
||||
- name: build
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: cmake --build . --config ${{ matrix.build_type }}
|
||||
|
||||
- name: test
|
||||
shell: bash
|
||||
working-directory: ${{ runner.workspace }}/_build
|
||||
run: ctest -C ${{ matrix.build_type }} -VV
|
||||
@@ -1,33 +0,0 @@
|
||||
name: test-bindings
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
python_bindings:
|
||||
name: Test GBM Python ${{ matrix.python-version }} bindings on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest, macos-latest, windows-latest ]
|
||||
python-version: [ "3.10", "3.11", "3.12", "3.13" ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install GBM Python bindings on ${{ matrix.os }}
|
||||
run: python -m pip install .
|
||||
- name: Run example on ${{ matrix.os }} under Python ${{ matrix.python-version }}
|
||||
run: python bindings/python/google_benchmark/example.py
|
||||
@@ -1,83 +0,0 @@
|
||||
name: Build and upload Python wheels
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
env:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
build_sdist:
|
||||
name: Build source distribution
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install Python 3.12
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- run: python -m pip install build
|
||||
- name: Build sdist
|
||||
run: python -m build --sdist
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist-sdist
|
||||
path: dist/*.tar.gz
|
||||
|
||||
build_wheels:
|
||||
name: Build Google Benchmark wheels on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, ubuntu-24.04-arm, macos-13, macos-14, windows-latest]
|
||||
steps:
|
||||
- name: Check out Google Benchmark
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
name: Install Python 3.12
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- run: pip install --upgrade pip uv
|
||||
|
||||
- name: Build wheels on ${{ matrix.os }} using cibuildwheel
|
||||
uses: pypa/cibuildwheel@v2.23.2
|
||||
env:
|
||||
CIBW_BUILD: "cp310-* cp311-* cp312-*"
|
||||
CIBW_BUILD_FRONTEND: "build[uv]"
|
||||
CIBW_SKIP: "*-musllinux_*"
|
||||
CIBW_ARCHS: auto64
|
||||
CIBW_BEFORE_ALL_LINUX: bash .github/install_bazel.sh
|
||||
# Grab the rootless Bazel installation inside the container.
|
||||
CIBW_ENVIRONMENT_LINUX: PATH=$PATH:$HOME/bin
|
||||
CIBW_TEST_COMMAND: python {project}/bindings/python/google_benchmark/example.py
|
||||
# unused by Bazel, but needed explicitly by delocate on MacOS.
|
||||
MACOSX_DEPLOYMENT_TARGET: "10.14"
|
||||
|
||||
- name: Upload Google Benchmark ${{ matrix.os }} wheels
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist-${{ matrix.os }}
|
||||
path: wheelhouse/*.whl
|
||||
|
||||
pypi_upload:
|
||||
name: Publish google-benchmark wheels to PyPI
|
||||
needs: [build_sdist, build_wheels]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: dist
|
||||
pattern: dist-*
|
||||
merge-multiple: true
|
||||
- uses: pypa/gh-action-pypi-publish@release/v1
|
||||
10
third_party/benchmark/.gitignore
vendored
10
third_party/benchmark/.gitignore
vendored
@@ -8,10 +8,8 @@
|
||||
!/cmake/*.cmake
|
||||
!/test/AssemblyTests.cmake
|
||||
*~
|
||||
*.swp
|
||||
*.pyc
|
||||
__pycache__
|
||||
.DS_Store
|
||||
|
||||
# lcov
|
||||
*.lcov
|
||||
@@ -46,7 +44,6 @@ rules.ninja
|
||||
|
||||
# bazel output symlinks.
|
||||
bazel-*
|
||||
MODULE.bazel.lock
|
||||
|
||||
# out-of-source build top-level folders.
|
||||
build/
|
||||
@@ -59,10 +56,3 @@ build*/
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
CMakeSettings.json
|
||||
|
||||
# Visual Studio Code cache/options directory
|
||||
.vscode/
|
||||
|
||||
# Python build stuff
|
||||
dist/
|
||||
*.egg-info*
|
||||
|
||||
18
third_party/benchmark/.pre-commit-config.yaml
vendored
18
third_party/benchmark/.pre-commit-config.yaml
vendored
@@ -1,18 +0,0 @@
|
||||
repos:
|
||||
- repo: https://github.com/keith/pre-commit-buildifier
|
||||
rev: 8.0.3
|
||||
hooks:
|
||||
- id: buildifier
|
||||
- id: buildifier-lint
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.15.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
types_or: [ python, pyi ]
|
||||
args: [ "--ignore-missing-imports", "--scripts-are-modules" ]
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.11.8
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [ --fix, --exit-non-zero-on-fix ]
|
||||
- id: ruff-format
|
||||
28
third_party/benchmark/.travis-libcxx-setup.sh
vendored
Normal file
28
third_party/benchmark/.travis-libcxx-setup.sh
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Install a newer CMake version
|
||||
curl -sSL https://cmake.org/files/v3.6/cmake-3.6.1-Linux-x86_64.sh -o install-cmake.sh
|
||||
chmod +x install-cmake.sh
|
||||
sudo ./install-cmake.sh --prefix=/usr/local --skip-license
|
||||
|
||||
# Checkout LLVM sources
|
||||
git clone --depth=1 https://github.com/llvm-mirror/llvm.git llvm-source
|
||||
git clone --depth=1 https://github.com/llvm-mirror/libcxx.git llvm-source/projects/libcxx
|
||||
git clone --depth=1 https://github.com/llvm-mirror/libcxxabi.git llvm-source/projects/libcxxabi
|
||||
|
||||
# Setup libc++ options
|
||||
if [ -z "$BUILD_32_BITS" ]; then
|
||||
export BUILD_32_BITS=OFF && echo disabling 32 bit build
|
||||
fi
|
||||
|
||||
# Build and install libc++ (Use unstable ABI for better sanitizer coverage)
|
||||
mkdir llvm-build && cd llvm-build
|
||||
cmake -DCMAKE_C_COMPILER=${C_COMPILER} -DCMAKE_CXX_COMPILER=${COMPILER} \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DLIBCXX_ABI_UNSTABLE=ON \
|
||||
-DLLVM_USE_SANITIZER=${LIBCXX_SANITIZER} \
|
||||
-DLLVM_BUILD_32_BITS=${BUILD_32_BITS} \
|
||||
../llvm-source
|
||||
make cxx -j2
|
||||
sudo make install-cxxabi install-cxx
|
||||
cd ../
|
||||
199
third_party/benchmark/.travis.yml
vendored
Normal file
199
third_party/benchmark/.travis.yml
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
sudo: required
|
||||
dist: trusty
|
||||
language: cpp
|
||||
|
||||
env:
|
||||
global:
|
||||
- /usr/local/bin:$PATH
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- lcov
|
||||
env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Coverage
|
||||
- compiler: gcc
|
||||
env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Debug
|
||||
- compiler: gcc
|
||||
env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Release
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-multilib
|
||||
env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Debug BUILD_32_BITS=ON
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-multilib
|
||||
env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Release BUILD_32_BITS=ON
|
||||
- compiler: gcc
|
||||
env:
|
||||
- INSTALL_GCC6_FROM_PPA=1
|
||||
- COMPILER=g++-6 C_COMPILER=gcc-6 BUILD_TYPE=Debug
|
||||
- ENABLE_SANITIZER=1
|
||||
- EXTRA_FLAGS="-fno-omit-frame-pointer -g -O2 -fsanitize=undefined,address -fuse-ld=gold"
|
||||
- compiler: clang
|
||||
env: COMPILER=clang++ C_COMPILER=clang BUILD_TYPE=Debug
|
||||
- compiler: clang
|
||||
env: COMPILER=clang++ C_COMPILER=clang BUILD_TYPE=Release
|
||||
# Clang w/ libc++
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
clang-3.8
|
||||
env:
|
||||
- COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug
|
||||
- LIBCXX_BUILD=1
|
||||
- EXTRA_FLAGS="-stdlib=libc++"
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
clang-3.8
|
||||
env:
|
||||
- COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Release
|
||||
- LIBCXX_BUILD=1
|
||||
- EXTRA_FLAGS="-stdlib=libc++"
|
||||
# Clang w/ 32bit libc++
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.8
|
||||
- g++-multilib
|
||||
env:
|
||||
- COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug
|
||||
- LIBCXX_BUILD=1
|
||||
- BUILD_32_BITS=ON
|
||||
- EXTRA_FLAGS="-stdlib=libc++ -m32"
|
||||
# Clang w/ 32bit libc++
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.8
|
||||
- g++-multilib
|
||||
env:
|
||||
- COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Release
|
||||
- LIBCXX_BUILD=1
|
||||
- BUILD_32_BITS=ON
|
||||
- EXTRA_FLAGS="-stdlib=libc++ -m32"
|
||||
# Clang w/ libc++, ASAN, UBSAN
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
clang-3.8
|
||||
env:
|
||||
- COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug
|
||||
- LIBCXX_BUILD=1 LIBCXX_SANITIZER="Undefined;Address"
|
||||
- ENABLE_SANITIZER=1
|
||||
- EXTRA_FLAGS="-stdlib=libc++ -g -O2 -fno-omit-frame-pointer -fsanitize=undefined,address -fno-sanitize-recover=all"
|
||||
- UBSAN_OPTIONS=print_stacktrace=1
|
||||
# Clang w/ libc++ and MSAN
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
clang-3.8
|
||||
env:
|
||||
- COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug
|
||||
- LIBCXX_BUILD=1 LIBCXX_SANITIZER=MemoryWithOrigins
|
||||
- ENABLE_SANITIZER=1
|
||||
- EXTRA_FLAGS="-stdlib=libc++ -g -O2 -fno-omit-frame-pointer -fsanitize=memory -fsanitize-memory-track-origins"
|
||||
# Clang w/ libc++ and MSAN
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
clang-3.8
|
||||
env:
|
||||
- COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=RelWithDebInfo
|
||||
- LIBCXX_BUILD=1 LIBCXX_SANITIZER=Thread
|
||||
- ENABLE_SANITIZER=1
|
||||
- EXTRA_FLAGS="-stdlib=libc++ -g -O2 -fno-omit-frame-pointer -fsanitize=thread -fno-sanitize-recover=all"
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang++ BUILD_TYPE=Debug
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang++ BUILD_TYPE=Release
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang++ BUILD_TYPE=Release BUILD_32_BITS=ON
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
compiler: gcc
|
||||
env:
|
||||
- COMPILER=g++-7 C_COMPILER=gcc-7 BUILD_TYPE=Debug
|
||||
|
||||
before_script:
|
||||
- if [ -n "${LIBCXX_BUILD}" ]; then
|
||||
source .travis-libcxx-setup.sh;
|
||||
fi
|
||||
- if [ -n "${ENABLE_SANITIZER}" ]; then
|
||||
export EXTRA_OPTIONS="-DBENCHMARK_ENABLE_ASSEMBLY_TESTS=OFF";
|
||||
else
|
||||
export EXTRA_OPTIONS="";
|
||||
fi
|
||||
- mkdir -p build && cd build
|
||||
|
||||
before_install:
|
||||
- if [ -z "$BUILD_32_BITS" ]; then
|
||||
export BUILD_32_BITS=OFF && echo disabling 32 bit build;
|
||||
fi
|
||||
- if [ -n "${INSTALL_GCC6_FROM_PPA}" ]; then
|
||||
sudo add-apt-repository -y "ppa:ubuntu-toolchain-r/test";
|
||||
sudo apt-get update --option Acquire::Retries=100 --option Acquire::http::Timeout="60";
|
||||
fi
|
||||
|
||||
install:
|
||||
- if [ -n "${INSTALL_GCC6_FROM_PPA}" ]; then
|
||||
travis_wait sudo -E apt-get -yq --no-install-suggests --no-install-recommends install g++-6;
|
||||
fi
|
||||
- if [ "${TRAVIS_OS_NAME}" == "linux" -a "${BUILD_32_BITS}" == "OFF" ]; then
|
||||
travis_wait sudo -E apt-get -y --no-install-suggests --no-install-recommends install llvm-3.9-tools;
|
||||
sudo cp /usr/lib/llvm-3.9/bin/FileCheck /usr/local/bin/;
|
||||
fi
|
||||
- if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then
|
||||
PATH=~/.local/bin:${PATH};
|
||||
pip install --user --upgrade pip;
|
||||
travis_wait pip install --user cpp-coveralls;
|
||||
fi
|
||||
- if [ "${C_COMPILER}" == "gcc-7" -a "${TRAVIS_OS_NAME}" == "osx" ]; then
|
||||
rm -f /usr/local/include/c++;
|
||||
brew update;
|
||||
travis_wait brew install gcc@7;
|
||||
fi
|
||||
- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then
|
||||
sudo apt-get update -qq;
|
||||
sudo apt-get install -qq unzip;
|
||||
wget https://github.com/bazelbuild/bazel/releases/download/0.10.1/bazel-0.10.1-installer-linux-x86_64.sh --output-document bazel-installer.sh;
|
||||
travis_wait sudo bash bazel-installer.sh;
|
||||
fi
|
||||
- if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
|
||||
curl -L -o bazel-installer.sh https://github.com/bazelbuild/bazel/releases/download/0.10.1/bazel-0.10.1-installer-darwin-x86_64.sh;
|
||||
travis_wait sudo bash bazel-installer.sh;
|
||||
fi
|
||||
|
||||
script:
|
||||
- cmake -DCMAKE_C_COMPILER=${C_COMPILER} -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_CXX_FLAGS="${EXTRA_FLAGS}" -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON -DBENCHMARK_BUILD_32_BITS=${BUILD_32_BITS} ${EXTRA_OPTIONS} ..
|
||||
- make
|
||||
- ctest -C ${BUILD_TYPE} --output-on-failure
|
||||
- bazel test -c dbg --define google_benchmark.have_regex=posix --announce_rc --verbose_failures --test_output=errors --keep_going //test/...
|
||||
|
||||
after_success:
|
||||
- if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then
|
||||
coveralls --include src --include include --gcov-options '\-lp' --root .. --build-root .;
|
||||
fi
|
||||
165
third_party/benchmark/.ycm_extra_conf.py
vendored
165
third_party/benchmark/.ycm_extra_conf.py
vendored
@@ -1,30 +1,25 @@
|
||||
import os
|
||||
|
||||
import ycm_core
|
||||
|
||||
# These are the compilation flags that will be used in case there's no
|
||||
# compilation database set (by default, one is not set).
|
||||
# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR.
|
||||
flags = [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-pedantic-errors",
|
||||
"-std=c++0x",
|
||||
"-fno-strict-aliasing",
|
||||
"-O3",
|
||||
"-DNDEBUG",
|
||||
# ...and the same thing goes for the magic -x option which specifies the
|
||||
# language that the files to be compiled are written in. This is mostly
|
||||
# relevant for c++ headers.
|
||||
# For a C project, you would set this to 'c' instead of 'c++'.
|
||||
"-x",
|
||||
"c++",
|
||||
"-I",
|
||||
"include",
|
||||
"-isystem",
|
||||
"/usr/include",
|
||||
"-isystem",
|
||||
"/usr/local/include",
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
'-pedantic-errors',
|
||||
'-std=c++0x',
|
||||
'-fno-strict-aliasing',
|
||||
'-O3',
|
||||
'-DNDEBUG',
|
||||
# ...and the same thing goes for the magic -x option which specifies the
|
||||
# language that the files to be compiled are written in. This is mostly
|
||||
# relevant for c++ headers.
|
||||
# For a C project, you would set this to 'c' instead of 'c++'.
|
||||
'-x', 'c++',
|
||||
'-I', 'include',
|
||||
'-isystem', '/usr/include',
|
||||
'-isystem', '/usr/local/include',
|
||||
]
|
||||
|
||||
|
||||
@@ -34,87 +29,87 @@ flags = [
|
||||
#
|
||||
# Most projects will NOT need to set this to anything; you can just change the
|
||||
# 'flags' list of compilation flags. Notice that YCM itself uses that approach.
|
||||
compilation_database_folder = ""
|
||||
compilation_database_folder = ''
|
||||
|
||||
if os.path.exists(compilation_database_folder):
|
||||
database = ycm_core.CompilationDatabase(compilation_database_folder)
|
||||
if os.path.exists( compilation_database_folder ):
|
||||
database = ycm_core.CompilationDatabase( compilation_database_folder )
|
||||
else:
|
||||
database = None
|
||||
|
||||
SOURCE_EXTENSIONS = [".cc"]
|
||||
database = None
|
||||
|
||||
SOURCE_EXTENSIONS = [ '.cc' ]
|
||||
|
||||
def DirectoryOfThisScript():
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
return os.path.dirname( os.path.abspath( __file__ ) )
|
||||
|
||||
|
||||
def MakeRelativePathsInFlagsAbsolute(flags, working_directory):
|
||||
if not working_directory:
|
||||
return list(flags)
|
||||
new_flags = []
|
||||
make_next_absolute = False
|
||||
path_flags = ["-isystem", "-I", "-iquote", "--sysroot="]
|
||||
for flag in flags:
|
||||
new_flag = flag
|
||||
def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
|
||||
if not working_directory:
|
||||
return list( flags )
|
||||
new_flags = []
|
||||
make_next_absolute = False
|
||||
path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
|
||||
for flag in flags:
|
||||
new_flag = flag
|
||||
|
||||
if make_next_absolute:
|
||||
make_next_absolute = False
|
||||
if not flag.startswith("/"):
|
||||
new_flag = os.path.join(working_directory, flag)
|
||||
if make_next_absolute:
|
||||
make_next_absolute = False
|
||||
if not flag.startswith( '/' ):
|
||||
new_flag = os.path.join( working_directory, flag )
|
||||
|
||||
for path_flag in path_flags:
|
||||
if flag == path_flag:
|
||||
make_next_absolute = True
|
||||
break
|
||||
for path_flag in path_flags:
|
||||
if flag == path_flag:
|
||||
make_next_absolute = True
|
||||
break
|
||||
|
||||
if flag.startswith(path_flag):
|
||||
path = flag[len(path_flag) :]
|
||||
new_flag = path_flag + os.path.join(working_directory, path)
|
||||
break
|
||||
if flag.startswith( path_flag ):
|
||||
path = flag[ len( path_flag ): ]
|
||||
new_flag = path_flag + os.path.join( working_directory, path )
|
||||
break
|
||||
|
||||
if new_flag:
|
||||
new_flags.append(new_flag)
|
||||
return new_flags
|
||||
if new_flag:
|
||||
new_flags.append( new_flag )
|
||||
return new_flags
|
||||
|
||||
|
||||
def IsHeaderFile(filename):
|
||||
extension = os.path.splitext(filename)[1]
|
||||
return extension in [".h", ".hxx", ".hpp", ".hh"]
|
||||
def IsHeaderFile( filename ):
|
||||
extension = os.path.splitext( filename )[ 1 ]
|
||||
return extension in [ '.h', '.hxx', '.hpp', '.hh' ]
|
||||
|
||||
|
||||
def GetCompilationInfoForFile(filename):
|
||||
# The compilation_commands.json file generated by CMake does not have
|
||||
# entries for header files. So we do our best by asking the db for flags for
|
||||
# a corresponding source file, if any. If one exists, the flags for that
|
||||
# file should be good enough.
|
||||
if IsHeaderFile(filename):
|
||||
basename = os.path.splitext(filename)[0]
|
||||
for extension in SOURCE_EXTENSIONS:
|
||||
replacement_file = basename + extension
|
||||
if os.path.exists(replacement_file):
|
||||
compilation_info = database.GetCompilationInfoForFile(
|
||||
replacement_file
|
||||
)
|
||||
if compilation_info.compiler_flags_:
|
||||
return compilation_info
|
||||
return None
|
||||
return database.GetCompilationInfoForFile(filename)
|
||||
def GetCompilationInfoForFile( filename ):
|
||||
# The compilation_commands.json file generated by CMake does not have entries
|
||||
# for header files. So we do our best by asking the db for flags for a
|
||||
# corresponding source file, if any. If one exists, the flags for that file
|
||||
# should be good enough.
|
||||
if IsHeaderFile( filename ):
|
||||
basename = os.path.splitext( filename )[ 0 ]
|
||||
for extension in SOURCE_EXTENSIONS:
|
||||
replacement_file = basename + extension
|
||||
if os.path.exists( replacement_file ):
|
||||
compilation_info = database.GetCompilationInfoForFile(
|
||||
replacement_file )
|
||||
if compilation_info.compiler_flags_:
|
||||
return compilation_info
|
||||
return None
|
||||
return database.GetCompilationInfoForFile( filename )
|
||||
|
||||
|
||||
def FlagsForFile(filename, **kwargs):
|
||||
if database:
|
||||
# Bear in mind that compilation_info.compiler_flags_ does NOT return a
|
||||
# python list, but a "list-like" StringVec object
|
||||
compilation_info = GetCompilationInfoForFile(filename)
|
||||
if not compilation_info:
|
||||
return None
|
||||
def FlagsForFile( filename, **kwargs ):
|
||||
if database:
|
||||
# Bear in mind that compilation_info.compiler_flags_ does NOT return a
|
||||
# python list, but a "list-like" StringVec object
|
||||
compilation_info = GetCompilationInfoForFile( filename )
|
||||
if not compilation_info:
|
||||
return None
|
||||
|
||||
final_flags = MakeRelativePathsInFlagsAbsolute(
|
||||
compilation_info.compiler_flags_,
|
||||
compilation_info.compiler_working_dir_,
|
||||
)
|
||||
else:
|
||||
relative_to = DirectoryOfThisScript()
|
||||
final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to)
|
||||
final_flags = MakeRelativePathsInFlagsAbsolute(
|
||||
compilation_info.compiler_flags_,
|
||||
compilation_info.compiler_working_dir_ )
|
||||
else:
|
||||
relative_to = DirectoryOfThisScript()
|
||||
final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
|
||||
|
||||
return {"flags": final_flags, "do_cache": True}
|
||||
return {
|
||||
'flags': final_flags,
|
||||
'do_cache': True
|
||||
}
|
||||
|
||||
24
third_party/benchmark/AUTHORS
vendored
24
third_party/benchmark/AUTHORS
vendored
@@ -9,64 +9,40 @@
|
||||
# Please keep the list sorted.
|
||||
|
||||
Albert Pretorius <pretoalb@gmail.com>
|
||||
Alex Steele <steeleal123@gmail.com>
|
||||
Andriy Berestovskyy <berestovskyy@gmail.com>
|
||||
Arne Beer <arne@twobeer.de>
|
||||
Carto
|
||||
Cezary Skrzyński <czars1988@gmail.com>
|
||||
Christian Wassermann <christian_wassermann@web.de>
|
||||
Christopher Seymour <chris.j.seymour@hotmail.com>
|
||||
Colin Braley <braley.colin@gmail.com>
|
||||
Daniel Harvey <danielharvey458@gmail.com>
|
||||
David Coeurjolly <david.coeurjolly@liris.cnrs.fr>
|
||||
Deniz Evrenci <denizevrenci@gmail.com>
|
||||
Dirac Research
|
||||
Dominik Czarnota <dominik.b.czarnota@gmail.com>
|
||||
Dominik Korman <kormandominik@gmail.com>
|
||||
Donald Aingworth <donalds_junk_mail@yahoo.com>
|
||||
Eric Backus <eric_backus@alum.mit.edu>
|
||||
Eric Fiselier <eric@efcs.ca>
|
||||
Eugene Zhuk <eugene.zhuk@gmail.com>
|
||||
Evgeny Safronov <division494@gmail.com>
|
||||
Fabien Pichot <pichot.fabien@gmail.com>
|
||||
Federico Ficarelli <federico.ficarelli@gmail.com>
|
||||
Felix Homann <linuxaudio@showlabor.de>
|
||||
Gergely Meszaros <maetveis@gmail.com>
|
||||
Gergő Szitár <szitar.gergo@gmail.com>
|
||||
Google Inc.
|
||||
Henrique Bucher <hbucher@gmail.com>
|
||||
International Business Machines Corporation
|
||||
Ismael Jimenez Martinez <ismael.jimenez.martinez@gmail.com>
|
||||
Jern-Kuan Leong <jernkuan@gmail.com>
|
||||
JianXiong Zhou <zhoujianxiong2@gmail.com>
|
||||
Joao Paulo Magalhaes <joaoppmagalhaes@gmail.com>
|
||||
Jordan Williams <jwillikers@protonmail.com>
|
||||
Jussi Knuuttila <jussi.knuuttila@gmail.com>
|
||||
Kaito Udagawa <umireon@gmail.com>
|
||||
Kishan Kumar <kumar.kishan@outlook.com>
|
||||
Lei Xu <eddyxu@gmail.com>
|
||||
Marcel Jacobse <mjacobse@uni-bremen.de>
|
||||
Matt Clarkson <mattyclarkson@gmail.com>
|
||||
Maxim Vafin <maxvafin@gmail.com>
|
||||
Mike Apodaca <gatorfax@gmail.com>
|
||||
Min-Yih Hsu <yihshyng223@gmail.com>
|
||||
MongoDB Inc.
|
||||
Nick Hutchinson <nshutchinson@gmail.com>
|
||||
Norman Heino <norman.heino@gmail.com>
|
||||
Oleksandr Sochka <sasha.sochka@gmail.com>
|
||||
Ori Livneh <ori.livneh@gmail.com>
|
||||
Paul Redmond <paul.redmond@gmail.com>
|
||||
Radoslav Yovchev <radoslav.tm@gmail.com>
|
||||
Raghu Raja <raghu@enfabrica.net>
|
||||
Rainer Orth <ro@cebitec.uni-bielefeld.de>
|
||||
Roman Lebedev <lebedev.ri@gmail.com>
|
||||
Sayan Bhattacharjee <aero.sayan@gmail.com>
|
||||
Shapr3D <google-contributors@shapr3d.com>
|
||||
Shuo Chen <chenshuo@chenshuo.com>
|
||||
Staffan Tjernstrom <staffantj@gmail.com>
|
||||
Steinar H. Gunderson <sgunderson@bigfoot.com>
|
||||
Stripe, Inc.
|
||||
Tobias Schmidt <tobias.schmidt@in.tum.de>
|
||||
Yixuan Qiu <yixuanq@gmail.com>
|
||||
Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
Zbigniew Skowron <zbychs@gmail.com>
|
||||
|
||||
72
third_party/benchmark/BUILD.bazel
vendored
72
third_party/benchmark/BUILD.bazel
vendored
@@ -1,38 +1,9 @@
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
COPTS = [
|
||||
"-pedantic",
|
||||
"-pedantic-errors",
|
||||
"-std=c++17",
|
||||
"-Wall",
|
||||
"-Wconversion",
|
||||
"-Wextra",
|
||||
"-Wshadow",
|
||||
# "-Wshorten-64-to-32",
|
||||
"-Wfloat-equal",
|
||||
"-fstrict-aliasing",
|
||||
## assert() are used a lot in tests upstream, which may be optimised out leading to
|
||||
## unused-variable warning.
|
||||
"-Wno-unused-variable",
|
||||
"-Werror=old-style-cast",
|
||||
]
|
||||
|
||||
MSVC_COPTS = [
|
||||
"/std:c++17",
|
||||
]
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
constraint_values = ["@platforms//os:windows"],
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "perfcounters",
|
||||
define_values = {
|
||||
"pfm": "1",
|
||||
values = {
|
||||
"cpu": "x64_windows",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
@@ -46,51 +17,20 @@ cc_library(
|
||||
],
|
||||
exclude = ["src/benchmark_main.cc"],
|
||||
),
|
||||
hdrs = [
|
||||
"include/benchmark/benchmark.h",
|
||||
"include/benchmark/export.h",
|
||||
],
|
||||
copts = select({
|
||||
":windows": MSVC_COPTS,
|
||||
"//conditions:default": COPTS,
|
||||
}),
|
||||
defines = [
|
||||
"BENCHMARK_STATIC_DEFINE",
|
||||
"BENCHMARK_VERSION=\\\"" + (module_version() if module_version() != None else "") + "\\\"",
|
||||
] + select({
|
||||
":perfcounters": ["HAVE_LIBPFM"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
includes = ["include"],
|
||||
hdrs = ["include/benchmark/benchmark.h"],
|
||||
linkopts = select({
|
||||
":windows": ["-DEFAULTLIB:shlwapi.lib"],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}),
|
||||
# Only static linking is allowed; no .so will be produced.
|
||||
# Using `defines` (i.e. not `local_defines`) means that no
|
||||
# dependent rules need to bother about defining the macro.
|
||||
linkstatic = True,
|
||||
local_defines = [
|
||||
# Turn on Large-file Support
|
||||
"_FILE_OFFSET_BITS=64",
|
||||
"_LARGEFILE64_SOURCE",
|
||||
"_LARGEFILE_SOURCE",
|
||||
],
|
||||
strip_include_prefix = "include",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = select({
|
||||
":perfcounters": ["@libpfm"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "benchmark_main",
|
||||
srcs = ["src/benchmark_main.cc"],
|
||||
hdrs = [
|
||||
"include/benchmark/benchmark.h",
|
||||
"include/benchmark/export.h",
|
||||
],
|
||||
includes = ["include"],
|
||||
hdrs = ["include/benchmark/benchmark.h"],
|
||||
strip_include_prefix = "include",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [":benchmark"],
|
||||
)
|
||||
|
||||
207
third_party/benchmark/CMakeLists.txt
vendored
207
third_party/benchmark/CMakeLists.txt
vendored
@@ -1,34 +1,27 @@
|
||||
# Require CMake 3.10. If available, use the policies up to CMake 3.22.
|
||||
cmake_minimum_required (VERSION 3.13...3.22)
|
||||
cmake_minimum_required (VERSION 2.8.12)
|
||||
|
||||
project (benchmark VERSION 1.9.4 LANGUAGES CXX)
|
||||
project (benchmark)
|
||||
|
||||
foreach(p
|
||||
CMP0054 # CMake 3.1
|
||||
CMP0056 # export EXE_LINKER_FLAGS to try_run
|
||||
CMP0057 # Support no if() IN_LIST operator
|
||||
)
|
||||
if(POLICY ${p})
|
||||
cmake_policy(SET ${p} NEW)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
option(BENCHMARK_ENABLE_TESTING "Enable testing of the benchmark library." ON)
|
||||
option(BENCHMARK_ENABLE_EXCEPTIONS "Enable the use of exceptions in the benchmark library." ON)
|
||||
option(BENCHMARK_ENABLE_LTO "Enable link time optimisation of the benchmark library." OFF)
|
||||
option(BENCHMARK_USE_LIBCXX "Build and test using libc++ as the standard library." OFF)
|
||||
option(BENCHMARK_ENABLE_WERROR "Build Release candidates with -Werror." ON)
|
||||
option(BENCHMARK_FORCE_WERROR "Build Release candidates with -Werror regardless of compiler issues." OFF)
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "PGI")
|
||||
# PGC++ maybe reporting false positives.
|
||||
set(BENCHMARK_ENABLE_WERROR OFF)
|
||||
endif()
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "NVHPC")
|
||||
set(BENCHMARK_ENABLE_WERROR OFF)
|
||||
endif()
|
||||
if(BENCHMARK_FORCE_WERROR)
|
||||
set(BENCHMARK_ENABLE_WERROR ON)
|
||||
endif(BENCHMARK_FORCE_WERROR)
|
||||
|
||||
if(NOT (MSVC OR CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC"))
|
||||
if(NOT MSVC)
|
||||
option(BENCHMARK_BUILD_32_BITS "Build a 32 bit version of the library." OFF)
|
||||
else()
|
||||
set(BENCHMARK_BUILD_32_BITS OFF CACHE BOOL "Build a 32 bit version of the library - unsupported when using MSVC)" FORCE)
|
||||
endif()
|
||||
option(BENCHMARK_ENABLE_INSTALL "Enable installation of benchmark. (Projects embedding benchmark may want to turn this OFF.)" ON)
|
||||
option(BENCHMARK_ENABLE_DOXYGEN "Build documentation with Doxygen." OFF)
|
||||
option(BENCHMARK_INSTALL_DOCS "Enable installation of documentation." ON)
|
||||
|
||||
# Allow unmet dependencies to be met using CMake's ExternalProject mechanics, which
|
||||
# may require downloading the source code.
|
||||
@@ -37,24 +30,6 @@ option(BENCHMARK_DOWNLOAD_DEPENDENCIES "Allow the downloading and in-tree buildi
|
||||
# This option can be used to disable building and running unit tests which depend on gtest
|
||||
# in cases where it is not possible to build or find a valid version of gtest.
|
||||
option(BENCHMARK_ENABLE_GTEST_TESTS "Enable building the unit tests which depend on gtest" ON)
|
||||
option(BENCHMARK_USE_BUNDLED_GTEST "Use bundled GoogleTest. If disabled, the find_package(GTest) will be used." ON)
|
||||
|
||||
option(BENCHMARK_ENABLE_LIBPFM "Enable performance counters provided by libpfm" OFF)
|
||||
|
||||
# Export only public symbols
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
# As of CMake 3.18, CMAKE_SYSTEM_PROCESSOR is not set properly for MSVC and
|
||||
# cross-compilation (e.g. Host=x86_64, target=aarch64) requires using the
|
||||
# undocumented, but working variable.
|
||||
# See https://gitlab.kitware.com/cmake/cmake/-/issues/15170
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${MSVC_CXX_ARCHITECTURE_ID})
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ARM")
|
||||
set(CMAKE_CROSSCOMPILING TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(ENABLE_ASSEMBLY_TESTS_DEFAULT OFF)
|
||||
function(should_enable_assembly_tests)
|
||||
@@ -66,7 +41,7 @@ function(should_enable_assembly_tests)
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
if (MSVC OR CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
|
||||
if (MSVC)
|
||||
return()
|
||||
elseif(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
|
||||
return()
|
||||
@@ -102,63 +77,29 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
include(GetGitVersion)
|
||||
get_git_version(GIT_VERSION)
|
||||
|
||||
# If no git version can be determined, use the version
|
||||
# from the project() command
|
||||
if ("${GIT_VERSION}" STREQUAL "v0.0.0")
|
||||
set(VERSION "v${benchmark_VERSION}")
|
||||
else()
|
||||
set(VERSION "${GIT_VERSION}")
|
||||
endif()
|
||||
|
||||
# Normalize version: drop "v" prefix, replace first "-" with ".",
|
||||
# drop everything after second "-" (including said "-").
|
||||
string(STRIP ${VERSION} VERSION)
|
||||
if(VERSION MATCHES v[^-]*-)
|
||||
string(REGEX REPLACE "v([^-]*)-([0-9]+)-.*" "\\1.\\2" NORMALIZED_VERSION ${VERSION})
|
||||
else()
|
||||
string(REGEX REPLACE "v(.*)" "\\1" NORMALIZED_VERSION ${VERSION})
|
||||
endif()
|
||||
|
||||
# Tell the user what versions we are using
|
||||
message(STATUS "Google Benchmark version: ${VERSION}, normalized to ${NORMALIZED_VERSION}")
|
||||
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" VERSION ${GIT_VERSION})
|
||||
message(STATUS "Version: ${VERSION}")
|
||||
|
||||
# The version of the libraries
|
||||
set(GENERIC_LIB_VERSION ${NORMALIZED_VERSION})
|
||||
string(SUBSTRING ${NORMALIZED_VERSION} 0 1 GENERIC_LIB_SOVERSION)
|
||||
set(GENERIC_LIB_VERSION ${VERSION})
|
||||
string(SUBSTRING ${VERSION} 0 1 GENERIC_LIB_SOVERSION)
|
||||
|
||||
# Import our CMake modules
|
||||
include(AddCXXCompilerFlag)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckLibraryExists)
|
||||
include(AddCXXCompilerFlag)
|
||||
include(CXXFeatureCheck)
|
||||
|
||||
check_library_exists(rt shm_open "" HAVE_LIB_RT)
|
||||
|
||||
if (BENCHMARK_BUILD_32_BITS)
|
||||
add_required_cxx_compiler_flag(-m32)
|
||||
endif()
|
||||
|
||||
set(BENCHMARK_CXX_STANDARD 17)
|
||||
|
||||
set(CMAKE_CXX_STANDARD ${BENCHMARK_CXX_STANDARD})
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if (MSVC)
|
||||
# Turn compiler warnings up to 11
|
||||
string(REGEX REPLACE "[-/]W[1-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
|
||||
# MP flag only applies to cl, not cl frontends to other compilers (e.g. clang-cl, icx-cl etc)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
endif()
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
if(BENCHMARK_ENABLE_WERROR)
|
||||
add_cxx_compiler_flag(-WX)
|
||||
endif()
|
||||
|
||||
if (NOT BENCHMARK_ENABLE_EXCEPTIONS)
|
||||
add_cxx_compiler_flag(-EHs-)
|
||||
add_cxx_compiler_flag(-EHa-)
|
||||
@@ -185,48 +126,45 @@ if (MSVC)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} /LTCG")
|
||||
endif()
|
||||
else()
|
||||
# Turn on Large-file Support
|
||||
add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||
add_definitions(-D_LARGEFILE64_SOURCE)
|
||||
add_definitions(-D_LARGEFILE_SOURCE)
|
||||
# Try and enable C++11. Don't use C++14 because it doesn't work in some
|
||||
# configurations.
|
||||
add_cxx_compiler_flag(-std=c++11)
|
||||
if (NOT HAVE_CXX_FLAG_STD_CXX11)
|
||||
add_cxx_compiler_flag(-std=c++0x)
|
||||
endif()
|
||||
|
||||
# Turn compiler warnings up to 11
|
||||
add_cxx_compiler_flag(-Wall)
|
||||
add_cxx_compiler_flag(-Wextra)
|
||||
add_cxx_compiler_flag(-Wshadow)
|
||||
add_cxx_compiler_flag(-Wfloat-equal)
|
||||
add_cxx_compiler_flag(-Wold-style-cast)
|
||||
add_cxx_compiler_flag(-Wconversion)
|
||||
if(BENCHMARK_ENABLE_WERROR)
|
||||
add_cxx_compiler_flag(-Werror)
|
||||
endif()
|
||||
if (NOT BENCHMARK_ENABLE_TESTING)
|
||||
# Disable warning when compiling tests as gtest does not use 'override'.
|
||||
add_cxx_compiler_flag(-Wsuggest-override)
|
||||
endif()
|
||||
add_cxx_compiler_flag(-pedantic)
|
||||
add_cxx_compiler_flag(-pedantic-errors)
|
||||
add_cxx_compiler_flag(-Wshorten-64-to-32)
|
||||
add_cxx_compiler_flag(-fstrict-aliasing)
|
||||
# Disable warnings regarding deprecated parts of the library while building
|
||||
# and testing those parts of the library.
|
||||
add_cxx_compiler_flag(-Wno-deprecated-declarations)
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Intel" OR CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
|
||||
# Intel silently ignores '-Wno-deprecated-declarations',
|
||||
# warning no. 1786 must be explicitly disabled.
|
||||
# See #631 for rationale.
|
||||
add_cxx_compiler_flag(-wd1786)
|
||||
add_cxx_compiler_flag(-fno-finite-math-only)
|
||||
endif()
|
||||
# Disable deprecation warnings for release builds (when -Werror is enabled).
|
||||
if(BENCHMARK_ENABLE_WERROR)
|
||||
add_cxx_compiler_flag(-Wno-deprecated)
|
||||
endif()
|
||||
if (NOT BENCHMARK_ENABLE_EXCEPTIONS)
|
||||
add_cxx_compiler_flag(-fno-exceptions)
|
||||
if (NOT MSVC)
|
||||
add_cxx_compiler_flag(-Wall)
|
||||
add_cxx_compiler_flag(-Wextra)
|
||||
add_cxx_compiler_flag(-Wshadow)
|
||||
add_cxx_compiler_flag(-Werror RELEASE)
|
||||
add_cxx_compiler_flag(-Werror RELWITHDEBINFO)
|
||||
add_cxx_compiler_flag(-Werror MINSIZEREL)
|
||||
add_cxx_compiler_flag(-pedantic)
|
||||
add_cxx_compiler_flag(-pedantic-errors)
|
||||
add_cxx_compiler_flag(-Wshorten-64-to-32)
|
||||
add_cxx_compiler_flag(-fstrict-aliasing)
|
||||
# Disable warnings regarding deprecated parts of the library while building
|
||||
# and testing those parts of the library.
|
||||
add_cxx_compiler_flag(-Wno-deprecated-declarations)
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
# Intel silently ignores '-Wno-deprecated-declarations',
|
||||
# warning no. 1786 must be explicitly disabled.
|
||||
# See #631 for rationale.
|
||||
add_cxx_compiler_flag(-wd1786)
|
||||
endif()
|
||||
# Disable deprecation warnings for release builds (when -Werror is enabled).
|
||||
add_cxx_compiler_flag(-Wno-deprecated RELEASE)
|
||||
add_cxx_compiler_flag(-Wno-deprecated RELWITHDEBINFO)
|
||||
add_cxx_compiler_flag(-Wno-deprecated MINSIZEREL)
|
||||
if (NOT BENCHMARK_ENABLE_EXCEPTIONS)
|
||||
add_cxx_compiler_flag(-fno-exceptions)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (HAVE_CXX_FLAG_FSTRICT_ALIASING)
|
||||
if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Intel" AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") #ICC17u2: Many false positives for Wstrict-aliasing
|
||||
if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Intel") #ICC17u2: Many false positives for Wstrict-aliasing
|
||||
add_cxx_compiler_flag(-Wstrict-aliasing)
|
||||
endif()
|
||||
endif()
|
||||
@@ -235,26 +173,21 @@ else()
|
||||
add_cxx_compiler_flag(-wd654)
|
||||
add_cxx_compiler_flag(-Wthread-safety)
|
||||
if (HAVE_CXX_FLAG_WTHREAD_SAFETY)
|
||||
cxx_feature_check(THREAD_SAFETY_ATTRIBUTES "-DINCLUDE_DIRECTORIES=${PROJECT_SOURCE_DIR}/include")
|
||||
cxx_feature_check(THREAD_SAFETY_ATTRIBUTES)
|
||||
endif()
|
||||
|
||||
# On most UNIX like platforms g++ and clang++ define _GNU_SOURCE as a
|
||||
# predefined macro, which turns on all of the wonderful libc extensions.
|
||||
# However g++ doesn't do this in Cygwin so we have to define it ourselves
|
||||
# However g++ doesn't do this in Cygwin so we have to define it ourselfs
|
||||
# since we depend on GNU/POSIX/BSD extensions.
|
||||
if (CYGWIN)
|
||||
add_definitions(-D_GNU_SOURCE=1)
|
||||
endif()
|
||||
|
||||
if (QNXNTO)
|
||||
add_definitions(-D_QNX_SOURCE)
|
||||
endif()
|
||||
|
||||
# Link time optimisation
|
||||
if (BENCHMARK_ENABLE_LTO)
|
||||
add_cxx_compiler_flag(-flto)
|
||||
add_cxx_compiler_flag(-Wno-lto-type-mismatch)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
|
||||
find_program(GCC_AR gcc-ar)
|
||||
if (GCC_AR)
|
||||
set(CMAKE_AR ${GCC_AR})
|
||||
@@ -263,7 +196,7 @@ else()
|
||||
if (GCC_RANLIB)
|
||||
set(CMAKE_RANLIB ${GCC_RANLIB})
|
||||
endif()
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
elseif("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")
|
||||
include(llvm-toolchain)
|
||||
endif()
|
||||
endif()
|
||||
@@ -291,8 +224,7 @@ if (BENCHMARK_USE_LIBCXX)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
add_cxx_compiler_flag(-stdlib=libc++)
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
|
||||
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" OR
|
||||
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "IntelLLVM")
|
||||
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
||||
add_cxx_compiler_flag(-nostdinc++)
|
||||
message(WARNING "libc++ header path must be manually specified using CMAKE_CXX_FLAGS")
|
||||
# Adding -nodefaultlibs directly to CMAKE_<TYPE>_LINKER_FLAGS will break
|
||||
@@ -318,16 +250,9 @@ if (NOT BENCHMARK_ENABLE_EXCEPTIONS AND HAVE_STD_REGEX
|
||||
AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX)
|
||||
message(WARNING "Using std::regex with exceptions disabled is not fully supported")
|
||||
endif()
|
||||
|
||||
cxx_feature_check(STEADY_CLOCK)
|
||||
# Ensure we have pthreads
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
cxx_feature_check(PTHREAD_AFFINITY)
|
||||
|
||||
if (BENCHMARK_ENABLE_LIBPFM)
|
||||
find_package(PFM REQUIRED)
|
||||
endif()
|
||||
|
||||
# Set up directories
|
||||
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||
@@ -337,18 +262,8 @@ add_subdirectory(src)
|
||||
|
||||
if (BENCHMARK_ENABLE_TESTING)
|
||||
enable_testing()
|
||||
if (BENCHMARK_ENABLE_GTEST_TESTS AND
|
||||
NOT (TARGET gtest AND TARGET gtest_main AND
|
||||
TARGET gmock AND TARGET gmock_main))
|
||||
if (BENCHMARK_USE_BUNDLED_GTEST)
|
||||
include(GoogleTest)
|
||||
else()
|
||||
find_package(GTest CONFIG REQUIRED)
|
||||
add_library(gtest ALIAS GTest::gtest)
|
||||
add_library(gtest_main ALIAS GTest::gtest_main)
|
||||
add_library(gmock ALIAS GTest::gmock)
|
||||
add_library(gmock_main ALIAS GTest::gmock_main)
|
||||
endif()
|
||||
if (BENCHMARK_ENABLE_GTEST_TESTS)
|
||||
include(HandleGTest)
|
||||
endif()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
33
third_party/benchmark/CONTRIBUTORS
vendored
33
third_party/benchmark/CONTRIBUTORS
vendored
@@ -22,75 +22,44 @@
|
||||
#
|
||||
# Please keep the list sorted.
|
||||
|
||||
Abhina Sreeskantharajan <abhina.sreeskantharajan@ibm.com>
|
||||
Albert Pretorius <pretoalb@gmail.com>
|
||||
Alex Steele <steelal123@gmail.com>
|
||||
Andriy Berestovskyy <berestovskyy@gmail.com>
|
||||
Arne Beer <arne@twobeer.de>
|
||||
Bátor Tallér <bator.taller@shapr3d.com>
|
||||
Billy Robert O'Neal III <billy.oneal@gmail.com> <bion@microsoft.com>
|
||||
Cezary Skrzyński <czars1988@gmail.com>
|
||||
Chris Kennelly <ckennelly@google.com> <ckennelly@ckennelly.com>
|
||||
Christian Wassermann <christian_wassermann@web.de>
|
||||
Christopher Seymour <chris.j.seymour@hotmail.com>
|
||||
Colin Braley <braley.colin@gmail.com>
|
||||
Cyrille Faucheux <cyrille.faucheux@gmail.com>
|
||||
Daniel Harvey <danielharvey458@gmail.com>
|
||||
David Coeurjolly <david.coeurjolly@liris.cnrs.fr>
|
||||
Deniz Evrenci <denizevrenci@gmail.com>
|
||||
Dominic Hamon <dma@stripysock.com> <dominic@google.com>
|
||||
Dominik Czarnota <dominik.b.czarnota@gmail.com>
|
||||
Dominik Korman <kormandominik@gmail.com>
|
||||
Donald Aingworth <donalds_junk_mail@yahoo.com>
|
||||
Doug Evans <xdje42@gmail.com>
|
||||
Eric Backus <eric_backus@alum.mit.edu>
|
||||
Eric Fiselier <eric@efcs.ca>
|
||||
Eugene Zhuk <eugene.zhuk@gmail.com>
|
||||
Evgeny Safronov <division494@gmail.com>
|
||||
Fabien Pichot <pichot.fabien@gmail.com>
|
||||
Fanbo Meng <fanbo.meng@ibm.com>
|
||||
Federico Ficarelli <federico.ficarelli@gmail.com>
|
||||
Felix Homann <linuxaudio@showlabor.de>
|
||||
Geoffrey Martin-Noble <gcmn@google.com> <gmngeoffrey@gmail.com>
|
||||
Gergely Meszaros <maetveis@gmail.com>
|
||||
Gergő Szitár <szitar.gergo@gmail.com>
|
||||
Hannes Hauswedell <h2@fsfe.org>
|
||||
Henrique Bucher <hbucher@gmail.com>
|
||||
Ismael Jimenez Martinez <ismael.jimenez.martinez@gmail.com>
|
||||
Iakov Sergeev <yahontu@gmail.com>
|
||||
Jern-Kuan Leong <jernkuan@gmail.com>
|
||||
JianXiong Zhou <zhoujianxiong2@gmail.com>
|
||||
Joao Paulo Magalhaes <joaoppmagalhaes@gmail.com>
|
||||
John Millikin <jmillikin@stripe.com>
|
||||
Jordan Williams <jwillikers@protonmail.com>
|
||||
Jussi Knuuttila <jussi.knuuttila@gmail.com>
|
||||
Kaito Udagawa <umireon@gmail.com>
|
||||
Kai Wolf <kai.wolf@gmail.com>
|
||||
Kishan Kumar <kumar.kishan@outlook.com>
|
||||
Kaito Udagawa <umireon@gmail.com>
|
||||
Lei Xu <eddyxu@gmail.com>
|
||||
Marcel Jacobse <mjacobse@uni-bremen.de>
|
||||
Matt Clarkson <mattyclarkson@gmail.com>
|
||||
Maxim Vafin <maxvafin@gmail.com>
|
||||
Mike Apodaca <gatorfax@gmail.com>
|
||||
Min-Yih Hsu <yihshyng223@gmail.com>
|
||||
Nick Hutchinson <nshutchinson@gmail.com>
|
||||
Norman Heino <norman.heino@gmail.com>
|
||||
Oleksandr Sochka <sasha.sochka@gmail.com>
|
||||
Ori Livneh <ori.livneh@gmail.com>
|
||||
Pascal Leroy <phl@google.com>
|
||||
Paul Redmond <paul.redmond@gmail.com>
|
||||
Pierre Phaneuf <pphaneuf@google.com>
|
||||
Radoslav Yovchev <radoslav.tm@gmail.com>
|
||||
Raghu Raja <raghu@enfabrica.net>
|
||||
Rainer Orth <ro@cebitec.uni-bielefeld.de>
|
||||
Raul Marin <rmrodriguez@cartodb.com>
|
||||
Ray Glover <ray.glover@uk.ibm.com>
|
||||
Robert Guo <robert.guo@mongodb.com>
|
||||
Roman Lebedev <lebedev.ri@gmail.com>
|
||||
Sayan Bhattacharjee <aero.sayan@gmail.com>
|
||||
Shuo Chen <chenshuo@chenshuo.com>
|
||||
Steven Wan <wan.yu@ibm.com>
|
||||
Tobias Schmidt <tobias.schmidt@in.tum.de>
|
||||
Tobias Ulvgård <tobias.ulvgard@dirac.se>
|
||||
Tom Madams <tom.ej.madams@gmail.com> <tmadams@google.com>
|
||||
Yixuan Qiu <yixuanq@gmail.com>
|
||||
|
||||
41
third_party/benchmark/MODULE.bazel
vendored
41
third_party/benchmark/MODULE.bazel
vendored
@@ -1,41 +0,0 @@
|
||||
module(
|
||||
name = "google_benchmark",
|
||||
version = "1.9.4",
|
||||
)
|
||||
|
||||
bazel_dep(name = "bazel_skylib", version = "1.7.1")
|
||||
bazel_dep(name = "platforms", version = "0.0.10")
|
||||
bazel_dep(name = "rules_cc", version = "0.0.9")
|
||||
|
||||
bazel_dep(name = "rules_python", version = "1.0.0", dev_dependency = True)
|
||||
bazel_dep(name = "googletest", version = "1.14.0", dev_dependency = True, repo_name = "com_google_googletest")
|
||||
|
||||
bazel_dep(name = "libpfm", version = "4.11.0.bcr.1")
|
||||
|
||||
# Register a toolchain for Python 3.9 to be able to build numpy. Python
|
||||
# versions >=3.10 are problematic.
|
||||
# A second reason for this is to be able to build Python hermetically instead
|
||||
# of relying on the changing default version from rules_python.
|
||||
|
||||
python = use_extension("@rules_python//python/extensions:python.bzl", "python", dev_dependency = True)
|
||||
python.toolchain(python_version = "3.8")
|
||||
python.toolchain(python_version = "3.9")
|
||||
python.toolchain(python_version = "3.10")
|
||||
python.toolchain(python_version = "3.11")
|
||||
python.toolchain(
|
||||
is_default = True,
|
||||
python_version = "3.12",
|
||||
)
|
||||
python.toolchain(python_version = "3.13")
|
||||
|
||||
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip", dev_dependency = True)
|
||||
pip.parse(
|
||||
hub_name = "tools_pip_deps",
|
||||
python_version = "3.9",
|
||||
requirements_lock = "//tools:requirements.txt",
|
||||
)
|
||||
use_repo(pip, "tools_pip_deps")
|
||||
|
||||
# -- bazel_dep definitions -- #
|
||||
|
||||
bazel_dep(name = "nanobind_bazel", version = "2.7.0", dev_dependency = True)
|
||||
1047
third_party/benchmark/README.md
vendored
1047
third_party/benchmark/README.md
vendored
File diff suppressed because it is too large
Load Diff
21
third_party/benchmark/WORKSPACE
vendored
21
third_party/benchmark/WORKSPACE
vendored
@@ -1,20 +1,7 @@
|
||||
workspace(name = "com_github_google_benchmark")
|
||||
|
||||
load("//:bazel/benchmark_deps.bzl", "benchmark_deps")
|
||||
|
||||
benchmark_deps()
|
||||
|
||||
load("@rules_python//python:repositories.bzl", "py_repositories")
|
||||
|
||||
py_repositories()
|
||||
|
||||
load("@rules_python//python:pip.bzl", "pip_parse")
|
||||
|
||||
pip_parse(
|
||||
name = "tools_pip_deps",
|
||||
requirements_lock = "//tools:requirements.txt",
|
||||
http_archive(
|
||||
name = "com_google_googletest",
|
||||
urls = ["https://github.com/google/googletest/archive/3f0cf6b62ad1eb50d8736538363d3580dd640c3e.zip"],
|
||||
strip_prefix = "googletest-3f0cf6b62ad1eb50d8736538363d3580dd640c3e",
|
||||
)
|
||||
|
||||
load("@tools_pip_deps//:requirements.bzl", "install_deps")
|
||||
|
||||
install_deps()
|
||||
|
||||
2
third_party/benchmark/WORKSPACE.bzlmod
vendored
2
third_party/benchmark/WORKSPACE.bzlmod
vendored
@@ -1,2 +0,0 @@
|
||||
# This file marks the root of the Bazel workspace.
|
||||
# See MODULE.bazel for dependencies and setup.
|
||||
2
third_party/benchmark/_config.yml
vendored
2
third_party/benchmark/_config.yml
vendored
@@ -1,2 +0,0 @@
|
||||
theme: jekyll-theme-midnight
|
||||
markdown: GFM
|
||||
2
third_party/benchmark/appveyor.yml
vendored
2
third_party/benchmark/appveyor.yml
vendored
@@ -41,7 +41,7 @@ build_script:
|
||||
- cmake --build . --config %configuration%
|
||||
|
||||
test_script:
|
||||
- ctest --build-config %configuration% --timeout 300 --output-on-failure
|
||||
- ctest -c %configuration% --timeout 300 --output-on-failure
|
||||
|
||||
artifacts:
|
||||
- path: '_build/CMakeFiles/*.log'
|
||||
|
||||
54
third_party/benchmark/bazel/benchmark_deps.bzl
vendored
54
third_party/benchmark/bazel/benchmark_deps.bzl
vendored
@@ -1,54 +0,0 @@
|
||||
"""
|
||||
This file contains the Bazel build dependencies for Google Benchmark (both C++ source and Python bindings).
|
||||
"""
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository")
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
def benchmark_deps():
|
||||
"""Loads dependencies required to build Google Benchmark."""
|
||||
|
||||
if "bazel_skylib" not in native.existing_rules():
|
||||
http_archive(
|
||||
name = "bazel_skylib",
|
||||
sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
if "rules_python" not in native.existing_rules():
|
||||
http_archive(
|
||||
name = "rules_python",
|
||||
sha256 = "e85ae30de33625a63eca7fc40a94fea845e641888e52f32b6beea91e8b1b2793",
|
||||
strip_prefix = "rules_python-0.27.1",
|
||||
url = "https://github.com/bazelbuild/rules_python/releases/download/0.27.1/rules_python-0.27.1.tar.gz",
|
||||
)
|
||||
|
||||
if "com_google_googletest" not in native.existing_rules():
|
||||
new_git_repository(
|
||||
name = "com_google_googletest",
|
||||
remote = "https://github.com/google/googletest.git",
|
||||
tag = "release-1.12.1",
|
||||
)
|
||||
|
||||
if "nanobind" not in native.existing_rules():
|
||||
new_git_repository(
|
||||
name = "nanobind",
|
||||
remote = "https://github.com/wjakob/nanobind.git",
|
||||
tag = "v1.9.2",
|
||||
build_file = "@//bindings/python:nanobind.BUILD",
|
||||
recursive_init_submodules = True,
|
||||
)
|
||||
|
||||
if "libpfm" not in native.existing_rules():
|
||||
# Downloaded from v4.9.0 tag at https://sourceforge.net/p/perfmon2/libpfm4/ref/master/tags/
|
||||
http_archive(
|
||||
name = "libpfm",
|
||||
build_file = str(Label("//tools:libpfm.BUILD.bazel")),
|
||||
sha256 = "5da5f8872bde14b3634c9688d980f68bda28b510268723cc12973eedbab9fecc",
|
||||
type = "tar.gz",
|
||||
strip_prefix = "libpfm-4.11.0",
|
||||
urls = ["https://sourceforge.net/projects/perfmon2/files/libpfm4/libpfm-4.11.0.tar.gz/download"],
|
||||
)
|
||||
@@ -1,34 +0,0 @@
|
||||
load("@nanobind_bazel//:build_defs.bzl", "nanobind_extension", "nanobind_stubgen")
|
||||
load("@rules_python//python:defs.bzl", "py_library", "py_test")
|
||||
|
||||
py_library(
|
||||
name = "google_benchmark",
|
||||
srcs = ["__init__.py"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":_benchmark",
|
||||
],
|
||||
)
|
||||
|
||||
nanobind_extension(
|
||||
name = "_benchmark",
|
||||
srcs = ["benchmark.cc"],
|
||||
deps = ["//:benchmark"],
|
||||
)
|
||||
|
||||
nanobind_stubgen(
|
||||
name = "benchmark_stubgen",
|
||||
marker_file = "bindings/python/google_benchmark/py.typed",
|
||||
module = ":_benchmark",
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "example",
|
||||
srcs = ["example.py"],
|
||||
python_version = "PY3",
|
||||
srcs_version = "PY3",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":google_benchmark",
|
||||
],
|
||||
)
|
||||
@@ -1,145 +0,0 @@
|
||||
# Copyright 2020 Google Inc. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
"""Python benchmarking utilities.
|
||||
|
||||
Example usage:
|
||||
import google_benchmark as benchmark
|
||||
|
||||
@benchmark.register
|
||||
def my_benchmark(state):
|
||||
... # Code executed outside `while` loop is not timed.
|
||||
|
||||
while state:
|
||||
... # Code executed within `while` loop is timed.
|
||||
|
||||
if __name__ == '__main__':
|
||||
benchmark.main()
|
||||
"""
|
||||
|
||||
import atexit
|
||||
|
||||
from absl import app
|
||||
|
||||
from google_benchmark import _benchmark
|
||||
from google_benchmark._benchmark import (
|
||||
Counter as Counter,
|
||||
State as State,
|
||||
kMicrosecond as kMicrosecond,
|
||||
kMillisecond as kMillisecond,
|
||||
kNanosecond as kNanosecond,
|
||||
kSecond as kSecond,
|
||||
o1 as o1,
|
||||
oAuto as oAuto,
|
||||
oLambda as oLambda,
|
||||
oLogN as oLogN,
|
||||
oN as oN,
|
||||
oNCubed as oNCubed,
|
||||
oNLogN as oNLogN,
|
||||
oNone as oNone,
|
||||
oNSquared as oNSquared,
|
||||
)
|
||||
|
||||
__version__ = "1.9.4"
|
||||
|
||||
|
||||
class __OptionMaker:
|
||||
"""A stateless class to collect benchmark options.
|
||||
|
||||
Collect all decorator calls like @option.range(start=0, limit=1<<5).
|
||||
"""
|
||||
|
||||
class Options:
|
||||
"""Pure data class to store options calls, along with the benchmarked
|
||||
function."""
|
||||
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
self.builder_calls = []
|
||||
|
||||
@classmethod
|
||||
def make(cls, func_or_options):
|
||||
"""Make Options from Options or the benchmarked function."""
|
||||
if isinstance(func_or_options, cls.Options):
|
||||
return func_or_options
|
||||
return cls.Options(func_or_options)
|
||||
|
||||
def __getattr__(self, builder_name):
|
||||
"""Append option call in the Options."""
|
||||
|
||||
# The function that get returned on @option.range(start=0, limit=1<<5).
|
||||
def __builder_method(*args, **kwargs):
|
||||
# The decorator that get called, either with the benchmared function
|
||||
# or the previous Options
|
||||
def __decorator(func_or_options):
|
||||
options = self.make(func_or_options)
|
||||
options.builder_calls.append((builder_name, args, kwargs))
|
||||
# The decorator returns Options so it is not technically a
|
||||
# decorator and needs a final call to @register
|
||||
return options
|
||||
|
||||
return __decorator
|
||||
|
||||
return __builder_method
|
||||
|
||||
|
||||
# Alias for nicer API.
|
||||
# We have to instantiate an object, even if stateless, to be able to use
|
||||
# __getattr__ on option.range
|
||||
option = __OptionMaker()
|
||||
|
||||
|
||||
def register(undefined=None, *, name=None):
|
||||
"""Register function for benchmarking."""
|
||||
if undefined is None:
|
||||
# Decorator is called without parenthesis so we return a decorator
|
||||
return lambda f: register(f, name=name)
|
||||
|
||||
# We have either the function to benchmark (simple case) or an instance of
|
||||
# Options (@option._ case).
|
||||
options = __OptionMaker.make(undefined)
|
||||
|
||||
if name is None:
|
||||
name = options.func.__name__
|
||||
|
||||
# We register the benchmark and reproduce all the @option._ calls onto the
|
||||
# benchmark builder pattern
|
||||
benchmark = _benchmark.RegisterBenchmark(name, options.func)
|
||||
for name, args, kwargs in options.builder_calls[::-1]:
|
||||
getattr(benchmark, name)(*args, **kwargs)
|
||||
|
||||
# return the benchmarked function because the decorator does not modify it
|
||||
return options.func
|
||||
|
||||
|
||||
def _flags_parser(argv):
|
||||
argv = _benchmark.Initialize(argv)
|
||||
return app.parse_flags_with_usage(argv)
|
||||
|
||||
|
||||
def _run_benchmarks(argv):
|
||||
if len(argv) > 1:
|
||||
raise app.UsageError("Too many command-line arguments.")
|
||||
return _benchmark.RunSpecifiedBenchmarks()
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
return app.run(_run_benchmarks, argv=argv, flags_parser=_flags_parser)
|
||||
|
||||
|
||||
# FIXME: can we rerun with disabled ASLR?
|
||||
|
||||
# Methods for use with custom main function.
|
||||
initialize = _benchmark.Initialize
|
||||
run_benchmarks = _benchmark.RunSpecifiedBenchmarks
|
||||
atexit.register(_benchmark.ClearRegisteredBenchmarks)
|
||||
@@ -1,184 +0,0 @@
|
||||
// Benchmark for Python.
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "nanobind/nanobind.h"
|
||||
#include "nanobind/operators.h"
|
||||
#include "nanobind/stl/bind_map.h"
|
||||
#include "nanobind/stl/string.h"
|
||||
#include "nanobind/stl/vector.h"
|
||||
|
||||
NB_MAKE_OPAQUE(benchmark::UserCounters);
|
||||
|
||||
namespace {
|
||||
namespace nb = nanobind;
|
||||
|
||||
std::vector<std::string> Initialize(const std::vector<std::string>& argv) {
|
||||
// The `argv` pointers here become invalid when this function returns, but
|
||||
// benchmark holds the pointer to `argv[0]`. We create a static copy of it
|
||||
// so it persists, and replace the pointer below.
|
||||
static std::string executable_name(argv[0]);
|
||||
std::vector<char*> ptrs;
|
||||
ptrs.reserve(argv.size());
|
||||
for (auto& arg : argv) {
|
||||
ptrs.push_back(const_cast<char*>(arg.c_str()));
|
||||
}
|
||||
ptrs[0] = const_cast<char*>(executable_name.c_str());
|
||||
int argc = static_cast<int>(argv.size());
|
||||
benchmark::Initialize(&argc, ptrs.data());
|
||||
std::vector<std::string> remaining_argv;
|
||||
remaining_argv.reserve(argc);
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
remaining_argv.emplace_back(ptrs[i]);
|
||||
}
|
||||
return remaining_argv;
|
||||
}
|
||||
|
||||
benchmark::internal::Benchmark* RegisterBenchmark(const std::string& name,
|
||||
nb::callable f) {
|
||||
return benchmark::RegisterBenchmark(
|
||||
name, [f](benchmark::State& state) { f(&state); });
|
||||
}
|
||||
|
||||
NB_MODULE(_benchmark, m) {
|
||||
|
||||
using benchmark::TimeUnit;
|
||||
nb::enum_<TimeUnit>(m, "TimeUnit")
|
||||
.value("kNanosecond", TimeUnit::kNanosecond)
|
||||
.value("kMicrosecond", TimeUnit::kMicrosecond)
|
||||
.value("kMillisecond", TimeUnit::kMillisecond)
|
||||
.value("kSecond", TimeUnit::kSecond)
|
||||
.export_values();
|
||||
|
||||
using benchmark::BigO;
|
||||
nb::enum_<BigO>(m, "BigO")
|
||||
.value("oNone", BigO::oNone)
|
||||
.value("o1", BigO::o1)
|
||||
.value("oN", BigO::oN)
|
||||
.value("oNSquared", BigO::oNSquared)
|
||||
.value("oNCubed", BigO::oNCubed)
|
||||
.value("oLogN", BigO::oLogN)
|
||||
.value("oNLogN", BigO::oNLogN)
|
||||
.value("oAuto", BigO::oAuto)
|
||||
.value("oLambda", BigO::oLambda)
|
||||
.export_values();
|
||||
|
||||
using benchmark::internal::Benchmark;
|
||||
nb::class_<Benchmark>(m, "Benchmark")
|
||||
// For methods returning a pointer to the current object, reference
|
||||
// return policy is used to ask nanobind not to take ownership of the
|
||||
// returned object and avoid calling delete on it.
|
||||
// https://pybind11.readthedocs.io/en/stable/advanced/functions.html#return-value-policies
|
||||
//
|
||||
// For methods taking a const std::vector<...>&, a copy is created
|
||||
// because a it is bound to a Python list.
|
||||
// https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html
|
||||
.def("unit", &Benchmark::Unit, nb::rv_policy::reference)
|
||||
.def("arg", &Benchmark::Arg, nb::rv_policy::reference)
|
||||
.def("args", &Benchmark::Args, nb::rv_policy::reference)
|
||||
.def("range", &Benchmark::Range, nb::rv_policy::reference,
|
||||
nb::arg("start"), nb::arg("limit"))
|
||||
.def("dense_range", &Benchmark::DenseRange,
|
||||
nb::rv_policy::reference, nb::arg("start"),
|
||||
nb::arg("limit"), nb::arg("step") = 1)
|
||||
.def("ranges", &Benchmark::Ranges, nb::rv_policy::reference)
|
||||
.def("args_product", &Benchmark::ArgsProduct,
|
||||
nb::rv_policy::reference)
|
||||
.def("arg_name", &Benchmark::ArgName, nb::rv_policy::reference)
|
||||
.def("arg_names", &Benchmark::ArgNames,
|
||||
nb::rv_policy::reference)
|
||||
.def("range_pair", &Benchmark::RangePair,
|
||||
nb::rv_policy::reference, nb::arg("lo1"), nb::arg("hi1"),
|
||||
nb::arg("lo2"), nb::arg("hi2"))
|
||||
.def("range_multiplier", &Benchmark::RangeMultiplier,
|
||||
nb::rv_policy::reference)
|
||||
.def("min_time", &Benchmark::MinTime, nb::rv_policy::reference)
|
||||
.def("min_warmup_time", &Benchmark::MinWarmUpTime,
|
||||
nb::rv_policy::reference)
|
||||
.def("iterations", &Benchmark::Iterations,
|
||||
nb::rv_policy::reference)
|
||||
.def("repetitions", &Benchmark::Repetitions,
|
||||
nb::rv_policy::reference)
|
||||
.def("report_aggregates_only", &Benchmark::ReportAggregatesOnly,
|
||||
nb::rv_policy::reference, nb::arg("value") = true)
|
||||
.def("display_aggregates_only", &Benchmark::DisplayAggregatesOnly,
|
||||
nb::rv_policy::reference, nb::arg("value") = true)
|
||||
.def("measure_process_cpu_time", &Benchmark::MeasureProcessCPUTime,
|
||||
nb::rv_policy::reference)
|
||||
.def("use_real_time", &Benchmark::UseRealTime,
|
||||
nb::rv_policy::reference)
|
||||
.def("use_manual_time", &Benchmark::UseManualTime,
|
||||
nb::rv_policy::reference)
|
||||
.def(
|
||||
"complexity",
|
||||
(Benchmark * (Benchmark::*)(benchmark::BigO)) & Benchmark::Complexity,
|
||||
nb::rv_policy::reference,
|
||||
nb::arg("complexity") = benchmark::oAuto);
|
||||
|
||||
using benchmark::Counter;
|
||||
nb::class_<Counter> py_counter(m, "Counter");
|
||||
|
||||
nb::enum_<Counter::Flags>(py_counter, "Flags", nb::is_arithmetic(), nb::is_flag())
|
||||
.value("kDefaults", Counter::Flags::kDefaults)
|
||||
.value("kIsRate", Counter::Flags::kIsRate)
|
||||
.value("kAvgThreads", Counter::Flags::kAvgThreads)
|
||||
.value("kAvgThreadsRate", Counter::Flags::kAvgThreadsRate)
|
||||
.value("kIsIterationInvariant", Counter::Flags::kIsIterationInvariant)
|
||||
.value("kIsIterationInvariantRate",
|
||||
Counter::Flags::kIsIterationInvariantRate)
|
||||
.value("kAvgIterations", Counter::Flags::kAvgIterations)
|
||||
.value("kAvgIterationsRate", Counter::Flags::kAvgIterationsRate)
|
||||
.value("kInvert", Counter::Flags::kInvert)
|
||||
.export_values();
|
||||
|
||||
nb::enum_<Counter::OneK>(py_counter, "OneK")
|
||||
.value("kIs1000", Counter::OneK::kIs1000)
|
||||
.value("kIs1024", Counter::OneK::kIs1024)
|
||||
.export_values();
|
||||
|
||||
py_counter
|
||||
.def(nb::init<double, Counter::Flags, Counter::OneK>(),
|
||||
nb::arg("value") = 0., nb::arg("flags") = Counter::kDefaults,
|
||||
nb::arg("k") = Counter::kIs1000)
|
||||
.def("__init__",
|
||||
([](Counter* c, double value) { new (c) Counter(value); }))
|
||||
.def_rw("value", &Counter::value)
|
||||
.def_rw("flags", &Counter::flags)
|
||||
.def_rw("oneK", &Counter::oneK)
|
||||
.def(nb::init_implicit<double>());
|
||||
|
||||
nb::implicitly_convertible<nb::int_, Counter>();
|
||||
|
||||
nb::bind_map<benchmark::UserCounters>(m, "UserCounters");
|
||||
|
||||
using benchmark::State;
|
||||
nb::class_<State>(m, "State")
|
||||
.def("__bool__", &State::KeepRunning)
|
||||
.def_prop_ro("keep_running", &State::KeepRunning)
|
||||
.def("pause_timing", &State::PauseTiming)
|
||||
.def("resume_timing", &State::ResumeTiming)
|
||||
.def("skip_with_error", &State::SkipWithError)
|
||||
.def_prop_ro("error_occurred", &State::error_occurred)
|
||||
.def("set_iteration_time", &State::SetIterationTime)
|
||||
.def_prop_rw("bytes_processed", &State::bytes_processed,
|
||||
&State::SetBytesProcessed)
|
||||
.def_prop_rw("complexity_n", &State::complexity_length_n,
|
||||
&State::SetComplexityN)
|
||||
.def_prop_rw("items_processed", &State::items_processed,
|
||||
&State::SetItemsProcessed)
|
||||
.def("set_label", &State::SetLabel)
|
||||
.def("range", &State::range, nb::arg("pos") = 0)
|
||||
.def_prop_ro("iterations", &State::iterations)
|
||||
.def_prop_ro("name", &State::name)
|
||||
.def_rw("counters", &State::counters)
|
||||
.def_prop_ro("thread_index", &State::thread_index)
|
||||
.def_prop_ro("threads", &State::threads);
|
||||
|
||||
m.def("Initialize", Initialize);
|
||||
m.def("RegisterBenchmark", RegisterBenchmark,
|
||||
nb::rv_policy::reference);
|
||||
m.def("RunSpecifiedBenchmarks",
|
||||
[]() { benchmark::RunSpecifiedBenchmarks(); });
|
||||
m.def("ClearRegisteredBenchmarks", benchmark::ClearRegisteredBenchmarks);
|
||||
};
|
||||
} // namespace
|
||||
@@ -1,140 +0,0 @@
|
||||
# Copyright 2020 Google Inc. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
"""Example of Python using C++ benchmark framework.
|
||||
|
||||
To run this example, you must first install the `google_benchmark` Python
|
||||
package.
|
||||
|
||||
To install using `setup.py`, download and extract the `google_benchmark` source.
|
||||
In the extracted directory, execute:
|
||||
python setup.py install
|
||||
"""
|
||||
|
||||
import random
|
||||
import time
|
||||
|
||||
import google_benchmark as benchmark
|
||||
from google_benchmark import Counter
|
||||
|
||||
|
||||
@benchmark.register
|
||||
def empty(state):
|
||||
while state:
|
||||
pass
|
||||
|
||||
|
||||
@benchmark.register
|
||||
def sum_million(state):
|
||||
while state:
|
||||
sum(range(1_000_000))
|
||||
|
||||
|
||||
@benchmark.register
|
||||
def pause_timing(state):
|
||||
"""Pause timing every iteration."""
|
||||
while state:
|
||||
# Construct a list of random ints every iteration without timing it
|
||||
state.pause_timing()
|
||||
random_list = [random.randint(0, 100) for _ in range(100)]
|
||||
state.resume_timing()
|
||||
# Time the in place sorting algorithm
|
||||
random_list.sort()
|
||||
|
||||
|
||||
@benchmark.register
|
||||
def skipped(state):
|
||||
if True: # Test some predicate here.
|
||||
state.skip_with_error("some error")
|
||||
return # NOTE: You must explicitly return, or benchmark will continue.
|
||||
|
||||
# Benchmark code would be here.
|
||||
|
||||
|
||||
@benchmark.register
|
||||
@benchmark.option.use_manual_time()
|
||||
def manual_timing(state):
|
||||
while state:
|
||||
# Manually count Python CPU time
|
||||
start = time.perf_counter() # perf_counter_ns() in Python 3.7+
|
||||
# Something to benchmark
|
||||
time.sleep(0.01)
|
||||
end = time.perf_counter()
|
||||
state.set_iteration_time(end - start)
|
||||
|
||||
|
||||
@benchmark.register
|
||||
def custom_counters(state):
|
||||
"""Collect custom metric using benchmark.Counter."""
|
||||
num_foo = 0.0
|
||||
while state:
|
||||
# Benchmark some code here
|
||||
# Collect some custom metric named foo
|
||||
num_foo += 0.13
|
||||
|
||||
# Automatic Counter from numbers.
|
||||
state.counters["foo"] = num_foo
|
||||
# Set a counter as a rate.
|
||||
state.counters["foo_rate"] = Counter(num_foo, Counter.kIsRate)
|
||||
# Set a counter as an inverse of rate.
|
||||
state.counters["foo_inv_rate"] = Counter(
|
||||
num_foo, Counter.kIsRate | Counter.kInvert
|
||||
)
|
||||
# Set a counter as a thread-average quantity.
|
||||
state.counters["foo_avg"] = Counter(num_foo, Counter.kAvgThreads)
|
||||
# There's also a combined flag:
|
||||
state.counters["foo_avg_rate"] = Counter(num_foo, Counter.kAvgThreadsRate)
|
||||
|
||||
|
||||
@benchmark.register
|
||||
@benchmark.option.measure_process_cpu_time()
|
||||
@benchmark.option.use_real_time()
|
||||
def with_options(state):
|
||||
while state:
|
||||
sum(range(1_000_000))
|
||||
|
||||
|
||||
@benchmark.register(name="sum_million_microseconds")
|
||||
@benchmark.option.unit(benchmark.kMicrosecond)
|
||||
def with_options2(state):
|
||||
while state:
|
||||
sum(range(1_000_000))
|
||||
|
||||
|
||||
@benchmark.register
|
||||
@benchmark.option.arg(100)
|
||||
@benchmark.option.arg(1000)
|
||||
def passing_argument(state):
|
||||
while state:
|
||||
sum(range(state.range(0)))
|
||||
|
||||
|
||||
@benchmark.register
|
||||
@benchmark.option.range(8, limit=8 << 10)
|
||||
def using_range(state):
|
||||
while state:
|
||||
sum(range(state.range(0)))
|
||||
|
||||
|
||||
@benchmark.register
|
||||
@benchmark.option.range_multiplier(2)
|
||||
@benchmark.option.range(1 << 10, 1 << 18)
|
||||
@benchmark.option.complexity(benchmark.oN)
|
||||
def computing_complexity(state):
|
||||
while state:
|
||||
sum(range(state.range(0)))
|
||||
state.complexity_n = state.range(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
benchmark.main()
|
||||
@@ -34,11 +34,9 @@ function(add_cxx_compiler_flag FLAG)
|
||||
check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG})
|
||||
set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}")
|
||||
if(${MANGLED_FLAG})
|
||||
if(ARGC GREATER 1)
|
||||
set(VARIANT ${ARGV1})
|
||||
set(VARIANT ${ARGV1})
|
||||
if(ARGV1)
|
||||
string(TOUPPER "_${VARIANT}" VARIANT)
|
||||
else()
|
||||
set(VARIANT "")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${BENCHMARK_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE)
|
||||
endif()
|
||||
@@ -51,11 +49,9 @@ function(add_required_cxx_compiler_flag FLAG)
|
||||
check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG})
|
||||
set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}")
|
||||
if(${MANGLED_FLAG})
|
||||
if(ARGC GREATER 1)
|
||||
set(VARIANT ${ARGV1})
|
||||
set(VARIANT ${ARGV1})
|
||||
if(ARGV1)
|
||||
string(TOUPPER "_${VARIANT}" VARIANT)
|
||||
else()
|
||||
set(VARIANT "")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE)
|
||||
|
||||
@@ -17,8 +17,6 @@ if(__cxx_feature_check)
|
||||
endif()
|
||||
set(__cxx_feature_check INCLUDED)
|
||||
|
||||
option(CXXFEATURECHECK_DEBUG OFF)
|
||||
|
||||
function(cxx_feature_check FILE)
|
||||
string(TOLOWER ${FILE} FILE)
|
||||
string(TOUPPER ${FILE} VAR)
|
||||
@@ -29,38 +27,26 @@ function(cxx_feature_check FILE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(FEATURE_CHECK_CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS})
|
||||
if (ARGC GREATER 1)
|
||||
message(STATUS "Enabling additional flags: ${ARGV1}")
|
||||
list(APPEND FEATURE_CHECK_CMAKE_FLAGS ${ARGV1})
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED COMPILE_${FEATURE})
|
||||
message(STATUS "Performing Test ${FEATURE}")
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
message(STATUS "Cross-compiling to test ${FEATURE}")
|
||||
try_compile(COMPILE_${FEATURE}
|
||||
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CMAKE_FLAGS ${FEATURE_CHECK_CMAKE_FLAGS}
|
||||
LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES}
|
||||
OUTPUT_VARIABLE COMPILE_OUTPUT_VAR)
|
||||
CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS}
|
||||
LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES})
|
||||
if(COMPILE_${FEATURE})
|
||||
message(WARNING
|
||||
"If you see build failures due to cross compilation, try setting HAVE_${VAR} to 0")
|
||||
set(RUN_${FEATURE} 0 CACHE INTERNAL "")
|
||||
set(RUN_${FEATURE} 0)
|
||||
else()
|
||||
set(RUN_${FEATURE} 1 CACHE INTERNAL "")
|
||||
set(RUN_${FEATURE} 1)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Compiling and running to test ${FEATURE}")
|
||||
message(STATUS "Performing Test ${FEATURE}")
|
||||
try_run(RUN_${FEATURE} COMPILE_${FEATURE}
|
||||
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CMAKE_FLAGS ${FEATURE_CHECK_CMAKE_FLAGS}
|
||||
LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES}
|
||||
COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT_VAR)
|
||||
CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS}
|
||||
LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -70,11 +56,7 @@ function(cxx_feature_check FILE)
|
||||
add_definitions(-DHAVE_${VAR})
|
||||
else()
|
||||
if(NOT COMPILE_${FEATURE})
|
||||
if(CXXFEATURECHECK_DEBUG)
|
||||
message(STATUS "Performing Test ${FEATURE} -- failed to compile: ${COMPILE_OUTPUT_VAR}")
|
||||
else()
|
||||
message(STATUS "Performing Test ${FEATURE} -- failed to compile")
|
||||
endif()
|
||||
message(STATUS "Performing Test ${FEATURE} -- failed to compile")
|
||||
else()
|
||||
message(STATUS "Performing Test ${FEATURE} -- compiled but failed to run")
|
||||
endif()
|
||||
|
||||
11
third_party/benchmark/cmake/Config.cmake.in
vendored
11
third_party/benchmark/cmake/Config.cmake.in
vendored
@@ -1,12 +1 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include (CMakeFindDependencyMacro)
|
||||
|
||||
find_dependency (Threads)
|
||||
|
||||
if (@BENCHMARK_ENABLE_LIBPFM@)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||
find_dependency (PFM)
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
|
||||
|
||||
22
third_party/benchmark/cmake/GetGitVersion.cmake
vendored
22
third_party/benchmark/cmake/GetGitVersion.cmake
vendored
@@ -20,17 +20,35 @@ set(__get_git_version INCLUDED)
|
||||
|
||||
function(get_git_version var)
|
||||
if(GIT_EXECUTABLE)
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --match "v[0-9]*.[0-9]*.[0-9]*" --abbrev=8 --dirty
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} describe --match "v[0-9]*.[0-9]*.[0-9]*" --abbrev=8
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
RESULT_VARIABLE status
|
||||
OUTPUT_VARIABLE GIT_VERSION
|
||||
ERROR_QUIET)
|
||||
if(status)
|
||||
if(${status})
|
||||
set(GIT_VERSION "v0.0.0")
|
||||
else()
|
||||
string(STRIP ${GIT_VERSION} GIT_VERSION)
|
||||
string(REGEX REPLACE "-[0-9]+-g" "-" GIT_VERSION ${GIT_VERSION})
|
||||
endif()
|
||||
|
||||
# Work out if the repository is dirty
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} update-index -q --refresh
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
OUTPUT_QUIET
|
||||
ERROR_QUIET)
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD --
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_DIFF_INDEX
|
||||
ERROR_QUIET)
|
||||
string(COMPARE NOTEQUAL "${GIT_DIFF_INDEX}" "" GIT_DIRTY)
|
||||
if (${GIT_DIRTY})
|
||||
set(GIT_VERSION "${GIT_VERSION}-dirty")
|
||||
endif()
|
||||
else()
|
||||
set(GIT_VERSION "v0.0.0")
|
||||
endif()
|
||||
|
||||
message(STATUS "git Version: ${GIT_VERSION}")
|
||||
set(${var} ${GIT_VERSION} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
58
third_party/benchmark/cmake/GoogleTest.cmake
vendored
58
third_party/benchmark/cmake/GoogleTest.cmake
vendored
@@ -1,58 +0,0 @@
|
||||
# Download and unpack googletest at configure time
|
||||
set(GOOGLETEST_PREFIX "${benchmark_BINARY_DIR}/third_party/googletest")
|
||||
configure_file(${benchmark_SOURCE_DIR}/cmake/GoogleTest.cmake.in ${GOOGLETEST_PREFIX}/CMakeLists.txt @ONLY)
|
||||
|
||||
set(GOOGLETEST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/googletest" CACHE PATH "") # Mind the quotes
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}"
|
||||
-DALLOW_DOWNLOADING_GOOGLETEST=${BENCHMARK_DOWNLOAD_DEPENDENCIES} -DGOOGLETEST_PATH:PATH=${GOOGLETEST_PATH} .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${GOOGLETEST_PREFIX}
|
||||
)
|
||||
|
||||
if(result)
|
||||
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} --build .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${GOOGLETEST_PREFIX}
|
||||
)
|
||||
|
||||
if(result)
|
||||
message(FATAL_ERROR "Build step for googletest failed: ${result}")
|
||||
endif()
|
||||
|
||||
# Prevent overriding the parent project's compiler/linker
|
||||
# settings on Windows
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
include(${GOOGLETEST_PREFIX}/googletest-paths.cmake)
|
||||
|
||||
# Add googletest directly to our build. This defines
|
||||
# the gtest and gtest_main targets.
|
||||
add_subdirectory(${GOOGLETEST_SOURCE_DIR}
|
||||
${GOOGLETEST_BINARY_DIR}
|
||||
EXCLUDE_FROM_ALL)
|
||||
|
||||
# googletest doesn't seem to want to stay build warning clean so let's not hurt ourselves.
|
||||
if (MSVC)
|
||||
target_compile_options(gtest PRIVATE "/wd4244" "/wd4722")
|
||||
target_compile_options(gtest_main PRIVATE "/wd4244" "/wd4722")
|
||||
target_compile_options(gmock PRIVATE "/wd4244" "/wd4722")
|
||||
target_compile_options(gmock_main PRIVATE "/wd4244" "/wd4722")
|
||||
else()
|
||||
target_compile_options(gtest PRIVATE "-w")
|
||||
target_compile_options(gtest_main PRIVATE "-w")
|
||||
target_compile_options(gmock PRIVATE "-w")
|
||||
target_compile_options(gmock_main PRIVATE "-w")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED GTEST_COMPILE_COMMANDS)
|
||||
set(GTEST_COMPILE_COMMANDS ON)
|
||||
endif()
|
||||
|
||||
set_target_properties(gtest PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:gtest,INTERFACE_INCLUDE_DIRECTORIES> EXPORT_COMPILE_COMMANDS ${GTEST_COMPILE_COMMANDS})
|
||||
set_target_properties(gtest_main PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:gtest_main,INTERFACE_INCLUDE_DIRECTORIES> EXPORT_COMPILE_COMMANDS ${GTEST_COMPILE_COMMANDS})
|
||||
set_target_properties(gmock PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:gmock,INTERFACE_INCLUDE_DIRECTORIES> EXPORT_COMPILE_COMMANDS ${GTEST_COMPILE_COMMANDS})
|
||||
set_target_properties(gmock_main PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:gmock_main,INTERFACE_INCLUDE_DIRECTORIES> EXPORT_COMPILE_COMMANDS ${GTEST_COMPILE_COMMANDS})
|
||||
60
third_party/benchmark/cmake/GoogleTest.cmake.in
vendored
60
third_party/benchmark/cmake/GoogleTest.cmake.in
vendored
@@ -1,60 +0,0 @@
|
||||
cmake_minimum_required (VERSION 3.13...3.22)
|
||||
|
||||
project(googletest-download NONE)
|
||||
|
||||
# Enable ExternalProject CMake module
|
||||
include(ExternalProject)
|
||||
|
||||
option(ALLOW_DOWNLOADING_GOOGLETEST "If googletest src tree is not found in location specified by GOOGLETEST_PATH, do fetch the archive from internet" OFF)
|
||||
set(GOOGLETEST_PATH "/usr/src/googletest" CACHE PATH
|
||||
"Path to the googletest root tree. Should contain googletest and googlemock subdirs. And CMakeLists.txt in root, and in both of these subdirs")
|
||||
|
||||
# Download and install GoogleTest
|
||||
|
||||
message(STATUS "Looking for Google Test sources")
|
||||
message(STATUS "Looking for Google Test sources in ${GOOGLETEST_PATH}")
|
||||
if(EXISTS "${GOOGLETEST_PATH}" AND IS_DIRECTORY "${GOOGLETEST_PATH}" AND EXISTS "${GOOGLETEST_PATH}/CMakeLists.txt" AND
|
||||
EXISTS "${GOOGLETEST_PATH}/googletest" AND IS_DIRECTORY "${GOOGLETEST_PATH}/googletest" AND EXISTS "${GOOGLETEST_PATH}/googletest/CMakeLists.txt" AND
|
||||
EXISTS "${GOOGLETEST_PATH}/googlemock" AND IS_DIRECTORY "${GOOGLETEST_PATH}/googlemock" AND EXISTS "${GOOGLETEST_PATH}/googlemock/CMakeLists.txt")
|
||||
message(STATUS "Found Google Test in ${GOOGLETEST_PATH}")
|
||||
|
||||
ExternalProject_Add(
|
||||
googletest
|
||||
PREFIX "${CMAKE_BINARY_DIR}"
|
||||
DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/download"
|
||||
SOURCE_DIR "${GOOGLETEST_PATH}" # use existing src dir.
|
||||
BINARY_DIR "${CMAKE_BINARY_DIR}/build"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
else()
|
||||
if(NOT ALLOW_DOWNLOADING_GOOGLETEST)
|
||||
message(SEND_ERROR "Did not find Google Test sources! Either pass correct path in GOOGLETEST_PATH, or enable BENCHMARK_DOWNLOAD_DEPENDENCIES, or disable BENCHMARK_USE_BUNDLED_GTEST, or disable BENCHMARK_ENABLE_GTEST_TESTS / BENCHMARK_ENABLE_TESTING.")
|
||||
return()
|
||||
else()
|
||||
message(STATUS "Did not find Google Test sources! Fetching from web...")
|
||||
ExternalProject_Add(
|
||||
googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG "v1.15.2"
|
||||
GIT_SHALLOW "ON"
|
||||
PREFIX "${CMAKE_BINARY_DIR}"
|
||||
STAMP_DIR "${CMAKE_BINARY_DIR}/stamp"
|
||||
DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/download"
|
||||
SOURCE_DIR "${CMAKE_BINARY_DIR}/src"
|
||||
BINARY_DIR "${CMAKE_BINARY_DIR}/build"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ExternalProject_Get_Property(googletest SOURCE_DIR BINARY_DIR)
|
||||
file(WRITE googletest-paths.cmake
|
||||
"set(GOOGLETEST_SOURCE_DIR \"${SOURCE_DIR}\")
|
||||
set(GOOGLETEST_BINARY_DIR \"${BINARY_DIR}\")
|
||||
")
|
||||
113
third_party/benchmark/cmake/HandleGTest.cmake
vendored
Normal file
113
third_party/benchmark/cmake/HandleGTest.cmake
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
|
||||
include(split_list)
|
||||
|
||||
macro(build_external_gtest)
|
||||
include(ExternalProject)
|
||||
set(GTEST_FLAGS "")
|
||||
if (BENCHMARK_USE_LIBCXX)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
list(APPEND GTEST_FLAGS -stdlib=libc++)
|
||||
else()
|
||||
message(WARNING "Unsupported compiler (${CMAKE_CXX_COMPILER}) when using libc++")
|
||||
endif()
|
||||
endif()
|
||||
if (BENCHMARK_BUILD_32_BITS)
|
||||
list(APPEND GTEST_FLAGS -m32)
|
||||
endif()
|
||||
if (NOT "${CMAKE_CXX_FLAGS}" STREQUAL "")
|
||||
list(APPEND GTEST_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
endif()
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" GTEST_BUILD_TYPE)
|
||||
if ("${GTEST_BUILD_TYPE}" STREQUAL "COVERAGE")
|
||||
set(GTEST_BUILD_TYPE "DEBUG")
|
||||
endif()
|
||||
# FIXME: Since 10/Feb/2017 the googletest trunk has had a bug where
|
||||
# -Werror=unused-function fires during the build on OS X. This is a temporary
|
||||
# workaround to keep our travis bots from failing. It should be removed
|
||||
# once gtest is fixed.
|
||||
if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
list(APPEND GTEST_FLAGS "-Wno-unused-function")
|
||||
endif()
|
||||
split_list(GTEST_FLAGS)
|
||||
set(EXCLUDE_FROM_ALL_OPT "")
|
||||
set(EXCLUDE_FROM_ALL_VALUE "")
|
||||
if (${CMAKE_VERSION} VERSION_GREATER "3.0.99")
|
||||
set(EXCLUDE_FROM_ALL_OPT "EXCLUDE_FROM_ALL")
|
||||
set(EXCLUDE_FROM_ALL_VALUE "ON")
|
||||
endif()
|
||||
ExternalProject_Add(googletest
|
||||
${EXCLUDE_FROM_ALL_OPT} ${EXCLUDE_FROM_ALL_VALUE}
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG master
|
||||
PREFIX "${CMAKE_BINARY_DIR}/googletest"
|
||||
INSTALL_DIR "${CMAKE_BINARY_DIR}/googletest"
|
||||
CMAKE_CACHE_ARGS
|
||||
-DCMAKE_BUILD_TYPE:STRING=${GTEST_BUILD_TYPE}
|
||||
-DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER}
|
||||
-DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER}
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||
-DCMAKE_INSTALL_LIBDIR:PATH=<INSTALL_DIR>/lib
|
||||
-DCMAKE_CXX_FLAGS:STRING=${GTEST_FLAGS}
|
||||
-Dgtest_force_shared_crt:BOOL=ON
|
||||
)
|
||||
|
||||
ExternalProject_Get_Property(googletest install_dir)
|
||||
set(GTEST_INCLUDE_DIRS ${install_dir}/include)
|
||||
file(MAKE_DIRECTORY ${GTEST_INCLUDE_DIRS})
|
||||
|
||||
set(LIB_SUFFIX "${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
set(LIB_PREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}")
|
||||
if("${GTEST_BUILD_TYPE}" STREQUAL "DEBUG")
|
||||
set(LIB_SUFFIX "d${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
endif()
|
||||
|
||||
# Use gmock_main instead of gtest_main because it initializes gtest as well.
|
||||
# Note: The libraries are listed in reverse order of their dependancies.
|
||||
foreach(LIB gtest gmock gmock_main)
|
||||
add_library(${LIB} UNKNOWN IMPORTED)
|
||||
set_target_properties(${LIB} PROPERTIES
|
||||
IMPORTED_LOCATION ${install_dir}/lib/${LIB_PREFIX}${LIB}${LIB_SUFFIX}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${GTEST_INCLUDE_DIRS}
|
||||
INTERFACE_LINK_LIBRARIES "${GTEST_BOTH_LIBRARIES}"
|
||||
)
|
||||
add_dependencies(${LIB} googletest)
|
||||
list(APPEND GTEST_BOTH_LIBRARIES ${LIB})
|
||||
endforeach()
|
||||
endmacro(build_external_gtest)
|
||||
|
||||
if (BENCHMARK_ENABLE_GTEST_TESTS)
|
||||
if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/googletest)
|
||||
set(GTEST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/googletest")
|
||||
set(INSTALL_GTEST OFF CACHE INTERNAL "")
|
||||
set(INSTALL_GMOCK OFF CACHE INTERNAL "")
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/googletest)
|
||||
set(GTEST_BOTH_LIBRARIES gtest gmock gmock_main)
|
||||
foreach(HEADER test mock)
|
||||
# CMake 2.8 and older don't respect INTERFACE_INCLUDE_DIRECTORIES, so we
|
||||
# have to add the paths ourselves.
|
||||
set(HFILE g${HEADER}/g${HEADER}.h)
|
||||
set(HPATH ${GTEST_ROOT}/google${HEADER}/include)
|
||||
find_path(HEADER_PATH_${HEADER} ${HFILE}
|
||||
NO_DEFAULT_PATHS
|
||||
HINTS ${HPATH}
|
||||
)
|
||||
if (NOT HEADER_PATH_${HEADER})
|
||||
message(FATAL_ERROR "Failed to find header ${HFILE} in ${HPATH}")
|
||||
endif()
|
||||
list(APPEND GTEST_INCLUDE_DIRS ${HEADER_PATH_${HEADER}})
|
||||
endforeach()
|
||||
elseif(BENCHMARK_DOWNLOAD_DEPENDENCIES)
|
||||
build_external_gtest()
|
||||
else()
|
||||
find_package(GTest REQUIRED)
|
||||
find_path(GMOCK_INCLUDE_DIRS gmock/gmock.h
|
||||
HINTS ${GTEST_INCLUDE_DIRS})
|
||||
if (NOT GMOCK_INCLUDE_DIRS)
|
||||
message(FATAL_ERROR "Failed to find header gmock/gmock.h with hint ${GTEST_INCLUDE_DIRS}")
|
||||
endif()
|
||||
set(GTEST_INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS})
|
||||
# FIXME: We don't currently require the gmock library to build the tests,
|
||||
# and it's likely we won't find it, so we don't try. As long as we've
|
||||
# found the gmock/gmock.h header and gtest_main that should be good enough.
|
||||
endif()
|
||||
endif()
|
||||
7
third_party/benchmark/cmake/benchmark.pc.in
vendored
7
third_party/benchmark/cmake/benchmark.pc.in
vendored
@@ -1,12 +1,11 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: @PROJECT_NAME@
|
||||
Description: Google microbenchmark framework
|
||||
Version: @NORMALIZED_VERSION@
|
||||
Version: @VERSION@
|
||||
|
||||
Libs: -L${libdir} -lbenchmark
|
||||
Libs.private: -lpthread @BENCHMARK_PRIVATE_LINK_LIBRARIES@
|
||||
Cflags: -I${includedir}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||
|
||||
Name: @PROJECT_NAME@
|
||||
Description: Google microbenchmark framework (with main() function)
|
||||
Version: @NORMALIZED_VERSION@
|
||||
Requires: benchmark
|
||||
Libs: -L${libdir} -lbenchmark_main
|
||||
16
third_party/benchmark/cmake/pthread_affinity.cpp
vendored
16
third_party/benchmark/cmake/pthread_affinity.cpp
vendored
@@ -1,16 +0,0 @@
|
||||
#include <pthread.h>
|
||||
int main() {
|
||||
cpu_set_t set;
|
||||
CPU_ZERO(&set);
|
||||
for (int i = 0; i < CPU_SETSIZE; ++i) {
|
||||
CPU_SET(i, &set);
|
||||
CPU_CLR(i, &set);
|
||||
}
|
||||
pthread_t self = pthread_self();
|
||||
int ret;
|
||||
ret = pthread_getaffinity_np(self, sizeof(set), &set);
|
||||
if (ret != 0) return ret;
|
||||
ret = pthread_setaffinity_np(self, sizeof(set), &set);
|
||||
if (ret != 0) return ret;
|
||||
return 0;
|
||||
}
|
||||
2
third_party/benchmark/docs/AssemblyTests.md
vendored
2
third_party/benchmark/docs/AssemblyTests.md
vendored
@@ -111,7 +111,6 @@ between compilers or compiler versions. A common example of this
|
||||
is matching stack frame addresses. In this case regular expressions
|
||||
can be used to match the differing bits of output. For example:
|
||||
|
||||
<!-- {% raw %} -->
|
||||
```c++
|
||||
int ExternInt;
|
||||
struct Point { int x, y, z; };
|
||||
@@ -128,7 +127,6 @@ extern "C" void test_store_point() {
|
||||
// CHECK: ret
|
||||
}
|
||||
```
|
||||
<!-- {% endraw %} -->
|
||||
|
||||
## Current Requirements and Limitations
|
||||
|
||||
|
||||
3
third_party/benchmark/docs/_config.yml
vendored
3
third_party/benchmark/docs/_config.yml
vendored
@@ -1,3 +0,0 @@
|
||||
theme: jekyll-theme-minimal
|
||||
logo: /assets/images/icon_black.png
|
||||
show_downloads: true
|
||||
BIN
third_party/benchmark/docs/assets/images/icon.png
vendored
BIN
third_party/benchmark/docs/assets/images/icon.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
BIN
third_party/benchmark/docs/assets/images/icon.xcf
vendored
BIN
third_party/benchmark/docs/assets/images/icon.xcf
vendored
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user