d3d11: be agnostic about deferred contexts

This brings the D3D11 API more in line with the D3D12 and Vulkan runtimes. To get the old behaviour with immediate contexts, just pass a NULL context.
This commit is contained in:
chyyran 2023-02-10 18:08:11 -05:00
parent 512a4c0050
commit 0cb6f6a346
19 changed files with 189 additions and 203 deletions

View file

@ -38,6 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <d3d11.h> #include <d3d11.h>
#else #else
typedef void ID3D11Device; typedef void ID3D11Device;
typedef void ID3D11DeviceContext;
typedef void ID3D11RenderTargetView; typedef void ID3D11RenderTargetView;
typedef void ID3D11ShaderResourceView; typedef void ID3D11ShaderResourceView;
#endif #endif
@ -289,11 +290,6 @@ typedef struct frame_vk_opt_t {
typedef struct filter_chain_d3d11_opt_t { typedef struct filter_chain_d3d11_opt_t {
/// The librashader API version. /// The librashader API version.
LIBRASHADER_API_VERSION version; LIBRASHADER_API_VERSION version;
/// Use a deferred context to record shader rendering state.
///
/// The deferred context will be executed on the immediate context
/// with `RenderContextState = true`.
bool use_deferred_context;
/// Whether or not to explicitly disable mipmap /// Whether or not to explicitly disable mipmap
/// generation regardless of shader preset settings. /// generation regardless of shader preset settings.
bool force_no_mipmaps; bool force_no_mipmaps;
@ -309,7 +305,7 @@ typedef struct _filter_chain_d3d11 *libra_d3d11_filter_chain_t;
/// Direct3D 11 parameters for the source image. /// Direct3D 11 parameters for the source image.
typedef struct libra_source_image_d3d11_t { typedef struct libra_source_image_d3d11_t {
/// A shader resource view into the source image /// A shader resource view into the source image
const ID3D11ShaderResourceView * handle; ID3D11ShaderResourceView * handle;
/// The width of the source image. /// The width of the source image.
uint32_t width; uint32_t width;
/// The height of the source image. /// The height of the source image.
@ -353,7 +349,7 @@ typedef struct _filter_chain_d3d12 *libra_d3d12_filter_chain_t;
/// Direct3D 12 parameters for the source image. /// Direct3D 12 parameters for the source image.
typedef struct libra_source_image_d3d12_t { typedef struct libra_source_image_d3d12_t {
/// The resource containing the image. /// The resource containing the image.
const ID3D12Resource * resource; ID3D12Resource * resource;
/// A CPU descriptor handle to a shader resource view of the image. /// A CPU descriptor handle to a shader resource view of the image.
D3D12_CPU_DESCRIPTOR_HANDLE descriptor; D3D12_CPU_DESCRIPTOR_HANDLE descriptor;
/// The format of the image. /// The format of the image.
@ -561,7 +557,7 @@ typedef libra_error_t (*PFN_libra_vk_filter_chain_free)(libra_vk_filter_chain_t
///libra_d3d11_filter_chain_create ///libra_d3d11_filter_chain_create
typedef libra_error_t (*PFN_libra_d3d11_filter_chain_create)(libra_shader_preset_t *preset, typedef libra_error_t (*PFN_libra_d3d11_filter_chain_create)(libra_shader_preset_t *preset,
const struct filter_chain_d3d11_opt_t *options, const struct filter_chain_d3d11_opt_t *options,
const ID3D11Device * device, ID3D11Device * device,
libra_d3d11_filter_chain_t *out); libra_d3d11_filter_chain_t *out);
#endif #endif
@ -569,10 +565,11 @@ typedef libra_error_t (*PFN_libra_d3d11_filter_chain_create)(libra_shader_preset
/// Function pointer definition for /// Function pointer definition for
///libra_d3d11_filter_chain_frame ///libra_d3d11_filter_chain_frame
typedef libra_error_t (*PFN_libra_d3d11_filter_chain_frame)(libra_d3d11_filter_chain_t *chain, typedef libra_error_t (*PFN_libra_d3d11_filter_chain_frame)(libra_d3d11_filter_chain_t *chain,
ID3D11DeviceContext * device_context,
size_t frame_count, size_t frame_count,
struct libra_source_image_d3d11_t image, struct libra_source_image_d3d11_t image,
struct libra_viewport_t viewport, struct libra_viewport_t viewport,
const ID3D11RenderTargetView * out, ID3D11RenderTargetView * out,
const float *mvp, const float *mvp,
const struct frame_d3d11_opt_t *opt); const struct frame_d3d11_opt_t *opt);
#endif #endif
@ -618,7 +615,7 @@ typedef libra_error_t (*PFN_libra_d3d11_filter_chain_free)(libra_d3d11_filter_ch
///libra_d3d12_filter_chain_create ///libra_d3d12_filter_chain_create
typedef libra_error_t (*PFN_libra_d3d12_filter_chain_create)(libra_shader_preset_t *preset, typedef libra_error_t (*PFN_libra_d3d12_filter_chain_create)(libra_shader_preset_t *preset,
const struct filter_chain_d3d12_opt_t *opt, const struct filter_chain_d3d12_opt_t *opt,
const ID3D12Device * device, ID3D12Device * device,
libra_d3d12_filter_chain_t *out); libra_d3d12_filter_chain_t *out);
#endif #endif
@ -626,7 +623,7 @@ typedef libra_error_t (*PFN_libra_d3d12_filter_chain_create)(libra_shader_preset
/// Function pointer definition for /// Function pointer definition for
///libra_d3d12_filter_chain_frame ///libra_d3d12_filter_chain_frame
typedef libra_error_t (*PFN_libra_d3d12_filter_chain_frame)(libra_d3d12_filter_chain_t *chain, typedef libra_error_t (*PFN_libra_d3d12_filter_chain_frame)(libra_d3d12_filter_chain_t *chain,
const ID3D12GraphicsCommandList * command_list, ID3D12GraphicsCommandList * command_list,
size_t frame_count, size_t frame_count,
struct libra_source_image_d3d12_t image, struct libra_source_image_d3d12_t image,
struct libra_viewport_t viewport, struct libra_viewport_t viewport,
@ -918,7 +915,12 @@ libra_error_t libra_vk_filter_chain_create(struct libra_device_vk_t vulkan,
/// Records rendering commands for a frame with the given parameters for the given filter chain /// Records rendering commands for a frame with the given parameters for the given filter chain
/// to the input command buffer. /// to the input command buffer.
/// ///
/// librashader will not do any queue submissions. /// * The input image must be in the `VK_SHADER_READ_ONLY_OPTIMAL` layout.
/// * The output image must be in `VK_COLOR_ATTACHMENT_OPTIMAL` layout.
///
/// librashader **will not** create a pipeline barrier for the final pass. The output image will
/// remain in `VK_COLOR_ATTACHMENT_OPTIMAL` after all shader passes. The caller must transition
/// the output image to the final layout.
/// ///
/// ## Safety /// ## Safety
/// - `libra_vk_filter_chain_frame` **must not be called within a RenderPass**. /// - `libra_vk_filter_chain_frame` **must not be called within a RenderPass**.
@ -1005,13 +1007,17 @@ libra_error_t libra_vk_filter_chain_free(libra_vk_filter_chain_t *chain);
/// - `out` must be aligned, but may be null, invalid, or uninitialized. /// - `out` must be aligned, but may be null, invalid, or uninitialized.
libra_error_t libra_d3d11_filter_chain_create(libra_shader_preset_t *preset, libra_error_t libra_d3d11_filter_chain_create(libra_shader_preset_t *preset,
const struct filter_chain_d3d11_opt_t *options, const struct filter_chain_d3d11_opt_t *options,
const ID3D11Device * device, ID3D11Device * device,
libra_d3d11_filter_chain_t *out); libra_d3d11_filter_chain_t *out);
#endif #endif
#if defined(LIBRA_RUNTIME_D3D11) #if defined(LIBRA_RUNTIME_D3D11)
/// Draw a frame with the given parameters for the given filter chain. /// Draw a frame with the given parameters for the given filter chain.
/// ///
/// If `device_context` is null, then commands are recorded onto the immediate context. Otherwise,
/// it will record commands onto the provided context. If the context is deferred, librashader
/// will not finalize command lists. The context must otherwise be associated with the `ID3D11Device`
///
/// ## Safety /// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this /// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error. /// function will return an error.
@ -1021,13 +1027,17 @@ libra_error_t libra_d3d11_filter_chain_create(libra_shader_preset_t *preset,
/// struct. /// struct.
/// - `out` must not be null. /// - `out` must not be null.
/// - `image.handle` must not be null. /// - `image.handle` must not be null.
/// - If `device_context` is null, commands will be recorded onto the immediate context of the `ID3D11Device`
/// this filter chain was created with. The context must otherwise be associated with the `ID3D11Device`
/// the filter chain was created with.
/// - You must ensure that only one thread has access to `chain` before you call this function. Only one /// - You must ensure that only one thread has access to `chain` before you call this function. Only one
/// thread at a time may call this function. /// thread at a time may call this function.
libra_error_t libra_d3d11_filter_chain_frame(libra_d3d11_filter_chain_t *chain, libra_error_t libra_d3d11_filter_chain_frame(libra_d3d11_filter_chain_t *chain,
ID3D11DeviceContext * device_context,
size_t frame_count, size_t frame_count,
struct libra_source_image_d3d11_t image, struct libra_source_image_d3d11_t image,
struct libra_viewport_t viewport, struct libra_viewport_t viewport,
const ID3D11RenderTargetView * out, ID3D11RenderTargetView * out,
const float *mvp, const float *mvp,
const struct frame_d3d11_opt_t *opt); const struct frame_d3d11_opt_t *opt);
#endif #endif
@ -1096,7 +1106,7 @@ libra_error_t libra_d3d11_filter_chain_free(libra_d3d11_filter_chain_t *chain);
/// - `out` must be aligned, but may be null, invalid, or uninitialized. /// - `out` must be aligned, but may be null, invalid, or uninitialized.
libra_error_t libra_d3d12_filter_chain_create(libra_shader_preset_t *preset, libra_error_t libra_d3d12_filter_chain_create(libra_shader_preset_t *preset,
const struct filter_chain_d3d12_opt_t *opt, const struct filter_chain_d3d12_opt_t *opt,
const ID3D12Device * device, ID3D12Device * device,
libra_d3d12_filter_chain_t *out); libra_d3d12_filter_chain_t *out);
#endif #endif
@ -1104,6 +1114,13 @@ libra_error_t libra_d3d12_filter_chain_create(libra_shader_preset_t *preset,
/// Records rendering commands for a frame with the given parameters for the given filter chain /// Records rendering commands for a frame with the given parameters for the given filter chain
/// to the input command list. /// to the input command list.
/// ///
/// * The input image must be in the `D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE` resource state.
/// * The output image must be in `D3D12_RESOURCE_STATE_RENDER_TARGET` resource state.
///
/// librashader **will not** create a resource barrier for the final pass. The output image will
/// remain in `D3D12_RESOURCE_STATE_RENDER_TARGET` after all shader passes. The caller must transition
/// the output image to the final resource state.
///
/// ## Safety /// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this /// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error. /// function will return an error.
@ -1113,11 +1130,12 @@ libra_error_t libra_d3d12_filter_chain_create(libra_shader_preset_t *preset,
/// struct. /// struct.
/// - `out` must be a descriptor handle to a render target view. /// - `out` must be a descriptor handle to a render target view.
/// - `image.resource` must not be null. /// - `image.resource` must not be null.
/// - `command_list` must not be null. /// - `command_list` must be a non-null pointer to a `ID3D12GraphicsCommandList` that is open,
/// and must be associated with the `ID3D12Device` this filter chain was created with.
/// - You must ensure that only one thread has access to `chain` before you call this function. Only one /// - You must ensure that only one thread has access to `chain` before you call this function. Only one
/// thread at a time may call this function. /// thread at a time may call this function.
libra_error_t libra_d3d12_filter_chain_frame(libra_d3d12_filter_chain_t *chain, libra_error_t libra_d3d12_filter_chain_frame(libra_d3d12_filter_chain_t *chain,
const ID3D12GraphicsCommandList * command_list, ID3D12GraphicsCommandList * command_list,
size_t frame_count, size_t frame_count,
struct libra_source_image_d3d12_t image, struct libra_source_image_d3d12_t image,
struct libra_viewport_t viewport, struct libra_viewport_t viewport,

View file

@ -195,15 +195,16 @@ libra_error_t __librashader__noop_vk_filter_chain_get_active_pass_count(
#if defined(LIBRA_RUNTIME_D3D11) #if defined(LIBRA_RUNTIME_D3D11)
libra_error_t __librashader__noop_d3d11_filter_chain_create( libra_error_t __librashader__noop_d3d11_filter_chain_create(
libra_shader_preset_t *preset, libra_shader_preset_t *preset,
const struct filter_chain_d3d11_opt_t *options, const ID3D11Device *device, const struct filter_chain_d3d11_opt_t *options, ID3D11Device *device,
libra_d3d11_filter_chain_t *out) { libra_d3d11_filter_chain_t *out) {
return NULL; return NULL;
} }
libra_error_t __librashader__noop_d3d11_filter_chain_frame( libra_error_t __librashader__noop_d3d11_filter_chain_frame(
libra_d3d11_filter_chain_t *chain, size_t frame_count, libra_d3d11_filter_chain_t *chain,
ID3D11DeviceContext *device_context, size_t frame_count,
struct libra_source_image_d3d11_t image, struct libra_viewport_t viewport, struct libra_source_image_d3d11_t image, struct libra_viewport_t viewport,
const ID3D11RenderTargetView *out, const float *mvp, ID3D11RenderTargetView *out, const float *mvp,
const struct frame_d3d11_opt_t *opt) { const struct frame_d3d11_opt_t *opt) {
return NULL; return NULL;
} }
@ -238,14 +239,14 @@ libra_error_t __librashader__noop_d3d11_filter_chain_get_active_pass_count(
#if defined(LIBRA_RUNTIME_D3D12) #if defined(LIBRA_RUNTIME_D3D12)
libra_error_t __librashader__noop_d3d12_filter_chain_create( libra_error_t __librashader__noop_d3d12_filter_chain_create(
libra_shader_preset_t *preset, libra_shader_preset_t *preset,
const struct filter_chain_d3d12_opt_t *options, const ID3D12Device *device, const struct filter_chain_d3d12_opt_t *options, ID3D12Device *device,
libra_d3d12_filter_chain_t *out) { libra_d3d12_filter_chain_t *out) {
return NULL; return NULL;
} }
libra_error_t __librashader__noop_d3d12_filter_chain_frame( libra_error_t __librashader__noop_d3d12_filter_chain_frame(
libra_d3d12_filter_chain_t *chain, libra_d3d12_filter_chain_t *chain,
const ID3D12GraphicsCommandList *command_list, size_t frame_count, ID3D12GraphicsCommandList *command_list, size_t frame_count,
struct libra_source_image_d3d12_t image, struct libra_viewport_t viewport, struct libra_source_image_d3d12_t image, struct libra_viewport_t viewport,
struct libra_output_image_d3d12_t out, const float *mvp, struct libra_output_image_d3d12_t out, const float *mvp,
const struct frame_d3d12_opt_t *opt) { const struct frame_d3d12_opt_t *opt) {

View file

@ -36,6 +36,7 @@ after_includes = """
#include <d3d11.h> #include <d3d11.h>
#else #else
typedef void ID3D11Device; typedef void ID3D11Device;
typedef void ID3D11DeviceContext;
typedef void ID3D11RenderTargetView; typedef void ID3D11RenderTargetView;
typedef void ID3D11ShaderResourceView; typedef void ID3D11ShaderResourceView;
#endif #endif
@ -64,6 +65,7 @@ typedef void D3D12_CPU_DESCRIPTOR_HANDLE;
"feature = runtime-d3d11" = "LIBRA_RUNTIME_D3D11" "feature = runtime-d3d11" = "LIBRA_RUNTIME_D3D11"
"feature = runtime-d3d12" = "LIBRA_RUNTIME_D3D12" "feature = runtime-d3d12" = "LIBRA_RUNTIME_D3D12"
[parse] [parse]
parse_deps = true parse_deps = true
include = ["librashader", include = ["librashader",
@ -140,6 +142,8 @@ include = [
"PFN_libra_d3d12_filter_chain_free", "PFN_libra_d3d12_filter_chain_free",
] ]
exclude = ["Option_ID3D11DeviceContext"]
[export.rename] [export.rename]
"LibrashaderError" = "_libra_error" "LibrashaderError" = "_libra_error"
"ShaderPreset" = "_shader_preset" "ShaderPreset" = "_shader_preset"
@ -157,11 +161,16 @@ include = [
"Image" = "VkImage" "Image" = "VkImage"
# hack to get proper pointer indirection for COM pointers # hack to get proper pointer indirection for COM pointers
"ID3D11Device" = "const ID3D11Device *" # we don't need one for ID3D11DeviceContext.
"ID3D11RenderTargetView" = "const ID3D11RenderTargetView *" "ID3D11Device" = "ID3D11Device *"
"ID3D11ShaderResourceView" = "const ID3D11ShaderResourceView *" "ID3D11DeviceContext" = "ID3D11DeviceContext *"
"ID3D11RenderTargetView" = "ID3D11RenderTargetView *"
"ID3D11ShaderResourceView" = "ID3D11ShaderResourceView *"
# hack to force cbindgen to not generate option type for nullable ID3D11DeviceContext.
"Option_ID3D11DeviceContext" = "ID3D11DeviceContext *"
# hack to get proper pointer indirection for COM pointers # hack to get proper pointer indirection for COM pointers
"ID3D12Device" = "const ID3D12Device *" "ID3D12Device" = "ID3D12Device *"
"ID3D12Resource" = "const ID3D12Resource *" "ID3D12Resource" = "ID3D12Resource *"
"ID3D12GraphicsCommandList" = "const ID3D12GraphicsCommandList *" "ID3D12GraphicsCommandList" = "ID3D12GraphicsCommandList *"

View file

@ -10,14 +10,14 @@ use std::mem::{ManuallyDrop, MaybeUninit};
use std::ptr::NonNull; use std::ptr::NonNull;
use std::slice; use std::slice;
use windows::Win32::Graphics::Direct3D11::{ use windows::Win32::Graphics::Direct3D11::{
ID3D11Device, ID3D11RenderTargetView, ID3D11ShaderResourceView, ID3D11Device, ID3D11DeviceContext, ID3D11RenderTargetView, ID3D11ShaderResourceView,
}; };
use librashader::runtime::d3d11::capi::options::FilterChainOptionsD3D11; use librashader::runtime::d3d11::capi::options::FilterChainOptionsD3D11;
use librashader::runtime::d3d11::capi::options::FrameOptionsD3D11; use librashader::runtime::d3d11::capi::options::FrameOptionsD3D11;
use librashader::runtime::{FilterChainParameters, Size, Viewport};
use crate::LIBRASHADER_API_VERSION; use crate::LIBRASHADER_API_VERSION;
use librashader::runtime::{FilterChainParameters, Size, Viewport};
/// Direct3D 11 parameters for the source image. /// Direct3D 11 parameters for the source image.
#[repr(C)] #[repr(C)]
@ -49,12 +49,6 @@ impl TryFrom<libra_source_image_d3d11_t> for D3D11InputView {
pub struct filter_chain_d3d11_opt_t { pub struct filter_chain_d3d11_opt_t {
/// The librashader API version. /// The librashader API version.
pub version: LIBRASHADER_API_VERSION, pub version: LIBRASHADER_API_VERSION,
/// Use a deferred context to record shader rendering state.
///
/// The deferred context will be executed on the immediate context
/// with `RenderContextState = true`.
pub use_deferred_context: bool,
/// Whether or not to explicitly disable mipmap /// Whether or not to explicitly disable mipmap
/// generation regardless of shader preset settings. /// generation regardless of shader preset settings.
pub force_no_mipmaps: bool, pub force_no_mipmaps: bool,
@ -62,7 +56,7 @@ pub struct filter_chain_d3d11_opt_t {
config_struct! { config_struct! {
impl FilterChainOptionsD3D11 => filter_chain_d3d11_opt_t { impl FilterChainOptionsD3D11 => filter_chain_d3d11_opt_t {
0 => [use_deferred_context, force_no_mipmaps]; 0 => [force_no_mipmaps];
} }
} }
@ -130,9 +124,20 @@ extern_fn! {
} }
} }
// This assert ensures that the bindings of Option<ManuallyDrop<ID3D11DeviceContext>> to ID3D11DeviceContext* is sound.
const _: () = assert!(
std::mem::size_of::<ID3D11DeviceContext>()
== std::mem::size_of::<Option<ManuallyDrop<ID3D11DeviceContext>>>()
);
extern_fn! { extern_fn! {
/// Draw a frame with the given parameters for the given filter chain. /// Draw a frame with the given parameters for the given filter chain.
/// ///
/// If `device_context` is null, then commands are recorded onto the immediate context. Otherwise,
/// it will record commands onto the provided context. If the context is deferred, librashader
/// will not finalize command lists. The context must otherwise be associated with the `ID3D11Device`
// the filter chain was created with.
///
/// ## Safety /// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this /// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error. /// function will return an error.
@ -142,10 +147,16 @@ extern_fn! {
/// struct. /// struct.
/// - `out` must not be null. /// - `out` must not be null.
/// - `image.handle` must not be null. /// - `image.handle` must not be null.
/// - If `device_context` is null, commands will be recorded onto the immediate context of the `ID3D11Device`
/// this filter chain was created with. The context must otherwise be associated with the `ID3D11Device`
/// the filter chain was created with.
/// - You must ensure that only one thread has access to `chain` before you call this function. Only one /// - You must ensure that only one thread has access to `chain` before you call this function. Only one
/// thread at a time may call this function. /// thread at a time may call this function.
fn libra_d3d11_filter_chain_frame( fn libra_d3d11_filter_chain_frame(
chain: *mut libra_d3d11_filter_chain_t, chain: *mut libra_d3d11_filter_chain_t,
// cbindgen can't discover that ID3D11DeviceContext has the niche optimization
// so ManuallyDrop<Option<ID3D11DeviceContext>> doesn't generate correct bindings.
device_context: Option<ManuallyDrop<ID3D11DeviceContext>>,
frame_count: usize, frame_count: usize,
image: libra_source_image_d3d11_t, image: libra_source_image_d3d11_t,
viewport: libra_viewport_t, viewport: libra_viewport_t,
@ -180,7 +191,7 @@ extern_fn! {
let opt = opt.map(FromUninit::from_uninit); let opt = opt.map(FromUninit::from_uninit);
let image = image.try_into()?; let image = image.try_into()?;
chain.frame(image, &viewport, frame_count, opt.as_ref())?; chain.frame(device_context.as_deref(), image, &viewport, frame_count, opt.as_ref())?;
} }
} }

View file

@ -16,9 +16,9 @@ use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT;
use librashader::runtime::d3d12::capi::options::FilterChainOptionsD3D12; use librashader::runtime::d3d12::capi::options::FilterChainOptionsD3D12;
use librashader::runtime::d3d12::capi::options::FrameOptionsD3D12; use librashader::runtime::d3d12::capi::options::FrameOptionsD3D12;
use crate::LIBRASHADER_API_VERSION;
use librashader::runtime::d3d12::{D3D12InputImage, D3D12OutputView}; use librashader::runtime::d3d12::{D3D12InputImage, D3D12OutputView};
use librashader::runtime::{FilterChainParameters, Size, Viewport}; use librashader::runtime::{FilterChainParameters, Size, Viewport};
use crate::LIBRASHADER_API_VERSION;
/// Direct3D 12 parameters for the source image. /// Direct3D 12 parameters for the source image.
#[repr(C)] #[repr(C)]
@ -149,6 +149,13 @@ extern_fn! {
/// Records rendering commands for a frame with the given parameters for the given filter chain /// Records rendering commands for a frame with the given parameters for the given filter chain
/// to the input command list. /// to the input command list.
/// ///
/// * The input image must be in the `D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE` resource state.
/// * The output image must be in `D3D12_RESOURCE_STATE_RENDER_TARGET` resource state.
///
/// librashader **will not** create a resource barrier for the final pass. The output image will
/// remain in `D3D12_RESOURCE_STATE_RENDER_TARGET` after all shader passes. The caller must transition
/// the output image to the final resource state.
///
/// ## Safety /// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this /// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error. /// function will return an error.
@ -158,7 +165,8 @@ extern_fn! {
/// struct. /// struct.
/// - `out` must be a descriptor handle to a render target view. /// - `out` must be a descriptor handle to a render target view.
/// - `image.resource` must not be null. /// - `image.resource` must not be null.
/// - `command_list` must not be null. /// - `command_list` must be a non-null pointer to a `ID3D12GraphicsCommandList` that is open,
/// and must be associated with the `ID3D12Device` this filter chain was created with.
/// - You must ensure that only one thread has access to `chain` before you call this function. Only one /// - You must ensure that only one thread has access to `chain` before you call this function. Only one
/// thread at a time may call this function. /// thread at a time may call this function.
fn libra_d3d12_filter_chain_frame( fn libra_d3d12_filter_chain_frame(

View file

@ -10,11 +10,11 @@ use std::mem::MaybeUninit;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::slice; use std::slice;
use crate::LIBRASHADER_API_VERSION;
use librashader::runtime::gl::capi::options::FilterChainOptionsGL; use librashader::runtime::gl::capi::options::FilterChainOptionsGL;
use librashader::runtime::gl::capi::options::FrameOptionsGL; use librashader::runtime::gl::capi::options::FrameOptionsGL;
use librashader::runtime::FilterChainParameters; use librashader::runtime::FilterChainParameters;
use librashader::runtime::{Size, Viewport}; use librashader::runtime::{Size, Viewport};
use crate::LIBRASHADER_API_VERSION;
/// A GL function loader that librashader needs to be initialized with. /// A GL function loader that librashader needs to be initialized with.
pub type libra_gl_loader_t = unsafe extern "system" fn(*const c_char) -> *const c_void; pub type libra_gl_loader_t = unsafe extern "system" fn(*const c_char) -> *const c_void;

View file

@ -171,7 +171,12 @@ extern_fn! {
/// Records rendering commands for a frame with the given parameters for the given filter chain /// Records rendering commands for a frame with the given parameters for the given filter chain
/// to the input command buffer. /// to the input command buffer.
/// ///
/// librashader will not do any queue submissions. /// * The input image must be in the `VK_SHADER_READ_ONLY_OPTIMAL` layout.
/// * The output image must be in `VK_COLOR_ATTACHMENT_OPTIMAL` layout.
///
/// librashader **will not** create a pipeline barrier for the final pass. The output image will
/// remain in `VK_COLOR_ATTACHMENT_OPTIMAL` after all shader passes. The caller must transition
/// the output image to the final layout.
/// ///
/// ## Safety /// ## Safety
/// - `libra_vk_filter_chain_frame` **must not be called within a RenderPass**. /// - `libra_vk_filter_chain_frame` **must not be called within a RenderPass**.

View file

@ -71,13 +71,12 @@ const FINAL_VBO_DATA: [D3D11Vertex; 4] = [
static VBO_DATA: &[D3D11Vertex; 8] = &concat_arrays!(OFFSCREEN_VBO_DATA, FINAL_VBO_DATA); static VBO_DATA: &[D3D11Vertex; 8] = &concat_arrays!(OFFSCREEN_VBO_DATA, FINAL_VBO_DATA);
pub(crate) struct DrawQuad { pub(crate) struct DrawQuad {
context: ID3D11DeviceContext,
stride: u32, stride: u32,
vbo: ID3D11Buffer, vbo: ID3D11Buffer,
} }
impl DrawQuad { impl DrawQuad {
pub fn new(device: &ID3D11Device, context: &ID3D11DeviceContext) -> error::Result<DrawQuad> { pub fn new(device: &ID3D11Device) -> error::Result<DrawQuad> {
unsafe { unsafe {
let mut vbo = None; let mut vbo = None;
device.CreateBuffer( device.CreateBuffer(
@ -100,18 +99,16 @@ impl DrawQuad {
Ok(DrawQuad { Ok(DrawQuad {
vbo, vbo,
context: context.clone(),
stride: std::mem::size_of::<D3D11Vertex>() as u32, stride: std::mem::size_of::<D3D11Vertex>() as u32,
}) })
} }
} }
pub fn bind_vbo_for_frame(&self) { pub fn bind_vbo_for_frame(&self, context: &ID3D11DeviceContext) {
unsafe { unsafe {
self.context context.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
self.context.IASetVertexBuffers( context.IASetVertexBuffers(
0, 0,
1, 1,
Some(&Some(self.vbo.clone())), Some(&Some(self.vbo.clone())),

View file

@ -56,10 +56,8 @@ pub struct FilterChainD3D11 {
} }
pub(crate) struct Direct3D11 { pub(crate) struct Direct3D11 {
pub(crate) device: ID3D11Device, pub(crate) _device: ID3D11Device,
pub(crate) current_context: ID3D11DeviceContext,
pub(crate) immediate_context: ID3D11DeviceContext, pub(crate) immediate_context: ID3D11DeviceContext,
pub context_is_deferred: bool,
} }
pub(crate) struct FilterCommon { pub(crate) struct FilterCommon {
@ -97,8 +95,6 @@ impl FilterChainD3D11 {
FilterChainError, FilterChainError,
>(preset.shaders, &preset.textures)?; >(preset.shaders, &preset.textures)?;
let use_deferred_context = options.map_or(false, |f| f.use_deferred_context);
let samplers = SamplerSet::new(device)?; let samplers = SamplerSet::new(device)?;
// initialize passes // initialize passes
@ -106,30 +102,10 @@ impl FilterChainD3D11 {
let immediate_context = unsafe { device.GetImmediateContext()? }; let immediate_context = unsafe { device.GetImmediateContext()? };
let current_context = if use_deferred_context {
// check if device supports deferred contexts
if let Err(_) = unsafe { device.CreateDeferredContext(0, None) } {
immediate_context.clone()
} else {
let mut context = None;
unsafe { device.CreateDeferredContext(0, Some(&mut context))? };
assume_d3d11_init!(context, "CreateDeferredContext");
context
}
} else {
immediate_context.clone()
};
// initialize output framebuffers // initialize output framebuffers
let mut output_framebuffers = Vec::new(); let mut output_framebuffers = Vec::new();
output_framebuffers.resize_with(filters.len(), || { output_framebuffers.resize_with(filters.len(), || {
OwnedFramebuffer::new( OwnedFramebuffer::new(device, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, false)
device,
&current_context,
Size::new(1, 1),
ImageFormat::R8G8B8A8Unorm,
false,
)
}); });
// resolve all results // resolve all results
@ -143,13 +119,7 @@ impl FilterChainD3D11 {
// // initialize feedback framebuffers // // initialize feedback framebuffers
let mut feedback_framebuffers = Vec::new(); let mut feedback_framebuffers = Vec::new();
feedback_framebuffers.resize_with(filters.len(), || { feedback_framebuffers.resize_with(filters.len(), || {
OwnedFramebuffer::new( OwnedFramebuffer::new(device, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, false)
device,
&current_context,
Size::new(1, 1),
ImageFormat::R8G8B8A8Unorm,
false,
)
}); });
// resolve all results // resolve all results
let feedback_framebuffers = feedback_framebuffers let feedback_framebuffers = feedback_framebuffers
@ -160,12 +130,12 @@ impl FilterChainD3D11 {
feedback_textures.resize_with(filters.len(), || None); feedback_textures.resize_with(filters.len(), || None);
// load luts // load luts
let luts = FilterChainD3D11::load_luts(device, &current_context, &preset.textures)?; let luts = FilterChainD3D11::load_luts(device, &immediate_context, &preset.textures)?;
let (history_framebuffers, history_textures) = let (history_framebuffers, history_textures) =
FilterChainD3D11::init_history(device, &current_context, &filters)?; FilterChainD3D11::init_history(device, &filters)?;
let draw_quad = DrawQuad::new(device, &current_context)?; let draw_quad = DrawQuad::new(device)?;
let state = D3D11State::new(device)?; let state = D3D11State::new(device)?;
Ok(FilterChainD3D11 { Ok(FilterChainD3D11 {
passes: filters, passes: filters,
@ -174,10 +144,8 @@ impl FilterChainD3D11 {
history_framebuffers, history_framebuffers,
common: FilterCommon { common: FilterCommon {
d3d11: Direct3D11 { d3d11: Direct3D11 {
device: device.clone(), _device: device.clone(),
current_context,
immediate_context, immediate_context,
context_is_deferred: use_deferred_context,
}, },
config: FilterMutable { config: FilterMutable {
passes_enabled: preset.shader_count as usize, passes_enabled: preset.shader_count as usize,
@ -317,7 +285,6 @@ impl FilterChainD3D11 {
fn init_history( fn init_history(
device: &ID3D11Device, device: &ID3D11Device,
context: &ID3D11DeviceContext,
filters: &Vec<FilterPass>, filters: &Vec<FilterPass>,
) -> error::Result<(VecDeque<OwnedFramebuffer>, Box<[Option<InputTexture>]>)> { ) -> error::Result<(VecDeque<OwnedFramebuffer>, Box<[Option<InputTexture>]>)> {
let required_images = let required_images =
@ -334,13 +301,7 @@ impl FilterChainD3D11 {
// eprintln!("[history] using frame history with {required_images} images"); // eprintln!("[history] using frame history with {required_images} images");
let mut framebuffers = VecDeque::with_capacity(required_images); let mut framebuffers = VecDeque::with_capacity(required_images);
framebuffers.resize_with(required_images, || { framebuffers.resize_with(required_images, || {
OwnedFramebuffer::new( OwnedFramebuffer::new(device, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, false)
device,
context,
Size::new(1, 1),
ImageFormat::R8G8B8A8Unorm,
false,
)
}); });
let framebuffers = framebuffers let framebuffers = framebuffers
@ -353,9 +314,13 @@ impl FilterChainD3D11 {
Ok((framebuffers, history_textures.into_boxed_slice())) Ok((framebuffers, history_textures.into_boxed_slice()))
} }
fn push_history(&mut self, input: &D3D11InputView) -> error::Result<()> { fn push_history(
&mut self,
ctx: &ID3D11DeviceContext,
input: &D3D11InputView,
) -> error::Result<()> {
if let Some(mut back) = self.history_framebuffers.pop_back() { if let Some(mut back) = self.history_framebuffers.pop_back() {
back.copy_from(input)?; back.copy_from(ctx, input)?;
self.history_framebuffers.push_front(back) self.history_framebuffers.push_front(back)
} }
@ -400,17 +365,23 @@ impl FilterChainD3D11 {
/// Process a frame with the input image. /// Process a frame with the input image.
pub fn frame( pub fn frame(
&mut self, &mut self,
ctx: Option<&ID3D11DeviceContext>,
input: D3D11InputView, input: D3D11InputView,
viewport: &Viewport<D3D11OutputView>, viewport: &Viewport<D3D11OutputView>,
frame_count: usize, frame_count: usize,
options: Option<&FrameOptionsD3D11>, options: Option<&FrameOptionsD3D11>,
) -> error::Result<()> { ) -> error::Result<()> {
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled); let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
// Need to clone this because pushing history needs a mutable borrow.
let immediate_context = &self.common.d3d11.immediate_context.clone();
let ctx = ctx.unwrap_or(immediate_context);
let passes = &mut self.passes[0..max]; let passes = &mut self.passes[0..max];
if let Some(options) = options { if let Some(options) = options {
if options.clear_history { if options.clear_history {
for framebuffer in &mut self.history_framebuffers { for framebuffer in &mut self.history_framebuffers {
framebuffer.clear()?; framebuffer.clear(ctx)?;
} }
} }
} }
@ -467,10 +438,8 @@ impl FilterChainD3D11 {
let passes_len = passes.len(); let passes_len = passes.len();
let (pass, last) = passes.split_at_mut(passes_len - 1); let (pass, last) = passes.split_at_mut(passes_len - 1);
let state_guard = self let state_guard = self.state.enter_filter_state(ctx);
.state self.common.draw_quad.bind_vbo_for_frame(ctx);
.enter_filter_state(&self.common.d3d11.current_context);
self.common.draw_quad.bind_vbo_for_frame();
for (index, pass) in pass.iter_mut().enumerate() { for (index, pass) in pass.iter_mut().enumerate() {
source.filter = pass.config.filter; source.filter = pass.config.filter;
@ -478,6 +447,7 @@ impl FilterChainD3D11 {
let target = &self.output_framebuffers[index]; let target = &self.output_framebuffers[index];
let size = target.size; let size = target.size;
pass.draw( pass.draw(
ctx,
index, index,
&self.common, &self.common,
pass.config.get_frame_count(frame_count), pass.config.get_frame_count(frame_count),
@ -506,6 +476,7 @@ impl FilterChainD3D11 {
source.filter = pass.config.filter; source.filter = pass.config.filter;
source.wrap_mode = pass.config.wrap_mode; source.wrap_mode = pass.config.wrap_mode;
pass.draw( pass.draw(
&ctx,
passes_len - 1, passes_len - 1,
&self.common, &self.common,
pass.config.get_frame_count(frame_count), pass.config.get_frame_count(frame_count),
@ -524,22 +495,8 @@ impl FilterChainD3D11 {
); );
drop(state_guard); drop(state_guard);
self.push_history(&input)?;
if self.common.d3d11.context_is_deferred { self.push_history(ctx, &input)?;
unsafe {
let mut command_list = None;
self.common
.d3d11
.current_context
.FinishCommandList(false, Some(&mut command_list))?;
assume_d3d11_init!(command_list, "FinishCommandList");
self.common
.d3d11
.immediate_context
.ExecuteCommandList(&command_list, true);
}
}
Ok(()) Ok(())
} }

View file

@ -14,7 +14,7 @@ use librashader_runtime::filter_pass::FilterPassMeta;
use librashader_runtime::quad::QuadType; use librashader_runtime::quad::QuadType;
use librashader_runtime::render_target::RenderTarget; use librashader_runtime::render_target::RenderTarget;
use windows::Win32::Graphics::Direct3D11::{ use windows::Win32::Graphics::Direct3D11::{
ID3D11Buffer, ID3D11InputLayout, ID3D11PixelShader, ID3D11SamplerState, ID3D11Buffer, ID3D11DeviceContext, ID3D11InputLayout, ID3D11PixelShader, ID3D11SamplerState,
ID3D11ShaderResourceView, ID3D11VertexShader, D3D11_MAPPED_SUBRESOURCE, ID3D11ShaderResourceView, ID3D11VertexShader, D3D11_MAPPED_SUBRESOURCE,
D3D11_MAP_WRITE_DISCARD, D3D11_VIEWPORT, D3D11_MAP_WRITE_DISCARD, D3D11_VIEWPORT,
}; };
@ -137,6 +137,7 @@ impl FilterPass {
pub(crate) fn draw( pub(crate) fn draw(
&mut self, &mut self,
ctx: &ID3D11DeviceContext,
pass_index: usize, pass_index: usize,
parent: &FilterCommon, parent: &FilterCommon,
frame_count: u32, frame_count: u32,
@ -147,19 +148,15 @@ impl FilterPass {
output: RenderTarget<D3D11OutputView>, output: RenderTarget<D3D11OutputView>,
vbo_type: QuadType, vbo_type: QuadType,
) -> error::Result<()> { ) -> error::Result<()> {
let _device = &parent.d3d11.device;
let context = &parent.d3d11.current_context;
if self.config.mipmap_input && !parent.disable_mipmaps { if self.config.mipmap_input && !parent.disable_mipmaps {
unsafe { unsafe {
context.GenerateMips(&source.view.handle); ctx.GenerateMips(&source.view.handle);
// context.GenerateMips(&original.view.handle);
} }
} }
unsafe { unsafe {
context.IASetInputLayout(&self.vertex_layout); ctx.IASetInputLayout(&self.vertex_layout);
context.VSSetShader(&self.vertex_shader, None); ctx.VSSetShader(&self.vertex_shader, None);
context.PSSetShader(&self.pixel_shader, None); ctx.PSSetShader(&self.pixel_shader, None);
} }
let mut textures: [Option<ID3D11ShaderResourceView>; 16] = std::array::from_fn(|_| None); let mut textures: [Option<ID3D11ShaderResourceView>; 16] = std::array::from_fn(|_| None);
@ -183,20 +180,20 @@ impl FilterPass {
// upload uniforms // upload uniforms
unsafe { unsafe {
let mut map = D3D11_MAPPED_SUBRESOURCE::default(); let mut map = D3D11_MAPPED_SUBRESOURCE::default();
context.Map(&ubo.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, Some(&mut map))?; ctx.Map(&ubo.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, Some(&mut map))?;
std::ptr::copy_nonoverlapping( std::ptr::copy_nonoverlapping(
self.uniform_storage.ubo_pointer(), self.uniform_storage.ubo_pointer(),
map.pData.cast(), map.pData.cast(),
ubo.size as usize, ubo.size as usize,
); );
context.Unmap(&ubo.buffer, 0); ctx.Unmap(&ubo.buffer, 0);
} }
if ubo.stage_mask.contains(BindingStage::VERTEX) { if ubo.stage_mask.contains(BindingStage::VERTEX) {
unsafe { context.VSSetConstantBuffers(ubo.binding, Some(&[ubo.buffer.clone()])) } unsafe { ctx.VSSetConstantBuffers(ubo.binding, Some(&[ubo.buffer.clone()])) }
} }
if ubo.stage_mask.contains(BindingStage::FRAGMENT) { if ubo.stage_mask.contains(BindingStage::FRAGMENT) {
unsafe { context.PSSetConstantBuffers(ubo.binding, Some(&[ubo.buffer.clone()])) } unsafe { ctx.PSSetConstantBuffers(ubo.binding, Some(&[ubo.buffer.clone()])) }
} }
} }
@ -204,26 +201,26 @@ impl FilterPass {
// upload push constants // upload push constants
unsafe { unsafe {
let mut map = D3D11_MAPPED_SUBRESOURCE::default(); let mut map = D3D11_MAPPED_SUBRESOURCE::default();
context.Map(&push.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, Some(&mut map))?; ctx.Map(&push.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, Some(&mut map))?;
std::ptr::copy_nonoverlapping( std::ptr::copy_nonoverlapping(
self.uniform_storage.push_pointer(), self.uniform_storage.push_pointer(),
map.pData.cast(), map.pData.cast(),
push.size as usize, push.size as usize,
); );
context.Unmap(&push.buffer, 0); ctx.Unmap(&push.buffer, 0);
} }
if push.stage_mask.contains(BindingStage::VERTEX) { if push.stage_mask.contains(BindingStage::VERTEX) {
unsafe { context.VSSetConstantBuffers(push.binding, Some(&[push.buffer.clone()])) } unsafe { ctx.VSSetConstantBuffers(push.binding, Some(&[push.buffer.clone()])) }
} }
if push.stage_mask.contains(BindingStage::FRAGMENT) { if push.stage_mask.contains(BindingStage::FRAGMENT) {
unsafe { context.PSSetConstantBuffers(push.binding, Some(&[push.buffer.clone()])) } unsafe { ctx.PSSetConstantBuffers(push.binding, Some(&[push.buffer.clone()])) }
} }
} }
unsafe { unsafe {
// reset RTVs // reset RTVs
context.OMSetRenderTargets(None, None); ctx.OMSetRenderTargets(None, None);
} }
unsafe { unsafe {
@ -233,11 +230,11 @@ impl FilterPass {
std::mem::size_of::<Option<windows::core::IUnknown>>() std::mem::size_of::<Option<windows::core::IUnknown>>()
== std::mem::size_of::<windows::core::IUnknown>() == std::mem::size_of::<windows::core::IUnknown>()
); );
context.PSSetShaderResources(0, Some(std::mem::transmute(textures.as_ref()))); ctx.PSSetShaderResources(0, Some(std::mem::transmute(textures.as_ref())));
context.PSSetSamplers(0, Some(std::mem::transmute(samplers.as_ref()))); ctx.PSSetSamplers(0, Some(std::mem::transmute(samplers.as_ref())));
context.OMSetRenderTargets(Some(&[output.output.handle.clone()]), None); ctx.OMSetRenderTargets(Some(&[output.output.handle.clone()]), None);
context.RSSetViewports(Some(&[D3D11_VIEWPORT { ctx.RSSetViewports(Some(&[D3D11_VIEWPORT {
TopLeftX: output.x, TopLeftX: output.x,
TopLeftY: output.y, TopLeftY: output.y,
Width: output.output.size.width as f32, Width: output.output.size.width as f32,
@ -247,12 +244,12 @@ impl FilterPass {
}])) }]))
} }
parent.draw_quad.draw_quad(context, vbo_type); parent.draw_quad.draw_quad(ctx, vbo_type);
unsafe { unsafe {
// unbind resources. // unbind resources.
context.PSSetShaderResources(0, Some(std::mem::transmute(NULL_TEXTURES.as_ref()))); ctx.PSSetShaderResources(0, Some(std::mem::transmute(NULL_TEXTURES.as_ref())));
context.OMSetRenderTargets(None, None); ctx.OMSetRenderTargets(None, None);
} }
Ok(()) Ok(())
} }

View file

@ -26,14 +26,12 @@ pub(crate) struct OwnedFramebuffer {
pub(crate) size: Size<u32>, pub(crate) size: Size<u32>,
format: DXGI_FORMAT, format: DXGI_FORMAT,
device: ID3D11Device, device: ID3D11Device,
context: ID3D11DeviceContext,
max_mipmap: u32, max_mipmap: u32,
} }
impl OwnedFramebuffer { impl OwnedFramebuffer {
pub fn new( pub fn new(
device: &ID3D11Device, device: &ID3D11Device,
context: &ID3D11DeviceContext,
size: Size<u32>, size: Size<u32>,
format: ImageFormat, format: ImageFormat,
mipmap: bool, mipmap: bool,
@ -56,7 +54,6 @@ impl OwnedFramebuffer {
size, size,
format, format,
device: device.clone(), device: device.clone(),
context: context.clone(),
max_mipmap: if mipmap { max_mipmap: if mipmap {
size.calculate_miplevels() size.calculate_miplevels()
} else { } else {
@ -99,10 +96,10 @@ impl OwnedFramebuffer {
Ok(size) Ok(size)
} }
pub fn clear(&mut self) -> error::Result<()> { pub fn clear(&mut self, ctx: &ID3D11DeviceContext) -> error::Result<()> {
let rtv = self.create_render_target_view()?; let rtv = self.create_render_target_view()?;
unsafe { unsafe {
self.context.ClearRenderTargetView(&rtv, CLEAR.as_ptr()); ctx.ClearRenderTargetView(&rtv, CLEAR.as_ptr());
} }
Ok(()) Ok(())
} }
@ -181,7 +178,11 @@ impl OwnedFramebuffer {
}) })
} }
pub fn copy_from(&mut self, image: &D3D11InputView) -> error::Result<()> { pub fn copy_from(
&mut self,
ctx: &ID3D11DeviceContext,
image: &D3D11InputView,
) -> error::Result<()> {
let original_resource: ID3D11Texture2D = unsafe { let original_resource: ID3D11Texture2D = unsafe {
let resource = image.handle.GetResource()?; let resource = image.handle.GetResource()?;
resource.cast()? resource.cast()?
@ -198,10 +199,8 @@ impl OwnedFramebuffer {
self.init(image.size, ImageFormat::from(format))?; self.init(image.size, ImageFormat::from(format))?;
} }
// todo: improve mipmap generation?
// will need a staging texture + full so might not be worth it.
unsafe { unsafe {
self.context.CopySubresourceRegion( ctx.CopySubresourceRegion(
&self.render, &self.render,
0, 0,
0, 0,
@ -222,7 +221,7 @@ impl OwnedFramebuffer {
let srvs = self.create_shader_resource_view()?; let srvs = self.create_shader_resource_view()?;
unsafe { unsafe {
self.context.GenerateMips(&srvs); ctx.GenerateMips(&srvs);
} }
Ok(()) Ok(())
} }

View file

@ -280,6 +280,7 @@ pub mod d3d11_hello_triangle {
pub viewport: D3D11_VIEWPORT, pub viewport: D3D11_VIEWPORT,
pub shader_output: Option<ID3D11Texture2D>, pub shader_output: Option<ID3D11Texture2D>,
pub frame_count: usize, pub frame_count: usize,
pub deferred_context: ID3D11DeviceContext,
} }
impl Sample { impl Sample {
@ -387,6 +388,11 @@ pub mod d3d11_hello_triangle {
.CreateRenderTargetView(&renderbuffer, None, Some(&mut rtv))?; .CreateRenderTargetView(&renderbuffer, None, Some(&mut rtv))?;
(renderbuffer, rtv.unwrap()) (renderbuffer, rtv.unwrap())
}; };
let mut context = None;
unsafe { self.device.CreateDeferredContext(0, Some(&mut context))? };
let context = context.expect("Could not create deferred context");
self.resources = Some(Resources { self.resources = Some(Resources {
swapchain, swapchain,
backbuffer_rtv: Some(rtv), backbuffer_rtv: Some(rtv),
@ -405,6 +411,7 @@ pub mod d3d11_hello_triangle {
triangle_uniform_values: Default::default(), triangle_uniform_values: Default::default(),
renderbuffer, renderbuffer,
renderbufffer_rtv: render_rtv, renderbufffer_rtv: render_rtv,
deferred_context: context,
viewport: D3D11_VIEWPORT { viewport: D3D11_VIEWPORT {
TopLeftX: 0.0, TopLeftX: 0.0,
TopLeftY: 0.0, TopLeftY: 0.0,
@ -561,6 +568,7 @@ pub mod d3d11_hello_triangle {
// eprintln!("w: {} h: {}", backbuffer_desc.Width, backbuffer_desc.Height); // eprintln!("w: {} h: {}", backbuffer_desc.Width, backbuffer_desc.Height);
self.filter self.filter
.frame( .frame(
Some(&resources.deferred_context),
D3D11InputView { D3D11InputView {
handle: srv, handle: srv,
size: Size { size: Size {
@ -585,6 +593,12 @@ pub mod d3d11_hello_triangle {
) )
.unwrap(); .unwrap();
let mut command_list = None;
resources
.deferred_context
.FinishCommandList(false, Some(&mut command_list))?;
let command_list = command_list.unwrap();
self.context.ExecuteCommandList(&command_list, false);
// self.context.CopyResource(&resources.backbuffer, &backup); // self.context.CopyResource(&resources.backbuffer, &backup);
} }

View file

@ -58,7 +58,6 @@ mod tests {
let sample = hello_triangle::d3d11_hello_triangle::Sample::new( let sample = hello_triangle::d3d11_hello_triangle::Sample::new(
filter.as_deref().unwrap_or(FILTER_PATH), filter.as_deref().unwrap_or(FILTER_PATH),
Some(&FilterChainOptionsD3D11 { Some(&FilterChainOptionsD3D11 {
use_deferred_context: false,
force_no_mipmaps: false, force_no_mipmaps: false,
}), }),
// replace below with 'None' for the triangle // replace below with 'None' for the triangle
@ -83,7 +82,6 @@ mod tests {
let sample = hello_triangle::d3d11_hello_triangle::Sample::new( let sample = hello_triangle::d3d11_hello_triangle::Sample::new(
FILTER_PATH, FILTER_PATH,
Some(&FilterChainOptionsD3D11 { Some(&FilterChainOptionsD3D11 {
use_deferred_context: false,
force_no_mipmaps: false, force_no_mipmaps: false,
}), }),
// replace below with 'None' for the triangle // replace below with 'None' for the triangle

View file

@ -15,12 +15,6 @@ pub struct FrameOptionsD3D11 {
#[repr(C)] #[repr(C)]
#[derive(Default, Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct FilterChainOptionsD3D11 { pub struct FilterChainOptionsD3D11 {
/// Use a deferred context to record shader rendering state.
///
/// The deferred context will be executed on the immediate context
/// with `RenderContextState = true`.
pub use_deferred_context: bool,
/// Whether or not to explicitly disable mipmap /// Whether or not to explicitly disable mipmap
/// generation regardless of shader preset settings. /// generation regardless of shader preset settings.
pub force_no_mipmaps: bool, pub force_no_mipmaps: bool,

View file

@ -492,37 +492,6 @@ impl FilterChainD3D12 {
let filters: error::Result<Vec<_>> = filters.into_iter().collect(); let filters: error::Result<Vec<_>> = filters.into_iter().collect();
let filters = filters?; let filters = filters?;
//
// // Need to take care of the heaps in a single thread because [;16] is not sized..?
// let filters: Vec<error::Result<FilterPass>> = filters
// .into_iter()
// .zip(work_heaps)
// .zip(sampler_work_heaps)
// .map(
// |(
// (
// (reflection, uniform_bindings, uniform_storage, pipeline, config, source),
// mut texture_heap,
// ),
// mut sampler_heap,
// )| {
// let texture_heap = texture_heap.alloc_range()?;
// let sampler_heap = sampler_heap.alloc_range()?;
// Ok(FilterPass {
// reflection,
// uniform_bindings,
// uniform_storage,
// pipeline,
// config,
// texture_heap,
// sampler_heap,
// source,
// })
// },
// )
// .collect();
// let filters: error::Result<Vec<_>> = filters.into_iter().collect();
// let filters = filters?;
// Panic SAFETY: mipmap_heap is always 1024 descriptors. // Panic SAFETY: mipmap_heap is always 1024 descriptors.
Ok(( Ok((

View file

@ -19,6 +19,7 @@ static ID3D11RenderTargetView* g_mainRenderTargetView = NULL;
static ID3D11Texture2D* g_pBackBuffer = NULL; static ID3D11Texture2D* g_pBackBuffer = NULL;
static ID3D11Texture2D* g_pFramebufferCopy = NULL; static ID3D11Texture2D* g_pFramebufferCopy = NULL;
static ID3D11ShaderResourceView* g_framebufferCopySRV = NULL; static ID3D11ShaderResourceView* g_framebufferCopySRV = NULL;
static ID3D11DeviceContext* g_deferredContext = NULL;
// Forward declarations of helper functions // Forward declarations of helper functions
bool CreateDeviceD3D(HWND hWnd); bool CreateDeviceD3D(HWND hWnd);
@ -70,8 +71,7 @@ int main(int, char**)
libra_d3d11_filter_chain_t filter_chain; libra_d3d11_filter_chain_t filter_chain;
filter_chain_d3d11_opt_t opt = { filter_chain_d3d11_opt_t opt = {
.use_deferred_context = true, .force_no_mipmaps = false,
.force_no_mipmaps = true,
}; };
libra.d3d11_filter_chain_create(&preset, &opt, g_pd3dDevice, &filter_chain); libra.d3d11_filter_chain_create(&preset, &opt, g_pd3dDevice, &filter_chain);
@ -187,9 +187,10 @@ int main(int, char**)
.frame_direction = -1 .frame_direction = -1
}; };
libra.d3d11_filter_chain_frame(&filter_chain, frameCount, input, vp, libra.d3d11_filter_chain_frame(&filter_chain, NULL, frameCount, input, vp,
g_mainRenderTargetView, NULL, &frame_opt); g_mainRenderTargetView, NULL, &frame_opt);
g_pSwapChain->Present(1, 0); // Present with vsync g_pSwapChain->Present(1, 0); // Present with vsync
//g_pSwapChain->Present(0, 0); // Present without vsync //g_pSwapChain->Present(0, 0); // Present without vsync
frameCount += 1; frameCount += 1;
@ -237,7 +238,9 @@ bool CreateDeviceD3D(HWND hWnd)
res = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext); res = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
if (res != S_OK) if (res != S_OK)
return false; return false;
res = g_pd3dDevice->CreateDeferredContext(0, &g_deferredContext);
if (res != S_OK)
return false;
CreateRenderTarget(); CreateRenderTarget();
return true; return true;
} }

View file

@ -55,17 +55,19 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
baseDeviceContext->QueryInterface(__uuidof(ID3D11DeviceContext1), baseDeviceContext->QueryInterface(__uuidof(ID3D11DeviceContext1),
reinterpret_cast<void**>(&deviceContext)); reinterpret_cast<void**>(&deviceContext));
ID3D11DeviceContext* deferredContext;
baseDevice->CreateDeferredContext(0, &deferredContext);
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
auto libra = librashader_load_instance(); auto libra = librashader_load_instance();
libra_shader_preset_t preset; libra_shader_preset_t preset;
auto error = libra.preset_create( auto error = libra.preset_create(
"../../../slang-shaders/crt/crt-lottes.slangp", "../../../slang-shaders/crt/crt-royale.slangp",
&preset); &preset);
libra_d3d11_filter_chain_t filter_chain; libra_d3d11_filter_chain_t filter_chain;
filter_chain_d3d11_opt_t opt = { filter_chain_d3d11_opt_t opt = {
.use_deferred_context = true,
.force_no_mipmaps = false, .force_no_mipmaps = false,
}; };
@ -485,9 +487,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
frame_d3d11_opt_t frame_opt = {.clear_history = false, frame_d3d11_opt_t frame_opt = {.clear_history = false,
.frame_direction = -1}; .frame_direction = -1};
libra.d3d11_filter_chain_frame(&filter_chain, frameCount, input, vp, libra.d3d11_filter_chain_frame(&filter_chain, deferredContext, frameCount, input,
vp,
framebufferRTV, NULL, &frame_opt); framebufferRTV, NULL, &frame_opt);
ID3D11CommandList* commandList;
deferredContext->FinishCommandList(false, &commandList);
deviceContext->ExecuteCommandList(commandList, true);
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
swapChain->Present(1, 0); swapChain->Present(1, 0);
frameCount += 1; frameCount += 1;

View file

@ -404,7 +404,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
libra_viewport_t vp = {0, 0, viewport.Width, viewport.Height, }; libra_viewport_t vp = {0, 0, viewport.Width, viewport.Height, };
libra.d3d11_filter_chain_frame(&filter_chain, frameCount, input, vp, libra.d3d11_filter_chain_frame(&filter_chain, NULL, frameCount, input, vp,
d3d11FrameBufferView, NULL, NULL); d3d11FrameBufferView, NULL, NULL);
copySrv->Release(); copySrv->Release();