rt: unify semantics binding logic
This commit is contained in:
parent
474cf37e68
commit
c3a532d729
20 changed files with 649 additions and 816 deletions
|
@ -36,10 +36,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D11)
|
#if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D11)
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
#else
|
#else
|
||||||
typedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D11ShaderResourceView;
|
typedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D1ShaderResourceView;
|
||||||
#endif
|
#endif
|
||||||
#if defined(LIBRA_RUNTIME_VULKAN)
|
#if defined(LIBRA_RUNTIME_VULKAN)
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan\vulkan.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Error codes for librashader error types.
|
/// Error codes for librashader error types.
|
||||||
|
@ -102,15 +102,15 @@ typedef struct libra_preset_param_t {
|
||||||
} libra_preset_param_t;
|
} libra_preset_param_t;
|
||||||
|
|
||||||
/// A list of preset parameters.
|
/// A list of preset parameters.
|
||||||
typedef struct libra_preset_param_list_t {
|
typedef struct libra_preset_parameter_list_t {
|
||||||
/// A pointer to the parameter
|
/// A pointer to the parameter
|
||||||
const struct libra_preset_param_t *parameters;
|
const struct libra_preset_param_t *parameters;
|
||||||
/// The number of parameters in the list.
|
/// The number of parameters in the list
|
||||||
uint64_t length;
|
uint64_t length;
|
||||||
/// For internal use only.
|
/// For internal use only.
|
||||||
/// Changing this causes immediate undefined behaviour on freeing this parameter list.
|
/// Changing this causes immediate undefined behaviour on freeing this parameter list.
|
||||||
uint64_t _internal_alloc;
|
uint64_t _internal_alloc;
|
||||||
} libra_preset_param_list_t;
|
} libra_preset_parameter_list_t;
|
||||||
|
|
||||||
#if defined(LIBRA_RUNTIME_OPENGL)
|
#if defined(LIBRA_RUNTIME_OPENGL)
|
||||||
/// A GL function loader that librashader needs to be initialized with.
|
/// A GL function loader that librashader needs to be initialized with.
|
||||||
|
@ -292,13 +292,9 @@ typedef libra_error_t (*PFN_libra_preset_get_param)(libra_shader_preset_t *prese
|
||||||
typedef libra_error_t (*PFN_libra_preset_print)(libra_shader_preset_t *preset);
|
typedef libra_error_t (*PFN_libra_preset_print)(libra_shader_preset_t *preset);
|
||||||
|
|
||||||
/// Function pointer definition for
|
/// Function pointer definition for
|
||||||
///libra_preset_get_runtime_params
|
///libra_preset_get_runtime_parameters
|
||||||
typedef libra_error_t (*PFN_libra_preset_get_runtime_params)(libra_shader_preset_t *preset,
|
typedef libra_error_t (*PFN_libra_preset_get_runtime_parameters)(libra_shader_preset_t *preset,
|
||||||
struct libra_preset_param_list_t *out);
|
struct libra_preset_parameter_list_t *out);
|
||||||
|
|
||||||
/// Function pointer definition for
|
|
||||||
///libra_preset_free_runtime_params
|
|
||||||
typedef libra_error_t (*PFN_libra_preset_free_runtime_params)(struct libra_preset_param_list_t preset);
|
|
||||||
|
|
||||||
/// Function pointer definition for libra_error_errno
|
/// Function pointer definition for libra_error_errno
|
||||||
typedef LIBRA_ERRNO (*PFN_libra_error_errno)(libra_error_t error);
|
typedef LIBRA_ERRNO (*PFN_libra_error_errno)(libra_error_t error);
|
||||||
|
@ -580,34 +576,8 @@ libra_error_t libra_preset_print(libra_shader_preset_t *preset);
|
||||||
/// ## Safety
|
/// ## Safety
|
||||||
/// - `preset` must be null or a valid and aligned pointer to a shader preset.
|
/// - `preset` must be null or a valid and aligned pointer to a shader preset.
|
||||||
/// - `out` must be an aligned pointer to a `libra_preset_parameter_list_t`.
|
/// - `out` must be an aligned pointer to a `libra_preset_parameter_list_t`.
|
||||||
/// - The output struct should be treated as immutable. Mutating any struct fields
|
libra_error_t libra_preset_get_runtime_parameters(libra_shader_preset_t *preset,
|
||||||
/// in the returned struct may at best cause memory leaks, and at worse
|
struct libra_preset_parameter_list_t *out);
|
||||||
/// cause undefined behaviour when later freed.
|
|
||||||
/// - It is safe to call `libra_preset_get_runtime_params` multiple times, however
|
|
||||||
/// the output struct must only be freed once per call.
|
|
||||||
libra_error_t libra_preset_get_runtime_params(libra_shader_preset_t *preset,
|
|
||||||
struct libra_preset_param_list_t *out);
|
|
||||||
|
|
||||||
/// Free the runtime parameters.
|
|
||||||
///
|
|
||||||
/// Unlike the other `free` functions provided by librashader,
|
|
||||||
/// `libra_preset_free_runtime_params` takes the struct directly.
|
|
||||||
/// The caller must take care to maintain the lifetime of any pointers
|
|
||||||
/// contained within the input `libra_preset_param_list_t`.
|
|
||||||
///
|
|
||||||
/// ## Safety
|
|
||||||
/// - Any pointers rooted at `parameters` becomes invalid after this function returns,
|
|
||||||
/// including any strings accessible via the input `libra_preset_param_list_t`.
|
|
||||||
/// The caller must ensure that there are no live pointers, aliased or unaliased,
|
|
||||||
/// to data accessible via the input `libra_preset_param_list_t`.
|
|
||||||
///
|
|
||||||
/// - Accessing any data pointed to via the input `libra_preset_param_list_t` after it
|
|
||||||
/// has been freed is a use-after-free and is immediate undefined behaviour.
|
|
||||||
///
|
|
||||||
/// - If any struct fields of the input `libra_preset_param_list_t` was modified from
|
|
||||||
/// their values given after `libra_preset_get_runtime_params`, this may result
|
|
||||||
/// in undefined behaviour.
|
|
||||||
libra_error_t libra_preset_free_runtime_params(struct libra_preset_param_list_t preset);
|
|
||||||
|
|
||||||
#if defined(LIBRA_RUNTIME_OPENGL)
|
#if defined(LIBRA_RUNTIME_OPENGL)
|
||||||
/// Initialize the OpenGL Context for librashader.
|
/// Initialize the OpenGL Context for librashader.
|
||||||
|
|
|
@ -56,8 +56,11 @@ impl From<libra_source_image_gl_t> for GLImage {
|
||||||
extern_fn! {
|
extern_fn! {
|
||||||
/// Initialize the OpenGL Context for librashader.
|
/// Initialize the OpenGL Context for librashader.
|
||||||
///
|
///
|
||||||
|
/// This only has to be done once throughout the lifetime of the application,
|
||||||
|
/// unless for whatever reason you switch OpenGL loaders mid-flight.
|
||||||
|
///
|
||||||
/// ## Safety
|
/// ## Safety
|
||||||
/// Attempting to create a filter chain will fail.
|
/// Attempting to create a filter chain will fail if the GL context is not initialized.
|
||||||
///
|
///
|
||||||
/// Reinitializing the OpenGL context with a different loader immediately invalidates previous filter
|
/// Reinitializing the OpenGL context with a different loader immediately invalidates previous filter
|
||||||
/// chain objects, and drawing with them causes immediate undefined behaviour.
|
/// chain objects, and drawing with them causes immediate undefined behaviour.
|
||||||
|
|
|
@ -15,6 +15,7 @@ use windows::Win32::Graphics::Direct3D11::{
|
||||||
ID3D11Buffer, ID3D11InputLayout, ID3D11PixelShader, ID3D11SamplerState,
|
ID3D11Buffer, ID3D11InputLayout, ID3D11PixelShader, ID3D11SamplerState,
|
||||||
ID3D11ShaderResourceView, ID3D11VertexShader, D3D11_MAP_WRITE_DISCARD,
|
ID3D11ShaderResourceView, ID3D11VertexShader, D3D11_MAP_WRITE_DISCARD,
|
||||||
};
|
};
|
||||||
|
use librashader_runtime::binding::{BindSemantics, TextureInput};
|
||||||
|
|
||||||
use crate::{D3D11OutputView, error};
|
use crate::{D3D11OutputView, error};
|
||||||
use crate::render_target::RenderTarget;
|
use crate::render_target::RenderTarget;
|
||||||
|
@ -50,6 +51,30 @@ const NULL_TEXTURES: &[Option<ID3D11ShaderResourceView>; 16] = &[
|
||||||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
impl TextureInput for InputTexture {
|
||||||
|
fn size(&self) -> Size<u32> {
|
||||||
|
self.view.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BindSemantics for FilterPass {
|
||||||
|
type InputTexture = InputTexture;
|
||||||
|
type SamplerSet = SamplerSet;
|
||||||
|
type DescriptorSet<'a> = (&'a mut [Option<ID3D11ShaderResourceView>; 16], &'a mut [Option<ID3D11SamplerState>; 16]);
|
||||||
|
type DeviceContext = ();
|
||||||
|
type UniformOffset = MemberOffset;
|
||||||
|
|
||||||
|
fn bind_texture<'a>(
|
||||||
|
descriptors: &mut Self::DescriptorSet<'a>, samplers: &Self::SamplerSet,
|
||||||
|
binding: &TextureBinding, texture: &Self::InputTexture,
|
||||||
|
_device: &Self::DeviceContext) {
|
||||||
|
let (texture_binding, sampler_binding) = descriptors;
|
||||||
|
texture_binding[binding.binding as usize] = Some(texture.view.handle.clone());
|
||||||
|
sampler_binding[binding.binding as usize] =
|
||||||
|
Some(samplers.get(texture.wrap_mode, texture.filter).clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// slang_process.cpp 229
|
// slang_process.cpp 229
|
||||||
impl FilterPass {
|
impl FilterPass {
|
||||||
pub fn get_format(&self) -> ImageFormat {
|
pub fn get_format(&self) -> ImageFormat {
|
||||||
|
@ -76,7 +101,7 @@ impl FilterPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
// framecount should be pre-modded
|
// framecount should be pre-modded
|
||||||
fn build_semantics(
|
fn build_semantics<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
pass_index: usize,
|
pass_index: usize,
|
||||||
parent: &FilterCommon,
|
parent: &FilterCommon,
|
||||||
|
@ -85,264 +110,35 @@ impl FilterPass {
|
||||||
frame_direction: i32,
|
frame_direction: i32,
|
||||||
fb_size: Size<u32>,
|
fb_size: Size<u32>,
|
||||||
viewport_size: Size<u32>,
|
viewport_size: Size<u32>,
|
||||||
|
mut descriptors: (&'a mut [Option<ID3D11ShaderResourceView>; 16], &'a mut [Option<ID3D11SamplerState>; 16]),
|
||||||
original: &InputTexture,
|
original: &InputTexture,
|
||||||
source: &InputTexture,
|
source: &InputTexture,
|
||||||
) -> (
|
|
||||||
[Option<ID3D11ShaderResourceView>; 16],
|
|
||||||
[Option<ID3D11SamplerState>; 16],
|
|
||||||
) {
|
) {
|
||||||
let mut textures: [Option<ID3D11ShaderResourceView>; 16] = std::array::from_fn(|_| None);
|
Self::bind_semantics(
|
||||||
let mut samplers: [Option<ID3D11SamplerState>; 16] = std::array::from_fn(|_| None);
|
&(),
|
||||||
|
&parent.samplers,
|
||||||
// Bind MVP
|
&mut self.uniform_storage,
|
||||||
if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::MVP.into()) {
|
&mut descriptors,
|
||||||
self.uniform_storage.bind_mat4(*offset, mvp, None);
|
mvp,
|
||||||
}
|
frame_count,
|
||||||
|
frame_direction,
|
||||||
// bind OutputSize
|
fb_size,
|
||||||
if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::Output.into()) {
|
viewport_size,
|
||||||
self.uniform_storage.bind_vec4(*offset, fb_size, None);
|
original,
|
||||||
}
|
source,
|
||||||
|
&self.uniform_bindings,
|
||||||
// bind FinalViewportSize
|
&self.reflection.meta.texture_meta,
|
||||||
if let Some(offset) = self
|
parent.output_textures[0..pass_index].iter()
|
||||||
.uniform_bindings
|
.map(|o| o.as_ref()),
|
||||||
.get(&UniqueSemantics::FinalViewport.into())
|
parent.feedback_textures.iter()
|
||||||
{
|
.map(|o| o.as_ref()),
|
||||||
self.uniform_storage.bind_vec4(*offset, viewport_size, None);
|
parent.history_textures.iter()
|
||||||
}
|
.map(|o| o.as_ref()),
|
||||||
|
parent.luts.iter()
|
||||||
// bind FrameCount
|
.map(|(u, i)| (*u, i.as_ref())),
|
||||||
if let Some(offset) = self
|
&self.source.parameters,
|
||||||
.uniform_bindings
|
&parent.config.parameters
|
||||||
.get(&UniqueSemantics::FrameCount.into())
|
);
|
||||||
{
|
|
||||||
self.uniform_storage.bind_scalar(*offset, frame_count, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind FrameDirection
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&UniqueSemantics::FrameDirection.into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_scalar(*offset, frame_direction, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind Original sampler
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::Original.semantics(0))
|
|
||||||
{
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&parent.samplers,
|
|
||||||
&mut textures,
|
|
||||||
&mut samplers,
|
|
||||||
binding,
|
|
||||||
original,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// bind OriginalSize
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::Original.semantics(0).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, original.view.size, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind Source sampler
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::Source.semantics(0))
|
|
||||||
{
|
|
||||||
// eprintln!("setting source binding to {}", binding.binding);
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&parent.samplers,
|
|
||||||
&mut textures,
|
|
||||||
&mut samplers,
|
|
||||||
binding,
|
|
||||||
source,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind SourceSize
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::Source.semantics(0).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, source.view.size, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::OriginalHistory.semantics(0))
|
|
||||||
{
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&parent.samplers,
|
|
||||||
&mut textures,
|
|
||||||
&mut samplers,
|
|
||||||
binding,
|
|
||||||
original,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::OriginalHistory.semantics(0).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, original.view.size, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (index, output) in parent.history_textures.iter().enumerate() {
|
|
||||||
let Some(output) = output else {
|
|
||||||
// eprintln!("no history");
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::OriginalHistory.semantics(index + 1))
|
|
||||||
{
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&parent.samplers,
|
|
||||||
&mut textures,
|
|
||||||
&mut samplers,
|
|
||||||
binding,
|
|
||||||
output,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(offset) = self.uniform_bindings.get(
|
|
||||||
&TextureSemantics::OriginalHistory
|
|
||||||
.semantics(index + 1)
|
|
||||||
.into(),
|
|
||||||
) {
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, output.view.size, None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PassOutput
|
|
||||||
for (index, output) in parent.output_textures[0..pass_index].iter().enumerate() {
|
|
||||||
let Some(output) = output else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::PassOutput.semantics(index))
|
|
||||||
{
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&parent.samplers,
|
|
||||||
&mut textures,
|
|
||||||
&mut samplers,
|
|
||||||
binding,
|
|
||||||
output,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::PassOutput.semantics(index).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, output.view.size, None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PassFeedback
|
|
||||||
for (index, feedback) in parent.feedback_textures.iter().enumerate() {
|
|
||||||
let Some(feedback) = feedback else {
|
|
||||||
// eprintln!("no passfeedback {index}");
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::PassFeedback.semantics(index))
|
|
||||||
{
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&parent.samplers,
|
|
||||||
&mut textures,
|
|
||||||
&mut samplers,
|
|
||||||
binding,
|
|
||||||
feedback,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::PassFeedback.semantics(index).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, feedback.view.size, None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind float parameters
|
|
||||||
for (id, offset) in
|
|
||||||
self.uniform_bindings
|
|
||||||
.iter()
|
|
||||||
.filter_map(|(binding, value)| match binding {
|
|
||||||
UniformBinding::Parameter(id) => Some((id, value)),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
{
|
|
||||||
let id = id.as_str();
|
|
||||||
|
|
||||||
let default = self
|
|
||||||
.source
|
|
||||||
.parameters
|
|
||||||
.iter()
|
|
||||||
.find(|&p| p.id == id)
|
|
||||||
.map(|f| f.initial)
|
|
||||||
.unwrap_or(0f32);
|
|
||||||
|
|
||||||
let value = *parent.config.parameters.get(id).unwrap_or(&default);
|
|
||||||
|
|
||||||
self.uniform_storage.bind_scalar(*offset, value, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind luts
|
|
||||||
for (index, lut) in &parent.luts {
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::User.semantics(*index))
|
|
||||||
{
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&parent.samplers,
|
|
||||||
&mut textures,
|
|
||||||
&mut samplers,
|
|
||||||
binding,
|
|
||||||
&lut.image,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::User.semantics(*index).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, lut.image.view.size, None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(textures, samplers)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn draw(
|
pub(crate) fn draw(
|
||||||
|
@ -370,7 +166,11 @@ impl FilterPass {
|
||||||
context.PSSetShader(&self.pixel_shader, None);
|
context.PSSetShader(&self.pixel_shader, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (textures, samplers) = self.build_semantics(
|
let mut textures: [Option<ID3D11ShaderResourceView>; 16] = std::array::from_fn(|_| None);
|
||||||
|
let mut samplers: [Option<ID3D11SamplerState>; 16] = std::array::from_fn(|_| None);
|
||||||
|
let mut descriptors = (&mut textures, &mut samplers);
|
||||||
|
|
||||||
|
self.build_semantics(
|
||||||
pass_index,
|
pass_index,
|
||||||
parent,
|
parent,
|
||||||
output.mvp,
|
output.mvp,
|
||||||
|
@ -378,6 +178,7 @@ impl FilterPass {
|
||||||
frame_direction,
|
frame_direction,
|
||||||
output.output.size,
|
output.output.size,
|
||||||
viewport.output.size,
|
viewport.output.size,
|
||||||
|
descriptors,
|
||||||
original,
|
original,
|
||||||
source,
|
source,
|
||||||
);
|
);
|
||||||
|
|
|
@ -37,14 +37,14 @@ pub struct D3D11OutputView {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct InputTexture {
|
pub struct InputTexture {
|
||||||
pub view: D3D11InputView,
|
pub view: D3D11InputView,
|
||||||
pub filter: FilterMode,
|
pub filter: FilterMode,
|
||||||
pub wrap_mode: WrapMode,
|
pub wrap_mode: WrapMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputTexture {
|
impl InputTexture {
|
||||||
pub fn from_framebuffer(
|
pub(crate) fn from_framebuffer(
|
||||||
fbo: &OwnedFramebuffer,
|
fbo: &OwnedFramebuffer,
|
||||||
wrap_mode: WrapMode,
|
wrap_mode: WrapMode,
|
||||||
filter: FilterMode,
|
filter: FilterMode,
|
||||||
|
@ -60,6 +60,12 @@ impl InputTexture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<InputTexture> for InputTexture {
|
||||||
|
fn as_ref(&self) -> &InputTexture {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct LutTexture {
|
pub(crate) struct LutTexture {
|
||||||
// The handle to the Texture2D must be kept alive.
|
// The handle to the Texture2D must be kept alive.
|
||||||
|
@ -70,6 +76,12 @@ pub(crate) struct LutTexture {
|
||||||
pub image: InputTexture,
|
pub image: InputTexture,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<InputTexture> for LutTexture {
|
||||||
|
fn as_ref(&self) -> &InputTexture {
|
||||||
|
&self.image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LutTexture {
|
impl LutTexture {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
device: &ID3D11Device,
|
device: &ID3D11Device,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::binding::{GlUniformStorage, UniformLocation, VariableLocation};
|
use crate::binding::{GlUniformStorage, UniformLocation, VariableLocation};
|
||||||
use crate::error::FilterChainError;
|
use crate::error::FilterChainError;
|
||||||
use crate::filter_pass::FilterPass;
|
use crate::filter_pass::{FilterPass, UniformOffset};
|
||||||
use crate::gl::{DrawQuad, Framebuffer, FramebufferInterface, GLInterface, LoadLut, UboRing};
|
use crate::gl::{DrawQuad, Framebuffer, FramebufferInterface, GLInterface, LoadLut, UboRing};
|
||||||
use crate::options::{FilterChainOptionsGL, FrameOptionsGL};
|
use crate::options::{FilterChainOptionsGL, FrameOptionsGL};
|
||||||
use crate::render_target::RenderTarget;
|
use crate::render_target::RenderTarget;
|
||||||
use crate::samplers::SamplerSet;
|
use crate::samplers::SamplerSet;
|
||||||
use crate::texture::Texture;
|
use crate::texture::InputTexture;
|
||||||
use crate::util::{gl_get_version, gl_u16_to_version};
|
use crate::util::{gl_get_version, gl_u16_to_version};
|
||||||
use crate::{error, util, GLImage};
|
use crate::{error, util, GLImage};
|
||||||
use gl::types::{GLint, GLuint};
|
use gl::types::{GLint, GLuint};
|
||||||
|
@ -37,11 +37,11 @@ pub(crate) struct FilterChainImpl<T: GLInterface> {
|
||||||
pub(crate) struct FilterCommon {
|
pub(crate) struct FilterCommon {
|
||||||
// semantics: ReflectSemantics,
|
// semantics: ReflectSemantics,
|
||||||
pub config: FilterMutable,
|
pub config: FilterMutable,
|
||||||
pub luts: FxHashMap<usize, Texture>,
|
pub luts: FxHashMap<usize, InputTexture>,
|
||||||
pub samplers: SamplerSet,
|
pub samplers: SamplerSet,
|
||||||
pub output_textures: Box<[Texture]>,
|
pub output_textures: Box<[InputTexture]>,
|
||||||
pub feedback_textures: Box<[Texture]>,
|
pub feedback_textures: Box<[InputTexture]>,
|
||||||
pub history_textures: Box<[Texture]>,
|
pub history_textures: Box<[InputTexture]>,
|
||||||
pub disable_mipmaps: bool,
|
pub disable_mipmaps: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,13 +114,13 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
||||||
let mut output_framebuffers = Vec::new();
|
let mut output_framebuffers = Vec::new();
|
||||||
output_framebuffers.resize_with(filters.len(), || T::FramebufferInterface::new(1));
|
output_framebuffers.resize_with(filters.len(), || T::FramebufferInterface::new(1));
|
||||||
let mut output_textures = Vec::new();
|
let mut output_textures = Vec::new();
|
||||||
output_textures.resize_with(filters.len(), Texture::default);
|
output_textures.resize_with(filters.len(), InputTexture::default);
|
||||||
|
|
||||||
// initialize feedback framebuffers
|
// initialize feedback framebuffers
|
||||||
let mut feedback_framebuffers = Vec::new();
|
let mut feedback_framebuffers = Vec::new();
|
||||||
feedback_framebuffers.resize_with(filters.len(), || T::FramebufferInterface::new(1));
|
feedback_framebuffers.resize_with(filters.len(), || T::FramebufferInterface::new(1));
|
||||||
let mut feedback_textures = Vec::new();
|
let mut feedback_textures = Vec::new();
|
||||||
feedback_textures.resize_with(filters.len(), Texture::default);
|
feedback_textures.resize_with(filters.len(), InputTexture::default);
|
||||||
|
|
||||||
// load luts
|
// load luts
|
||||||
let luts = T::LoadLut::load_luts(&preset.textures)?;
|
let luts = T::LoadLut::load_luts(&preset.textures)?;
|
||||||
|
@ -304,21 +304,21 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
||||||
for param in reflection.meta.parameter_meta.values() {
|
for param in reflection.meta.parameter_meta.values() {
|
||||||
uniform_bindings.insert(
|
uniform_bindings.insert(
|
||||||
UniformBinding::Parameter(param.id.clone()),
|
UniformBinding::Parameter(param.id.clone()),
|
||||||
(Self::reflect_uniform_location(program, param), param.offset),
|
UniformOffset::new(Self::reflect_uniform_location(program, param), param.offset),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (semantics, param) in &reflection.meta.unique_meta {
|
for (semantics, param) in &reflection.meta.unique_meta {
|
||||||
uniform_bindings.insert(
|
uniform_bindings.insert(
|
||||||
UniformBinding::SemanticVariable(*semantics),
|
UniformBinding::SemanticVariable(*semantics),
|
||||||
(Self::reflect_uniform_location(program, param), param.offset),
|
UniformOffset::new(Self::reflect_uniform_location(program, param), param.offset),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (semantics, param) in &reflection.meta.texture_size_meta {
|
for (semantics, param) in &reflection.meta.texture_size_meta {
|
||||||
uniform_bindings.insert(
|
uniform_bindings.insert(
|
||||||
UniformBinding::TextureSize(*semantics),
|
UniformBinding::TextureSize(*semantics),
|
||||||
(Self::reflect_uniform_location(program, param), param.offset),
|
UniformOffset::new(Self::reflect_uniform_location(program, param), param.offset),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,7 +351,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
||||||
filters: &[FilterPass<T>],
|
filters: &[FilterPass<T>],
|
||||||
filter: FilterMode,
|
filter: FilterMode,
|
||||||
wrap_mode: WrapMode,
|
wrap_mode: WrapMode,
|
||||||
) -> (VecDeque<Framebuffer>, Box<[Texture]>) {
|
) -> (VecDeque<Framebuffer>, Box<[InputTexture]>) {
|
||||||
let mut required_images = 0;
|
let mut required_images = 0;
|
||||||
|
|
||||||
for pass in filters {
|
for pass in filters {
|
||||||
|
@ -388,7 +388,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
||||||
framebuffers.resize_with(required_images, || T::FramebufferInterface::new(1));
|
framebuffers.resize_with(required_images, || T::FramebufferInterface::new(1));
|
||||||
|
|
||||||
let mut history_textures = Vec::new();
|
let mut history_textures = Vec::new();
|
||||||
history_textures.resize_with(required_images, || Texture {
|
history_textures.resize_with(required_images, || InputTexture {
|
||||||
image: Default::default(),
|
image: Default::default(),
|
||||||
filter,
|
filter,
|
||||||
mip_filter: filter,
|
mip_filter: filter,
|
||||||
|
@ -470,7 +470,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// shader_gl3: 2067
|
// shader_gl3: 2067
|
||||||
let original = Texture {
|
let original = InputTexture {
|
||||||
image: *input,
|
image: *input,
|
||||||
filter,
|
filter,
|
||||||
mip_filter: filter,
|
mip_filter: filter,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gl::types::{GLsizei, GLuint};
|
use gl::types::{GLint, GLsizei, GLuint};
|
||||||
use librashader_reflect::back::cross::CrossGlslContext;
|
use librashader_reflect::back::cross::CrossGlslContext;
|
||||||
use librashader_reflect::back::ShaderCompilerOutput;
|
use librashader_reflect::back::ShaderCompilerOutput;
|
||||||
use librashader_reflect::reflect::ShaderReflection;
|
use librashader_reflect::reflect::ShaderReflection;
|
||||||
|
@ -6,18 +6,32 @@ use librashader_reflect::reflect::ShaderReflection;
|
||||||
use librashader_common::{ImageFormat, Size, Viewport};
|
use librashader_common::{ImageFormat, Size, Viewport};
|
||||||
use librashader_preprocess::ShaderSource;
|
use librashader_preprocess::ShaderSource;
|
||||||
use librashader_presets::ShaderPassConfig;
|
use librashader_presets::ShaderPassConfig;
|
||||||
use librashader_reflect::reflect::semantics::{
|
use librashader_reflect::reflect::semantics::{MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniqueSemantics};
|
||||||
MemberOffset, TextureSemantics, UniformBinding, UniqueSemantics,
|
|
||||||
};
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
use librashader_runtime::binding::{BindSemantics, ContextOffset, TextureInput};
|
||||||
|
|
||||||
use crate::binding::{GlUniformStorage, UniformLocation, VariableLocation};
|
use crate::binding::{GlUniformBinder, GlUniformStorage, UniformLocation, VariableLocation};
|
||||||
use crate::filter_chain::FilterCommon;
|
use crate::filter_chain::FilterCommon;
|
||||||
use crate::Framebuffer;
|
use crate::Framebuffer;
|
||||||
use crate::gl::{BindTexture, GLInterface, UboRing};
|
use crate::gl::{BindTexture, GLInterface, UboRing};
|
||||||
use crate::render_target::RenderTarget;
|
use crate::render_target::RenderTarget;
|
||||||
|
use crate::samplers::SamplerSet;
|
||||||
|
|
||||||
use crate::texture::Texture;
|
use crate::texture::InputTexture;
|
||||||
|
|
||||||
|
pub struct UniformOffset {
|
||||||
|
pub location: VariableLocation,
|
||||||
|
pub offset: MemberOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UniformOffset {
|
||||||
|
pub fn new(location: VariableLocation, offset: MemberOffset) -> Self {
|
||||||
|
Self {
|
||||||
|
location,
|
||||||
|
offset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FilterPass<T: GLInterface> {
|
pub struct FilterPass<T: GLInterface> {
|
||||||
pub reflection: ShaderReflection,
|
pub reflection: ShaderReflection,
|
||||||
|
@ -26,11 +40,42 @@ pub struct FilterPass<T: GLInterface> {
|
||||||
pub ubo_location: UniformLocation<GLuint>,
|
pub ubo_location: UniformLocation<GLuint>,
|
||||||
pub ubo_ring: Option<T::UboRing>,
|
pub ubo_ring: Option<T::UboRing>,
|
||||||
pub(crate) uniform_storage: GlUniformStorage,
|
pub(crate) uniform_storage: GlUniformStorage,
|
||||||
pub uniform_bindings: FxHashMap<UniformBinding, (VariableLocation, MemberOffset)>,
|
pub uniform_bindings: FxHashMap<UniformBinding, UniformOffset>,
|
||||||
pub source: ShaderSource,
|
pub source: ShaderSource,
|
||||||
pub config: ShaderPassConfig,
|
pub config: ShaderPassConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TextureInput for InputTexture {
|
||||||
|
fn size(&self) -> Size<u32> {
|
||||||
|
self.image.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ContextOffset<GlUniformBinder, UniformLocation<GLint>> for UniformOffset {
|
||||||
|
fn offset(&self) -> MemberOffset {
|
||||||
|
self.offset
|
||||||
|
}
|
||||||
|
|
||||||
|
fn context(&self) -> UniformLocation<GLint> {
|
||||||
|
self.location.location()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: GLInterface> BindSemantics<GlUniformBinder, UniformLocation<GLint>> for FilterPass<T> {
|
||||||
|
type InputTexture = InputTexture;
|
||||||
|
type SamplerSet = SamplerSet;
|
||||||
|
type DescriptorSet<'a> = ();
|
||||||
|
type DeviceContext = ();
|
||||||
|
type UniformOffset = UniformOffset;
|
||||||
|
|
||||||
|
fn bind_texture<'a>(
|
||||||
|
_descriptors: &mut Self::DescriptorSet<'a>, samplers: &Self::SamplerSet,
|
||||||
|
binding: &TextureBinding, texture: &Self::InputTexture,
|
||||||
|
_device: &Self::DeviceContext) {
|
||||||
|
T::BindTexture::bind_texture(&samplers, binding, texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: GLInterface> FilterPass<T> {
|
impl<T: GLInterface> FilterPass<T> {
|
||||||
pub(crate) fn draw(
|
pub(crate) fn draw(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -39,8 +84,8 @@ impl<T: GLInterface> FilterPass<T> {
|
||||||
frame_count: u32,
|
frame_count: u32,
|
||||||
frame_direction: i32,
|
frame_direction: i32,
|
||||||
viewport: &Viewport<&Framebuffer>,
|
viewport: &Viewport<&Framebuffer>,
|
||||||
original: &Texture,
|
original: &InputTexture,
|
||||||
source: &Texture,
|
source: &InputTexture,
|
||||||
output: RenderTarget,
|
output: RenderTarget,
|
||||||
) {
|
) {
|
||||||
let framebuffer = output.framebuffer;
|
let framebuffer = output.framebuffer;
|
||||||
|
@ -124,216 +169,33 @@ impl<T: GLInterface> FilterPass<T> {
|
||||||
frame_direction: i32,
|
frame_direction: i32,
|
||||||
fb_size: Size<u32>,
|
fb_size: Size<u32>,
|
||||||
viewport: &Viewport<&Framebuffer>,
|
viewport: &Viewport<&Framebuffer>,
|
||||||
original: &Texture,
|
original: &InputTexture,
|
||||||
source: &Texture,
|
source: &InputTexture,
|
||||||
) {
|
) {
|
||||||
// Bind MVP
|
Self::bind_semantics(
|
||||||
if let Some((location, offset)) = self.uniform_bindings.get(&UniqueSemantics::MVP.into()) {
|
&(),
|
||||||
self.uniform_storage
|
&parent.samplers,
|
||||||
.bind_mat4(*offset, mvp, location.location());
|
&mut self.uniform_storage,
|
||||||
}
|
&mut (),
|
||||||
|
mvp,
|
||||||
// bind OutputSize
|
frame_count,
|
||||||
if let Some((location, offset)) = self.uniform_bindings.get(&UniqueSemantics::Output.into())
|
frame_direction,
|
||||||
{
|
fb_size,
|
||||||
self.uniform_storage
|
viewport.output.size,
|
||||||
.bind_vec4(*offset, fb_size, location.location());
|
original,
|
||||||
}
|
source,
|
||||||
|
&self.uniform_bindings,
|
||||||
// bind FinalViewportSize
|
&self.reflection.meta.texture_meta,
|
||||||
if let Some((location, offset)) = self
|
parent.output_textures[0..pass_index].iter()
|
||||||
.uniform_bindings
|
.map(|o| o.bound()),
|
||||||
.get(&UniqueSemantics::FinalViewport.into())
|
parent.feedback_textures.iter()
|
||||||
{
|
.map(|o| o.bound()),
|
||||||
self.uniform_storage
|
parent.history_textures.iter()
|
||||||
.bind_vec4(*offset, viewport.output.size, location.location());
|
.map(|o| o.bound()),
|
||||||
}
|
parent.luts.iter()
|
||||||
|
.map(|(u, i)| (*u, i)),
|
||||||
// bind FrameCount
|
&self.source.parameters,
|
||||||
if let Some((location, offset)) = self
|
&parent.config.parameters
|
||||||
.uniform_bindings
|
);
|
||||||
.get(&UniqueSemantics::FrameCount.into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_scalar(*offset, frame_count, location.location());
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind FrameDirection
|
|
||||||
if let Some((location, offset)) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&UniqueSemantics::FrameDirection.into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_scalar(*offset, frame_direction, location.location());
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind Original sampler
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::Original.semantics(0))
|
|
||||||
{
|
|
||||||
T::BindTexture::bind_texture(&parent.samplers, binding, original);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind OriginalSize
|
|
||||||
if let Some((location, offset)) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::Original.semantics(0).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, original.image.size, location.location());
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind Source sampler
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::Source.semantics(0))
|
|
||||||
{
|
|
||||||
// eprintln!("setting source binding to {}", binding.binding);
|
|
||||||
T::BindTexture::bind_texture(&parent.samplers, binding, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind SourceSize
|
|
||||||
if let Some((location, offset)) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::Source.semantics(0).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, source.image.size, location.location());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::OriginalHistory.semantics(0))
|
|
||||||
{
|
|
||||||
T::BindTexture::bind_texture(&parent.samplers, binding, original);
|
|
||||||
}
|
|
||||||
if let Some((location, offset)) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::OriginalHistory.semantics(0).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, original.image.size, location.location());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (index, output) in parent.history_textures.iter().enumerate() {
|
|
||||||
if !output.is_bound() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::OriginalHistory.semantics(index + 1))
|
|
||||||
{
|
|
||||||
T::BindTexture::bind_texture(&parent.samplers, binding, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((location, offset)) = self.uniform_bindings.get(
|
|
||||||
&TextureSemantics::OriginalHistory
|
|
||||||
.semantics(index + 1)
|
|
||||||
.into(),
|
|
||||||
) {
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, output.image.size, location.location());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PassOutput
|
|
||||||
for (index, output) in parent.output_textures[0..pass_index].iter().enumerate() {
|
|
||||||
if !output.is_bound() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::PassOutput.semantics(index))
|
|
||||||
{
|
|
||||||
T::BindTexture::bind_texture(&parent.samplers, binding, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((location, offset)) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::PassOutput.semantics(index).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, output.image.size, location.location());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PassFeedback
|
|
||||||
for (index, feedback) in parent.feedback_textures.iter().enumerate() {
|
|
||||||
if !feedback.is_bound() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::PassFeedback.semantics(index))
|
|
||||||
{
|
|
||||||
T::BindTexture::bind_texture(&parent.samplers, binding, feedback);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((location, offset)) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::PassFeedback.semantics(index).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, feedback.image.size, location.location());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind float parameters
|
|
||||||
for (id, (location, offset)) in
|
|
||||||
self.uniform_bindings
|
|
||||||
.iter()
|
|
||||||
.filter_map(|(binding, value)| match binding {
|
|
||||||
UniformBinding::Parameter(id) => Some((id, value)),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
{
|
|
||||||
let id = id.as_str();
|
|
||||||
// presets override params
|
|
||||||
let default = self
|
|
||||||
.source
|
|
||||||
.parameters
|
|
||||||
.iter()
|
|
||||||
.find(|&p| p.id == id)
|
|
||||||
.map(|f| f.initial)
|
|
||||||
.unwrap_or(0f32);
|
|
||||||
|
|
||||||
let value = *parent.config.parameters.get(id).unwrap_or(&default);
|
|
||||||
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_scalar(*offset, value, location.location());
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind luts
|
|
||||||
for (index, lut) in &parent.luts {
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::User.semantics(*index))
|
|
||||||
{
|
|
||||||
T::BindTexture::bind_texture(&parent.samplers, binding, lut);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((location, offset)) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::User.semantics(*index).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, lut.image.size, location.location());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::framebuffer::GLImage;
|
use crate::framebuffer::GLImage;
|
||||||
use crate::gl::FramebufferInterface;
|
use crate::gl::FramebufferInterface;
|
||||||
use crate::texture::Texture;
|
use crate::texture::InputTexture;
|
||||||
use gl::types::{GLenum, GLuint};
|
use gl::types::{GLenum, GLuint};
|
||||||
use librashader_common::{FilterMode, ImageFormat, Size, Viewport, WrapMode};
|
use librashader_common::{FilterMode, ImageFormat, Size, Viewport, WrapMode};
|
||||||
use librashader_presets::Scale2D;
|
use librashader_presets::Scale2D;
|
||||||
|
@ -52,8 +52,8 @@ impl Framebuffer {
|
||||||
scaling: Scale2D,
|
scaling: Scale2D,
|
||||||
format: ImageFormat,
|
format: ImageFormat,
|
||||||
viewport: &Viewport<&Framebuffer>,
|
viewport: &Viewport<&Framebuffer>,
|
||||||
original: &Texture,
|
original: &InputTexture,
|
||||||
source: &Texture,
|
source: &InputTexture,
|
||||||
mipmap: bool,
|
mipmap: bool,
|
||||||
) -> Result<Size<u32>> {
|
) -> Result<Size<u32>> {
|
||||||
T::scale(self, scaling, format, viewport, original, source, mipmap)
|
T::scale(self, scaling, format, viewport, original, source, mipmap)
|
||||||
|
@ -63,8 +63,8 @@ impl Framebuffer {
|
||||||
T::copy_from(self, image)
|
T::copy_from(self, image)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn as_texture(&self, filter: FilterMode, wrap_mode: WrapMode) -> Texture {
|
pub(crate) fn as_texture(&self, filter: FilterMode, wrap_mode: WrapMode) -> InputTexture {
|
||||||
Texture {
|
InputTexture {
|
||||||
image: GLImage {
|
image: GLImage {
|
||||||
handle: self.image,
|
handle: self.image,
|
||||||
format: self.format,
|
format: self.format,
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::error::{FilterChainError, Result};
|
||||||
use crate::framebuffer::GLImage;
|
use crate::framebuffer::GLImage;
|
||||||
use crate::gl::framebuffer::Framebuffer;
|
use crate::gl::framebuffer::Framebuffer;
|
||||||
use crate::gl::FramebufferInterface;
|
use crate::gl::FramebufferInterface;
|
||||||
use crate::texture::Texture;
|
use crate::texture::InputTexture;
|
||||||
use gl::types::{GLenum, GLint, GLsizei};
|
use gl::types::{GLenum, GLint, GLsizei};
|
||||||
use librashader_common::{ImageFormat, Size, Viewport};
|
use librashader_common::{ImageFormat, Size, Viewport};
|
||||||
use librashader_presets::Scale2D;
|
use librashader_presets::Scale2D;
|
||||||
|
@ -39,8 +39,8 @@ impl FramebufferInterface for Gl3Framebuffer {
|
||||||
scaling: Scale2D,
|
scaling: Scale2D,
|
||||||
format: ImageFormat,
|
format: ImageFormat,
|
||||||
viewport: &Viewport<&Framebuffer>,
|
viewport: &Viewport<&Framebuffer>,
|
||||||
_original: &Texture,
|
_original: &InputTexture,
|
||||||
source: &Texture,
|
source: &InputTexture,
|
||||||
mipmap: bool,
|
mipmap: bool,
|
||||||
) -> Result<Size<u32>> {
|
) -> Result<Size<u32>> {
|
||||||
if fb.is_raw {
|
if fb.is_raw {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::framebuffer::GLImage;
|
use crate::framebuffer::GLImage;
|
||||||
use crate::gl::LoadLut;
|
use crate::gl::LoadLut;
|
||||||
use crate::texture::Texture;
|
use crate::texture::InputTexture;
|
||||||
use gl::types::{GLsizei, GLuint};
|
use gl::types::{GLsizei, GLuint};
|
||||||
use librashader_common::Size;
|
use librashader_common::Size;
|
||||||
use librashader_presets::TextureConfig;
|
use librashader_presets::TextureConfig;
|
||||||
|
@ -11,7 +11,7 @@ use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
pub struct Gl3LutLoad;
|
pub struct Gl3LutLoad;
|
||||||
impl LoadLut for Gl3LutLoad {
|
impl LoadLut for Gl3LutLoad {
|
||||||
fn load_luts(textures: &[TextureConfig]) -> Result<FxHashMap<usize, Texture>> {
|
fn load_luts(textures: &[TextureConfig]) -> Result<FxHashMap<usize, InputTexture>> {
|
||||||
let mut luts = FxHashMap::default();
|
let mut luts = FxHashMap::default();
|
||||||
let pixel_unpack = unsafe {
|
let pixel_unpack = unsafe {
|
||||||
let mut binding = 0;
|
let mut binding = 0;
|
||||||
|
@ -64,7 +64,7 @@ impl LoadLut for Gl3LutLoad {
|
||||||
|
|
||||||
luts.insert(
|
luts.insert(
|
||||||
index,
|
index,
|
||||||
Texture {
|
InputTexture {
|
||||||
image: GLImage {
|
image: GLImage {
|
||||||
handle,
|
handle,
|
||||||
format: gl::RGBA8,
|
format: gl::RGBA8,
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::gl::BindTexture;
|
use crate::gl::BindTexture;
|
||||||
use crate::samplers::SamplerSet;
|
use crate::samplers::SamplerSet;
|
||||||
use crate::texture::Texture;
|
use crate::texture::InputTexture;
|
||||||
use librashader_reflect::reflect::semantics::TextureBinding;
|
use librashader_reflect::reflect::semantics::TextureBinding;
|
||||||
|
|
||||||
pub struct Gl3BindTexture;
|
pub struct Gl3BindTexture;
|
||||||
|
|
||||||
impl BindTexture for Gl3BindTexture {
|
impl BindTexture for Gl3BindTexture {
|
||||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture) {
|
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &InputTexture) {
|
||||||
unsafe {
|
unsafe {
|
||||||
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
||||||
gl::ActiveTexture(gl::TEXTURE0 + binding.binding);
|
gl::ActiveTexture(gl::TEXTURE0 + binding.binding);
|
||||||
|
@ -19,7 +19,7 @@ impl BindTexture for Gl3BindTexture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_mipmaps(texture: &Texture) {
|
fn gen_mipmaps(texture: &InputTexture) {
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
|
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
|
||||||
gl::GenerateMipmap(gl::TEXTURE_2D);
|
gl::GenerateMipmap(gl::TEXTURE_2D);
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::error::{FilterChainError, Result};
|
||||||
use crate::framebuffer::GLImage;
|
use crate::framebuffer::GLImage;
|
||||||
use crate::gl::framebuffer::Framebuffer;
|
use crate::gl::framebuffer::Framebuffer;
|
||||||
use crate::gl::FramebufferInterface;
|
use crate::gl::FramebufferInterface;
|
||||||
use crate::texture::Texture;
|
use crate::texture::InputTexture;
|
||||||
use gl::types::{GLenum, GLint, GLsizei};
|
use gl::types::{GLenum, GLint, GLsizei};
|
||||||
use librashader_common::{ImageFormat, Size, Viewport};
|
use librashader_common::{ImageFormat, Size, Viewport};
|
||||||
use librashader_presets::Scale2D;
|
use librashader_presets::Scale2D;
|
||||||
|
@ -37,8 +37,8 @@ impl FramebufferInterface for Gl46Framebuffer {
|
||||||
scaling: Scale2D,
|
scaling: Scale2D,
|
||||||
format: ImageFormat,
|
format: ImageFormat,
|
||||||
viewport: &Viewport<&Framebuffer>,
|
viewport: &Viewport<&Framebuffer>,
|
||||||
_original: &Texture,
|
_original: &InputTexture,
|
||||||
source: &Texture,
|
source: &InputTexture,
|
||||||
mipmap: bool,
|
mipmap: bool,
|
||||||
) -> Result<Size<u32>> {
|
) -> Result<Size<u32>> {
|
||||||
if fb.is_raw {
|
if fb.is_raw {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::framebuffer::GLImage;
|
use crate::framebuffer::GLImage;
|
||||||
use crate::gl::LoadLut;
|
use crate::gl::LoadLut;
|
||||||
use crate::texture::Texture;
|
use crate::texture::InputTexture;
|
||||||
use gl::types::{GLsizei, GLuint};
|
use gl::types::{GLsizei, GLuint};
|
||||||
use librashader_common::Size;
|
use librashader_common::Size;
|
||||||
use librashader_presets::TextureConfig;
|
use librashader_presets::TextureConfig;
|
||||||
|
@ -11,7 +11,7 @@ use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
pub struct Gl46LutLoad;
|
pub struct Gl46LutLoad;
|
||||||
impl LoadLut for Gl46LutLoad {
|
impl LoadLut for Gl46LutLoad {
|
||||||
fn load_luts(textures: &[TextureConfig]) -> Result<FxHashMap<usize, Texture>> {
|
fn load_luts(textures: &[TextureConfig]) -> Result<FxHashMap<usize, InputTexture>> {
|
||||||
let mut luts = FxHashMap::default();
|
let mut luts = FxHashMap::default();
|
||||||
let pixel_unpack = unsafe {
|
let pixel_unpack = unsafe {
|
||||||
let mut binding = 0;
|
let mut binding = 0;
|
||||||
|
@ -66,7 +66,7 @@ impl LoadLut for Gl46LutLoad {
|
||||||
|
|
||||||
luts.insert(
|
luts.insert(
|
||||||
index,
|
index,
|
||||||
Texture {
|
InputTexture {
|
||||||
image: GLImage {
|
image: GLImage {
|
||||||
handle,
|
handle,
|
||||||
format: gl::RGBA8,
|
format: gl::RGBA8,
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::gl::BindTexture;
|
use crate::gl::BindTexture;
|
||||||
use crate::samplers::SamplerSet;
|
use crate::samplers::SamplerSet;
|
||||||
use crate::texture::Texture;
|
use crate::texture::InputTexture;
|
||||||
use librashader_reflect::reflect::semantics::TextureBinding;
|
use librashader_reflect::reflect::semantics::TextureBinding;
|
||||||
|
|
||||||
pub struct Gl46BindTexture;
|
pub struct Gl46BindTexture;
|
||||||
|
|
||||||
impl BindTexture for Gl46BindTexture {
|
impl BindTexture for Gl46BindTexture {
|
||||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture) {
|
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &InputTexture) {
|
||||||
unsafe {
|
unsafe {
|
||||||
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
||||||
gl::BindTextureUnit(binding.binding, texture.image.handle);
|
gl::BindTextureUnit(binding.binding, texture.image.handle);
|
||||||
|
@ -17,7 +17,7 @@ impl BindTexture for Gl46BindTexture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_mipmaps(texture: &Texture) {
|
fn gen_mipmaps(texture: &InputTexture) {
|
||||||
unsafe { gl::GenerateTextureMipmap(texture.image.handle) }
|
unsafe { gl::GenerateTextureMipmap(texture.image.handle) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::binding::UniformLocation;
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::framebuffer::GLImage;
|
use crate::framebuffer::GLImage;
|
||||||
use crate::samplers::SamplerSet;
|
use crate::samplers::SamplerSet;
|
||||||
use crate::texture::Texture;
|
use crate::texture::InputTexture;
|
||||||
pub use framebuffer::Framebuffer;
|
pub use framebuffer::Framebuffer;
|
||||||
use gl::types::{GLenum, GLuint};
|
use gl::types::{GLenum, GLuint};
|
||||||
use librashader_common::{ImageFormat, Size, Viewport};
|
use librashader_common::{ImageFormat, Size, Viewport};
|
||||||
|
@ -16,7 +16,7 @@ use librashader_runtime::uniforms::UniformStorageAccess;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
pub trait LoadLut {
|
pub trait LoadLut {
|
||||||
fn load_luts(textures: &[TextureConfig]) -> Result<FxHashMap<usize, Texture>>;
|
fn load_luts(textures: &[TextureConfig]) -> Result<FxHashMap<usize, InputTexture>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DrawQuad {
|
pub trait DrawQuad {
|
||||||
|
@ -42,8 +42,8 @@ pub trait FramebufferInterface {
|
||||||
scaling: Scale2D,
|
scaling: Scale2D,
|
||||||
format: ImageFormat,
|
format: ImageFormat,
|
||||||
viewport: &Viewport<&Framebuffer>,
|
viewport: &Viewport<&Framebuffer>,
|
||||||
_original: &Texture,
|
_original: &InputTexture,
|
||||||
source: &Texture,
|
source: &InputTexture,
|
||||||
mipmap: bool,
|
mipmap: bool,
|
||||||
) -> Result<Size<u32>>;
|
) -> Result<Size<u32>>;
|
||||||
fn clear<const REBIND: bool>(fb: &Framebuffer);
|
fn clear<const REBIND: bool>(fb: &Framebuffer);
|
||||||
|
@ -52,8 +52,8 @@ pub trait FramebufferInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BindTexture {
|
pub trait BindTexture {
|
||||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture);
|
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &InputTexture);
|
||||||
fn gen_mipmaps(texture: &Texture);
|
fn gen_mipmaps(texture: &InputTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GLInterface {
|
pub trait GLInterface {
|
||||||
|
|
|
@ -1,16 +1,32 @@
|
||||||
|
use gl::types::GLuint;
|
||||||
use crate::framebuffer::GLImage;
|
use crate::framebuffer::GLImage;
|
||||||
use librashader_common::{FilterMode, WrapMode};
|
use librashader_common::{FilterMode, WrapMode};
|
||||||
|
|
||||||
#[derive(Default, Debug, Copy, Clone)]
|
#[derive(Default, Debug, Copy, Clone)]
|
||||||
pub struct Texture {
|
pub struct InputTexture {
|
||||||
pub image: GLImage,
|
pub image: GLImage,
|
||||||
pub filter: FilterMode,
|
pub filter: FilterMode,
|
||||||
pub mip_filter: FilterMode,
|
pub mip_filter: FilterMode,
|
||||||
pub wrap_mode: WrapMode,
|
pub wrap_mode: WrapMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Texture {
|
impl InputTexture {
|
||||||
pub fn is_bound(&self) -> bool {
|
pub fn is_bound(&self) -> bool {
|
||||||
self.image.handle != 0
|
self.image.handle != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a reference to itself if the texture is bound.
|
||||||
|
pub fn bound(&self) -> Option<&Self> {
|
||||||
|
if self.is_bound() {
|
||||||
|
Some(&self)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<InputTexture> for InputTexture {
|
||||||
|
fn as_ref(&self) -> &InputTexture {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,8 +14,9 @@ use librashader_reflect::reflect::semantics::{
|
||||||
BindingStage, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniqueSemantics,
|
BindingStage, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniqueSemantics,
|
||||||
};
|
};
|
||||||
use librashader_reflect::reflect::ShaderReflection;
|
use librashader_reflect::reflect::ShaderReflection;
|
||||||
use librashader_runtime::uniforms::{UniformStorage, UniformStorageAccess};
|
use librashader_runtime::uniforms::{BindUniform, NoUniformBinder, UniformStorage, UniformStorageAccess};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
use librashader_runtime::binding::{BindSemantics, TextureInput};
|
||||||
|
|
||||||
pub struct FilterPass {
|
pub struct FilterPass {
|
||||||
pub device: Arc<ash::Device>,
|
pub device: Arc<ash::Device>,
|
||||||
|
@ -30,6 +31,42 @@ pub struct FilterPass {
|
||||||
pub frames_in_flight: u32,
|
pub frames_in_flight: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TextureInput for InputImage {
|
||||||
|
fn size(&self) -> Size<u32> {
|
||||||
|
self.image.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BindSemantics for FilterPass {
|
||||||
|
type InputTexture = InputImage;
|
||||||
|
type SamplerSet = SamplerSet;
|
||||||
|
type DescriptorSet<'a> = vk::DescriptorSet;
|
||||||
|
type DeviceContext = Arc<ash::Device>;
|
||||||
|
type UniformOffset = MemberOffset;
|
||||||
|
|
||||||
|
fn bind_texture<'a>(
|
||||||
|
descriptors: &mut Self::DescriptorSet<'a>, samplers: &Self::SamplerSet,
|
||||||
|
binding: &TextureBinding, texture: &Self::InputTexture, device: &Self::DeviceContext) {
|
||||||
|
let sampler = samplers.get(texture.wrap_mode, texture.filter_mode, texture.mip_filter);
|
||||||
|
let image_info = [vk::DescriptorImageInfo::builder()
|
||||||
|
.sampler(sampler.handle)
|
||||||
|
.image_view(texture.image_view)
|
||||||
|
.image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
|
||||||
|
.build()];
|
||||||
|
|
||||||
|
let write_desc = [vk::WriteDescriptorSet::builder()
|
||||||
|
.dst_set(*descriptors)
|
||||||
|
.dst_binding(binding.binding)
|
||||||
|
.dst_array_element(0)
|
||||||
|
.descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)
|
||||||
|
.image_info(&image_info)
|
||||||
|
.build()];
|
||||||
|
unsafe {
|
||||||
|
device.update_descriptor_sets(&write_desc, &[]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FilterPass {
|
impl FilterPass {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn bind_texture(
|
fn bind_texture(
|
||||||
|
@ -81,7 +118,7 @@ impl FilterPass {
|
||||||
source: &InputImage,
|
source: &InputImage,
|
||||||
output: &RenderTarget,
|
output: &RenderTarget,
|
||||||
) -> error::Result<()> {
|
) -> error::Result<()> {
|
||||||
let descriptor = *&self.graphics_pipeline.layout.descriptor_sets
|
let mut descriptor = *&self.graphics_pipeline.layout.descriptor_sets
|
||||||
[(frame_count % self.frames_in_flight) as usize];
|
[(frame_count % self.frames_in_flight) as usize];
|
||||||
|
|
||||||
self.build_semantics(
|
self.build_semantics(
|
||||||
|
@ -92,7 +129,7 @@ impl FilterPass {
|
||||||
frame_direction,
|
frame_direction,
|
||||||
output.output.size,
|
output.output.size,
|
||||||
viewport.output.size,
|
viewport.output.size,
|
||||||
&descriptor,
|
&mut descriptor,
|
||||||
original,
|
original,
|
||||||
source,
|
source,
|
||||||
);
|
);
|
||||||
|
@ -182,262 +219,41 @@ impl FilterPass {
|
||||||
|
|
||||||
fn build_semantics(
|
fn build_semantics(
|
||||||
&mut self,
|
&mut self,
|
||||||
_pass_index: usize,
|
pass_index: usize,
|
||||||
parent: &FilterCommon,
|
parent: &FilterCommon,
|
||||||
mvp: &[f32; 16],
|
mvp: &[f32; 16],
|
||||||
frame_count: u32,
|
frame_count: u32,
|
||||||
frame_direction: i32,
|
frame_direction: i32,
|
||||||
fb_size: Size<u32>,
|
fb_size: Size<u32>,
|
||||||
viewport_size: Size<u32>,
|
viewport_size: Size<u32>,
|
||||||
descriptor_set: &vk::DescriptorSet,
|
mut descriptor_set: &mut vk::DescriptorSet,
|
||||||
original: &InputImage,
|
original: &InputImage,
|
||||||
source: &InputImage,
|
source: &InputImage,
|
||||||
) {
|
) {
|
||||||
if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::MVP.into()) {
|
Self::bind_semantics(
|
||||||
self.uniform_storage.bind_mat4(*offset, mvp, None);
|
&self.device,
|
||||||
}
|
&parent.samplers,
|
||||||
|
&mut self.uniform_storage,
|
||||||
// bind OutputSize
|
&mut descriptor_set,
|
||||||
if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::Output.into()) {
|
mvp,
|
||||||
self.uniform_storage.bind_vec4(*offset, fb_size, None);
|
frame_count,
|
||||||
}
|
frame_direction,
|
||||||
|
fb_size,
|
||||||
// bind FinalViewportSize
|
viewport_size,
|
||||||
if let Some(offset) = self
|
original,
|
||||||
.uniform_bindings
|
source,
|
||||||
.get(&UniqueSemantics::FinalViewport.into())
|
&self.uniform_bindings,
|
||||||
{
|
&self.reflection.meta.texture_meta,
|
||||||
self.uniform_storage.bind_vec4(*offset, viewport_size, None);
|
parent.output_inputs[0..pass_index].iter()
|
||||||
}
|
.map(|o| o.as_ref()),
|
||||||
|
parent.feedback_inputs.iter()
|
||||||
// bind FrameCount
|
.map(|o| o.as_ref()),
|
||||||
if let Some(offset) = self
|
parent.history_textures.iter()
|
||||||
.uniform_bindings
|
.map(|o| o.as_ref()),
|
||||||
.get(&UniqueSemantics::FrameCount.into())
|
parent.luts.iter()
|
||||||
{
|
.map(|(u, i)| (*u, i.as_ref())),
|
||||||
self.uniform_storage.bind_scalar(*offset, frame_count, None);
|
&self.source.parameters,
|
||||||
}
|
&parent.config.parameters
|
||||||
|
);
|
||||||
// bind FrameDirection
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&UniqueSemantics::FrameDirection.into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_scalar(*offset, frame_direction, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind Original sampler
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::Original.semantics(0))
|
|
||||||
{
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&self.device,
|
|
||||||
&parent.samplers,
|
|
||||||
*descriptor_set,
|
|
||||||
binding,
|
|
||||||
original,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind OriginalSize
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::Original.semantics(0).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, original.image.size, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind Source sampler
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::Source.semantics(0))
|
|
||||||
{
|
|
||||||
// eprintln!("setting source binding to {}", binding.binding);
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&self.device,
|
|
||||||
&parent.samplers,
|
|
||||||
*descriptor_set,
|
|
||||||
binding,
|
|
||||||
source,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind SourceSize
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::Source.semantics(0).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, source.image.size, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::OriginalHistory.semantics(0))
|
|
||||||
{
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&self.device,
|
|
||||||
&parent.samplers,
|
|
||||||
*descriptor_set,
|
|
||||||
binding,
|
|
||||||
original,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::OriginalHistory.semantics(0).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, original.image.size, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (index, output) in parent.history_textures.iter().enumerate() {
|
|
||||||
let Some(output) = output else {
|
|
||||||
// eprintln!("no history");
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::OriginalHistory.semantics(index + 1))
|
|
||||||
{
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&self.device,
|
|
||||||
&parent.samplers,
|
|
||||||
*descriptor_set,
|
|
||||||
binding,
|
|
||||||
output,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(offset) = self.uniform_bindings.get(
|
|
||||||
&TextureSemantics::OriginalHistory
|
|
||||||
.semantics(index + 1)
|
|
||||||
.into(),
|
|
||||||
) {
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, output.image.size, None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PassOutput
|
|
||||||
for (index, output) in parent.output_inputs.iter().enumerate() {
|
|
||||||
let Some(output) = output else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::PassOutput.semantics(index))
|
|
||||||
{
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&self.device,
|
|
||||||
&parent.samplers,
|
|
||||||
*descriptor_set,
|
|
||||||
binding,
|
|
||||||
output,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::PassOutput.semantics(index).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, output.image.size, None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PassFeedback
|
|
||||||
for (index, feedback) in parent.feedback_inputs.iter().enumerate() {
|
|
||||||
let Some(feedback) = feedback else {
|
|
||||||
// eprintln!("no passfeedback {index}");
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::PassFeedback.semantics(index))
|
|
||||||
{
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&self.device,
|
|
||||||
&parent.samplers,
|
|
||||||
*descriptor_set,
|
|
||||||
binding,
|
|
||||||
feedback,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::PassFeedback.semantics(index).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, feedback.image.size, None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind float parameters
|
|
||||||
for (id, offset) in
|
|
||||||
self.uniform_bindings
|
|
||||||
.iter()
|
|
||||||
.filter_map(|(binding, value)| match binding {
|
|
||||||
UniformBinding::Parameter(id) => Some((id, value)),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
{
|
|
||||||
let id = id.as_str();
|
|
||||||
|
|
||||||
let default = self
|
|
||||||
.source
|
|
||||||
.parameters
|
|
||||||
.iter()
|
|
||||||
.find(|&p| p.id == id)
|
|
||||||
.map(|f| f.initial)
|
|
||||||
.unwrap_or(0f32);
|
|
||||||
|
|
||||||
let value = *parent.config.parameters.get(id).unwrap_or(&default);
|
|
||||||
|
|
||||||
self.uniform_storage.bind_scalar(*offset, value, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind luts
|
|
||||||
for (index, lut) in &parent.luts {
|
|
||||||
if let Some(binding) = self
|
|
||||||
.reflection
|
|
||||||
.meta
|
|
||||||
.texture_meta
|
|
||||||
.get(&TextureSemantics::User.semantics(*index))
|
|
||||||
{
|
|
||||||
FilterPass::bind_texture(
|
|
||||||
&self.device,
|
|
||||||
&parent.samplers,
|
|
||||||
*descriptor_set,
|
|
||||||
binding,
|
|
||||||
&lut.image,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(offset) = self
|
|
||||||
.uniform_bindings
|
|
||||||
.get(&TextureSemantics::User.semantics(*index).into())
|
|
||||||
{
|
|
||||||
self.uniform_storage
|
|
||||||
.bind_vec4(*offset, lut.image.image.size, None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,3 +249,9 @@ impl LutTexture {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<InputImage> for LutTexture {
|
||||||
|
fn as_ref(&self) -> &InputImage {
|
||||||
|
&self.image
|
||||||
|
}
|
||||||
|
}
|
|
@ -518,7 +518,7 @@ pub struct VulkanImage {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct InputImage {
|
pub struct InputImage {
|
||||||
/// A handle to the `VkImage`.
|
/// A handle to the `VkImage`.
|
||||||
pub image: VulkanImage,
|
pub image: VulkanImage,
|
||||||
/// A handle to the `VkImageView` for the image.
|
/// A handle to the `VkImageView` for the image.
|
||||||
|
@ -527,3 +527,9 @@ pub(crate) struct InputImage {
|
||||||
pub filter_mode: FilterMode,
|
pub filter_mode: FilterMode,
|
||||||
pub mip_filter: FilterMode,
|
pub mip_filter: FilterMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<InputImage> for InputImage {
|
||||||
|
fn as_ref(&self) -> &InputImage {
|
||||||
|
&self
|
||||||
|
}
|
||||||
|
}
|
338
librashader-runtime/src/binding.rs
Normal file
338
librashader-runtime/src/binding.rs
Normal file
|
@ -0,0 +1,338 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::hash::BuildHasher;
|
||||||
|
use librashader_common::Size;
|
||||||
|
use librashader_preprocess::ShaderParameter;
|
||||||
|
use librashader_reflect::reflect::semantics::{MemberOffset, Semantic, TextureBinding, TextureSemantics, UniformBinding, UniqueSemantics};
|
||||||
|
use crate::uniforms::{BindUniform, NoUniformBinder, UniformStorage};
|
||||||
|
|
||||||
|
/// Trait for input textures used during uniform binding,
|
||||||
|
pub trait TextureInput {
|
||||||
|
/// Gets the size of this input texture.
|
||||||
|
fn size(&self) -> Size<u32>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A uniform member offset with context that needs to be resolved.
|
||||||
|
pub trait ContextOffset<H, C>
|
||||||
|
where
|
||||||
|
H: BindUniform<C, f32>,
|
||||||
|
H: BindUniform<C, u32>,
|
||||||
|
H: BindUniform<C, i32>,
|
||||||
|
H: for<'a> BindUniform<C, &'a [f32; 4]>,
|
||||||
|
H: for<'a> BindUniform<C, &'a [f32; 16]>,
|
||||||
|
{
|
||||||
|
/// Gets the `MemberOffset` part of the offset.
|
||||||
|
fn offset(&self) -> MemberOffset;
|
||||||
|
|
||||||
|
/// Gets the context part of the offset.
|
||||||
|
fn context(&self) -> C;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H> ContextOffset<H, Option<()>> for MemberOffset
|
||||||
|
where
|
||||||
|
H: BindUniform<Option<()>, f32>,
|
||||||
|
H: BindUniform<Option<()>, u32>,
|
||||||
|
H: BindUniform<Option<()>, i32>,
|
||||||
|
H: for<'a> BindUniform<Option<()>, &'a [f32; 4]>,
|
||||||
|
H: for<'a> BindUniform<Option<()>, &'a [f32; 16]>,
|
||||||
|
{
|
||||||
|
fn offset(&self) -> MemberOffset {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn context(&self) -> Option<()> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait that abstracts binding of semantics to shader uniforms.
|
||||||
|
pub trait BindSemantics<H=NoUniformBinder, C=Option<()>>
|
||||||
|
where
|
||||||
|
H: BindUniform<C, f32>,
|
||||||
|
H: BindUniform<C, u32>,
|
||||||
|
H: BindUniform<C, i32>,
|
||||||
|
H: for<'b> BindUniform<C, &'b [f32; 4]>,
|
||||||
|
H: for<'b> BindUniform<C, &'b [f32; 16]>
|
||||||
|
{
|
||||||
|
/// The type of the input texture used for semantic binding.
|
||||||
|
type InputTexture: TextureInput;
|
||||||
|
|
||||||
|
/// The set of texture samplers available.
|
||||||
|
type SamplerSet;
|
||||||
|
|
||||||
|
/// The descriptor set or object that holds sampler and texture bindings.
|
||||||
|
type DescriptorSet<'a>;
|
||||||
|
|
||||||
|
/// The device context containing the state of the graphics processor.
|
||||||
|
type DeviceContext;
|
||||||
|
|
||||||
|
/// The type of uniform offsets to use.
|
||||||
|
type UniformOffset: ContextOffset<H, C>;
|
||||||
|
|
||||||
|
|
||||||
|
/// Bind a texture to the input descriptor set
|
||||||
|
fn bind_texture<'a>(
|
||||||
|
descriptors: &mut Self::DescriptorSet<'a>,
|
||||||
|
samplers: &Self::SamplerSet,
|
||||||
|
binding: &TextureBinding,
|
||||||
|
texture: &Self::InputTexture,
|
||||||
|
device: &Self::DeviceContext
|
||||||
|
);
|
||||||
|
|
||||||
|
#[clippy::allow(too_many_arguments)]
|
||||||
|
/// Write uniform and texture semantics to the provided storages.
|
||||||
|
fn bind_semantics<'a>(
|
||||||
|
device: &Self::DeviceContext,
|
||||||
|
sampler_set: &Self::SamplerSet,
|
||||||
|
uniform_storage: &mut UniformStorage<H, C>,
|
||||||
|
descriptor_set: &mut Self::DescriptorSet<'a>,
|
||||||
|
mvp: &[f32; 16],
|
||||||
|
frame_count: u32,
|
||||||
|
frame_direction: i32,
|
||||||
|
framebuffer_size: Size<u32>,
|
||||||
|
viewport_size: Size<u32>,
|
||||||
|
original: &Self::InputTexture,
|
||||||
|
source: &Self::InputTexture,
|
||||||
|
uniform_bindings: &HashMap<UniformBinding, Self::UniformOffset, impl BuildHasher>,
|
||||||
|
texture_meta: &HashMap<Semantic<TextureSemantics>, TextureBinding, impl BuildHasher>,
|
||||||
|
pass_outputs: impl Iterator<Item = Option<impl AsRef<Self::InputTexture>>>,
|
||||||
|
pass_feedback: impl Iterator<Item = Option<impl AsRef<Self::InputTexture>>>,
|
||||||
|
original_history: impl Iterator<Item = Option<impl AsRef<Self::InputTexture>>>,
|
||||||
|
lookup_textures: impl Iterator<Item = (usize, impl AsRef<Self::InputTexture>)>,
|
||||||
|
parameter_defaults: &[ShaderParameter],
|
||||||
|
runtime_parameters: &HashMap<String, f32, impl BuildHasher>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Bind MVP
|
||||||
|
if let Some(offset) = uniform_bindings.get(&UniqueSemantics::MVP.into()) {
|
||||||
|
uniform_storage.bind_mat4(offset.offset(), mvp, offset.context());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind OutputSize
|
||||||
|
if let Some(offset) = uniform_bindings.get(&UniqueSemantics::Output.into()) {
|
||||||
|
uniform_storage.bind_vec4(offset.offset(), framebuffer_size, offset.context());
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind FinalViewportSize
|
||||||
|
if let Some(offset) = uniform_bindings
|
||||||
|
.get(&UniqueSemantics::FinalViewport.into())
|
||||||
|
{
|
||||||
|
uniform_storage.bind_vec4(offset.offset(), viewport_size, offset.context());
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind FrameCount
|
||||||
|
if let Some(offset) = uniform_bindings
|
||||||
|
.get(&UniqueSemantics::FrameCount.into())
|
||||||
|
{
|
||||||
|
uniform_storage.bind_scalar(offset.offset(), frame_count, offset.context());
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind FrameDirection
|
||||||
|
if let Some(offset) = uniform_bindings
|
||||||
|
.get(&UniqueSemantics::FrameDirection.into())
|
||||||
|
{
|
||||||
|
uniform_storage
|
||||||
|
.bind_scalar(offset.offset(), frame_direction, offset.context());
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind Original sampler
|
||||||
|
if let Some(binding) = texture_meta
|
||||||
|
.get(&TextureSemantics::Original.semantics(0))
|
||||||
|
{
|
||||||
|
Self::bind_texture(
|
||||||
|
descriptor_set,
|
||||||
|
sampler_set,
|
||||||
|
binding,
|
||||||
|
original,
|
||||||
|
device
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind OriginalSize
|
||||||
|
if let Some(offset) = uniform_bindings
|
||||||
|
.get(&TextureSemantics::Original.semantics(0).into())
|
||||||
|
{
|
||||||
|
uniform_storage
|
||||||
|
.bind_vec4(offset.offset(), original.size(), offset.context());
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind Source sampler
|
||||||
|
if let Some(binding) = texture_meta
|
||||||
|
.get(&TextureSemantics::Source.semantics(0))
|
||||||
|
{
|
||||||
|
Self::bind_texture(
|
||||||
|
descriptor_set,
|
||||||
|
sampler_set,
|
||||||
|
binding,
|
||||||
|
source,
|
||||||
|
device
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind SourcelSize
|
||||||
|
if let Some(offset) = uniform_bindings
|
||||||
|
.get(&TextureSemantics::Source.semantics(0).into())
|
||||||
|
{
|
||||||
|
uniform_storage
|
||||||
|
.bind_vec4(offset.offset(), source.size(), offset.context());
|
||||||
|
}
|
||||||
|
|
||||||
|
// OriginalHistory0 aliases OriginalHistory
|
||||||
|
|
||||||
|
// bind OriginalHistory0 sampler
|
||||||
|
if let Some(binding) = texture_meta
|
||||||
|
.get(&TextureSemantics::OriginalHistory.semantics(0))
|
||||||
|
{
|
||||||
|
Self::bind_texture(
|
||||||
|
descriptor_set,
|
||||||
|
sampler_set,
|
||||||
|
binding,
|
||||||
|
original,
|
||||||
|
device
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind OriginalHistory0Size
|
||||||
|
if let Some(offset) = uniform_bindings
|
||||||
|
.get(&TextureSemantics::OriginalHistory.semantics(0).into())
|
||||||
|
{
|
||||||
|
uniform_storage
|
||||||
|
.bind_vec4(offset.offset(), original.size(), offset.context());
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind OriginalHistory1-..
|
||||||
|
for (index, history) in original_history.enumerate() {
|
||||||
|
let Some(history) = history else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let history = history.as_ref();
|
||||||
|
|
||||||
|
if let Some(binding) = texture_meta
|
||||||
|
.get(&TextureSemantics::OriginalHistory.semantics(index + 1))
|
||||||
|
{
|
||||||
|
Self::bind_texture(
|
||||||
|
descriptor_set,
|
||||||
|
sampler_set,
|
||||||
|
binding,
|
||||||
|
history,
|
||||||
|
device
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(offset) = uniform_bindings.get(
|
||||||
|
&TextureSemantics::OriginalHistory
|
||||||
|
.semantics(index + 1)
|
||||||
|
.into(),
|
||||||
|
) {
|
||||||
|
uniform_storage
|
||||||
|
.bind_vec4(offset.offset(), history.size(), offset.context());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind PassOutput0..
|
||||||
|
// The caller should be responsible for limiting this up to
|
||||||
|
// pass_index
|
||||||
|
for (index, output) in pass_outputs.enumerate() {
|
||||||
|
let Some(output) = output else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let output = output.as_ref();
|
||||||
|
|
||||||
|
if let Some(binding) = texture_meta
|
||||||
|
.get(&TextureSemantics::PassOutput.semantics(index))
|
||||||
|
{
|
||||||
|
Self::bind_texture(
|
||||||
|
descriptor_set,
|
||||||
|
sampler_set,
|
||||||
|
binding,
|
||||||
|
output,
|
||||||
|
device
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(offset) = uniform_bindings.get(
|
||||||
|
&TextureSemantics::PassOutput
|
||||||
|
.semantics(index)
|
||||||
|
.into(),
|
||||||
|
) {
|
||||||
|
uniform_storage
|
||||||
|
.bind_vec4(offset.offset(), output.size(), offset.context());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind PassFeedback0..
|
||||||
|
for (index, feedback) in pass_feedback.enumerate() {
|
||||||
|
let Some(output) = feedback else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let feedback = output.as_ref();
|
||||||
|
|
||||||
|
if let Some(binding) = texture_meta
|
||||||
|
.get(&TextureSemantics::PassFeedback.semantics(index))
|
||||||
|
{
|
||||||
|
Self::bind_texture(
|
||||||
|
descriptor_set,
|
||||||
|
sampler_set,
|
||||||
|
binding,
|
||||||
|
feedback,
|
||||||
|
device
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(offset) = uniform_bindings.get(
|
||||||
|
&TextureSemantics::PassFeedback
|
||||||
|
.semantics(index)
|
||||||
|
.into(),
|
||||||
|
) {
|
||||||
|
uniform_storage
|
||||||
|
.bind_vec4(offset.offset(), feedback.size(), offset.context());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind User parameters
|
||||||
|
for (id, offset) in
|
||||||
|
uniform_bindings
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(binding, value)| match binding {
|
||||||
|
UniformBinding::Parameter(id) => Some((id, value)),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
{
|
||||||
|
let id = id.as_str();
|
||||||
|
|
||||||
|
let default = parameter_defaults.iter()
|
||||||
|
.find(|&p| p.id == id)
|
||||||
|
.map(|f| f.initial)
|
||||||
|
.unwrap_or(0f32);
|
||||||
|
|
||||||
|
let value = *runtime_parameters.get(id).unwrap_or(&default);
|
||||||
|
|
||||||
|
uniform_storage.bind_scalar(offset.offset(), value, offset.context());
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind luts
|
||||||
|
for (index, lut) in lookup_textures {
|
||||||
|
let lut = lut.as_ref();
|
||||||
|
if let Some(binding) = texture_meta
|
||||||
|
.get(&TextureSemantics::User.semantics(index))
|
||||||
|
{
|
||||||
|
Self::bind_texture(
|
||||||
|
descriptor_set,
|
||||||
|
sampler_set,
|
||||||
|
binding,
|
||||||
|
lut,
|
||||||
|
device
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(offset) = uniform_bindings
|
||||||
|
.get(&TextureSemantics::User.semantics(index).into())
|
||||||
|
{
|
||||||
|
uniform_storage
|
||||||
|
.bind_vec4(offset.offset(), lut.size(), offset.context());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,3 +18,6 @@ pub mod image;
|
||||||
|
|
||||||
/// Ringbuffer helpers
|
/// Ringbuffer helpers
|
||||||
pub mod ringbuffer;
|
pub mod ringbuffer;
|
||||||
|
|
||||||
|
/// Generic implementation of semantics binding.
|
||||||
|
pub mod binding;
|
||||||
|
|
Loading…
Add table
Reference in a new issue