Skip to content

Commit

Permalink
Revert "Switch setFrameScheduledCallback to use utils::Invocable (#7792
Browse files Browse the repository at this point in the history
…)"

This reverts commit e7feee7.
  • Loading branch information
bejado committed May 10, 2024
1 parent aeb0c14 commit 0d22805
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 93 deletions.
3 changes: 1 addition & 2 deletions filament/backend/include/backend/DriverEnums.h
Expand Up @@ -24,7 +24,6 @@

#include <backend/PresentCallable.h>

#include <utils/Invocable.h>
#include <utils/ostream.h>

#include <math/vec4.h>
Expand Down Expand Up @@ -1225,7 +1224,7 @@ static_assert(sizeof(StencilState::StencilOperations) == 5u,
static_assert(sizeof(StencilState) == 12u,
"StencilState size not what was intended");

using FrameScheduledCallback = utils::Invocable<void(backend::PresentCallable)>;
using FrameScheduledCallback = void(*)(PresentCallable callable, void* user);

enum class Workaround : uint16_t {
// The EASU pass must split because shader compiler flattens early-exit branch
Expand Down
4 changes: 3 additions & 1 deletion filament/backend/include/backend/PresentCallable.h
Expand Up @@ -48,7 +48,7 @@ namespace filament::backend {
* and optional user data:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* swapChain->setFrameScheduledCallback(nullptr, myFrameScheduledCallback);
* swapChain->setFrameScheduledCallback(myFrameScheduledCallback, nullptr);
* if (renderer->beginFrame(swapChain)) {
* renderer->render(view);
* renderer->endFrame();
Expand All @@ -58,6 +58,8 @@ namespace filament::backend {
* @remark Only Filament's Metal backend supports PresentCallables and frame callbacks. Other
* backends ignore the callback (which will never be called) and proceed normally.
*
* @remark The SwapChain::FrameScheduledCallback is called on an arbitrary thread.
*
* Applications *must* call each PresentCallable they receive. Each PresentCallable represents a
* frame that is waiting to be presented. If an application fails to call a PresentCallable, a
* memory leak could occur. To "cancel" the presentation of a frame, pass false to the
Expand Down
4 changes: 2 additions & 2 deletions filament/backend/include/private/backend/DriverAPI.inc
Expand Up @@ -138,8 +138,8 @@ DECL_DRIVER_API_N(beginFrame,

DECL_DRIVER_API_N(setFrameScheduledCallback,
backend::SwapChainHandle, sch,
backend::CallbackHandler*, handler,
backend::FrameScheduledCallback&&, callback)
backend::FrameScheduledCallback, callback,
void*, user)

DECL_DRIVER_API_N(setFrameCompletedCallback,
backend::SwapChainHandle, sch,
Expand Down
6 changes: 3 additions & 3 deletions filament/backend/src/metal/MetalDriver.mm
Expand Up @@ -237,10 +237,10 @@
}
}

void MetalDriver::setFrameScheduledCallback(
Handle<HwSwapChain> sch, CallbackHandler* handler, FrameScheduledCallback&& callback) {
void MetalDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch,
FrameScheduledCallback callback, void* user) {
auto* swapChain = handle_cast<MetalSwapChain>(sch);
swapChain->setFrameScheduledCallback(handler, std::move(callback));
swapChain->setFrameScheduledCallback(callback, user);
}

void MetalDriver::setFrameCompletedCallback(Handle<HwSwapChain> sch,
Expand Down
25 changes: 11 additions & 14 deletions filament/backend/src/metal/MetalHandles.h
Expand Up @@ -31,8 +31,6 @@

#include "private/backend/SamplerGroup.h"

#include <backend/DriverEnums.h>

#include <utils/bitset.h>
#include <utils/CString.h>
#include <utils/FixedCapacityVector.h>
Expand Down Expand Up @@ -73,9 +71,9 @@ class MetalSwapChain : public HwSwapChain {

void releaseDrawable();

void setFrameScheduledCallback(CallbackHandler* handler, FrameScheduledCallback&& callback);
void setFrameCompletedCallback(
CallbackHandler* handler, CallbackHandler::Callback callback, void* user);
void setFrameScheduledCallback(FrameScheduledCallback callback, void* user);
void setFrameCompletedCallback(CallbackHandler* handler,
CallbackHandler::Callback callback, void* user);

// For CAMetalLayer-backed SwapChains, presents the drawable or schedules a
// FrameScheduledCallback.
Expand Down Expand Up @@ -112,15 +110,14 @@ class MetalSwapChain : public HwSwapChain {
MetalExternalImage externalImage;
SwapChainType type;

// These fields store a callback to notify the client that a frame is ready for presentation. If
// !frameScheduled.callback, then the Metal backend automatically calls presentDrawable when the
// frame is committed. Otherwise, the Metal backend will not automatically present the frame.
// Instead, clients bear the responsibility of presenting the frame by calling the
// PresentCallable object.
struct {
CallbackHandler* handler = nullptr;
FrameScheduledCallback callback = {};
} frameScheduled;
// These two fields store a callback and user data to notify the client that a frame is ready
// for presentation.
// If frameScheduledCallback is nullptr, then the Metal backend automatically calls
// presentDrawable when the frame is committed.
// Otherwise, the Metal backend will not automatically present the frame. Instead, clients bear
// the responsibility of presenting the frame by calling the PresentCallable object.
FrameScheduledCallback frameScheduledCallback = nullptr;
void* frameScheduledUserData = nullptr;

struct {
CallbackHandler* handler = nullptr;
Expand Down
40 changes: 11 additions & 29 deletions filament/backend/src/metal/MetalHandles.mm
Expand Up @@ -221,10 +221,9 @@ static inline MTLTextureUsage getMetalTextureUsage(TextureUsage usage) {
depthStencilTexture = [context.device newTextureWithDescriptor:descriptor];
}

void MetalSwapChain::setFrameScheduledCallback(
CallbackHandler* handler, FrameScheduledCallback&& callback) {
frameScheduled.handler = handler;
frameScheduled.callback = std::move(callback);
void MetalSwapChain::setFrameScheduledCallback(FrameScheduledCallback callback, void* user) {
frameScheduledCallback = callback;
frameScheduledUserData = user;
}

void MetalSwapChain::setFrameCompletedCallback(CallbackHandler* handler,
Expand All @@ -239,7 +238,7 @@ static inline MTLTextureUsage getMetalTextureUsage(TextureUsage usage) {
scheduleFrameCompletedCallback();
}
if (drawable) {
if (frameScheduled.callback) {
if (frameScheduledCallback) {
scheduleFrameScheduledCallback();
} else {
[getPendingCommandBuffer(&context) presentDrawable:drawable];
Expand Down Expand Up @@ -297,38 +296,21 @@ void presentDrawable(bool presentFrame, void* user) {
}

void MetalSwapChain::scheduleFrameScheduledCallback() {
if (!frameScheduled.callback) {
if (!frameScheduledCallback) {
return;
}

assert_invariant(drawable);

struct Callback {
Callback(FrameScheduledCallback&& callback, id<CAMetalDrawable> drawable,
MetalDriver* driver)
: f(std::move(callback)), data(PresentDrawableData::create(drawable, driver)) {}
FrameScheduledCallback f;
// PresentDrawableData* is destroyed by maybePresentAndDestroyAsync() later.
std::unique_ptr<PresentDrawableData> data;
static void func(void* user) {
auto* const c = reinterpret_cast<Callback*>(user);
PresentDrawableData* presentDrawableData = c->data.release();
PresentCallable presentCallable(presentDrawable, presentDrawableData);
c->f(presentCallable);
delete c;
}
};
// Destroy this by calling maybePresentAndDestroyAsync() later.
auto* presentData = PresentDrawableData::create(drawable, context.driver);

// This callback pointer will be captured by the block. Even if the scheduled handler is never
// called, the unique_ptr will still ensure we don't leak memory.
__block auto callback =
std::make_unique<Callback>(std::move(frameScheduled.callback), drawable, context.driver);
FrameScheduledCallback userCallback = frameScheduledCallback;
void* userData = frameScheduledUserData;

backend::CallbackHandler* handler = frameScheduled.handler;
MetalDriver* driver = context.driver;
[getPendingCommandBuffer(&context) addScheduledHandler:^(id<MTLCommandBuffer> cb) {
Callback* user = callback.release();
driver->scheduleCallback(handler, user, &Callback::func);
PresentCallable callable(presentDrawable, static_cast<void*>(presentData));
userCallback(callable, userData);
}];
}

Expand Down
2 changes: 1 addition & 1 deletion filament/backend/src/noop/NoopDriver.cpp
Expand Up @@ -54,7 +54,7 @@ void NoopDriver::beginFrame(int64_t monotonic_clock_ns,
}

void NoopDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch,
CallbackHandler* handler, FrameScheduledCallback&& callback) {
FrameScheduledCallback callback, void* user) {

}

Expand Down
2 changes: 1 addition & 1 deletion filament/backend/src/opengl/OpenGLDriver.cpp
Expand Up @@ -3417,7 +3417,7 @@ void OpenGLDriver::beginFrame(
}

void OpenGLDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch,
CallbackHandler* handler, FrameScheduledCallback&& callback) {
FrameScheduledCallback callback, void* user) {
DEBUG_MARKER()
}

Expand Down
2 changes: 1 addition & 1 deletion filament/backend/src/vulkan/VulkanDriver.cpp
Expand Up @@ -394,7 +394,7 @@ void VulkanDriver::beginFrame(int64_t monotonic_clock_ns,
}

void VulkanDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch,
CallbackHandler* handler, FrameScheduledCallback&& callback) {
FrameScheduledCallback callback, void* user) {
}

void VulkanDriver::setFrameCompletedCallback(Handle<HwSwapChain> sch,
Expand Down
40 changes: 16 additions & 24 deletions filament/include/filament/SwapChain.h
Expand Up @@ -21,7 +21,6 @@

#include <backend/CallbackHandler.h>
#include <backend/DriverEnums.h>
#include <backend/PresentCallable.h>

#include <utils/compiler.h>
#include <utils/Invocable.h>
Expand Down Expand Up @@ -265,49 +264,42 @@ class UTILS_PUBLIC SwapChain : public FilamentAPI {
* backend.
*
* A FrameScheduledCallback can be set on an individual SwapChain through
* SwapChain::setFrameScheduledCallback. If the callback is set for a given frame, then the
* SwapChain will *not* automatically schedule itself for presentation. Instead, the application
* must call the PresentCallable passed to the FrameScheduledCallback.
* SwapChain::setFrameScheduledCallback. If the callback is set, then the SwapChain will *not*
* automatically schedule itself for presentation. Instead, the application must call the
* PresentCallable passed to the FrameScheduledCallback.
*
* Each SwapChain can have only one FrameScheduledCallback set per frame. If
* setFrameScheduledCallback is called multiple times on the same SwapChain before
* Renderer::endFrame(), the most recent call effectively overwrites any previously set
* callback. This allows the callback to be updated as needed before the frame has finished
* encoding.
*
* The "last" callback set by setFrameScheduledCallback gets "latched" when Renderer::endFrame()
* is executed. At this point, the state of the callback is fixed and is the one used for the
* frame that was just encoded. Subsequent changes to the callback using
* setFrameScheduledCallback after endFrame() apply to the next frame.
*
* Use \c setFrameScheduledCallback() (with default arguments) to unset the callback.
* There may be only one FrameScheduledCallback set per SwapChain. A call to
* SwapChain::setFrameScheduledCallback will overwrite any previous FrameScheduledCallbacks set
* on the same SwapChain.
*
* If your application delays the call to the PresentCallable by, for example, calling it on a
* separate thread, you must ensure all PresentCallables have been called before shutting down
* the Filament Engine. You can do this by issuing an Engine::flushAndWait before calling
* Engine::shutdown. This is necessary to ensure the Filament Engine has had a chance to clean
* up all memory related to frame presentation.
*
* @param handler Handler to dispatch the callback or nullptr for the default handler.
* @param callback Callback called when the frame is scheduled.
* @param callback A callback, or nullptr to unset.
* @param user An optional pointer to user data passed to the callback function.
*
* @remark Only Filament's Metal backend supports PresentCallables and frame callbacks. Other
* backends ignore the callback (which will never be called) and proceed normally.
*
* @see CallbackHandler
* @remark The SwapChain::FrameScheduledCallback is called on an arbitrary thread.
*
* @see PresentCallable
*/
void setFrameScheduledCallback(backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
FrameScheduledCallback&& callback = {});
void setFrameScheduledCallback(FrameScheduledCallback UTILS_NULLABLE callback,
void* UTILS_NULLABLE user = nullptr);

/**
* Returns whether or not this SwapChain currently has a FrameScheduledCallback set.
* Returns the SwapChain::FrameScheduledCallback that was previously set with
* SwapChain::setFrameScheduledCallback, or nullptr if one is not set.
*
* @return true, if the last call to setFrameScheduledCallback set a callback
* @return the previously-set FrameScheduledCallback, or nullptr
*
* @see SwapChain::setFrameCompletedCallback
*/
bool isFrameScheduledCallbackSet() const noexcept;
UTILS_NULLABLE FrameScheduledCallback getFrameScheduledCallback() const noexcept;

/**
* FrameCompletedCallback is a callback function that notifies an application when a frame's
Expand Down
9 changes: 4 additions & 5 deletions filament/src/SwapChain.cpp
Expand Up @@ -28,13 +28,12 @@ void* SwapChain::getNativeWindow() const noexcept {
return downcast(this)->getNativeWindow();
}

void SwapChain::setFrameScheduledCallback(
backend::CallbackHandler* handler, FrameScheduledCallback&& callback) {
downcast(this)->setFrameScheduledCallback(handler, std::move(callback));
void SwapChain::setFrameScheduledCallback(FrameScheduledCallback callback, void* user) {
downcast(this)->setFrameScheduledCallback(callback, user);
}

bool SwapChain::isFrameScheduledCallbackSet() const noexcept {
return downcast(this)->isFrameScheduledCallbackSet();
SwapChain::FrameScheduledCallback SwapChain::getFrameScheduledCallback() const noexcept {
return downcast(this)->getFrameScheduledCallback();
}

void SwapChain::setFrameCompletedCallback(backend::CallbackHandler* handler,
Expand Down
11 changes: 5 additions & 6 deletions filament/src/details/SwapChain.cpp
Expand Up @@ -69,14 +69,13 @@ void FSwapChain::terminate(FEngine& engine) noexcept {
engine.getDriverApi().destroySwapChain(mHwSwapChain);
}

void FSwapChain::setFrameScheduledCallback(
backend::CallbackHandler* handler, FrameScheduledCallback&& callback) {
mFrameScheduledCallbackIsSet = bool(callback);
mEngine.getDriverApi().setFrameScheduledCallback(mHwSwapChain, handler, std::move(callback));
void FSwapChain::setFrameScheduledCallback(FrameScheduledCallback callback, void* user) {
mFrameScheduledCallback = callback;
mEngine.getDriverApi().setFrameScheduledCallback(mHwSwapChain, callback, user);
}

bool FSwapChain::isFrameScheduledCallbackSet() const noexcept {
return mFrameScheduledCallbackIsSet;
SwapChain::FrameScheduledCallback FSwapChain::getFrameScheduledCallback() const noexcept {
return mFrameScheduledCallback;
}

void FSwapChain::setFrameCompletedCallback(backend::CallbackHandler* handler,
Expand Down
7 changes: 3 additions & 4 deletions filament/src/details/SwapChain.h
Expand Up @@ -78,10 +78,9 @@ class FSwapChain : public SwapChain {
return mHwSwapChain;
}

void setFrameScheduledCallback(
backend::CallbackHandler* handler, FrameScheduledCallback&& callback);
void setFrameScheduledCallback(FrameScheduledCallback callback, void* user);

bool isFrameScheduledCallbackSet() const noexcept;
FrameScheduledCallback getFrameScheduledCallback() const noexcept;

void setFrameCompletedCallback(backend::CallbackHandler* handler,
utils::Invocable<void(SwapChain*)>&& callback) noexcept;
Expand All @@ -97,7 +96,7 @@ class FSwapChain : public SwapChain {
private:
FEngine& mEngine;
backend::Handle<backend::HwSwapChain> mHwSwapChain;
bool mFrameScheduledCallbackIsSet = false;
FrameScheduledCallback mFrameScheduledCallback{};
void* mNativeWindow{};
uint32_t mWidth{};
uint32_t mHeight{};
Expand Down

0 comments on commit 0d22805

Please sign in to comment.