Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding draft extension for host-provided scratch memory #423

Open
wants to merge 9 commits into
base: next
Choose a base branch
from
63 changes: 63 additions & 0 deletions include/clap/ext/draft/scratch-memory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once

#include "../../plugin.h"

// This extension lets the plugin request "scratch" memory
// from the host. Scratch memory can be accessed during the
// `process()` callback, but is not persistent between callbacks.
abique marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"but it's content isn't persistent between callbacks."

It could be confused with it's allocation that isn't persistent.

//
// The motivation for this extension is to allow the plugin host
// to "share" a single scratch buffer across multiple plugin
// instances.
//
// For example, imagine the host needs to process three plugins
// in sequence, and each plugin requires 10K of scratch memory.
// If each plugin pre-allocates its own scratch memory, then 30K
// of memory is being allocated in total. However, if each plugin
// requests 10K of scratch memory from the host, then the host can
// allocate a single 10K scratch buffer, and make it available to all
// three plugins.
//
// On memory-constrained platforms, this optimization may allow for
// more plugins to be used simultaneously. On platforms with lots
// of memory, this optimization may improve CPU cache usage.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both optimization: space and CPU cache are valid regardless of the available memory on the system.


static CLAP_CONSTEXPR const char CLAP_EXT_SCRATCH_MEMORY[] = "clap.scratch-memory/1";

#ifdef __cplusplus
extern "C" {
#endif

typedef struct clap_host_scratch_memory {
// Asks the host for certain amount of scratch memory.
// If the host is unable to provide the memory, it should
// return "false".
//
// Note that any memory the host allocates to satisfy
// the requested scratch size can be de-allocated by the
// host when the plugin is de-activated.
jatinchowdhury18 marked this conversation as resolved.
Show resolved Hide resolved
Comment on lines +47 to +49
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: does this imply that if a plugin transitions activated -> deactivated -> being-activated, in the final being-activated state it must re-request scratch memory via a call to reserve? Or is the prior reservation still valid?

//
// [main-thread & being-activated]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: I think [being-activated] should be documented somewhere, because I believe it is necessary for correctness here (assuming it means that the plugin may only call this whilst it is in the call stack of a call to clap_plugin.activate by the host): otherwise there could be a race between calls to reserve and access?

bool(CLAP_ABI *pre_reserve)(const clap_host_t *host, size_t scratch_size_bytes);
abique marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we ever use size_t in any other extension? -> uint?_t ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, uint32_t would do the job I think.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use uint64_t which is size_t in most of our systems? The host has the option to return no for values out of bounds

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a preference for uint32_t vs uint64_t... but Trinitou is right that CLAP doesn't use size_t anywhere else, so I don't think we should use it here.

Copy link
Contributor

@abique abique Oct 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A scratch size bigger than 4 GB would be problematic I suppose, remember nthreads * max_scratch_size.
Anyway regardless of the type, many host will likely have their own threshold.
uint32_t seems sufficient to me, but I'm happy with uint64_t as well.


// Asks the host for the previously requested scratch memory.
// If the host returned "true" when scratch memory was requested,
// then this method must return a pointer to a memory block at least
// as large as the requested size. If the host returned "false"
// when scratch memory was requested then this method should return
// null.
jatinchowdhury18 marked this conversation as resolved.
Show resolved Hide resolved
//
// The provided memory is not initialized, and may have been used
// by other plugin instances, so the plugin must correctly initialize
// the memory when using it.
//
// The provided memory is owned by the host, so the plugin should not
// attempt to free the memory.
//
// [audio-thread]
void*(CLAP_ABI *access)(const clap_host_t *host);
} clap_host_scratch_memory_t;

#ifdef __cplusplus
}
#endif
Loading