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)
|
||||
#include <d3d11.h>
|
||||
#else
|
||||
typedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D11ShaderResourceView;
|
||||
typedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D1ShaderResourceView;
|
||||
#endif
|
||||
#if defined(LIBRA_RUNTIME_VULKAN)
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan\vulkan.h>
|
||||
#endif
|
||||
|
||||
/// Error codes for librashader error types.
|
||||
|
@ -102,15 +102,15 @@ typedef struct libra_preset_param_t {
|
|||
} libra_preset_param_t;
|
||||
|
||||
/// A list of preset parameters.
|
||||
typedef struct libra_preset_param_list_t {
|
||||
typedef struct libra_preset_parameter_list_t {
|
||||
/// A pointer to the parameter
|
||||
const struct libra_preset_param_t *parameters;
|
||||
/// The number of parameters in the list.
|
||||
/// The number of parameters in the list
|
||||
uint64_t length;
|
||||
/// For internal use only.
|
||||
/// Changing this causes immediate undefined behaviour on freeing this parameter list.
|
||||
uint64_t _internal_alloc;
|
||||
} libra_preset_param_list_t;
|
||||
} libra_preset_parameter_list_t;
|
||||
|
||||
#if defined(LIBRA_RUNTIME_OPENGL)
|
||||
/// 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);
|
||||
|
||||
/// Function pointer definition for
|
||||
///libra_preset_get_runtime_params
|
||||
typedef libra_error_t (*PFN_libra_preset_get_runtime_params)(libra_shader_preset_t *preset,
|
||||
struct libra_preset_param_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);
|
||||
///libra_preset_get_runtime_parameters
|
||||
typedef libra_error_t (*PFN_libra_preset_get_runtime_parameters)(libra_shader_preset_t *preset,
|
||||
struct libra_preset_parameter_list_t *out);
|
||||
|
||||
/// Function pointer definition for libra_error_errno
|
||||
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
|
||||
/// - `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`.
|
||||
/// - The output struct should be treated as immutable. Mutating any struct fields
|
||||
/// in the returned struct may at best cause memory leaks, and at worse
|
||||
/// 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);
|
||||
libra_error_t libra_preset_get_runtime_parameters(libra_shader_preset_t *preset,
|
||||
struct libra_preset_parameter_list_t *out);
|
||||
|
||||
#if defined(LIBRA_RUNTIME_OPENGL)
|
||||
/// Initialize the OpenGL Context for librashader.
|
||||
|
|
|
@ -56,8 +56,11 @@ impl From<libra_source_image_gl_t> for GLImage {
|
|||
extern_fn! {
|
||||
/// 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
|
||||
/// 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
|
||||
/// chain objects, and drawing with them causes immediate undefined behaviour.
|
||||
|
|
|
@ -15,6 +15,7 @@ use windows::Win32::Graphics::Direct3D11::{
|
|||
ID3D11Buffer, ID3D11InputLayout, ID3D11PixelShader, ID3D11SamplerState,
|
||||
ID3D11ShaderResourceView, ID3D11VertexShader, D3D11_MAP_WRITE_DISCARD,
|
||||
};
|
||||
use librashader_runtime::binding::{BindSemantics, TextureInput};
|
||||
|
||||
use crate::{D3D11OutputView, error};
|
||||
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,
|
||||
];
|
||||
|
||||
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
|
||||
impl FilterPass {
|
||||
pub fn get_format(&self) -> ImageFormat {
|
||||
|
@ -76,7 +101,7 @@ impl FilterPass {
|
|||
}
|
||||
|
||||
// framecount should be pre-modded
|
||||
fn build_semantics(
|
||||
fn build_semantics<'a>(
|
||||
&mut self,
|
||||
pass_index: usize,
|
||||
parent: &FilterCommon,
|
||||
|
@ -85,266 +110,37 @@ impl FilterPass {
|
|||
frame_direction: i32,
|
||||
fb_size: Size<u32>,
|
||||
viewport_size: Size<u32>,
|
||||
mut descriptors: (&'a mut [Option<ID3D11ShaderResourceView>; 16], &'a mut [Option<ID3D11SamplerState>; 16]),
|
||||
original: &InputTexture,
|
||||
source: &InputTexture,
|
||||
) -> (
|
||||
[Option<ID3D11ShaderResourceView>; 16],
|
||||
[Option<ID3D11SamplerState>; 16],
|
||||
) {
|
||||
let mut textures: [Option<ID3D11ShaderResourceView>; 16] = std::array::from_fn(|_| None);
|
||||
let mut samplers: [Option<ID3D11SamplerState>; 16] = std::array::from_fn(|_| None);
|
||||
|
||||
// Bind MVP
|
||||
if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::MVP.into()) {
|
||||
self.uniform_storage.bind_mat4(*offset, mvp, None);
|
||||
}
|
||||
|
||||
// bind OutputSize
|
||||
if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::Output.into()) {
|
||||
self.uniform_storage.bind_vec4(*offset, fb_size, None);
|
||||
}
|
||||
|
||||
// bind FinalViewportSize
|
||||
if let Some(offset) = self
|
||||
.uniform_bindings
|
||||
.get(&UniqueSemantics::FinalViewport.into())
|
||||
{
|
||||
self.uniform_storage.bind_vec4(*offset, viewport_size, None);
|
||||
}
|
||||
|
||||
// bind FrameCount
|
||||
if let Some(offset) = self
|
||||
.uniform_bindings
|
||||
.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(
|
||||
Self::bind_semantics(
|
||||
&(),
|
||||
&parent.samplers,
|
||||
&mut textures,
|
||||
&mut samplers,
|
||||
binding,
|
||||
&mut self.uniform_storage,
|
||||
&mut descriptors,
|
||||
mvp,
|
||||
frame_count,
|
||||
frame_direction,
|
||||
fb_size,
|
||||
viewport_size,
|
||||
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,
|
||||
&self.uniform_bindings,
|
||||
&self.reflection.meta.texture_meta,
|
||||
parent.output_textures[0..pass_index].iter()
|
||||
.map(|o| o.as_ref()),
|
||||
parent.feedback_textures.iter()
|
||||
.map(|o| o.as_ref()),
|
||||
parent.history_textures.iter()
|
||||
.map(|o| o.as_ref()),
|
||||
parent.luts.iter()
|
||||
.map(|(u, i)| (*u, i.as_ref())),
|
||||
&self.source.parameters,
|
||||
&parent.config.parameters
|
||||
);
|
||||
}
|
||||
|
||||
// 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(
|
||||
&mut self,
|
||||
pass_index: usize,
|
||||
|
@ -370,7 +166,11 @@ impl FilterPass {
|
|||
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,
|
||||
parent,
|
||||
output.mvp,
|
||||
|
@ -378,6 +178,7 @@ impl FilterPass {
|
|||
frame_direction,
|
||||
output.output.size,
|
||||
viewport.output.size,
|
||||
descriptors,
|
||||
original,
|
||||
source,
|
||||
);
|
||||
|
|
|
@ -37,14 +37,14 @@ pub struct D3D11OutputView {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct InputTexture {
|
||||
pub struct InputTexture {
|
||||
pub view: D3D11InputView,
|
||||
pub filter: FilterMode,
|
||||
pub wrap_mode: WrapMode,
|
||||
}
|
||||
|
||||
impl InputTexture {
|
||||
pub fn from_framebuffer(
|
||||
pub(crate) fn from_framebuffer(
|
||||
fbo: &OwnedFramebuffer,
|
||||
wrap_mode: WrapMode,
|
||||
filter: FilterMode,
|
||||
|
@ -60,6 +60,12 @@ impl InputTexture {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsRef<InputTexture> for InputTexture {
|
||||
fn as_ref(&self) -> &InputTexture {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct LutTexture {
|
||||
// The handle to the Texture2D must be kept alive.
|
||||
|
@ -70,6 +76,12 @@ pub(crate) struct LutTexture {
|
|||
pub image: InputTexture,
|
||||
}
|
||||
|
||||
impl AsRef<InputTexture> for LutTexture {
|
||||
fn as_ref(&self) -> &InputTexture {
|
||||
&self.image
|
||||
}
|
||||
}
|
||||
|
||||
impl LutTexture {
|
||||
pub fn new(
|
||||
device: &ID3D11Device,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::binding::{GlUniformStorage, UniformLocation, VariableLocation};
|
||||
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::options::{FilterChainOptionsGL, FrameOptionsGL};
|
||||
use crate::render_target::RenderTarget;
|
||||
use crate::samplers::SamplerSet;
|
||||
use crate::texture::Texture;
|
||||
use crate::texture::InputTexture;
|
||||
use crate::util::{gl_get_version, gl_u16_to_version};
|
||||
use crate::{error, util, GLImage};
|
||||
use gl::types::{GLint, GLuint};
|
||||
|
@ -37,11 +37,11 @@ pub(crate) struct FilterChainImpl<T: GLInterface> {
|
|||
pub(crate) struct FilterCommon {
|
||||
// semantics: ReflectSemantics,
|
||||
pub config: FilterMutable,
|
||||
pub luts: FxHashMap<usize, Texture>,
|
||||
pub luts: FxHashMap<usize, InputTexture>,
|
||||
pub samplers: SamplerSet,
|
||||
pub output_textures: Box<[Texture]>,
|
||||
pub feedback_textures: Box<[Texture]>,
|
||||
pub history_textures: Box<[Texture]>,
|
||||
pub output_textures: Box<[InputTexture]>,
|
||||
pub feedback_textures: Box<[InputTexture]>,
|
||||
pub history_textures: Box<[InputTexture]>,
|
||||
pub disable_mipmaps: bool,
|
||||
}
|
||||
|
||||
|
@ -114,13 +114,13 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
|||
let mut output_framebuffers = Vec::new();
|
||||
output_framebuffers.resize_with(filters.len(), || T::FramebufferInterface::new(1));
|
||||
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
|
||||
let mut feedback_framebuffers = Vec::new();
|
||||
feedback_framebuffers.resize_with(filters.len(), || T::FramebufferInterface::new(1));
|
||||
let mut feedback_textures = Vec::new();
|
||||
feedback_textures.resize_with(filters.len(), Texture::default);
|
||||
feedback_textures.resize_with(filters.len(), InputTexture::default);
|
||||
|
||||
// load luts
|
||||
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() {
|
||||
uniform_bindings.insert(
|
||||
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 {
|
||||
uniform_bindings.insert(
|
||||
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 {
|
||||
uniform_bindings.insert(
|
||||
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>],
|
||||
filter: FilterMode,
|
||||
wrap_mode: WrapMode,
|
||||
) -> (VecDeque<Framebuffer>, Box<[Texture]>) {
|
||||
) -> (VecDeque<Framebuffer>, Box<[InputTexture]>) {
|
||||
let mut required_images = 0;
|
||||
|
||||
for pass in filters {
|
||||
|
@ -388,7 +388,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
|||
framebuffers.resize_with(required_images, || T::FramebufferInterface::new(1));
|
||||
|
||||
let mut history_textures = Vec::new();
|
||||
history_textures.resize_with(required_images, || Texture {
|
||||
history_textures.resize_with(required_images, || InputTexture {
|
||||
image: Default::default(),
|
||||
filter,
|
||||
mip_filter: filter,
|
||||
|
@ -470,7 +470,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
|||
}
|
||||
|
||||
// shader_gl3: 2067
|
||||
let original = Texture {
|
||||
let original = InputTexture {
|
||||
image: *input,
|
||||
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::ShaderCompilerOutput;
|
||||
use librashader_reflect::reflect::ShaderReflection;
|
||||
|
@ -6,18 +6,32 @@ use librashader_reflect::reflect::ShaderReflection;
|
|||
use librashader_common::{ImageFormat, Size, Viewport};
|
||||
use librashader_preprocess::ShaderSource;
|
||||
use librashader_presets::ShaderPassConfig;
|
||||
use librashader_reflect::reflect::semantics::{
|
||||
MemberOffset, TextureSemantics, UniformBinding, UniqueSemantics,
|
||||
};
|
||||
use librashader_reflect::reflect::semantics::{MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniqueSemantics};
|
||||
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::Framebuffer;
|
||||
use crate::gl::{BindTexture, GLInterface, UboRing};
|
||||
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 reflection: ShaderReflection,
|
||||
|
@ -26,11 +40,42 @@ pub struct FilterPass<T: GLInterface> {
|
|||
pub ubo_location: UniformLocation<GLuint>,
|
||||
pub ubo_ring: Option<T::UboRing>,
|
||||
pub(crate) uniform_storage: GlUniformStorage,
|
||||
pub uniform_bindings: FxHashMap<UniformBinding, (VariableLocation, MemberOffset)>,
|
||||
pub uniform_bindings: FxHashMap<UniformBinding, UniformOffset>,
|
||||
pub source: ShaderSource,
|
||||
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> {
|
||||
pub(crate) fn draw(
|
||||
&mut self,
|
||||
|
@ -39,8 +84,8 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
frame_count: u32,
|
||||
frame_direction: i32,
|
||||
viewport: &Viewport<&Framebuffer>,
|
||||
original: &Texture,
|
||||
source: &Texture,
|
||||
original: &InputTexture,
|
||||
source: &InputTexture,
|
||||
output: RenderTarget,
|
||||
) {
|
||||
let framebuffer = output.framebuffer;
|
||||
|
@ -124,216 +169,33 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
frame_direction: i32,
|
||||
fb_size: Size<u32>,
|
||||
viewport: &Viewport<&Framebuffer>,
|
||||
original: &Texture,
|
||||
source: &Texture,
|
||||
original: &InputTexture,
|
||||
source: &InputTexture,
|
||||
) {
|
||||
// Bind MVP
|
||||
if let Some((location, offset)) = self.uniform_bindings.get(&UniqueSemantics::MVP.into()) {
|
||||
self.uniform_storage
|
||||
.bind_mat4(*offset, mvp, location.location());
|
||||
}
|
||||
|
||||
// bind OutputSize
|
||||
if let Some((location, offset)) = self.uniform_bindings.get(&UniqueSemantics::Output.into())
|
||||
{
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset, fb_size, location.location());
|
||||
}
|
||||
|
||||
// bind FinalViewportSize
|
||||
if let Some((location, offset)) = self
|
||||
.uniform_bindings
|
||||
.get(&UniqueSemantics::FinalViewport.into())
|
||||
{
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset, viewport.output.size, location.location());
|
||||
}
|
||||
|
||||
// bind FrameCount
|
||||
if let Some((location, offset)) = self
|
||||
.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());
|
||||
}
|
||||
}
|
||||
Self::bind_semantics(
|
||||
&(),
|
||||
&parent.samplers,
|
||||
&mut self.uniform_storage,
|
||||
&mut (),
|
||||
mvp,
|
||||
frame_count,
|
||||
frame_direction,
|
||||
fb_size,
|
||||
viewport.output.size,
|
||||
original,
|
||||
source,
|
||||
&self.uniform_bindings,
|
||||
&self.reflection.meta.texture_meta,
|
||||
parent.output_textures[0..pass_index].iter()
|
||||
.map(|o| o.bound()),
|
||||
parent.feedback_textures.iter()
|
||||
.map(|o| o.bound()),
|
||||
parent.history_textures.iter()
|
||||
.map(|o| o.bound()),
|
||||
parent.luts.iter()
|
||||
.map(|(u, i)| (*u, i)),
|
||||
&self.source.parameters,
|
||||
&parent.config.parameters
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::error::Result;
|
||||
use crate::framebuffer::GLImage;
|
||||
use crate::gl::FramebufferInterface;
|
||||
use crate::texture::Texture;
|
||||
use crate::texture::InputTexture;
|
||||
use gl::types::{GLenum, GLuint};
|
||||
use librashader_common::{FilterMode, ImageFormat, Size, Viewport, WrapMode};
|
||||
use librashader_presets::Scale2D;
|
||||
|
@ -52,8 +52,8 @@ impl Framebuffer {
|
|||
scaling: Scale2D,
|
||||
format: ImageFormat,
|
||||
viewport: &Viewport<&Framebuffer>,
|
||||
original: &Texture,
|
||||
source: &Texture,
|
||||
original: &InputTexture,
|
||||
source: &InputTexture,
|
||||
mipmap: bool,
|
||||
) -> Result<Size<u32>> {
|
||||
T::scale(self, scaling, format, viewport, original, source, mipmap)
|
||||
|
@ -63,8 +63,8 @@ impl Framebuffer {
|
|||
T::copy_from(self, image)
|
||||
}
|
||||
|
||||
pub(crate) fn as_texture(&self, filter: FilterMode, wrap_mode: WrapMode) -> Texture {
|
||||
Texture {
|
||||
pub(crate) fn as_texture(&self, filter: FilterMode, wrap_mode: WrapMode) -> InputTexture {
|
||||
InputTexture {
|
||||
image: GLImage {
|
||||
handle: self.image,
|
||||
format: self.format,
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::error::{FilterChainError, Result};
|
|||
use crate::framebuffer::GLImage;
|
||||
use crate::gl::framebuffer::Framebuffer;
|
||||
use crate::gl::FramebufferInterface;
|
||||
use crate::texture::Texture;
|
||||
use crate::texture::InputTexture;
|
||||
use gl::types::{GLenum, GLint, GLsizei};
|
||||
use librashader_common::{ImageFormat, Size, Viewport};
|
||||
use librashader_presets::Scale2D;
|
||||
|
@ -39,8 +39,8 @@ impl FramebufferInterface for Gl3Framebuffer {
|
|||
scaling: Scale2D,
|
||||
format: ImageFormat,
|
||||
viewport: &Viewport<&Framebuffer>,
|
||||
_original: &Texture,
|
||||
source: &Texture,
|
||||
_original: &InputTexture,
|
||||
source: &InputTexture,
|
||||
mipmap: bool,
|
||||
) -> Result<Size<u32>> {
|
||||
if fb.is_raw {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::error::Result;
|
||||
use crate::framebuffer::GLImage;
|
||||
use crate::gl::LoadLut;
|
||||
use crate::texture::Texture;
|
||||
use crate::texture::InputTexture;
|
||||
use gl::types::{GLsizei, GLuint};
|
||||
use librashader_common::Size;
|
||||
use librashader_presets::TextureConfig;
|
||||
|
@ -11,7 +11,7 @@ use rustc_hash::FxHashMap;
|
|||
|
||||
pub struct 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 pixel_unpack = unsafe {
|
||||
let mut binding = 0;
|
||||
|
@ -64,7 +64,7 @@ impl LoadLut for Gl3LutLoad {
|
|||
|
||||
luts.insert(
|
||||
index,
|
||||
Texture {
|
||||
InputTexture {
|
||||
image: GLImage {
|
||||
handle,
|
||||
format: gl::RGBA8,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::gl::BindTexture;
|
||||
use crate::samplers::SamplerSet;
|
||||
use crate::texture::Texture;
|
||||
use crate::texture::InputTexture;
|
||||
use librashader_reflect::reflect::semantics::TextureBinding;
|
||||
|
||||
pub struct Gl3BindTexture;
|
||||
|
||||
impl BindTexture for Gl3BindTexture {
|
||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture) {
|
||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &InputTexture) {
|
||||
unsafe {
|
||||
// eprintln!("setting {} to texunit {}", texture.image.handle, 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 {
|
||||
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
|
||||
gl::GenerateMipmap(gl::TEXTURE_2D);
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::error::{FilterChainError, Result};
|
|||
use crate::framebuffer::GLImage;
|
||||
use crate::gl::framebuffer::Framebuffer;
|
||||
use crate::gl::FramebufferInterface;
|
||||
use crate::texture::Texture;
|
||||
use crate::texture::InputTexture;
|
||||
use gl::types::{GLenum, GLint, GLsizei};
|
||||
use librashader_common::{ImageFormat, Size, Viewport};
|
||||
use librashader_presets::Scale2D;
|
||||
|
@ -37,8 +37,8 @@ impl FramebufferInterface for Gl46Framebuffer {
|
|||
scaling: Scale2D,
|
||||
format: ImageFormat,
|
||||
viewport: &Viewport<&Framebuffer>,
|
||||
_original: &Texture,
|
||||
source: &Texture,
|
||||
_original: &InputTexture,
|
||||
source: &InputTexture,
|
||||
mipmap: bool,
|
||||
) -> Result<Size<u32>> {
|
||||
if fb.is_raw {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::error::Result;
|
||||
use crate::framebuffer::GLImage;
|
||||
use crate::gl::LoadLut;
|
||||
use crate::texture::Texture;
|
||||
use crate::texture::InputTexture;
|
||||
use gl::types::{GLsizei, GLuint};
|
||||
use librashader_common::Size;
|
||||
use librashader_presets::TextureConfig;
|
||||
|
@ -11,7 +11,7 @@ use rustc_hash::FxHashMap;
|
|||
|
||||
pub struct 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 pixel_unpack = unsafe {
|
||||
let mut binding = 0;
|
||||
|
@ -66,7 +66,7 @@ impl LoadLut for Gl46LutLoad {
|
|||
|
||||
luts.insert(
|
||||
index,
|
||||
Texture {
|
||||
InputTexture {
|
||||
image: GLImage {
|
||||
handle,
|
||||
format: gl::RGBA8,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::gl::BindTexture;
|
||||
use crate::samplers::SamplerSet;
|
||||
use crate::texture::Texture;
|
||||
use crate::texture::InputTexture;
|
||||
use librashader_reflect::reflect::semantics::TextureBinding;
|
||||
|
||||
pub struct Gl46BindTexture;
|
||||
|
||||
impl BindTexture for Gl46BindTexture {
|
||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture) {
|
||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &InputTexture) {
|
||||
unsafe {
|
||||
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
||||
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) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::binding::UniformLocation;
|
|||
use crate::error::Result;
|
||||
use crate::framebuffer::GLImage;
|
||||
use crate::samplers::SamplerSet;
|
||||
use crate::texture::Texture;
|
||||
use crate::texture::InputTexture;
|
||||
pub use framebuffer::Framebuffer;
|
||||
use gl::types::{GLenum, GLuint};
|
||||
use librashader_common::{ImageFormat, Size, Viewport};
|
||||
|
@ -16,7 +16,7 @@ use librashader_runtime::uniforms::UniformStorageAccess;
|
|||
use rustc_hash::FxHashMap;
|
||||
|
||||
pub trait LoadLut {
|
||||
fn load_luts(textures: &[TextureConfig]) -> Result<FxHashMap<usize, Texture>>;
|
||||
fn load_luts(textures: &[TextureConfig]) -> Result<FxHashMap<usize, InputTexture>>;
|
||||
}
|
||||
|
||||
pub trait DrawQuad {
|
||||
|
@ -42,8 +42,8 @@ pub trait FramebufferInterface {
|
|||
scaling: Scale2D,
|
||||
format: ImageFormat,
|
||||
viewport: &Viewport<&Framebuffer>,
|
||||
_original: &Texture,
|
||||
source: &Texture,
|
||||
_original: &InputTexture,
|
||||
source: &InputTexture,
|
||||
mipmap: bool,
|
||||
) -> Result<Size<u32>>;
|
||||
fn clear<const REBIND: bool>(fb: &Framebuffer);
|
||||
|
@ -52,8 +52,8 @@ pub trait FramebufferInterface {
|
|||
}
|
||||
|
||||
pub trait BindTexture {
|
||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture);
|
||||
fn gen_mipmaps(texture: &Texture);
|
||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &InputTexture);
|
||||
fn gen_mipmaps(texture: &InputTexture);
|
||||
}
|
||||
|
||||
pub trait GLInterface {
|
||||
|
|
|
@ -1,16 +1,32 @@
|
|||
use gl::types::GLuint;
|
||||
use crate::framebuffer::GLImage;
|
||||
use librashader_common::{FilterMode, WrapMode};
|
||||
|
||||
#[derive(Default, Debug, Copy, Clone)]
|
||||
pub struct Texture {
|
||||
pub struct InputTexture {
|
||||
pub image: GLImage,
|
||||
pub filter: FilterMode,
|
||||
pub mip_filter: FilterMode,
|
||||
pub wrap_mode: WrapMode,
|
||||
}
|
||||
|
||||
impl Texture {
|
||||
impl InputTexture {
|
||||
pub fn is_bound(&self) -> bool {
|
||||
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,
|
||||
};
|
||||
use librashader_reflect::reflect::ShaderReflection;
|
||||
use librashader_runtime::uniforms::{UniformStorage, UniformStorageAccess};
|
||||
use librashader_runtime::uniforms::{BindUniform, NoUniformBinder, UniformStorage, UniformStorageAccess};
|
||||
use rustc_hash::FxHashMap;
|
||||
use librashader_runtime::binding::{BindSemantics, TextureInput};
|
||||
|
||||
pub struct FilterPass {
|
||||
pub device: Arc<ash::Device>,
|
||||
|
@ -30,6 +31,42 @@ pub struct FilterPass {
|
|||
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 {
|
||||
#[inline(always)]
|
||||
fn bind_texture(
|
||||
|
@ -81,7 +118,7 @@ impl FilterPass {
|
|||
source: &InputImage,
|
||||
output: &RenderTarget,
|
||||
) -> 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];
|
||||
|
||||
self.build_semantics(
|
||||
|
@ -92,7 +129,7 @@ impl FilterPass {
|
|||
frame_direction,
|
||||
output.output.size,
|
||||
viewport.output.size,
|
||||
&descriptor,
|
||||
&mut descriptor,
|
||||
original,
|
||||
source,
|
||||
);
|
||||
|
@ -182,262 +219,41 @@ impl FilterPass {
|
|||
|
||||
fn build_semantics(
|
||||
&mut self,
|
||||
_pass_index: usize,
|
||||
pass_index: usize,
|
||||
parent: &FilterCommon,
|
||||
mvp: &[f32; 16],
|
||||
frame_count: u32,
|
||||
frame_direction: i32,
|
||||
fb_size: Size<u32>,
|
||||
viewport_size: Size<u32>,
|
||||
descriptor_set: &vk::DescriptorSet,
|
||||
mut descriptor_set: &mut vk::DescriptorSet,
|
||||
original: &InputImage,
|
||||
source: &InputImage,
|
||||
) {
|
||||
if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::MVP.into()) {
|
||||
self.uniform_storage.bind_mat4(*offset, mvp, None);
|
||||
}
|
||||
|
||||
// bind OutputSize
|
||||
if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::Output.into()) {
|
||||
self.uniform_storage.bind_vec4(*offset, fb_size, None);
|
||||
}
|
||||
|
||||
// bind FinalViewportSize
|
||||
if let Some(offset) = self
|
||||
.uniform_bindings
|
||||
.get(&UniqueSemantics::FinalViewport.into())
|
||||
{
|
||||
self.uniform_storage.bind_vec4(*offset, viewport_size, None);
|
||||
}
|
||||
|
||||
// bind FrameCount
|
||||
if let Some(offset) = self
|
||||
.uniform_bindings
|
||||
.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(
|
||||
Self::bind_semantics(
|
||||
&self.device,
|
||||
&parent.samplers,
|
||||
*descriptor_set,
|
||||
binding,
|
||||
&mut self.uniform_storage,
|
||||
&mut descriptor_set,
|
||||
mvp,
|
||||
frame_count,
|
||||
frame_direction,
|
||||
fb_size,
|
||||
viewport_size,
|
||||
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,
|
||||
&self.uniform_bindings,
|
||||
&self.reflection.meta.texture_meta,
|
||||
parent.output_inputs[0..pass_index].iter()
|
||||
.map(|o| o.as_ref()),
|
||||
parent.feedback_inputs.iter()
|
||||
.map(|o| o.as_ref()),
|
||||
parent.history_textures.iter()
|
||||
.map(|o| o.as_ref()),
|
||||
parent.luts.iter()
|
||||
.map(|(u, i)| (*u, i.as_ref())),
|
||||
&self.source.parameters,
|
||||
&parent.config.parameters
|
||||
);
|
||||
}
|
||||
|
||||
// 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)]
|
||||
pub(crate) struct InputImage {
|
||||
pub struct InputImage {
|
||||
/// A handle to the `VkImage`.
|
||||
pub image: VulkanImage,
|
||||
/// A handle to the `VkImageView` for the image.
|
||||
|
@ -527,3 +527,9 @@ pub(crate) struct InputImage {
|
|||
pub filter_mode: 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
|
||||
pub mod ringbuffer;
|
||||
|
||||
/// Generic implementation of semantics binding.
|
||||
pub mod binding;
|
||||
|
|
Loading…
Add table
Reference in a new issue