capi: expose deferred API and make order consistent.

gotta get all these ABI breaks done before release.
This commit is contained in:
chyyran 2023-02-11 03:46:42 -05:00
parent fa6cd87c60
commit 0eac766685
15 changed files with 456 additions and 58 deletions

View file

@ -497,12 +497,22 @@ typedef libra_error_t (*PFN_libra_gl_filter_chain_free)(libra_gl_filter_chain_t
#if defined(LIBRA_RUNTIME_VULKAN)
/// Function pointer definition for
///libra_vk_filter_chain_create
typedef libra_error_t (*PFN_libra_vk_filter_chain_create)(struct libra_device_vk_t vulkan,
libra_shader_preset_t *preset,
typedef libra_error_t (*PFN_libra_vk_filter_chain_create)(libra_shader_preset_t *preset,
struct libra_device_vk_t vulkan,
const struct filter_chain_vk_opt_t *options,
libra_vk_filter_chain_t *out);
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
/// Function pointer definition for
///libra_vk_filter_chain_create_deferred
typedef libra_error_t (*PFN_libra_vk_filter_chain_create_deferred)(libra_shader_preset_t *preset,
struct libra_device_vk_t vulkan,
VkCommandBuffer command_buffer,
const struct filter_chain_vk_opt_t *options,
libra_vk_filter_chain_t *out);
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
/// Function pointer definition for
///libra_vk_filter_chain_frame
@ -556,11 +566,21 @@ typedef libra_error_t (*PFN_libra_vk_filter_chain_free)(libra_vk_filter_chain_t
/// Function pointer definition for
///libra_d3d11_filter_chain_create
typedef libra_error_t (*PFN_libra_d3d11_filter_chain_create)(libra_shader_preset_t *preset,
const struct filter_chain_d3d11_opt_t *options,
ID3D11Device * device,
const struct filter_chain_d3d11_opt_t *options,
libra_d3d11_filter_chain_t *out);
#endif
#if defined(LIBRA_RUNTIME_D3D11)
/// Function pointer definition for
///libra_d3d11_filter_chain_create_deferred
typedef libra_error_t (*PFN_libra_d3d11_filter_chain_create_deferred)(libra_shader_preset_t *preset,
ID3D11Device * device,
ID3D11DeviceContext * device_context,
const struct filter_chain_d3d11_opt_t *options,
libra_d3d11_filter_chain_t *out);
#endif
#if defined(LIBRA_RUNTIME_D3D11)
/// Function pointer definition for
///libra_d3d11_filter_chain_frame
@ -571,7 +591,7 @@ typedef libra_error_t (*PFN_libra_d3d11_filter_chain_frame)(libra_d3d11_filter_c
struct libra_viewport_t viewport,
ID3D11RenderTargetView * out,
const float *mvp,
const struct frame_d3d11_opt_t *opt);
const struct frame_d3d11_opt_t *options);
#endif
#if defined(LIBRA_RUNTIME_D3D11)
@ -614,11 +634,21 @@ typedef libra_error_t (*PFN_libra_d3d11_filter_chain_free)(libra_d3d11_filter_ch
/// Function pointer definition for
///libra_d3d12_filter_chain_create
typedef libra_error_t (*PFN_libra_d3d12_filter_chain_create)(libra_shader_preset_t *preset,
const struct filter_chain_d3d12_opt_t *opt,
ID3D12Device * device,
const struct filter_chain_d3d12_opt_t *options,
libra_d3d12_filter_chain_t *out);
#endif
#if defined(LIBRA_RUNTIME_D3D12)
/// Function pointer definition for
///libra_d3d12_filter_chain_create_deferred
typedef libra_error_t (*PFN_libra_d3d12_filter_chain_create_deferred)(libra_shader_preset_t *preset,
ID3D12Device * device,
ID3D12GraphicsCommandList * command_list,
const struct filter_chain_d3d12_opt_t *options,
libra_d3d12_filter_chain_t *out);
#endif
#if defined(LIBRA_RUNTIME_D3D12)
/// Function pointer definition for
///libra_d3d12_filter_chain_frame
@ -905,12 +935,37 @@ libra_error_t libra_gl_filter_chain_free(libra_gl_filter_chain_t *chain);
/// - `preset` must be either null, or valid and aligned.
/// - `options` must be either null, or valid and aligned.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
libra_error_t libra_vk_filter_chain_create(struct libra_device_vk_t vulkan,
libra_shader_preset_t *preset,
libra_error_t libra_vk_filter_chain_create(libra_shader_preset_t *preset,
struct libra_device_vk_t vulkan,
const struct filter_chain_vk_opt_t *options,
libra_vk_filter_chain_t *out);
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
/// Create the filter chain given the shader preset deferring and GPU-side initialization
/// to the caller. This function therefore requires no external synchronization of the device queue.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - The handles provided in `vulkan` must be valid for the command buffers that
/// `libra_vk_filter_chain_frame` will write to. Namely, the VkDevice must have been
/// created with the `VK_KHR_dynamic_rendering` extension.
/// - `preset` must be either null, or valid and aligned.
/// - `options` must be either null, or valid and aligned.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
///
/// The provided command buffer must be ready for recording and contain no prior commands.
/// The caller is responsible for ending the command buffer and immediately submitting it to a
/// graphics queue. The command buffer must be completely executed before calling `libra_vk_filter_chain_frame`.
libra_error_t libra_vk_filter_chain_create_deferred(libra_shader_preset_t *preset,
struct libra_device_vk_t vulkan,
VkCommandBuffer command_buffer,
const struct filter_chain_vk_opt_t *options,
libra_vk_filter_chain_t *out);
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
/// Records rendering commands for a frame with the given parameters for the given filter chain
/// to the input command buffer.
@ -1006,11 +1061,43 @@ libra_error_t libra_vk_filter_chain_free(libra_vk_filter_chain_t *chain);
/// - `device` must not be null.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
libra_error_t libra_d3d11_filter_chain_create(libra_shader_preset_t *preset,
const struct filter_chain_d3d11_opt_t *options,
ID3D11Device * device,
const struct filter_chain_d3d11_opt_t *options,
libra_d3d11_filter_chain_t *out);
#endif
#if defined(LIBRA_RUNTIME_D3D11)
/// Create the filter chain given the shader preset, deferring and GPU-side initialization
/// to the caller. This function is therefore requires no external synchronization of the
/// immediate context, as long as the immediate context is not used as the input context,
/// nor of the device, as long as the device is not single-threaded only.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` must be either null, or valid and aligned.
/// - `options` must be either null, or valid and aligned.
/// - `device` must not be null.
/// - `device_context` not be null.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
///
/// The provided context must either be immediate, or immediately submitted after this function
/// returns, **before drawing frames**, or lookup textures will fail to load and the filter chain
/// will be in an invalid state.
///
/// If the context is deferred, it must be ready for command recording, and have no prior commands
/// recorded. No commands shall be recorded after, the caller must immediately call [`FinishCommandList`](https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-finishcommandlist)
/// and execute the command list on the immediate context after this function returns.
///
/// If the context is immediate, then access to the immediate context requires external synchronization.
libra_error_t libra_d3d11_filter_chain_create_deferred(libra_shader_preset_t *preset,
ID3D11Device * device,
ID3D11DeviceContext * device_context,
const struct filter_chain_d3d11_opt_t *options,
libra_d3d11_filter_chain_t *out);
#endif
#if defined(LIBRA_RUNTIME_D3D11)
/// Draw a frame with the given parameters for the given filter chain.
///
@ -1039,7 +1126,7 @@ libra_error_t libra_d3d11_filter_chain_frame(libra_d3d11_filter_chain_t *chain,
struct libra_viewport_t viewport,
ID3D11RenderTargetView * out,
const float *mvp,
const struct frame_d3d11_opt_t *opt);
const struct frame_d3d11_opt_t *options);
#endif
#if defined(LIBRA_RUNTIME_D3D11)
@ -1105,11 +1192,35 @@ libra_error_t libra_d3d11_filter_chain_free(libra_d3d11_filter_chain_t *chain);
/// - `device` must not be null.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
libra_error_t libra_d3d12_filter_chain_create(libra_shader_preset_t *preset,
const struct filter_chain_d3d12_opt_t *opt,
ID3D12Device * device,
const struct filter_chain_d3d12_opt_t *options,
libra_d3d12_filter_chain_t *out);
#endif
#if defined(LIBRA_RUNTIME_D3D12)
/// Create the filter chain given the shader preset deferring and GPU-side initialization
/// to the caller. This function therefore requires no external synchronization of the device queue.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` must be either null, or valid and aligned.
/// - `options` must be either null, or valid and aligned.
/// - `device` must not be null.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
/// - `cmd` must not be null.
///
/// The provided command list must be ready for recording and contain no prior commands.
/// The caller is responsible for ending the command list and immediately submitting it to a
/// graphics queue. The command list must be completely executed before calling `libra_d3d12_filter_chain_frame`.
libra_error_t libra_d3d12_filter_chain_create_deferred(libra_shader_preset_t *preset,
ID3D12Device * device,
ID3D12GraphicsCommandList * command_list,
const struct filter_chain_d3d12_opt_t *options,
libra_d3d12_filter_chain_t *out);
#endif
#if defined(LIBRA_RUNTIME_D3D12)
/// Records rendering commands for a frame with the given parameters for the given filter chain
/// to the input command list.

View file

@ -29,12 +29,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Uncomment the following defines to activate runtimes.
//#define LIBRA_RUNTIME_OPENGL
//#define LIBRA_RUNTIME_VULKAN
//
//#if defined(_WIN32)
//#define LIBRA_RUNTIME_D3D11
//#endif
// #define LIBRA_RUNTIME_OPENGL
// #define LIBRA_RUNTIME_VULKAN
// #if defined(_WIN32)
// #define LIBRA_RUNTIME_D3D11
// #define LIBRA_RUNTIME_D3D12
// #endif
#if defined(_WIN32)
#include <windows.h>
@ -153,11 +154,18 @@ libra_error_t __librashader__noop_gl_filter_chain_get_active_pass_count(
#if defined(LIBRA_RUNTIME_VULKAN)
libra_error_t __librashader__noop_vk_filter_chain_create(
struct libra_device_vk_t vulkan, libra_shader_preset_t *preset,
libra_shader_preset_t *preset, struct libra_device_vk_t vulkan,
const struct filter_chain_vk_opt_t *options, libra_vk_filter_chain_t *out) {
return NULL;
}
libra_error_t __librashader__noop_vk_filter_chain_create_deferred(
libra_shader_preset_t *preset, struct libra_device_vk_t vulkan,
VkCommandBuffer command_buffer, const struct filter_chain_vk_opt_t *options,
libra_vk_filter_chain_t *out) {
return NULL;
}
libra_error_t __librashader__noop_vk_filter_chain_frame(
libra_vk_filter_chain_t *chain, VkCommandBuffer command_buffer,
size_t frame_count, struct libra_source_image_vk_t image,
@ -194,8 +202,15 @@ libra_error_t __librashader__noop_vk_filter_chain_get_active_pass_count(
#if defined(LIBRA_RUNTIME_D3D11)
libra_error_t __librashader__noop_d3d11_filter_chain_create(
libra_shader_preset_t *preset,
const struct filter_chain_d3d11_opt_t *options, ID3D11Device *device,
libra_shader_preset_t *preset, ID3D11Device *device,
const struct filter_chain_d3d11_opt_t *options,
libra_d3d11_filter_chain_t *out) {
return NULL;
}
libra_error_t __librashader__noop_d3d11_filter_chain_create_deferred(
libra_shader_preset_t *preset, ID3D11Device *device, ID3D11DeviceContext *device_context,
const struct filter_chain_d3d11_opt_t *options,
libra_d3d11_filter_chain_t *out) {
return NULL;
}
@ -238,8 +253,16 @@ libra_error_t __librashader__noop_d3d11_filter_chain_get_active_pass_count(
#if defined(LIBRA_RUNTIME_D3D12)
libra_error_t __librashader__noop_d3d12_filter_chain_create(
libra_shader_preset_t *preset,
const struct filter_chain_d3d12_opt_t *options, ID3D12Device *device,
libra_shader_preset_t *preset, ID3D12Device *device,
const struct filter_chain_d3d12_opt_t *options,
libra_d3d12_filter_chain_t *out) {
return NULL;
}
libra_error_t __librashader__noop_d3d12_filter_chain_create_deferred(
libra_shader_preset_t *preset, ID3D12Device *device,
ID3D12GraphicsCommandList *command_list,
const struct filter_chain_d3d12_opt_t *options,
libra_d3d12_filter_chain_t *out) {
return NULL;
}
@ -505,6 +528,30 @@ typedef struct libra_instance_t {
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
PFN_libra_vk_filter_chain_create vk_filter_chain_create;
/// Create the filter chain given the shader preset deferring and GPU-side
/// initialization to the caller. This function therefore requires no
/// external synchronization of the device queue.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - The handles provided in `vulkan` must be valid for the command buffers
/// that
/// `libra_vk_filter_chain_frame` will write to. Namely, the VkDevice must
/// have been
/// created with the `VK_KHR_dynamic_rendering` extension.
/// - `preset` must be either null, or valid and aligned.
/// - `options` must be either null, or valid and aligned.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
///
/// The provided command buffer must be ready for recording and contain no
/// prior commands. The caller is responsible for ending the command buffer
/// and immediately submitting it to a graphics queue. The command buffer
/// must be completely executed before calling
/// `libra_vk_filter_chain_frame`.
PFN_libra_vk_filter_chain_create_deferred vk_filter_chain_create_deferred;
/// Records rendering commands for a frame with the given parameters for the
/// given filter chain
/// to the input command buffer.
@ -582,6 +629,39 @@ typedef struct libra_instance_t {
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
PFN_libra_d3d11_filter_chain_create d3d11_filter_chain_create;
/// Create the filter chain given the shader preset, deferring and GPU-side
/// initialization
/// to the caller. This function is therefore requires no external
/// synchronization of the immediate context, as long as the immediate
/// context is not used as the input context, nor of the device, as long as
/// the device is not single-threaded only.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` must be either null, or valid and aligned.
/// - `options` must be either null, or valid and aligned.
/// - `device` must not be null.
/// - `device_context` not be null.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
///
/// The provided context must either be immediate, or immediately submitted
/// after this function returns, **before drawing frames**, or lookup
/// textures will fail to load and the filter chain will be in an invalid
/// state.
///
/// If the context is deferred, it must be ready for command recording, and
/// have no prior commands recorded. No commands shall be recorded after,
/// the caller must immediately call
/// [`FinishCommandList`](https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-finishcommandlist)
/// and execute the command list on the immediate context after this
/// function returns.
///
/// If the context is immediate, then access to the immediate context
/// requires external synchronization.
PFN_libra_d3d11_filter_chain_create_deferred d3d11_filter_chain_create_deferred;
/// Draw a frame with the given parameters for the given filter chain.
///
/// ## Safety
@ -652,6 +732,27 @@ typedef struct libra_instance_t {
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
PFN_libra_d3d12_filter_chain_create d3d12_filter_chain_create;
/// Create the filter chain given the shader preset deferring and GPU-side
/// initialization
/// to the caller. This function therefore requires no external
/// synchronization of the device queue.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` must be either null, or valid and aligned.
/// - `options` must be either null, or valid and aligned.
/// - `device` must not be null.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
/// - `cmd` must not be null.
///
/// The provided command list must be ready for recording and contain no
/// prior commands. The caller is responsible for ending the command list
/// and immediately submitting it to a graphics queue. The command list must
/// be completely executed before calling `libra_d3d12_filter_chain_frame`
PFN_libra_d3d12_filter_chain_create_deferred d3d12_filter_chain_create_deferred;
/// Draw a frame with the given parameters for the given filter chain.
///
/// ## Safety
@ -747,6 +848,7 @@ libra_instance_t __librashader_make_null_instance() {
#if defined(LIBRA_RUNTIME_VULKAN)
.vk_filter_chain_create = __librashader__noop_vk_filter_chain_create,
.vk_filter_chain_create_deferred = __librashader__noop_vk_filter_chain_create_deferred,
.vk_filter_chain_frame = __librashader__noop_vk_filter_chain_frame,
.vk_filter_chain_free = __librashader__noop_vk_filter_chain_free,
.vk_filter_chain_get_active_pass_count =
@ -762,6 +864,8 @@ libra_instance_t __librashader_make_null_instance() {
#if defined(LIBRA_RUNTIME_D3D11)
.d3d11_filter_chain_create =
__librashader__noop_d3d11_filter_chain_create,
.d3d11_filter_chain_create_deferred =
__librashader__noop_d3d11_filter_chain_create_deferred,
.d3d11_filter_chain_frame =
__librashader__noop_d3d11_filter_chain_frame,
.d3d11_filter_chain_free = __librashader__noop_d3d11_filter_chain_free,
@ -778,6 +882,8 @@ libra_instance_t __librashader_make_null_instance() {
#if defined(LIBRA_RUNTIME_D3D12)
.d3d12_filter_chain_create =
__librashader__noop_d3d12_filter_chain_create,
.d3d12_filter_chain_create_deferred =
__librashader__noop_d3d12_filter_chain_create_deferred,
.d3d12_filter_chain_frame =
__librashader__noop_d3d12_filter_chain_frame,
.d3d12_filter_chain_free = __librashader__noop_d3d12_filter_chain_free,
@ -849,6 +955,7 @@ libra_instance_t librashader_load_instance() {
#if defined(LIBRA_RUNTIME_VULKAN)
_LIBRASHADER_ASSIGN(librashader, instance, vk_filter_chain_create);
_LIBRASHADER_ASSIGN(librashader, instance, vk_filter_chain_create_deferred);
_LIBRASHADER_ASSIGN(librashader, instance, vk_filter_chain_frame);
_LIBRASHADER_ASSIGN(librashader, instance, vk_filter_chain_free);
_LIBRASHADER_ASSIGN(librashader, instance,
@ -863,6 +970,7 @@ libra_instance_t librashader_load_instance() {
#if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D11)
_LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_create);
_LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_create_deferred);
_LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_frame);
_LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_free);
_LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_get_param);
@ -875,6 +983,7 @@ libra_instance_t librashader_load_instance() {
#if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D12)
_LIBRASHADER_ASSIGN(librashader, instance, d3d12_filter_chain_create);
_LIBRASHADER_ASSIGN(librashader, instance, d3d12_filter_chain_create_deferred);
_LIBRASHADER_ASSIGN(librashader, instance, d3d12_filter_chain_frame);
_LIBRASHADER_ASSIGN(librashader, instance, d3d12_filter_chain_free);
_LIBRASHADER_ASSIGN(librashader, instance, d3d12_filter_chain_get_param);

View file

@ -115,6 +115,7 @@ include = [
# vulkan
"PFN_libra_vk_filter_chain_create",
"PFN_libra_vk_filter_chain_create_deferred",
"PFN_libra_vk_filter_chain_frame",
"PFN_libra_vk_filter_chain_set_param",
"PFN_libra_vk_filter_chain_get_param",
@ -124,6 +125,7 @@ include = [
# d3d11
"PFN_libra_d3d11_filter_chain_create",
"PFN_libra_d3d11_filter_chain_create_deferred",
"PFN_libra_d3d11_filter_chain_frame",
"PFN_libra_d3d11_filter_chain_set_param",
"PFN_libra_d3d11_filter_chain_get_param",
@ -132,8 +134,9 @@ include = [
"PFN_libra_d3d11_filter_chain_free",
# d3d11
# d3d12
"PFN_libra_d3d12_filter_chain_create",
"PFN_libra_d3d12_filter_chain_create_deferred",
"PFN_libra_d3d12_filter_chain_frame",
"PFN_libra_d3d12_filter_chain_set_param",
"PFN_libra_d3d12_filter_chain_get_param",

View file

@ -92,8 +92,8 @@ extern_fn! {
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
fn libra_d3d11_filter_chain_create(
preset: *mut libra_shader_preset_t,
options: *const MaybeUninit<filter_chain_d3d11_opt_t>,
device: ManuallyDrop<ID3D11Device>,
options: *const MaybeUninit<filter_chain_d3d11_opt_t>,
out: *mut MaybeUninit<libra_d3d11_filter_chain_t>
) {
assert_non_null!(preset);
@ -111,8 +111,8 @@ extern_fn! {
let options = options.map(FromUninit::from_uninit);
let chain = librashader::runtime::d3d11::capi::FilterChainD3D11::load_from_preset(
&device,
*preset,
&device,
options.as_ref(),
)?;
@ -124,6 +124,69 @@ extern_fn! {
}
}
extern_fn! {
/// Create the filter chain given the shader preset, deferring and GPU-side initialization
/// to the caller. This function is therefore requires no external synchronization of the
/// immediate context, as long as the immediate context is not used as the input context,
/// nor of the device, as long as the device is not single-threaded only.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` must be either null, or valid and aligned.
/// - `options` must be either null, or valid and aligned.
/// - `device` must not be null.
/// - `device_context` not be null.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
///
/// The provided context must either be immediate, or immediately submitted after this function
/// returns, **before drawing frames**, or lookup textures will fail to load and the filter chain
/// will be in an invalid state.
///
/// If the context is deferred, it must be ready for command recording, and have no prior commands
/// recorded. No commands shall be recorded after, the caller must immediately call [`FinishCommandList`](https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-finishcommandlist)
/// and execute the command list on the immediate context after this function returns.
///
/// If the context is immediate, then access to the immediate context requires external synchronization.
fn libra_d3d11_filter_chain_create_deferred(
preset: *mut libra_shader_preset_t,
device: ManuallyDrop<ID3D11Device>,
device_context: ManuallyDrop<ID3D11DeviceContext>,
options: *const MaybeUninit<filter_chain_d3d11_opt_t>,
out: *mut MaybeUninit<libra_d3d11_filter_chain_t>
) {
assert_non_null!(preset);
let preset = unsafe {
let preset_ptr = &mut *preset;
let preset = preset_ptr.take();
Box::from_raw(preset.unwrap().as_ptr())
};
let options = if options.is_null() {
None
} else {
Some(unsafe { options.read() })
};
let options = options.map(FromUninit::from_uninit);
let chain = unsafe {
librashader::runtime::d3d11::capi::FilterChainD3D11::load_from_preset_deferred(
*preset,
&device,
&device_context,
options.as_ref(),
)?
};
unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
chain,
)))))
}
}
}
// This assert ensures that the bindings of Option<ManuallyDrop<ID3D11DeviceContext>> to ID3D11DeviceContext* is sound.
const _: () = assert!(
std::mem::size_of::<ID3D11DeviceContext>()
@ -162,7 +225,7 @@ extern_fn! {
viewport: libra_viewport_t,
out: ManuallyDrop<ID3D11RenderTargetView>,
mvp: *const f32,
opt: *const MaybeUninit<frame_d3d11_opt_t>
options: *const MaybeUninit<frame_d3d11_opt_t>
) mut |chain| {
assert_some_ptr!(mut chain);
@ -172,10 +235,10 @@ extern_fn! {
Some(<&[f32; 16]>::try_from(unsafe { slice::from_raw_parts(mvp, 16) }).unwrap())
};
let opt = if opt.is_null() {
let options = if options.is_null() {
None
} else {
Some(unsafe { opt.read() })
Some(unsafe { options.read() })
};
let viewport = Viewport {
@ -188,10 +251,10 @@ extern_fn! {
mvp,
};
let opt = opt.map(FromUninit::from_uninit);
let options = options.map(FromUninit::from_uninit);
let image = image.try_into()?;
chain.frame(device_context.as_deref(), image, &viewport, frame_count, opt.as_ref())?;
chain.frame(device_context.as_deref(), image, &viewport, frame_count, options.as_ref())?;
}
}

View file

@ -113,8 +113,8 @@ extern_fn! {
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
fn libra_d3d12_filter_chain_create(
preset: *mut libra_shader_preset_t,
opt: *const MaybeUninit<filter_chain_d3d12_opt_t>,
device: ManuallyDrop<ID3D12Device>,
options: *const MaybeUninit<filter_chain_d3d12_opt_t>,
out: *mut MaybeUninit<libra_d3d12_filter_chain_t>
) {
assert_non_null!(preset);
@ -124,17 +124,17 @@ extern_fn! {
Box::from_raw(preset.unwrap().as_ptr())
};
let opt = if opt.is_null() {
let options = if options.is_null() {
None
} else {
Some(unsafe { opt.read() })
Some(unsafe { options.read() })
};
let opt = opt.map(FromUninit::from_uninit);
let options = options.map(FromUninit::from_uninit);
let chain = librashader::runtime::d3d12::capi::FilterChainD3D12::load_from_preset(
&device,
*preset,
opt.as_ref(),
&device,
options.as_ref(),
)?;
unsafe {
@ -145,6 +145,61 @@ extern_fn! {
}
}
extern_fn! {
/// Create the filter chain given the shader preset deferring and GPU-side initialization
/// to the caller. This function therefore requires no external synchronization of the device queue.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` must be either null, or valid and aligned.
/// - `options` must be either null, or valid and aligned.
/// - `device` must not be null.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
/// - `cmd` must not be null.
///
/// The provided command list must be ready for recording and contain no prior commands.
/// The caller is responsible for ending the command list and immediately submitting it to a
/// graphics queue. The command list must be completely executed before calling `libra_d3d12_filter_chain_frame`.
fn libra_d3d12_filter_chain_create_deferred(
preset: *mut libra_shader_preset_t,
device: ManuallyDrop<ID3D12Device>,
command_list: ManuallyDrop<ID3D12GraphicsCommandList>,
options: *const MaybeUninit<filter_chain_d3d12_opt_t>,
out: *mut MaybeUninit<libra_d3d12_filter_chain_t>
) {
assert_non_null!(preset);
let preset = unsafe {
let preset_ptr = &mut *preset;
let preset = preset_ptr.take();
Box::from_raw(preset.unwrap().as_ptr())
};
let options = if options.is_null() {
None
} else {
Some(unsafe { options.read() })
};
let options = options.map(FromUninit::from_uninit);
let chain = unsafe {
librashader::runtime::d3d12::capi::FilterChainD3D12::load_from_preset_deferred(
*preset,
&device,
&command_list,
options.as_ref(),
)?
};
unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
chain,
)))))
}
}
}
extern_fn! {
/// Records rendering commands for a frame with the given parameters for the given filter chain
/// to the input command list.

View file

@ -136,8 +136,8 @@ extern_fn! {
/// - `options` must be either null, or valid and aligned.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
fn libra_vk_filter_chain_create(
vulkan: libra_device_vk_t,
preset: *mut libra_shader_preset_t,
vulkan: libra_device_vk_t,
options: *const MaybeUninit<filter_chain_vk_opt_t>,
out: *mut MaybeUninit<libra_vk_filter_chain_t>
) {
@ -157,7 +157,63 @@ extern_fn! {
let vulkan: VulkanInstance = vulkan.into();
let options = options.map(FromUninit::from_uninit);
let chain = librashader::runtime::vk::capi::FilterChainVulkan::load_from_preset(vulkan, *preset, options.as_ref())?;
let chain = librashader::runtime::vk::capi::FilterChainVulkan::load_from_preset(*preset, vulkan, options.as_ref())?;
unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
chain,
)))))
}
}
}
extern_fn! {
/// Create the filter chain given the shader preset deferring and GPU-side initialization
/// to the caller. This function therefore requires no external synchronization of the device queue.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - The handles provided in `vulkan` must be valid for the command buffers that
/// `libra_vk_filter_chain_frame` will write to. Namely, the VkDevice must have been
/// created with the `VK_KHR_dynamic_rendering` extension.
/// - `preset` must be either null, or valid and aligned.
/// - `options` must be either null, or valid and aligned.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
///
/// The provided command buffer must be ready for recording and contain no prior commands.
/// The caller is responsible for ending the command buffer and immediately submitting it to a
/// graphics queue. The command buffer must be completely executed before calling `libra_vk_filter_chain_frame`.
fn libra_vk_filter_chain_create_deferred(
preset: *mut libra_shader_preset_t,
vulkan: libra_device_vk_t,
command_buffer: vk::CommandBuffer,
options: *const MaybeUninit<filter_chain_vk_opt_t>,
out: *mut MaybeUninit<libra_vk_filter_chain_t>
) {
assert_non_null!(preset);
let preset = unsafe {
let preset_ptr = &mut *preset;
let preset = preset_ptr.take();
Box::from_raw(preset.unwrap().as_ptr())
};
let options = if options.is_null() {
None
} else {
Some(unsafe { options.read() })
};
let vulkan: VulkanInstance = vulkan.into();
let options = options.map(FromUninit::from_uninit);
let chain = unsafe {
librashader::runtime::vk::capi::FilterChainVulkan::load_from_preset_deferred(*preset,
vulkan,
command_buffer,
options.as_ref())?
};
unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(

View file

@ -76,23 +76,23 @@ pub(crate) struct FilterCommon {
impl FilterChainD3D11 {
/// Load the shader preset at the given path into a filter chain.
pub fn load_from_path(
device: &ID3D11Device,
path: impl AsRef<Path>,
device: &ID3D11Device,
options: Option<&FilterChainOptionsD3D11>,
) -> error::Result<FilterChainD3D11> {
// load passes from preset
let preset = ShaderPreset::try_parse(path)?;
Self::load_from_preset(device, preset, options)
Self::load_from_preset(preset, device, options)
}
/// Load a filter chain from a pre-parsed `ShaderPreset`.
pub fn load_from_preset(
device: &ID3D11Device,
preset: ShaderPreset,
device: &ID3D11Device,
options: Option<&FilterChainOptionsD3D11>,
) -> error::Result<FilterChainD3D11> {
let immediate_context = unsafe { device.GetImmediateContext()? };
unsafe { Self::load_from_preset_deferred(device, preset, &immediate_context, options) }
unsafe { Self::load_from_preset_deferred(preset, device, &immediate_context, options) }
}
/// Load a filter chain from a pre-parsed `ShaderPreset`, deferring and GPU-side initialization
@ -111,8 +111,8 @@ impl FilterChainD3D11 {
///
/// If the context is immediate, then access to the immediate context requires external synchronization.
pub unsafe fn load_from_preset_deferred(
device: &ID3D11Device,
preset: ShaderPreset,
device: &ID3D11Device,
ctx: &ID3D11DeviceContext,
options: Option<&FilterChainOptionsD3D11>,
) -> error::Result<FilterChainD3D11> {

View file

@ -290,7 +290,7 @@ pub mod d3d11_hello_triangle {
image: Option<Image>,
) -> Result<Self> {
let (dxgi_factory, device, context) = create_device()?;
let filter = FilterChainD3D11::load_from_path(&device, filter, filter_options).unwrap();
let filter = FilterChainD3D11::load_from_path(filter, &device, filter_options).unwrap();
let lut = if let Some(image) = image {
let lut = LutTexture::new(
&device,

View file

@ -141,19 +141,19 @@ impl Drop for FrameResiduals {
impl FilterChainD3D12 {
/// Load the shader preset at the given path into a filter chain.
pub fn load_from_path(
device: &ID3D12Device,
path: impl AsRef<Path>,
device: &ID3D12Device,
options: Option<&FilterChainOptionsD3D12>,
) -> error::Result<FilterChainD3D12> {
// load passes from preset
let preset = ShaderPreset::try_parse(path)?;
Self::load_from_preset(device, preset, options)
Self::load_from_preset(preset, device, options)
}
/// Load a filter chain from a pre-parsed `ShaderPreset`.
pub fn load_from_preset(
device: &ID3D12Device,
preset: ShaderPreset,
device: &ID3D12Device,
options: Option<&FilterChainOptionsD3D12>,
) -> error::Result<FilterChainD3D12> {
unsafe {
@ -173,7 +173,7 @@ impl FilterChainD3D12 {
let fence_event = CreateEventA(None, false, false, None)?;
let fence: ID3D12Fence = device.CreateFence(0, D3D12_FENCE_FLAG_NONE)?;
let filter_chain = Self::load_from_preset_deferred(device, preset, &cmd, options)?;
let filter_chain = Self::load_from_preset_deferred(preset, device, &cmd, options)?;
cmd.Close()?;
queue.ExecuteCommandLists(&[cmd.cast()?]);
@ -197,8 +197,8 @@ impl FilterChainD3D12 {
/// The caller is responsible for ending the command list and immediately submitting it to a
/// graphics queue. The command list must be completely executed before calling [`frame`](Self::frame).
pub unsafe fn load_from_preset_deferred(
device: &ID3D12Device,
preset: ShaderPreset,
device: &ID3D12Device,
cmd: &ID3D12GraphicsCommandList,
options: Option<&FilterChainOptionsD3D12>,
) -> error::Result<FilterChainD3D12> {

View file

@ -287,7 +287,7 @@ pub mod d3d12_hello_triangle {
}
}
let filter = FilterChainD3D12::load_from_path(&device, filter, None).unwrap();
let filter = FilterChainD3D12::load_from_path(filter, &device, None).unwrap();
Ok(Sample {
dxgi_factory,

View file

@ -220,8 +220,8 @@ impl Drop for FrameResiduals {
impl FilterChainVulkan {
/// Load the shader preset at the given path into a filter chain.
pub fn load_from_path<V, E>(
vulkan: V,
path: impl AsRef<Path>,
vulkan: V,
options: Option<&FilterChainOptionsVulkan>,
) -> error::Result<FilterChainVulkan>
where
@ -230,13 +230,13 @@ impl FilterChainVulkan {
{
// load passes from preset
let preset = ShaderPreset::try_parse(path)?;
Self::load_from_preset(vulkan, preset, options)
Self::load_from_preset(preset, vulkan, options)
}
/// Load a filter chain from a pre-parsed `ShaderPreset`.
pub fn load_from_preset<V, E>(
vulkan: V,
preset: ShaderPreset,
vulkan: V,
options: Option<&FilterChainOptionsVulkan>,
) -> error::Result<FilterChainVulkan>
where
@ -278,8 +278,8 @@ impl FilterChainVulkan {
let filter_chain = unsafe {
Self::load_from_preset_deferred::<_, Infallible>(
vulkan,
preset,
vulkan,
command_buffer,
options,
)?
@ -308,8 +308,8 @@ impl FilterChainVulkan {
/// The caller is responsible for ending the command buffer and immediately submitting it to a
/// graphics queue. The command buffer must be completely executed before calling [`frame`](Self::frame).
pub unsafe fn load_from_preset_deferred<V, E>(
vulkan: V,
preset: ShaderPreset,
vulkan: V,
cmd: vk::CommandBuffer,
options: Option<&FilterChainOptionsVulkan>,
) -> error::Result<FilterChainVulkan>

View file

@ -42,9 +42,9 @@ mod tests {
let entry = unsafe { ash::Entry::load().unwrap() };
let base = VulkanBase::new(entry).unwrap();
let filter = FilterChainVulkan::load_from_path(
&base,
// "../test/slang-shaders/crt/crt-royale.slangp",
"../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV-GLASS.slangp",
&base,
// "../test/slang-shaders/test/feedback.slancargogp",
// "../test/basic.slangp",
Some(&FilterChainOptionsVulkan {

View file

@ -74,7 +74,8 @@ int main(int, char**)
.force_no_mipmaps = false,
};
libra.d3d11_filter_chain_create(&preset, &opt, g_pd3dDevice, &filter_chain);
libra.d3d11_filter_chain_create_deferred(
&preset, g_pd3dDevice, g_pd3dDeviceContext, & opt, &filter_chain);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.

View file

@ -71,7 +71,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
.force_no_mipmaps = false,
};
libra.d3d11_filter_chain_create(&preset, &opt, device, &filter_chain);
libra.d3d11_filter_chain_create(&preset, device, &opt, &filter_chain);
///////////////////////////////////////////////////////////////////////////////////////////////
IDXGIDevice1* dxgiDevice;

View file

@ -141,7 +141,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
libra_d3d11_filter_chain_t filter_chain;
libra.d3d11_filter_chain_create(&preset, NULL, d3d11Device,
libra.d3d11_filter_chain_create(&preset, d3d11Device, NULL,
&filter_chain);
// Create Swap Chain