Compare commits

...

4 Commits

Author SHA1 Message Date
Benjamin Doherty
98d4874a3a Add missing VulkanDriver.h header 2025-12-09 14:26:07 -08:00
Mathias Agopian
c67ed7a1d7 fix use-after-free of the EGL swapchain (#9495)
PlatformEGLAndroid holds onto the current swapchain in order to use
it when beginFrame is called. Usually the swapchain is set just before
beginFrame is called. However, that's not the case for standalone
views. These are independent of the swapchain and doing "swapchain
stuff" for them is nonsensical.

So make sure that:

1. PlatfromEGLAndroid doesn't hold onto a dangling pointer when the 
   swapchain is destroyed. And add proper null checks.
2. Don't do the "swapchain stuff" when beginFrame is called in the
   context of a standalone view.
   We now reserve frameID 0 for that purpose (meaning the frameid is
   non sensical for these).

We're currently relying on frameID to not wrap-around. At 120 fps, 
that's about 1 year. This will be addressed in a later PR.

FIXES=[462827028, 461399487]
2025-12-08 15:14:03 -08:00
Powei Feng
e9a3399d44 Revert "Add flag to guard camera near/far assertion (#9472)"
This reverts commit 3a92cdab3a.
2025-12-04 13:45:30 -08:00
Powei Feng
515637b3a5 Bump version to 1.68.1 2025-12-02 16:17:33 -08:00
12 changed files with 50 additions and 39 deletions

View File

@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.68.0'
implementation 'com.google.android.filament:filament-android:1.68.1'
}
```
@@ -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.68.0'
pod 'Filament', '~> 1.68.1'
```
## Documentation

View File

@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.68.0
VERSION_NAME=1.68.1
POM_DESCRIPTION=Real-time physically based rendering engine for Android.

View File

@@ -178,20 +178,30 @@ void PlatformEGLAndroid::beginFrame(
int64_t const monotonic_clock_ns,
int64_t refreshIntervalNs,
uint32_t const frameId) noexcept {
// associate the user frameid with the system frame id
setPresentFrameId(mCurrentDrawSwapChain, frameId);
// if frameId is 0, it means we're not associated to a particular frame, which is the case
// for standalone views. And in this case we skip the performance hint (since we wouldn't get
// the right timing anyway as well as the frame info timing collections)
if (mPerformanceHintSession.isValid()) {
// associate the user frameid with the system frame id.
if (frameId && mCurrentDrawSwapChain) {
// mCurrentDrawSwapChain could be null if we're called from renderStandaloneView
setPresentFrameId(mCurrentDrawSwapChain, frameId);
}
if (frameId && mPerformanceHintSession.isValid()) {
if (refreshIntervalNs <= 0) {
// we're not provided with a target time, use the display period, if everything fails,
// assume 16.67ms
refreshIntervalNs = 16'666'667;
CompositorTiming compositorTiming{};
bool const hasCompositorTiming =
queryCompositorTiming(mCurrentDrawSwapChain, &compositorTiming);
if (hasCompositorTiming && compositorTiming.compositeInterval > 0) {
refreshIntervalNs = compositorTiming.compositeInterval;
if (mCurrentDrawSwapChain) {
// mCurrentDrawSwapChain could be null if we're called from renderStandaloneView
CompositorTiming compositorTiming{};
bool const hasCompositorTiming =
queryCompositorTiming(mCurrentDrawSwapChain, &compositorTiming);
if (hasCompositorTiming && compositorTiming.compositeInterval > 0) {
refreshIntervalNs = compositorTiming.compositeInterval;
}
}
}
mStartTimeOfActualWork = clock::time_point(std::chrono::nanoseconds(monotonic_clock_ns));
@@ -440,6 +450,10 @@ Platform::SwapChain* PlatformEGLAndroid::createSwapChain(
void PlatformEGLAndroid::destroySwapChain(SwapChain* swapChain) noexcept {
if (swapChain) {
SwapChainEGLAndroid* const sc = static_cast<SwapChainEGLAndroid*>(swapChain);
if (mCurrentDrawSwapChain == sc) {
// don't keep a dangling pointer around
mCurrentDrawSwapChain = nullptr;
}
sc->terminate(*this);
delete sc;
}

View File

@@ -447,12 +447,14 @@ void VulkanDriver::beginFrame(int64_t monotonic_clock_ns,
int64_t refreshIntervalNs, uint32_t frameId) {
FVK_PROFILE_MARKER(PROFILE_NAME_BEGINFRAME);
if (mCurrentSwapChain) { // This should be guaranteed
// if frameId is 0, it means we're not associated to a particular frame, which is the case
// for standalone views. And in this case we skip the frame info timing collection.
if (frameId && mCurrentSwapChain) { // This should be guaranteed
mPlatform->setPresentFrameId(mCurrentSwapChain->swapChain, frameId);
}
// Check if any command have finished and reset all its used resources. The resources
// wont be destroyed but their reference count will decreased if the command is already
// won't be destroyed but their reference count will be decreased if the command is already
// completed.
//
// This will let us check if any VulkanBuffer is currently in flight or not.

View File

@@ -41,6 +41,7 @@
#include "vulkan/utils/Definitions.h"
#include "backend/DriverEnums.h"
#include "backend/BufferObjectStreamDescriptor.h"
#include "DriverBase.h"
#include "private/backend/Driver.h"

View File

@@ -20,6 +20,8 @@
#include <math/mat4.h>
#include <utils/Panic.h>
#include <math/vec2.h>
#include <math/vec3.h>
#include <math/vec4.h>
@@ -34,6 +36,10 @@ using namespace math;
void Camera::setProjection(double const fovInDegrees, double const aspect,
double const near, double const far, Fov const direction) {
FILAMENT_CHECK_PRECONDITION(near > 0 && far > near)
<< "Camera preconditions not met in setProjection(): near <= 0 or far <= near, near="
<< near << ", far=" << far;
setCustomProjection(
projection(direction, fovInDegrees, aspect, near),
projection(direction, fovInDegrees, aspect, near, far),
@@ -43,6 +49,10 @@ void Camera::setProjection(double const fovInDegrees, double const aspect,
void Camera::setLensProjection(double const focalLengthInMillimeters,
double const aspect, double const near, double const far) {
FILAMENT_CHECK_PRECONDITION(near > 0 && far > near)
<< "Camera preconditions not met in setLensProjection(): near <= 0 or far <= near, near="
<< near << ", far=" << far;
setCustomProjection(
projection(focalLengthInMillimeters, aspect, near),
projection(focalLengthInMillimeters, aspect, near, far),

View File

@@ -95,13 +95,8 @@ mat4 FCamera::projection(double const focalLengthInMillimeters,
void UTILS_NOINLINE FCamera::setCustomProjection(mat4 const& projection,
mat4 const& projectionForCulling, double const near, double const far) noexcept {
FILAMENT_CHECK_PRECONDITION(near > 0)
<< "Camera preconditions not met in setCustomProjection(): near <= 0, near=" << near;
auto const& featureFlags = mEngine.features.engine.debug;
FILAMENT_FLAG_GUARDED_CHECK_PRECONDITION(far > near,
featureFlags.assert_camera_projection_near_far)
<< "Camera preconditions not met in setCustomProjection(): far <= near, near="
<< near << ", far=" << far;
FILAMENT_CHECK_PRECONDITION(near != far)
<< "Camera preconditions not met in setCustomProjection(): near = far = " << near;
for (auto& eyeProjection: mEyeProjection) {
eyeProjection = projection;
@@ -115,13 +110,8 @@ void UTILS_NOINLINE FCamera::setCustomEyeProjection(mat4 const* projection, size
mat4 const& projectionForCulling, double const near, double const far) {
const Engine::Config& config = mEngine.getConfig();
FILAMENT_CHECK_PRECONDITION(near > 0)
<< "Camera preconditions not met in setCustomEyeProjection(): near <= 0, near=" << near;
auto const& featureFlags = mEngine.features.engine.debug;
FILAMENT_FLAG_GUARDED_CHECK_PRECONDITION(far > near,
featureFlags.assert_camera_projection_near_far)
<< "Camera preconditions not met in setCustomEyeProjection(): far <= near, near="
<< near << ", far=" << far;
FILAMENT_CHECK_PRECONDITION(near != far)
<< "Camera preconditions not met in setCustomEyeProjection(): near = far = " << near;
FILAMENT_CHECK_PRECONDITION(count >= config.stereoscopicEyeCount)
<< "All eye projections must be supplied together, count must be >= "

View File

@@ -778,7 +778,6 @@ public:
bool assert_material_instance_texture_descriptor_set_compatible =
CORRECTNESS_ASSERTION_DEFAULT;
bool assert_texture_can_generate_mipmap = CORRECTNESS_ASSERTION_DEFAULT;
bool assert_camera_projection_near_far = CORRECTNESS_ASSERTION_DEFAULT;
} debug;
struct {
bool disable_gpu_frame_complete_metric = true;
@@ -848,9 +847,6 @@ public:
{ "engine.debug.assert_texture_can_generate_mipmap",
"Assert if a texture has the correct usage set for generating mipmaps.",
&features.engine.debug.assert_texture_can_generate_mipmap, false },
{ "engine.debug.assert_camera_projection_near_far",
"Assert that the near plane is smaller than the far plane.",
&features.engine.debug.assert_camera_projection_near_far, false },
{ "material.check_crc32_after_loading",
"Verify the checksum of package data when a material is loaded.",
&features.material.check_crc32_after_loading, false },

View File

@@ -571,7 +571,6 @@ void FRenderer::renderStandaloneView(FView const* view) {
if (UTILS_LIKELY(view->getScene())) {
mPreviousRenderTargets.clear();
mFrameId++;
// ask the engine to do what it needs to (e.g. updates light buffer, materials...)
FEngine& engine = mEngine;
@@ -581,8 +580,7 @@ void FRenderer::renderStandaloneView(FView const* view) {
driver.beginFrame(
steady_clock::now().time_since_epoch().count(),
mDisplayInfo.refreshRate == 0.0 ? 0 : int64_t(
1'000'000'000.0 / mDisplayInfo.refreshRate),
mFrameId);
1'000'000'000.0 / mDisplayInfo.refreshRate), 0);
// because we don't have a "present" call, we use flush so the driver can submit
// the command buffer; we do this before driver.endFrame() to mimic what would
@@ -591,7 +589,7 @@ void FRenderer::renderStandaloneView(FView const* view) {
engine.submitFrame();
driver.endFrame(mFrameId);
driver.endFrame(0);
// engine.flush() has already been called by renderInternal(), but we need an extra one
// for endFrame() above. This operation in actually not too heavy, it just kicks the

View File

@@ -209,7 +209,7 @@ private:
backend::Handle<backend::HwRenderTarget> mRenderTargetHandle;
FSwapChain* mSwapChain = nullptr;
size_t mCommandsHighWatermark = 0;
uint32_t mFrameId = 0;
uint32_t mFrameId = 1; // id 0 is reserved for standalone views
FrameInfoManager mFrameInfoManager;
backend::TextureFormat mHdrTranslucent;
backend::TextureFormat mHdrQualityMedium;

View File

@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.68.0"
spec.version = "1.68.1"
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.68.0/filament-v1.68.0-ios.tgz" }
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.68.1/filament-v1.68.1-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {

View File

@@ -1,6 +1,6 @@
{
"name": "filament",
"version": "1.68.0",
"version": "1.68.1",
"description": "Real-time physically based rendering engine",
"main": "filament.js",
"module": "filament.js",