Compare commits
5 Commits
v1.50.0
...
exv/webgl-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea9fdbeb5c | ||
|
|
5fd7a4e153 | ||
|
|
20ff230b92 | ||
|
|
44ff79ad34 | ||
|
|
102d2db008 |
@@ -8,4 +8,4 @@ appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
|
||||
|
||||
## Release notes for next branch cut
|
||||
|
||||
- utils: remove usages of `SpinLock`. Fixes b/321101014.
|
||||
- Metal: fix some shader artifacts by disabling fast math optimizations.
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.50.0'
|
||||
implementation 'com.google.android.filament:filament-android:1.49.3'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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.50.0'
|
||||
pod 'Filament', '~> 1.49.3'
|
||||
```
|
||||
|
||||
### Snapshots
|
||||
|
||||
@@ -1637,6 +1637,10 @@ public class View {
|
||||
* circle of confusion scale factor (amount of blur)
|
||||
*/
|
||||
public float cocScale = 1.0f;
|
||||
/**
|
||||
* width/height aspect ratio of the circle of confusion (simulate anamorphic lenses)
|
||||
*/
|
||||
public float cocAspectRatio = 1.0f;
|
||||
/**
|
||||
* maximum aperture diameter in meters (zero to disable rotation)
|
||||
*/
|
||||
@@ -1878,7 +1882,7 @@ public class View {
|
||||
* Options for Temporal Anti-aliasing (TAA)
|
||||
* Most TAA parameters are extremely costly to change, as they will trigger the TAA post-process
|
||||
* shaders to be recompiled. These options should be changed or set during initialization.
|
||||
* `filterWidth`, `feedback` and `jitterPattern`, however, can be changed at any time.
|
||||
* `filterWidth`, `feedback` and `jitterPattern`, however, could be changed at any time.
|
||||
*
|
||||
* `feedback` of 0.1 effectively accumulates a maximum of 19 samples in steady state.
|
||||
* see "A Survey of Temporal Antialiasing Techniques" by Lei Yang and all for more information.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.50.0
|
||||
VERSION_NAME=1.49.3
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -103,10 +103,19 @@ void MetalShaderCompiler::terminate() noexcept {
|
||||
NSString* objcSource = [[NSString alloc] initWithBytes:source.data()
|
||||
length:source.size() - 1
|
||||
encoding:NSUTF8StringEncoding];
|
||||
|
||||
// By default, Metal uses the most recent language version.
|
||||
MTLCompileOptions* options = [MTLCompileOptions new];
|
||||
|
||||
// Disable Fast Math optimizations.
|
||||
// This ensures that operations adhere to IEEE standards for floating-point arithmetic,
|
||||
// which is crucial for half precision floats in scenarios where fast math optimizations
|
||||
// lead to inaccuracies, such as in handling special values like NaN or Infinity.
|
||||
options.fastMathEnabled = NO;
|
||||
|
||||
NSError* error = nil;
|
||||
// When options is nil, Metal uses the most recent language version available.
|
||||
id<MTLLibrary> library = [device newLibraryWithSource:objcSource
|
||||
options:nil
|
||||
options:options
|
||||
error:&error];
|
||||
if (library == nil) {
|
||||
if (error) {
|
||||
|
||||
@@ -293,6 +293,7 @@ struct DepthOfFieldOptions {
|
||||
MEDIAN
|
||||
};
|
||||
float cocScale = 1.0f; //!< circle of confusion scale factor (amount of blur)
|
||||
float cocAspectRatio = 1.0f; //!< width/height aspect ratio of the circle of confusion (simulate anamorphic lenses)
|
||||
float maxApertureDiameter = 0.01f; //!< maximum aperture diameter in meters (zero to disable rotation)
|
||||
bool enabled = false; //!< enable or disable depth of field effect
|
||||
Filter filter = Filter::MEDIAN; //!< filter to use for filling gaps in the kernel
|
||||
|
||||
@@ -1428,7 +1428,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> depth,
|
||||
const CameraInfo& cameraInfo,
|
||||
bool translucent,
|
||||
float bokehAspectRatio,
|
||||
float2 bokehScale,
|
||||
const DepthOfFieldOptions& dofOptions) noexcept {
|
||||
|
||||
assert_invariant(depth);
|
||||
@@ -1818,8 +1818,8 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
|
||||
mi->setParameter("tiles", tilesCocMinMax,
|
||||
{ .filterMin = SamplerMinFilter::NEAREST });
|
||||
mi->setParameter("cocToTexelScale", float2{
|
||||
bokehAspectRatio / (inputDesc.width * dofResolution),
|
||||
1.0 / (inputDesc.height * dofResolution)
|
||||
bokehScale.x / (inputDesc.width * dofResolution),
|
||||
bokehScale.y / (inputDesc.height * dofResolution)
|
||||
});
|
||||
mi->setParameter("cocToPixelScale", (1.0f / float(dofResolution)));
|
||||
mi->setParameter("ringCounts", float4{
|
||||
|
||||
@@ -162,7 +162,7 @@ public:
|
||||
FrameGraphId<FrameGraphTexture> depth,
|
||||
const CameraInfo& cameraInfo,
|
||||
bool translucent,
|
||||
float bokehAspectRatio,
|
||||
math::float2 bokehScale,
|
||||
const DepthOfFieldOptions& dofOptions) noexcept;
|
||||
|
||||
// Bloom
|
||||
|
||||
@@ -30,12 +30,11 @@
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <utils/JobSystem.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/SpinLock.h>
|
||||
#include <utils/Systrace.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <mutex>
|
||||
#include <tuple>
|
||||
|
||||
namespace filament {
|
||||
@@ -649,9 +648,9 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) {
|
||||
Config c;
|
||||
// This lock protects the data inside Config, which is written to by the Filament thread,
|
||||
// and read from multiple Job threads.
|
||||
utils::Mutex configLock;
|
||||
utils::SpinLock configLock;
|
||||
{
|
||||
std::lock_guard<utils::Mutex> const lock(configLock);
|
||||
std::lock_guard<utils::SpinLock> lock(configLock);
|
||||
c.lutDimension = builder->dimension;
|
||||
c.adaptationTransform = adaptationTransform(builder->whiteBalance);
|
||||
c.colorGradingIn = selectColorGradingTransformIn(builder->toneMapping);
|
||||
@@ -688,7 +687,7 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) {
|
||||
[data, converted, b, &c, &configLock, builder](JobSystem&, JobSystem::Job*) {
|
||||
Config config;
|
||||
{
|
||||
std::lock_guard<utils::Mutex> lock(configLock);
|
||||
std::lock_guard<utils::SpinLock> lock(configLock);
|
||||
config = c;
|
||||
}
|
||||
half4* UTILS_RESTRICT p = (half4*) data + b * config.lutDimension * config.lutDimension;
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <utils/Mutex.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <optional>
|
||||
|
||||
namespace filament {
|
||||
|
||||
|
||||
@@ -1043,9 +1043,13 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
|
||||
// The bokeh height is always correct regardless of the dynamic resolution scaling.
|
||||
// (because the CoC is calculated w.r.t. the height), so we only need to adjust
|
||||
// the width.
|
||||
float const bokehAspectRatio = scale.x / scale.y;
|
||||
float const aspect = (scale.x / scale.y) * dofOptions.cocAspectRatio;
|
||||
float2 const bokehScale{
|
||||
aspect < 1.0f ? aspect : 1.0f,
|
||||
aspect > 1.0f ? 1.0f / aspect : 1.0f
|
||||
};
|
||||
input = ppm.dof(fg, input, depth, cameraInfo, needsAlphaChannel,
|
||||
bokehAspectRatio, dofOptions);
|
||||
bokehScale, dofOptions);
|
||||
}
|
||||
|
||||
FrameGraphId<FrameGraphTexture> bloom, flare;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.50.0"
|
||||
spec.version = "1.49.3"
|
||||
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.50.0/filament-v1.50.0-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.49.3/filament-v1.49.3-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -47,6 +47,9 @@ const float kToastDelayDuration = 2.0f;
|
||||
- (void)createRenderables;
|
||||
- (void)createLights;
|
||||
|
||||
- (void)appWillResignActive:(NSNotification*)notification;
|
||||
- (void)appDidBecomeActive:(NSNotification*)notification;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FILViewController {
|
||||
@@ -73,6 +76,16 @@ const float kToastDelayDuration = 2.0f;
|
||||
|
||||
self.title = @"https://google.github.io/filament/remote";
|
||||
|
||||
// Observe lifecycle notifications to prevent us from rendering in the background.
|
||||
[NSNotificationCenter.defaultCenter addObserver:self
|
||||
selector:@selector(appWillResignActive:)
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:nil];
|
||||
[NSNotificationCenter.defaultCenter addObserver:self
|
||||
selector:@selector(appDidBecomeActive:)
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:nil];
|
||||
|
||||
// Arguments:
|
||||
// --model <path>
|
||||
// path to glb or gltf file to load from documents directory
|
||||
@@ -125,6 +138,14 @@ const float kToastDelayDuration = 2.0f;
|
||||
[self.view addSubview:_toastLabel];
|
||||
}
|
||||
|
||||
- (void)appWillResignActive:(NSNotification*)notification {
|
||||
[self stopDisplayLink];
|
||||
}
|
||||
|
||||
- (void)appDidBecomeActive:(NSNotification*)notification {
|
||||
[self startDisplayLink];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[self startDisplayLink];
|
||||
}
|
||||
@@ -330,6 +351,7 @@ const float kToastDelayDuration = 2.0f;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||
delete _server;
|
||||
delete _automation;
|
||||
self.modelView.engine->destroy(_indirectLight);
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
namespace filament {
|
||||
|
||||
// update this when a new version of filament wouldn't work with older materials
|
||||
static constexpr size_t MATERIAL_VERSION = 50;
|
||||
static constexpr size_t MATERIAL_VERSION = 49;
|
||||
|
||||
/**
|
||||
* Supported shading models
|
||||
|
||||
@@ -37,6 +37,7 @@ set(DIST_HDRS
|
||||
${PUBLIC_HDR_DIR}/${TARGET}/PrivateImplementation-impl.h
|
||||
${PUBLIC_HDR_DIR}/${TARGET}/SingleInstanceComponentManager.h
|
||||
${PUBLIC_HDR_DIR}/${TARGET}/Slice.h
|
||||
${PUBLIC_HDR_DIR}/${TARGET}/SpinLock.h
|
||||
${PUBLIC_HDR_DIR}/${TARGET}/StructureOfArrays.h
|
||||
${PUBLIC_HDR_DIR}/${TARGET}/unwindows.h
|
||||
)
|
||||
|
||||
@@ -38,6 +38,7 @@ protected:
|
||||
utils::Arena<utils::ObjectPoolAllocator<Payload>, LockingPolicy::NoLock> mPoolAllocatorNoLock;
|
||||
utils::Arena<utils::ObjectPoolAllocator<Payload>, std::mutex> mPoolAllocatorStdMutex;
|
||||
utils::Arena<utils::ObjectPoolAllocator<Payload>, utils::Mutex> mPoolAllocatorUtilsMutex;
|
||||
utils::Arena<utils::ObjectPoolAllocator<Payload>, LockingPolicy::SpinLock> mPoolAllocatorSpinlock;
|
||||
utils::Arena<utils::ThreadSafeObjectPoolAllocator<Payload>, LockingPolicy::NoLock> mPoolAllocatorAtomic;
|
||||
};
|
||||
|
||||
@@ -47,6 +48,7 @@ Allocators::Allocators()
|
||||
: mPoolAllocatorNoLock("nolock", POOL_ITEM_COUNT * sizeof(Payload)),
|
||||
mPoolAllocatorStdMutex("std::mutex", POOL_ITEM_COUNT * sizeof(Payload)),
|
||||
mPoolAllocatorUtilsMutex("utils::Mutex", POOL_ITEM_COUNT * sizeof(Payload)),
|
||||
mPoolAllocatorSpinlock("spinlock", POOL_ITEM_COUNT * sizeof(Payload)),
|
||||
mPoolAllocatorAtomic("atomic", POOL_ITEM_COUNT * sizeof(Payload)) {
|
||||
}
|
||||
|
||||
@@ -79,6 +81,15 @@ BENCHMARK_DEFINE_F(Allocators, poolAllocator_utils_mutex)(benchmark::State& stat
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(Allocators, poolAllocator_spinlock)(benchmark::State& state) {
|
||||
auto& pool = mPoolAllocatorSpinlock;
|
||||
PerformanceCounters pc(state);
|
||||
for (auto _ : state) {
|
||||
Payload* p = pool.alloc<Payload>(1);
|
||||
pool.free(p);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(Allocators, poolAllocator_atomic)(benchmark::State& state) {
|
||||
auto& pool = mPoolAllocatorAtomic;
|
||||
PerformanceCounters pc(state);
|
||||
@@ -96,6 +107,10 @@ BENCHMARK_REGISTER_F(Allocators, poolAllocator_utils_mutex)
|
||||
->ThreadRange(1, 4)
|
||||
->Threads(benchmark::CPUInfo::Get().num_cpus * 2);
|
||||
|
||||
BENCHMARK_REGISTER_F(Allocators, poolAllocator_spinlock)
|
||||
->ThreadRange(1, 4)
|
||||
->Threads(benchmark::CPUInfo::Get().num_cpus * 2);
|
||||
|
||||
BENCHMARK_REGISTER_F(Allocators, poolAllocator_atomic)
|
||||
->ThreadRange(1, 4)
|
||||
->Threads(benchmark::CPUInfo::Get().num_cpus * 2);
|
||||
|
||||
@@ -41,6 +41,15 @@ static void BM_utils_mutex(benchmark::State& state) {
|
||||
}
|
||||
}
|
||||
|
||||
static void BM_spinlock(benchmark::State& state) {
|
||||
static LockingPolicy::SpinLock l;
|
||||
PerformanceCounters pc(state);
|
||||
for (auto _ : state) {
|
||||
l.lock();
|
||||
l.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK(BM_std_mutex)
|
||||
->Threads(1)
|
||||
->Threads(2)
|
||||
@@ -52,3 +61,9 @@ BENCHMARK(BM_utils_mutex)
|
||||
->Threads(2)
|
||||
->Threads(8)
|
||||
->ThreadPerCpu();
|
||||
|
||||
BENCHMARK(BM_spinlock)
|
||||
->Threads(1)
|
||||
->Threads(2)
|
||||
->Threads(8)
|
||||
->ThreadPerCpu();
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <utils/debug.h>
|
||||
#include <utils/memalign.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/SpinLock.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
@@ -477,6 +478,7 @@ struct NoLock {
|
||||
void unlock() noexcept { }
|
||||
};
|
||||
|
||||
using SpinLock = utils::SpinLock;
|
||||
using Mutex = utils::Mutex;
|
||||
|
||||
} // namespace LockingPolicy
|
||||
|
||||
@@ -387,7 +387,7 @@ private:
|
||||
uint8_t mParallelSplitCount = 0; // # of split allowable in parallel_for
|
||||
Job* mRootJob = nullptr;
|
||||
|
||||
utils::Mutex mThreadMapLock; // this should have very little contention
|
||||
utils::SpinLock mThreadMapLock; // this should have very little contention
|
||||
tsl::robin_map<std::thread::id, ThreadState *> mThreadMap;
|
||||
};
|
||||
|
||||
|
||||
90
libs/utils/include/utils/SpinLock.h
Normal file
90
libs/utils/include/utils/SpinLock.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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_UTILS_SPINLOCK_H
|
||||
#define TNT_UTILS_SPINLOCK_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <utils/Mutex.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <type_traits>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace utils {
|
||||
namespace details {
|
||||
|
||||
class SpinLock {
|
||||
std::atomic_flag mLock = ATOMIC_FLAG_INIT;
|
||||
|
||||
public:
|
||||
void lock() noexcept {
|
||||
UTILS_PREFETCHW(&mLock);
|
||||
#ifdef __ARM_ACLE
|
||||
// we signal an event on this CPU, so that the first yield() will be a no-op,
|
||||
// and falls through the test_and_set(). This is more efficient than a while { }
|
||||
// construct.
|
||||
UTILS_SIGNAL_EVENT();
|
||||
do {
|
||||
yield();
|
||||
} while (mLock.test_and_set(std::memory_order_acquire));
|
||||
#else
|
||||
goto start;
|
||||
do {
|
||||
yield();
|
||||
start: ;
|
||||
} while (mLock.test_and_set(std::memory_order_acquire));
|
||||
#endif
|
||||
}
|
||||
|
||||
void unlock() noexcept {
|
||||
mLock.clear(std::memory_order_release);
|
||||
#ifdef __ARM_ARCH_7A__
|
||||
// on ARMv7a SEL is needed
|
||||
UTILS_SIGNAL_EVENT();
|
||||
// as well as a memory barrier is needed
|
||||
__dsb(0xA); // ISHST = 0xA (b1010)
|
||||
#else
|
||||
// on ARMv8 we could avoid the call to SE, but we'd need to write the
|
||||
// test_and_set() above by hand, so the WFE only happens without a STRX first.
|
||||
UTILS_BROADCAST_EVENT();
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
inline void yield() noexcept {
|
||||
// on x86 call pause instruction, on ARM call WFE
|
||||
UTILS_WAIT_FOR_EVENT();
|
||||
}
|
||||
};
|
||||
} // namespace details
|
||||
|
||||
#if UTILS_HAS_SANITIZE_THREAD
|
||||
// Active spins with atomics slow down execution too much under ThreadSanitizer.
|
||||
using SpinLock = Mutex;
|
||||
#elif defined(__ARM_ARCH_7A__)
|
||||
// We've had problems with "wfe" on some ARM-V7 devices, causing spurious SIGILL
|
||||
using SpinLock = Mutex;
|
||||
#else
|
||||
using SpinLock = details::SpinLock;
|
||||
#endif
|
||||
|
||||
} // namespace utils
|
||||
|
||||
#endif // TNT_UTILS_SPINLOCK_H
|
||||
@@ -293,7 +293,7 @@ void JobSystem::wakeOne() noexcept {
|
||||
}
|
||||
|
||||
inline JobSystem::ThreadState& JobSystem::getState() noexcept {
|
||||
std::lock_guard<utils::Mutex> lock(mThreadMapLock);
|
||||
std::lock_guard<utils::SpinLock> lock(mThreadMapLock);
|
||||
auto iter = mThreadMap.find(std::this_thread::get_id());
|
||||
ASSERT_PRECONDITION(iter != mThreadMap.end(), "This thread has not been adopted.");
|
||||
return *iter->second;
|
||||
@@ -585,7 +585,7 @@ void JobSystem::runAndWait(JobSystem::Job*& job) noexcept {
|
||||
void JobSystem::adopt() {
|
||||
const auto tid = std::this_thread::get_id();
|
||||
|
||||
std::unique_lock<utils::Mutex> lock(mThreadMapLock);
|
||||
std::unique_lock<utils::SpinLock> lock(mThreadMapLock);
|
||||
auto iter = mThreadMap.find(tid);
|
||||
ThreadState* const state = iter == mThreadMap.end() ? nullptr : iter->second;
|
||||
lock.unlock();
|
||||
@@ -618,7 +618,7 @@ void JobSystem::adopt() {
|
||||
|
||||
void JobSystem::emancipate() {
|
||||
const auto tid = std::this_thread::get_id();
|
||||
std::lock_guard<utils::Mutex> lock(mThreadMapLock);
|
||||
std::lock_guard<utils::SpinLock> lock(mThreadMapLock);
|
||||
auto iter = mThreadMap.find(tid);
|
||||
ThreadState* const state = iter == mThreadMap.end() ? nullptr : iter->second;
|
||||
ASSERT_PRECONDITION(state, "this thread is not an adopted thread");
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace utils {
|
||||
|
||||
bool Path::mkdir() const {
|
||||
|
||||
@@ -391,6 +391,8 @@ int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, DepthOfFieldOpt
|
||||
CHECK_KEY(tok);
|
||||
if (compare(tok, jsonChunk, "cocScale") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cocScale);
|
||||
} else if (compare(tok, jsonChunk, "cocAspectRatio") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cocAspectRatio);
|
||||
} else if (compare(tok, jsonChunk, "maxApertureDiameter") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->maxApertureDiameter);
|
||||
} else if (compare(tok, jsonChunk, "enabled") == 0) {
|
||||
@@ -424,6 +426,7 @@ int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, DepthOfFieldOpt
|
||||
std::ostream& operator<<(std::ostream& out, const DepthOfFieldOptions& in) {
|
||||
return out << "{\n"
|
||||
<< "\"cocScale\": " << (in.cocScale) << ",\n"
|
||||
<< "\"cocAspectRatio\": " << (in.cocAspectRatio) << ",\n"
|
||||
<< "\"maxApertureDiameter\": " << (in.maxApertureDiameter) << ",\n"
|
||||
<< "\"enabled\": " << to_string(in.enabled) << ",\n"
|
||||
<< "\"filter\": " << (in.filter) << ",\n"
|
||||
|
||||
@@ -1036,6 +1036,7 @@ void ViewerGui::updateUserInterface() {
|
||||
ImGui::Checkbox("Enabled##dofEnabled", &mSettings.view.dof.enabled);
|
||||
ImGui::SliderFloat("Focus distance", &mSettings.viewer.cameraFocusDistance, 0.0f, 30.0f);
|
||||
ImGui::SliderFloat("Blur scale", &mSettings.view.dof.cocScale, 0.1f, 10.0f);
|
||||
ImGui::SliderFloat("CoC aspect-ratio", &mSettings.view.dof.cocAspectRatio, 0.25f, 4.0f);
|
||||
ImGui::SliderInt("Ring count", &dofRingCount, 1, 17);
|
||||
ImGui::SliderInt("Max CoC", &dofMaxCoC, 1, 32);
|
||||
ImGui::Checkbox("Native Resolution", &mSettings.view.dof.nativeResolution);
|
||||
|
||||
@@ -27,9 +27,7 @@ JsonType JsonishLexer::readIdentifier() noexcept {
|
||||
consume();
|
||||
}
|
||||
|
||||
const char* lexemeEnd = mCursor - 1;
|
||||
|
||||
size_t lexemeSize = lexemeEnd - lexemeStart;
|
||||
size_t lexemeSize = mCursor - lexemeStart;
|
||||
|
||||
// Check what kind of keyword we got here.
|
||||
if (strncmp("true", lexemeStart, lexemeSize) == 0) {
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <getopt/getopt.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
@@ -60,6 +60,7 @@ Filament.loadGeneratedExtensions = function() {
|
||||
Filament.View.prototype.setDepthOfFieldOptionsDefaults = function(overrides) {
|
||||
const options = {
|
||||
cocScale: 1.0,
|
||||
cocAspectRatio: 1.0,
|
||||
maxApertureDiameter: 0.01,
|
||||
enabled: false,
|
||||
filter: Filament.View$DepthOfFieldOptions$Filter.MEDIAN,
|
||||
|
||||
6
web/filament-js/filament.d.ts
vendored
6
web/filament-js/filament.d.ts
vendored
@@ -1409,6 +1409,10 @@ export interface View$DepthOfFieldOptions {
|
||||
* circle of confusion scale factor (amount of blur)
|
||||
*/
|
||||
cocScale?: number;
|
||||
/**
|
||||
* width/height aspect ratio of the circle of confusion (simulate anamorphic lenses)
|
||||
*/
|
||||
cocAspectRatio?: number;
|
||||
/**
|
||||
* maximum aperture diameter in meters (zero to disable rotation)
|
||||
*/
|
||||
@@ -1659,7 +1663,7 @@ export enum View$TemporalAntiAliasingOptions$JitterPattern {
|
||||
* Options for Temporal Anti-aliasing (TAA)
|
||||
* Most TAA parameters are extremely costly to change, as they will trigger the TAA post-process
|
||||
* shaders to be recompiled. These options should be changed or set during initialization.
|
||||
* `filterWidth`, `feedback` and `jitterPattern`, however, can be changed at any time.
|
||||
* `filterWidth`, `feedback` and `jitterPattern`, however, could be changed at any time.
|
||||
*
|
||||
* `feedback` of 0.1 effectively accumulates a maximum of 19 samples in steady state.
|
||||
* see "A Survey of Temporal Antialiasing Techniques" by Lei Yang and all for more information.
|
||||
|
||||
@@ -58,6 +58,7 @@ value_object<View::FogOptions>("View$FogOptions")
|
||||
|
||||
value_object<View::DepthOfFieldOptions>("View$DepthOfFieldOptions")
|
||||
.field("cocScale", &View::DepthOfFieldOptions::cocScale)
|
||||
.field("cocAspectRatio", &View::DepthOfFieldOptions::cocAspectRatio)
|
||||
.field("maxApertureDiameter", &View::DepthOfFieldOptions::maxApertureDiameter)
|
||||
.field("enabled", &View::DepthOfFieldOptions::enabled)
|
||||
.field("filter", &View::DepthOfFieldOptions::filter)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "filament",
|
||||
"version": "1.50.0",
|
||||
"version": "1.49.3",
|
||||
"description": "Real-time physically based rendering engine",
|
||||
"main": "filament.js",
|
||||
"module": "filament.js",
|
||||
|
||||
@@ -203,7 +203,9 @@ set(HTML_FILES
|
||||
skinning.html
|
||||
suzanne.html
|
||||
test-filament-viewer.html
|
||||
triangle.html)
|
||||
triangle.html
|
||||
benchmark-shader-compilation.html
|
||||
benchmark-shader-compilation.js)
|
||||
|
||||
set(ASSET_FILES
|
||||
assets/favicon.png)
|
||||
|
||||
22
web/samples/benchmark-shader-compilation.html
Normal file
22
web/samples/benchmark-shader-compilation.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Shader Compilation Benchmark</title>
|
||||
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1">
|
||||
<style>
|
||||
body { margin: 0; overflow: hidden; }
|
||||
canvas { touch-action: none; width: 100%; height: 100%; }
|
||||
.frame-time { position: absolute; color: #ffffff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="frame-time">
|
||||
Average Frame Time: <span id="frame-time-counter">Calculating...</span>
|
||||
</div>
|
||||
<canvas></canvas>
|
||||
<script src="filament.js"></script>
|
||||
<script src="gl-matrix-min.js"></script>
|
||||
<script src="benchmark-shader-compilation.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
141
web/samples/benchmark-shader-compilation.js
Normal file
141
web/samples/benchmark-shader-compilation.js
Normal file
@@ -0,0 +1,141 @@
|
||||
Filament.init(['nonlit.filamat'], () => {
|
||||
window.VertexAttribute = Filament.VertexAttribute;
|
||||
window.AttributeType = Filament.VertexBuffer$AttributeType;
|
||||
window.Projection = Filament.Camera$Projection;
|
||||
window.app = new App(
|
||||
document.getElementsByTagName('canvas')[0],
|
||||
document.getElementById('frame-time-counter'));
|
||||
});
|
||||
|
||||
const NUMBER_OF_TRIANGLES = 100;
|
||||
// probably 60 fps; record 1 seconds ish worth of frames.
|
||||
const NUMBER_OF_FRAMES_TO_RECORD_FPS = 1 * 60;
|
||||
|
||||
class App {
|
||||
constructor(canvas, frameTimeCounter) {
|
||||
this.canvas = canvas;
|
||||
this.frameTimeCounter = frameTimeCounter;
|
||||
|
||||
this.lastFrameTime = null;
|
||||
this.frameDeltas = [];
|
||||
for (let i = 0; i < NUMBER_OF_FRAMES_TO_RECORD_FPS; ++i) {
|
||||
this.frameDeltas.push(0);
|
||||
}
|
||||
this.frameDeltasIndex = 0;
|
||||
this.frameDeltasSum = 0;
|
||||
this.frameTimeIsValid = false;
|
||||
|
||||
const engine = this.engine = Filament.Engine.create(this.canvas);
|
||||
this.scene = engine.createScene();
|
||||
this.triangles = [];
|
||||
for (let i = 0; i < NUMBER_OF_TRIANGLES; ++i) {
|
||||
const entity = Filament.EntityManager.get().create();
|
||||
this.triangles.push({entity: entity});
|
||||
this.scene.addEntity(entity);
|
||||
}
|
||||
|
||||
const TRIANGLE_POSITIONS = new Float32Array([
|
||||
1,
|
||||
0,
|
||||
Math.cos(Math.PI * 2 / 3),
|
||||
Math.sin(Math.PI * 2 / 3),
|
||||
Math.cos(Math.PI * 4 / 3),
|
||||
Math.sin(Math.PI * 4 / 3),
|
||||
]);
|
||||
|
||||
const TRIANGLE_COLORS =
|
||||
new Uint32Array([0xffff0000, 0xff00ff00, 0xff0000ff]);
|
||||
|
||||
this.vb =
|
||||
Filament.VertexBuffer.Builder()
|
||||
.vertexCount(3)
|
||||
.bufferCount(2)
|
||||
.attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT2, 0, 8)
|
||||
.attribute(VertexAttribute.COLOR, 1, AttributeType.UBYTE4, 0, 4)
|
||||
.normalized(VertexAttribute.COLOR)
|
||||
.build(engine);
|
||||
|
||||
this.vb.setBufferAt(engine, 0, TRIANGLE_POSITIONS);
|
||||
this.vb.setBufferAt(engine, 1, TRIANGLE_COLORS);
|
||||
|
||||
this.ib = Filament.IndexBuffer.Builder()
|
||||
.indexCount(3)
|
||||
.bufferType(Filament.IndexBuffer$IndexType.USHORT)
|
||||
.build(engine);
|
||||
|
||||
this.ib.setBuffer(engine, new Uint16Array([0, 1, 2]));
|
||||
|
||||
this.swapChain = engine.createSwapChain();
|
||||
this.renderer = engine.createRenderer();
|
||||
this.camera = engine.createCamera(Filament.EntityManager.get().create());
|
||||
|
||||
this.view = engine.createView();
|
||||
this.view.setSampleCount(4);
|
||||
this.view.setCamera(this.camera);
|
||||
this.view.setScene(this.scene);
|
||||
|
||||
this.renderer.setClearOptions(
|
||||
{clearColor: [0.0, 0.1, 0.2, 1.0], clear: true});
|
||||
|
||||
this.resize();
|
||||
this.render = this.render.bind(this);
|
||||
this.resize = this.resize.bind(this);
|
||||
window.addEventListener('resize', this.resize);
|
||||
window.requestAnimationFrame(this.render);
|
||||
}
|
||||
|
||||
render() {
|
||||
const frameTime = Date.now();
|
||||
if (this.lastFrameTime) {
|
||||
const delta = frameTime - this.lastFrameTime;
|
||||
this.frameDeltasSum =
|
||||
this.frameDeltasSum - this.frameDeltas[this.frameDeltasIndex] + delta;
|
||||
this.frameDeltas[this.frameDeltasIndex] = delta;
|
||||
this.frameDeltasIndex =
|
||||
(this.frameDeltasIndex + 1) % NUMBER_OF_FRAMES_TO_RECORD_FPS;
|
||||
if (this.frameDeltasIndex == 0) {
|
||||
this.frameTimeIsValid = true;
|
||||
}
|
||||
}
|
||||
this.lastFrameTime = frameTime;
|
||||
|
||||
if (this.frameTimeIsValid) {
|
||||
const averageFrameDelta =
|
||||
this.frameDeltasSum * 1.0 / NUMBER_OF_FRAMES_TO_RECORD_FPS;
|
||||
this.frameTimeCounter.innerHTML = averageFrameDelta.toFixed(2) + ' ms';
|
||||
}
|
||||
|
||||
this.triangles.forEach(triangle => {
|
||||
if (triangle.mat) {
|
||||
this.engine.destroyMaterial(triangle.mat);
|
||||
}
|
||||
triangle.mat = this.engine.createMaterial('nonlit.filamat');
|
||||
const matinst = triangle.mat.getDefaultInstance();
|
||||
Filament.RenderableManager.Builder(1)
|
||||
.boundingBox({center: [-1, -1, -1], halfExtent: [1, 1, 1]})
|
||||
.material(0, matinst)
|
||||
.geometry(
|
||||
0, Filament.RenderableManager$PrimitiveType.TRIANGLES, this.vb,
|
||||
this.ib)
|
||||
.build(this.engine, triangle.entity);
|
||||
});
|
||||
|
||||
const radians = Date.now() / 1000;
|
||||
const transform = mat4.fromRotation(mat4.create(), radians, [0, 0, 1]);
|
||||
const tcm = this.engine.getTransformManager();
|
||||
const inst = tcm.getInstance(this.triangles[0].entity);
|
||||
tcm.setTransform(inst, transform);
|
||||
inst.delete();
|
||||
this.renderer.render(this.swapChain, this.view);
|
||||
window.requestAnimationFrame(this.render);
|
||||
}
|
||||
|
||||
resize() {
|
||||
const dpr = window.devicePixelRatio;
|
||||
const width = this.canvas.width = window.innerWidth * dpr;
|
||||
const height = this.canvas.height = window.innerHeight * dpr;
|
||||
this.view.setViewport([0, 0, width, height]);
|
||||
const aspect = width / height;
|
||||
this.camera.setProjection(Projection.ORTHO, -aspect, aspect, -1, 1, 0, 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user