gl/reflect: abstract away common uniform storage buffers
This commit is contained in:
parent
2c953d638f
commit
83b7cd38a0
12 changed files with 383 additions and 445 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -456,6 +456,7 @@ name = "librashader-reflect"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bytemuck",
|
||||
"librashader-common",
|
||||
"librashader-preprocess",
|
||||
"naga",
|
||||
|
|
|
@ -21,6 +21,9 @@ naga = { version = "0.10.0", features = ["glsl-in", "spv-in", "spv-out", "glsl-o
|
|||
rspirv = { version = "0.11.0+1.5.4", optional = true }
|
||||
rspirv-reflect = { git = "https://github.com/Traverse-Research/rspirv-reflect", optional = true }
|
||||
|
||||
|
||||
bytemuck = "1.12.3"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
unstable-rust-pipeline = [ "naga", "rspirv", "rspirv-reflect" ]
|
||||
|
|
|
@ -13,6 +13,7 @@ pub mod semantics;
|
|||
mod naga;
|
||||
#[cfg(feature = "unstable-rust-pipeline")]
|
||||
mod rspirv;
|
||||
pub mod uniforms;
|
||||
|
||||
pub trait ReflectShader {
|
||||
fn reflect(
|
||||
|
|
96
librashader-reflect/src/reflect/uniforms.rs
Normal file
96
librashader-reflect/src/reflect/uniforms.rs
Normal file
|
@ -0,0 +1,96 @@
|
|||
use std::marker::PhantomData;
|
||||
use crate::reflect::semantics::MemberOffset;
|
||||
|
||||
pub trait UniformScalar: Copy + bytemuck::Pod {}
|
||||
impl UniformScalar for f32 {}
|
||||
impl UniformScalar for i32 {}
|
||||
impl UniformScalar for u32 {}
|
||||
|
||||
pub struct NoUniformBinder;
|
||||
impl <T> BindUniform<Option<()>, T> for NoUniformBinder {
|
||||
fn bind_uniform(_: T, _: Option<()>) -> Option<()> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BindUniform<C, T> {
|
||||
fn bind_uniform(value: T, ctx: C) -> Option<()>;
|
||||
}
|
||||
|
||||
pub struct UniformBuffer<H=NoUniformBinder, C = Option<()>> {
|
||||
pub ubo: Box<[u8]>,
|
||||
pub push: Box<[u8]>,
|
||||
_h: PhantomData<H>,
|
||||
_c: PhantomData<C>
|
||||
}
|
||||
|
||||
impl <H, C> UniformBuffer<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]>
|
||||
{
|
||||
pub fn new(ubo_size: usize, push_size: usize) -> Self {
|
||||
UniformBuffer {
|
||||
ubo: vec![0u8; ubo_size].into_boxed_slice(),
|
||||
push: vec![0u8; push_size].into_boxed_slice(),
|
||||
_h: Default::default(),
|
||||
_c: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn write_scalar_inner<T: UniformScalar>(buffer: &mut [u8], value: T, ctx: C)
|
||||
where H: BindUniform<C, T>
|
||||
{
|
||||
if let None = H::bind_uniform(value, ctx) {
|
||||
let buffer = bytemuck::cast_slice_mut(buffer);
|
||||
buffer[0] = value;
|
||||
};
|
||||
}
|
||||
|
||||
fn write_mat4_inner(buffer: &mut [u8], mat4: &[f32; 16], ctx: C) {
|
||||
if let None = H::bind_uniform(mat4, ctx) {
|
||||
let mat4 = bytemuck::cast_slice(mat4);
|
||||
buffer.copy_from_slice(mat4);
|
||||
}
|
||||
}
|
||||
|
||||
fn write_vec4_inner(buffer: &mut [u8], vec4: impl Into<[f32; 4]>, ctx: C) {
|
||||
let vec4 = vec4.into();
|
||||
if let None = H::bind_uniform(&vec4, ctx) {
|
||||
let vec4 = bytemuck::cast_slice(&vec4);
|
||||
buffer.copy_from_slice(vec4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn bind_mat4(&mut self, offset: MemberOffset, value: &[f32; 16], ctx: C) {
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.ubo, offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push, offset),
|
||||
};
|
||||
let size = value.len() * std::mem::size_of::<f32>();
|
||||
|
||||
Self::write_mat4_inner(&mut buffer[offset..][..size], value, ctx);
|
||||
}
|
||||
|
||||
pub fn bind_vec4(&mut self, offset: MemberOffset, value: impl Into<[f32; 4]>, ctx: C) {
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.ubo, offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push, offset),
|
||||
};
|
||||
|
||||
Self::write_vec4_inner(&mut buffer[offset..][..16], value, ctx);
|
||||
}
|
||||
|
||||
pub fn bind_scalar<T: UniformScalar>(&mut self, offset: MemberOffset, value: T, ctx: C)
|
||||
where H: BindUniform<C, T>
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.ubo, offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push, offset),
|
||||
};
|
||||
|
||||
Self::write_scalar_inner(&mut buffer[offset..][..4], value, ctx)
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
use gl::types::GLint;
|
||||
use librashader_reflect::reflect::semantics::BindingStage;
|
||||
use librashader_reflect::reflect::uniforms::{BindUniform, UniformBuffer, UniformScalar};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum VariableLocation {
|
||||
|
@ -33,3 +34,79 @@ impl UniformLocation<GLint> {
|
|||
validity
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type BufferStorage = UniformBuffer<GlUniformBinder, UniformLocation<GLint>>;
|
||||
|
||||
|
||||
pub trait GlUniformScalar: UniformScalar {
|
||||
const FACTORY: unsafe fn(GLint, Self) -> ();
|
||||
}
|
||||
|
||||
impl GlUniformScalar for f32 {
|
||||
const FACTORY: unsafe fn(GLint, Self) -> () = gl::Uniform1f;
|
||||
}
|
||||
|
||||
impl GlUniformScalar for i32 {
|
||||
const FACTORY: unsafe fn(GLint, Self) -> () = gl::Uniform1i;
|
||||
}
|
||||
|
||||
impl GlUniformScalar for u32 {
|
||||
const FACTORY: unsafe fn(GLint, Self) -> () = gl::Uniform1ui;
|
||||
}
|
||||
|
||||
pub(crate) struct GlUniformBinder;
|
||||
impl<T> BindUniform<UniformLocation<GLint>, T> for GlUniformBinder
|
||||
where T: GlUniformScalar
|
||||
{
|
||||
fn bind_uniform(value: T, location: UniformLocation<GLint>) -> Option<()> {
|
||||
if location.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT) {
|
||||
unsafe {
|
||||
if location.is_valid(BindingStage::VERTEX) {
|
||||
T::FACTORY(location.vertex, value);
|
||||
}
|
||||
if location.is_valid(BindingStage::FRAGMENT) {
|
||||
T::FACTORY(location.fragment, value);
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BindUniform<UniformLocation<GLint>, &[f32; 4]> for GlUniformBinder {
|
||||
fn bind_uniform(vec4: &[f32; 4], location: UniformLocation<GLint>) -> Option<()> {
|
||||
if location.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT) {
|
||||
unsafe {
|
||||
if location.is_valid(BindingStage::VERTEX) {
|
||||
gl::Uniform4fv(location.vertex, 1, vec4.as_ptr());
|
||||
}
|
||||
if location.is_valid(BindingStage::FRAGMENT) {
|
||||
gl::Uniform4fv(location.fragment, 1, vec4.as_ptr());
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BindUniform<UniformLocation<GLint>, &[f32; 16]> for GlUniformBinder {
|
||||
fn bind_uniform(mat4: &[f32; 16], location: UniformLocation<GLint>) -> Option<()> {
|
||||
if location.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT) {
|
||||
unsafe {
|
||||
if location.is_valid(BindingStage::VERTEX) {
|
||||
gl::UniformMatrix4fv(location.vertex, 1, gl::FALSE, mat4.as_ptr());
|
||||
}
|
||||
if location.is_valid(BindingStage::FRAGMENT) {
|
||||
gl::UniformMatrix4fv(location.fragment, 1, gl::FALSE, mat4.as_ptr());
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
}else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ use librashader_reflect::front::shaderc::GlslangCompilation;
|
|||
use crate::options::{FilterChainOptions, FrameOptions};
|
||||
use crate::samplers::SamplerSet;
|
||||
use crate::texture::Texture;
|
||||
use crate::binding::BufferStorage;
|
||||
|
||||
pub struct FilterChain {
|
||||
passes: Box<[FilterPass]>,
|
||||
|
@ -435,24 +436,18 @@ impl FilterChain {
|
|||
None
|
||||
};
|
||||
|
||||
let uniform_buffer = vec![
|
||||
0;
|
||||
reflection
|
||||
.ubo
|
||||
.as_ref()
|
||||
.map(|ubo| ubo.size as usize)
|
||||
.unwrap_or(0)
|
||||
]
|
||||
.into_boxed_slice();
|
||||
let push_buffer = vec![
|
||||
0;
|
||||
reflection
|
||||
.push_constant
|
||||
.as_ref()
|
||||
.map(|push| push.size as usize)
|
||||
.unwrap_or(0)
|
||||
]
|
||||
.into_boxed_slice();
|
||||
let uniform_storage = BufferStorage::new(reflection
|
||||
.ubo
|
||||
.as_ref()
|
||||
.map(|ubo| ubo.size as usize)
|
||||
.unwrap_or(0),
|
||||
reflection
|
||||
.push_constant
|
||||
.as_ref()
|
||||
.map(|push| push.size as usize)
|
||||
.unwrap_or(0)
|
||||
);
|
||||
|
||||
|
||||
let mut uniform_bindings = FxHashMap::default();
|
||||
for param in reflection.meta.parameter_meta.values() {
|
||||
|
@ -500,8 +495,7 @@ impl FilterChain {
|
|||
program,
|
||||
ubo_location,
|
||||
ubo_ring,
|
||||
uniform_buffer,
|
||||
push_buffer,
|
||||
uniform_storage,
|
||||
uniform_bindings,
|
||||
source,
|
||||
config
|
||||
|
|
|
@ -8,8 +8,9 @@ use librashader_preprocess::ShaderSource;
|
|||
use librashader_presets::ShaderPassConfig;
|
||||
use librashader_reflect::reflect::semantics::{BindingStage, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, VariableSemantics};
|
||||
use rustc_hash::FxHashMap;
|
||||
use librashader_reflect::reflect::uniforms::UniformBuffer;
|
||||
|
||||
use crate::binding::{UniformLocation, VariableLocation};
|
||||
use crate::binding::{BufferStorage, GlUniformBinder, UniformLocation, VariableLocation};
|
||||
use crate::filter_chain::FilterCommon;
|
||||
use crate::framebuffer::Viewport;
|
||||
use crate::render_target::RenderTarget;
|
||||
|
@ -17,111 +18,20 @@ use crate::samplers::SamplerSet;
|
|||
use crate::texture::Texture;
|
||||
use crate::util::{InlineRingBuffer, RingBuffer};
|
||||
|
||||
|
||||
pub struct FilterPass {
|
||||
pub reflection: ShaderReflection,
|
||||
pub compiled: ShaderCompilerOutput<String, GlslangGlslContext>,
|
||||
pub program: GLuint,
|
||||
pub ubo_location: UniformLocation<GLuint>,
|
||||
pub ubo_ring: Option<InlineRingBuffer<GLuint, 16>>,
|
||||
pub uniform_buffer: Box<[u8]>,
|
||||
pub push_buffer: Box<[u8]>,
|
||||
pub(crate) uniform_storage: BufferStorage,
|
||||
pub uniform_bindings: FxHashMap<UniformBinding, (VariableLocation, MemberOffset)>,
|
||||
pub source: ShaderSource,
|
||||
pub config: ShaderPassConfig,
|
||||
}
|
||||
|
||||
impl FilterPass {
|
||||
fn build_mat4(location: UniformLocation<GLint>, buffer: &mut [u8], mvp: &[f32; 16]) {
|
||||
if location.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT) {
|
||||
unsafe {
|
||||
if location.is_valid(BindingStage::VERTEX) {
|
||||
gl::UniformMatrix4fv(location.vertex, 1, gl::FALSE, mvp.as_ptr());
|
||||
}
|
||||
if location.is_valid(BindingStage::FRAGMENT) {
|
||||
gl::UniformMatrix4fv(location.fragment, 1, gl::FALSE, mvp.as_ptr());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mvp = bytemuck::cast_slice(mvp);
|
||||
buffer.copy_from_slice(mvp);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_vec4(location: UniformLocation<GLint>, buffer: &mut [u8], size: impl Into<[f32; 4]>) {
|
||||
let vec4 = size.into();
|
||||
if location.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT) {
|
||||
unsafe {
|
||||
if location.is_valid(BindingStage::VERTEX) {
|
||||
gl::Uniform4fv(location.vertex, 1, vec4.as_ptr());
|
||||
}
|
||||
if location.is_valid(BindingStage::FRAGMENT) {
|
||||
gl::Uniform4fv(location.fragment, 1, vec4.as_ptr());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let vec4 = bytemuck::cast_slice(&vec4);
|
||||
buffer.copy_from_slice(vec4);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn build_uniform<T>(
|
||||
location: UniformLocation<GLint>,
|
||||
buffer: &mut [u8],
|
||||
value: T,
|
||||
glfn: unsafe fn(GLint, T) -> (),
|
||||
) where
|
||||
T: Copy,
|
||||
T: bytemuck::Pod,
|
||||
{
|
||||
if location.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT) {
|
||||
unsafe {
|
||||
if location.is_valid(BindingStage::VERTEX) {
|
||||
glfn(location.vertex, value);
|
||||
}
|
||||
if location.is_valid(BindingStage::FRAGMENT) {
|
||||
glfn(location.fragment, value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let buffer = bytemuck::cast_slice_mut(buffer);
|
||||
buffer[0] = value;
|
||||
}
|
||||
}
|
||||
|
||||
fn build_uint(location: UniformLocation<GLint>, buffer: &mut [u8], value: u32) {
|
||||
Self::build_uniform(location, buffer, value, gl::Uniform1ui)
|
||||
}
|
||||
|
||||
fn build_sint(location: UniformLocation<GLint>, buffer: &mut [u8], value: i32) {
|
||||
Self::build_uniform(location, buffer, value, gl::Uniform1i)
|
||||
}
|
||||
|
||||
fn build_float(location: UniformLocation<GLint>, buffer: &mut [u8], value: f32) {
|
||||
Self::build_uniform(location, buffer, value, gl::Uniform1f)
|
||||
}
|
||||
|
||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture) {
|
||||
unsafe {
|
||||
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
||||
gl::ActiveTexture(gl::TEXTURE0 + binding.binding);
|
||||
|
||||
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
|
||||
gl::BindSampler(binding.binding,
|
||||
samplers.get(texture.wrap_mode, texture.filter, texture.mip_filter));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_format(&self) -> ShaderFormat {
|
||||
let mut fb_format = ShaderFormat::R8G8B8A8Unorm;
|
||||
if self.config.srgb_framebuffer {
|
||||
fb_format = ShaderFormat::R8G8B8A8Srgb;
|
||||
} else if self.config.float_framebuffer {
|
||||
fb_format = ShaderFormat::R16G16B16A16Sfloat;
|
||||
}
|
||||
fb_format
|
||||
}
|
||||
|
||||
// todo: fix rendertargets (i.e. non-final pass is internal, final pass is user provided fbo)
|
||||
pub fn draw(
|
||||
&mut self,
|
||||
|
@ -152,7 +62,6 @@ impl FilterPass {
|
|||
original,
|
||||
source,
|
||||
);
|
||||
// shader_gl3:1514
|
||||
|
||||
if self.ubo_location.vertex != gl::INVALID_INDEX
|
||||
&& self.ubo_location.fragment != gl::INVALID_INDEX
|
||||
|
@ -167,7 +76,7 @@ impl FilterPass {
|
|||
gl::UNIFORM_BUFFER,
|
||||
0,
|
||||
size as GLsizeiptr,
|
||||
self.uniform_buffer.as_ptr().cast(),
|
||||
self.uniform_storage.ubo.as_ptr().cast(),
|
||||
);
|
||||
gl::BindBuffer(gl::UNIFORM_BUFFER, 0);
|
||||
|
||||
|
@ -211,6 +120,30 @@ impl FilterPass {
|
|||
}
|
||||
}
|
||||
|
||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture) {
|
||||
unsafe {
|
||||
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
||||
gl::ActiveTexture(gl::TEXTURE0 + binding.binding);
|
||||
|
||||
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
|
||||
gl::BindSampler(binding.binding,
|
||||
samplers.get(texture.wrap_mode, texture.filter, texture.mip_filter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl FilterPass {
|
||||
pub fn get_format(&self) -> ShaderFormat {
|
||||
let mut fb_format = ShaderFormat::R8G8B8A8Unorm;
|
||||
if self.config.srgb_framebuffer {
|
||||
fb_format = ShaderFormat::R8G8B8A8Srgb;
|
||||
} else if self.config.float_framebuffer {
|
||||
fb_format = ShaderFormat::R16G16B16A16Sfloat;
|
||||
}
|
||||
fb_format
|
||||
}
|
||||
|
||||
// framecount should be pre-modded
|
||||
fn build_semantics(
|
||||
&mut self,
|
||||
|
@ -228,12 +161,7 @@ impl FilterPass {
|
|||
if let Some((location, offset)) =
|
||||
self.uniform_bindings.get(&VariableSemantics::MVP.into())
|
||||
{
|
||||
let mvp_size = mvp.len() * std::mem::size_of::<f32>();
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_mat4(location.location(), &mut buffer[offset..][..mvp_size], mvp)
|
||||
self.uniform_storage.bind_mat4(*offset, mvp, location.location());
|
||||
}
|
||||
|
||||
// bind OutputSize
|
||||
|
@ -241,12 +169,7 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&VariableSemantics::Output.into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
|
||||
FilterPass::build_vec4(location.location(), &mut buffer[offset..][..16], fb_size)
|
||||
self.uniform_storage.bind_vec4(*offset, fb_size, location.location());
|
||||
}
|
||||
|
||||
// bind FinalViewportSize
|
||||
|
@ -254,15 +177,7 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&VariableSemantics::FinalViewport.into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
viewport.output.size,
|
||||
)
|
||||
self.uniform_storage.bind_vec4(*offset,viewport.output.size, location.location());
|
||||
}
|
||||
|
||||
// bind FrameCount
|
||||
|
@ -270,11 +185,7 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&VariableSemantics::FrameCount.into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_uint(location.location(), &mut buffer[offset..][..4], frame_count)
|
||||
self.uniform_storage.bind_scalar(*offset, frame_count, location.location());
|
||||
}
|
||||
|
||||
// bind FrameDirection
|
||||
|
@ -282,15 +193,7 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&VariableSemantics::FrameDirection.into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_sint(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..4],
|
||||
frame_direction,
|
||||
)
|
||||
self.uniform_storage.bind_scalar(*offset, frame_direction, location.location());
|
||||
}
|
||||
|
||||
// bind Original sampler
|
||||
|
@ -308,15 +211,8 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&TextureSemantics::Original.semantics(0).into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
original.image.size,
|
||||
);
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset,original.image.size, location.location());
|
||||
}
|
||||
|
||||
// bind Source sampler
|
||||
|
@ -335,15 +231,8 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&TextureSemantics::Source.semantics(0).into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
source.image.size,
|
||||
);
|
||||
self.uniform_storage.bind_vec4(*offset,
|
||||
source.image.size, location.location());
|
||||
}
|
||||
|
||||
if let Some(binding) = self
|
||||
|
@ -358,15 +247,8 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&TextureSemantics::OriginalHistory.semantics(0).into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
original.image.size,
|
||||
);
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset,original.image.size, location.location());
|
||||
}
|
||||
|
||||
for (index, output) in parent.history_textures.iter().enumerate() {
|
||||
|
@ -384,15 +266,8 @@ impl FilterPass {
|
|||
.semantics(index + 1)
|
||||
.into(),
|
||||
) {
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
output.image.size,
|
||||
);
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset,output.image.size, location.location());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,15 +286,8 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&TextureSemantics::PassOutput.semantics(index).into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
output.image.size,
|
||||
);
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset,output.image.size, location.location());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,15 +309,8 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&TextureSemantics::PassFeedback.semantics(index).into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
feedback.image.size,
|
||||
);
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset,feedback.image.size, location.location());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -463,12 +324,6 @@ impl FilterPass {
|
|||
})
|
||||
{
|
||||
let id = id.as_str();
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
|
||||
// todo: cache parameters.
|
||||
// presets override params
|
||||
let default = self
|
||||
.source
|
||||
|
@ -484,7 +339,8 @@ impl FilterPass {
|
|||
.get(id)
|
||||
.unwrap_or(&default);
|
||||
|
||||
FilterPass::build_float(location.location(), &mut buffer[offset..][..4], value)
|
||||
self.uniform_storage
|
||||
.bind_scalar(*offset, value, location.location());
|
||||
}
|
||||
|
||||
// bind luts
|
||||
|
@ -502,15 +358,8 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&TextureSemantics::User.semantics(*index).into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
lut.image.size,
|
||||
);
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset, lut.image.size, location.location());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ mod tests {
|
|||
fn triangle_gl() {
|
||||
let (glfw, window, events, shader, vao) = hello_triangle::setup();
|
||||
let mut filter =
|
||||
FilterChain::load_from_path("../test/slang-shaders/crt/crt-royale.slangp", None)
|
||||
FilterChain::load_from_path("../test/slang-shaders/vhs/VHSPro.slangp", None)
|
||||
.unwrap();
|
||||
hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use gl::types::{GLenum, GLuint};
|
||||
use gl::types::{GLenum, GLint, GLuint};
|
||||
use librashader_common::Size;
|
||||
use librashader_reflect::back::cross::GlVersion;
|
||||
use librashader_reflect::reflect::semantics::BindingStage;
|
||||
use librashader_reflect::reflect::uniforms::{BindUniform, UniformBuffer, UniformScalar};
|
||||
use crate::binding::UniformLocation;
|
||||
|
||||
pub fn calc_miplevel(size: Size<u32>) -> u32 {
|
||||
let mut size = std::cmp::max(size.width, size.height);
|
||||
|
@ -126,4 +129,4 @@ pub fn gl_u16_to_version(version: u16) -> GlVersion {
|
|||
460 => GlVersion::V4_60,
|
||||
_ => GlVersion::V1_50
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use gl::types::GLint;
|
||||
use librashader_reflect::reflect::semantics::BindingStage;
|
||||
use librashader_reflect::reflect::uniforms::{BindUniform, UniformBuffer, UniformScalar};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum VariableLocation {
|
||||
|
@ -33,3 +34,79 @@ impl UniformLocation<GLint> {
|
|||
validity
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type BufferStorage = UniformBuffer<GlUniformBinder, UniformLocation<GLint>>;
|
||||
|
||||
|
||||
pub trait GlUniformScalar: UniformScalar {
|
||||
const FACTORY: unsafe fn(GLint, Self) -> ();
|
||||
}
|
||||
|
||||
impl GlUniformScalar for f32 {
|
||||
const FACTORY: unsafe fn(GLint, Self) -> () = gl::Uniform1f;
|
||||
}
|
||||
|
||||
impl GlUniformScalar for i32 {
|
||||
const FACTORY: unsafe fn(GLint, Self) -> () = gl::Uniform1i;
|
||||
}
|
||||
|
||||
impl GlUniformScalar for u32 {
|
||||
const FACTORY: unsafe fn(GLint, Self) -> () = gl::Uniform1ui;
|
||||
}
|
||||
|
||||
pub(crate) struct GlUniformBinder;
|
||||
impl<T> BindUniform<UniformLocation<GLint>, T> for GlUniformBinder
|
||||
where T: GlUniformScalar
|
||||
{
|
||||
fn bind_uniform(value: T, location: UniformLocation<GLint>) -> Option<()> {
|
||||
if location.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT) {
|
||||
unsafe {
|
||||
if location.is_valid(BindingStage::VERTEX) {
|
||||
T::FACTORY(location.vertex, value);
|
||||
}
|
||||
if location.is_valid(BindingStage::FRAGMENT) {
|
||||
T::FACTORY(location.fragment, value);
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BindUniform<UniformLocation<GLint>, &[f32; 4]> for GlUniformBinder {
|
||||
fn bind_uniform(vec4: &[f32; 4], location: UniformLocation<GLint>) -> Option<()> {
|
||||
if location.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT) {
|
||||
unsafe {
|
||||
if location.is_valid(BindingStage::VERTEX) {
|
||||
gl::Uniform4fv(location.vertex, 1, vec4.as_ptr());
|
||||
}
|
||||
if location.is_valid(BindingStage::FRAGMENT) {
|
||||
gl::Uniform4fv(location.fragment, 1, vec4.as_ptr());
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BindUniform<UniformLocation<GLint>, &[f32; 16]> for GlUniformBinder {
|
||||
fn bind_uniform(mat4: &[f32; 16], location: UniformLocation<GLint>) -> Option<()> {
|
||||
if location.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT) {
|
||||
unsafe {
|
||||
if location.is_valid(BindingStage::VERTEX) {
|
||||
gl::UniformMatrix4fv(location.vertex, 1, gl::FALSE, mat4.as_ptr());
|
||||
}
|
||||
if location.is_valid(BindingStage::FRAGMENT) {
|
||||
gl::UniformMatrix4fv(location.fragment, 1, gl::FALSE, mat4.as_ptr());
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
}else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::binding::{UniformLocation, VariableLocation};
|
||||
use crate::binding::{BufferStorage, UniformLocation, VariableLocation};
|
||||
use crate::filter_pass::FilterPass;
|
||||
use crate::framebuffer::{Framebuffer, GlImage, Viewport};
|
||||
use crate::quad_render::DrawQuad;
|
||||
|
@ -433,24 +433,17 @@ impl FilterChain {
|
|||
None
|
||||
};
|
||||
|
||||
let uniform_buffer = vec![
|
||||
0;
|
||||
reflection
|
||||
.ubo
|
||||
.as_ref()
|
||||
.map(|ubo| ubo.size as usize)
|
||||
.unwrap_or(0)
|
||||
]
|
||||
.into_boxed_slice();
|
||||
let push_buffer = vec![
|
||||
0;
|
||||
reflection
|
||||
.push_constant
|
||||
.as_ref()
|
||||
.map(|push| push.size as usize)
|
||||
.unwrap_or(0)
|
||||
]
|
||||
.into_boxed_slice();
|
||||
let uniform_storage = BufferStorage::new(reflection
|
||||
.ubo
|
||||
.as_ref()
|
||||
.map(|ubo| ubo.size as usize)
|
||||
.unwrap_or(0),
|
||||
reflection
|
||||
.push_constant
|
||||
.as_ref()
|
||||
.map(|push| push.size as usize)
|
||||
.unwrap_or(0)
|
||||
);
|
||||
|
||||
let mut uniform_bindings = FxHashMap::default();
|
||||
for param in reflection.meta.parameter_meta.values() {
|
||||
|
@ -498,8 +491,7 @@ impl FilterChain {
|
|||
program,
|
||||
ubo_location,
|
||||
ubo_ring,
|
||||
uniform_buffer,
|
||||
push_buffer,
|
||||
uniform_storage,
|
||||
uniform_bindings,
|
||||
source,
|
||||
config
|
||||
|
|
|
@ -9,7 +9,7 @@ use librashader_presets::ShaderPassConfig;
|
|||
use librashader_reflect::reflect::semantics::{BindingStage, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, VariableSemantics};
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use crate::binding::{UniformLocation, VariableLocation};
|
||||
use crate::binding::{BufferStorage, UniformLocation, VariableLocation};
|
||||
use crate::filter_chain::FilterCommon;
|
||||
use crate::framebuffer::Viewport;
|
||||
use crate::render_target::RenderTarget;
|
||||
|
@ -23,103 +23,13 @@ pub struct FilterPass {
|
|||
pub program: GLuint,
|
||||
pub ubo_location: UniformLocation<GLuint>,
|
||||
pub ubo_ring: Option<InlineRingBuffer<GLuint, 16>>,
|
||||
pub uniform_buffer: Box<[u8]>,
|
||||
pub push_buffer: Box<[u8]>,
|
||||
pub(crate) uniform_storage: BufferStorage,
|
||||
pub uniform_bindings: FxHashMap<UniformBinding, (VariableLocation, MemberOffset)>,
|
||||
pub source: ShaderSource,
|
||||
pub config: ShaderPassConfig,
|
||||
}
|
||||
|
||||
impl FilterPass {
|
||||
fn build_mat4(location: UniformLocation<GLint>, buffer: &mut [u8], mvp: &[f32; 16]) {
|
||||
if location.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT) {
|
||||
unsafe {
|
||||
if location.is_valid(BindingStage::VERTEX) {
|
||||
gl::UniformMatrix4fv(location.vertex, 1, gl::FALSE, mvp.as_ptr());
|
||||
}
|
||||
if location.is_valid(BindingStage::FRAGMENT) {
|
||||
gl::UniformMatrix4fv(location.fragment, 1, gl::FALSE, mvp.as_ptr());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mvp = bytemuck::cast_slice(mvp);
|
||||
buffer.copy_from_slice(mvp);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_vec4(location: UniformLocation<GLint>, buffer: &mut [u8], size: impl Into<[f32; 4]>) {
|
||||
let vec4 = size.into();
|
||||
if location.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT) {
|
||||
unsafe {
|
||||
if location.is_valid(BindingStage::VERTEX) {
|
||||
gl::Uniform4fv(location.vertex, 1, vec4.as_ptr());
|
||||
}
|
||||
if location.is_valid(BindingStage::FRAGMENT) {
|
||||
gl::Uniform4fv(location.fragment, 1, vec4.as_ptr());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let vec4 = bytemuck::cast_slice(&vec4);
|
||||
buffer.copy_from_slice(vec4);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn build_uniform<T>(
|
||||
location: UniformLocation<GLint>,
|
||||
buffer: &mut [u8],
|
||||
value: T,
|
||||
glfn: unsafe fn(GLint, T) -> (),
|
||||
) where
|
||||
T: Copy,
|
||||
T: bytemuck::Pod,
|
||||
{
|
||||
if location.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT) {
|
||||
unsafe {
|
||||
if location.is_valid(BindingStage::VERTEX) {
|
||||
glfn(location.vertex, value);
|
||||
}
|
||||
if location.is_valid(BindingStage::FRAGMENT) {
|
||||
glfn(location.fragment, value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let buffer = bytemuck::cast_slice_mut(buffer);
|
||||
buffer[0] = value;
|
||||
}
|
||||
}
|
||||
|
||||
fn build_uint(location: UniformLocation<GLint>, buffer: &mut [u8], value: u32) {
|
||||
Self::build_uniform(location, buffer, value, gl::Uniform1ui)
|
||||
}
|
||||
|
||||
fn build_sint(location: UniformLocation<GLint>, buffer: &mut [u8], value: i32) {
|
||||
Self::build_uniform(location, buffer, value, gl::Uniform1i)
|
||||
}
|
||||
|
||||
fn build_float(location: UniformLocation<GLint>, buffer: &mut [u8], value: f32) {
|
||||
Self::build_uniform(location, buffer, value, gl::Uniform1f)
|
||||
}
|
||||
|
||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture) {
|
||||
unsafe {
|
||||
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
||||
gl::BindTextureUnit(binding.binding, texture.image.handle);
|
||||
gl::BindSampler(binding.binding,
|
||||
samplers.get(texture.wrap_mode, texture.filter, texture.mip_filter));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_format(&self) -> ShaderFormat {
|
||||
let mut fb_format = ShaderFormat::R8G8B8A8Unorm;
|
||||
if self.config.srgb_framebuffer {
|
||||
fb_format = ShaderFormat::R8G8B8A8Srgb;
|
||||
} else if self.config.float_framebuffer {
|
||||
fb_format = ShaderFormat::R16G16B16A16Sfloat;
|
||||
}
|
||||
fb_format
|
||||
}
|
||||
|
||||
// todo: fix rendertargets (i.e. non-final pass is internal, final pass is user provided fbo)
|
||||
pub fn draw(
|
||||
&mut self,
|
||||
|
@ -135,7 +45,6 @@ impl FilterPass {
|
|||
let framebuffer = output.framebuffer;
|
||||
|
||||
unsafe {
|
||||
// gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle);
|
||||
gl::UseProgram(self.program);
|
||||
}
|
||||
|
||||
|
@ -150,7 +59,6 @@ impl FilterPass {
|
|||
original,
|
||||
source,
|
||||
);
|
||||
// shader_gl3:1514
|
||||
|
||||
if self.ubo_location.vertex != gl::INVALID_INDEX
|
||||
&& self.ubo_location.fragment != gl::INVALID_INDEX
|
||||
|
@ -164,7 +72,7 @@ impl FilterPass {
|
|||
*buffer,
|
||||
0,
|
||||
size as GLsizeiptr,
|
||||
self.uniform_buffer.as_ptr().cast(),
|
||||
self.uniform_storage.ubo.as_ptr().cast(),
|
||||
);
|
||||
|
||||
if self.ubo_location.vertex != gl::INVALID_INDEX {
|
||||
|
@ -205,6 +113,27 @@ impl FilterPass {
|
|||
}
|
||||
}
|
||||
|
||||
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture) {
|
||||
unsafe {
|
||||
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
||||
gl::BindTextureUnit(binding.binding, texture.image.handle);
|
||||
gl::BindSampler(binding.binding,
|
||||
samplers.get(texture.wrap_mode, texture.filter, texture.mip_filter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FilterPass {
|
||||
pub fn get_format(&self) -> ShaderFormat {
|
||||
let mut fb_format = ShaderFormat::R8G8B8A8Unorm;
|
||||
if self.config.srgb_framebuffer {
|
||||
fb_format = ShaderFormat::R8G8B8A8Srgb;
|
||||
} else if self.config.float_framebuffer {
|
||||
fb_format = ShaderFormat::R16G16B16A16Sfloat;
|
||||
}
|
||||
fb_format
|
||||
}
|
||||
|
||||
// framecount should be pre-modded
|
||||
fn build_semantics(
|
||||
&mut self,
|
||||
|
@ -222,12 +151,7 @@ impl FilterPass {
|
|||
if let Some((location, offset)) =
|
||||
self.uniform_bindings.get(&VariableSemantics::MVP.into())
|
||||
{
|
||||
let mvp_size = mvp.len() * std::mem::size_of::<f32>();
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_mat4(location.location(), &mut buffer[offset..][..mvp_size], mvp)
|
||||
self.uniform_storage.bind_mat4(*offset, mvp, location.location());
|
||||
}
|
||||
|
||||
// bind OutputSize
|
||||
|
@ -235,12 +159,7 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&VariableSemantics::Output.into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
|
||||
FilterPass::build_vec4(location.location(), &mut buffer[offset..][..16], fb_size)
|
||||
self.uniform_storage.bind_vec4(*offset, fb_size, location.location());
|
||||
}
|
||||
|
||||
// bind FinalViewportSize
|
||||
|
@ -248,15 +167,7 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&VariableSemantics::FinalViewport.into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
viewport.output.size,
|
||||
)
|
||||
self.uniform_storage.bind_vec4(*offset,viewport.output.size, location.location());
|
||||
}
|
||||
|
||||
// bind FrameCount
|
||||
|
@ -264,11 +175,7 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&VariableSemantics::FrameCount.into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_uint(location.location(), &mut buffer[offset..][..4], frame_count)
|
||||
self.uniform_storage.bind_scalar(*offset, frame_count, location.location());
|
||||
}
|
||||
|
||||
// bind FrameDirection
|
||||
|
@ -276,15 +183,7 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&VariableSemantics::FrameDirection.into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_sint(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..4],
|
||||
frame_direction,
|
||||
)
|
||||
self.uniform_storage.bind_scalar(*offset, frame_direction, location.location());
|
||||
}
|
||||
|
||||
// bind Original sampler
|
||||
|
@ -302,15 +201,8 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&TextureSemantics::Original.semantics(0).into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
original.image.size,
|
||||
);
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset,original.image.size, location.location());
|
||||
}
|
||||
|
||||
// bind Source sampler
|
||||
|
@ -329,15 +221,8 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&TextureSemantics::Source.semantics(0).into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
source.image.size,
|
||||
);
|
||||
self.uniform_storage.bind_vec4(*offset,
|
||||
source.image.size, location.location());
|
||||
}
|
||||
|
||||
if let Some(binding) = self
|
||||
|
@ -352,15 +237,8 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&TextureSemantics::OriginalHistory.semantics(0).into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
original.image.size,
|
||||
);
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset,original.image.size, location.location());
|
||||
}
|
||||
|
||||
for (index, output) in parent.history_textures.iter().enumerate() {
|
||||
|
@ -378,15 +256,8 @@ impl FilterPass {
|
|||
.semantics(index + 1)
|
||||
.into(),
|
||||
) {
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
output.image.size,
|
||||
);
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset,output.image.size, location.location());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,15 +276,8 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&TextureSemantics::PassOutput.semantics(index).into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
output.image.size,
|
||||
);
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset,output.image.size, location.location());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -435,15 +299,8 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&TextureSemantics::PassFeedback.semantics(index).into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
feedback.image.size,
|
||||
);
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset,feedback.image.size, location.location());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,12 +314,6 @@ impl FilterPass {
|
|||
})
|
||||
{
|
||||
let id = id.as_str();
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
|
||||
// todo: cache parameters.
|
||||
// presets override params
|
||||
let default = self
|
||||
.source
|
||||
|
@ -478,7 +329,8 @@ impl FilterPass {
|
|||
.get(id)
|
||||
.unwrap_or(&default);
|
||||
|
||||
FilterPass::build_float(location.location(), &mut buffer[offset..][..4], value)
|
||||
self.uniform_storage
|
||||
.bind_scalar(*offset, value, location.location());
|
||||
}
|
||||
|
||||
// bind luts
|
||||
|
@ -496,15 +348,8 @@ impl FilterPass {
|
|||
.uniform_bindings
|
||||
.get(&TextureSemantics::User.semantics(*index).into())
|
||||
{
|
||||
let (buffer, offset) = match offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||
};
|
||||
FilterPass::build_vec4(
|
||||
location.location(),
|
||||
&mut buffer[offset..][..16],
|
||||
lut.image.size,
|
||||
);
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset, lut.image.size, location.location());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue