gl: implement PassOutput binding
This commit is contained in:
parent
23b13ef047
commit
1e9d180bf0
|
@ -104,19 +104,20 @@ impl FilterChain {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FilterChain {
|
pub struct FilterChain {
|
||||||
passes: Vec<FilterPass>,
|
passes: Box<[FilterPass]>,
|
||||||
common: FilterCommon,
|
common: FilterCommon,
|
||||||
quad_vao: GLuint,
|
quad_vao: GLuint,
|
||||||
|
output_framebuffers: Box<[Framebuffer]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FilterCommon {
|
pub struct FilterCommon {
|
||||||
semantics: ReflectSemantics,
|
semantics: ReflectSemantics,
|
||||||
pub(crate) preset: ShaderPreset,
|
pub(crate) preset: ShaderPreset,
|
||||||
original_history: Vec<Framebuffer>,
|
pub original_history: Box<[Framebuffer]>,
|
||||||
history: Vec<Texture>,
|
pub history: Vec<Texture>,
|
||||||
feedback: Vec<Texture>,
|
pub feedback: Vec<Texture>,
|
||||||
pub(crate) luts: FxHashMap<usize, Texture>,
|
pub(crate) luts: FxHashMap<usize, Texture>,
|
||||||
outputs: Vec<Framebuffer>,
|
pub output_textures: Box<[Texture]>,
|
||||||
pub(crate) quad_vbo: GLuint,
|
pub(crate) quad_vbo: GLuint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,18 +126,13 @@ type ShaderPassMeta<'a> = (
|
||||||
ShaderSource,
|
ShaderSource,
|
||||||
CompilerBackend<
|
CompilerBackend<
|
||||||
impl CompileShader<GLSL, Options = GlVersion, Context = GlslangGlslContext>
|
impl CompileShader<GLSL, Options = GlVersion, Context = GlslangGlslContext>
|
||||||
+ ReflectShader
|
+ ReflectShader
|
||||||
+ Sized,
|
+ Sized,
|
||||||
>,
|
>,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl FilterChain {
|
impl FilterChain {
|
||||||
fn load_preset(
|
fn load_preset(preset: &ShaderPreset) -> (Vec<ShaderPassMeta>, ReflectSemantics) {
|
||||||
preset: &ShaderPreset,
|
|
||||||
) -> (
|
|
||||||
Vec<ShaderPassMeta>,
|
|
||||||
ReflectSemantics,
|
|
||||||
) {
|
|
||||||
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
|
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
|
||||||
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> =
|
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> =
|
||||||
Default::default();
|
Default::default();
|
||||||
|
@ -305,7 +301,10 @@ impl FilterChain {
|
||||||
Ok(luts)
|
Ok(luts)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_passes(passes: Vec<ShaderPassMeta>, semantics: &ReflectSemantics) -> Result<Vec<FilterPass>, Box<dyn Error>> {
|
pub fn init_passes(
|
||||||
|
passes: Vec<ShaderPassMeta>,
|
||||||
|
semantics: &ReflectSemantics,
|
||||||
|
) -> Result<Box<[FilterPass]>, Box<dyn Error>> {
|
||||||
let mut filters = Vec::new();
|
let mut filters = Vec::new();
|
||||||
|
|
||||||
// initialize passes
|
// initialize passes
|
||||||
|
@ -401,7 +400,7 @@ impl FilterChain {
|
||||||
.map(|ubo| ubo.size as usize)
|
.map(|ubo| ubo.size as usize)
|
||||||
.unwrap_or(0)
|
.unwrap_or(0)
|
||||||
]
|
]
|
||||||
.into_boxed_slice();
|
.into_boxed_slice();
|
||||||
let push_buffer = vec![
|
let push_buffer = vec![
|
||||||
0;
|
0;
|
||||||
reflection
|
reflection
|
||||||
|
@ -410,12 +409,12 @@ impl FilterChain {
|
||||||
.map(|push| push.size as usize)
|
.map(|push| push.size as usize)
|
||||||
.unwrap_or(0)
|
.unwrap_or(0)
|
||||||
]
|
]
|
||||||
.into_boxed_slice();
|
.into_boxed_slice();
|
||||||
|
|
||||||
// todo: reflect indexed parameters
|
// todo: reflect indexed parameters
|
||||||
let mut locations = FxHashMap::default();
|
let mut variable_bindings = FxHashMap::default();
|
||||||
for param in reflection.meta.parameter_meta.values() {
|
for param in reflection.meta.parameter_meta.values() {
|
||||||
locations.insert(
|
variable_bindings.insert(
|
||||||
UniformBinding::Parameter(param.id.clone()),
|
UniformBinding::Parameter(param.id.clone()),
|
||||||
(
|
(
|
||||||
FilterChain::reflect_uniform_location(program, param),
|
FilterChain::reflect_uniform_location(program, param),
|
||||||
|
@ -425,7 +424,7 @@ impl FilterChain {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (semantics, param) in &reflection.meta.variable_meta {
|
for (semantics, param) in &reflection.meta.variable_meta {
|
||||||
locations.insert(
|
variable_bindings.insert(
|
||||||
UniformBinding::SemanticVariable(*semantics),
|
UniformBinding::SemanticVariable(*semantics),
|
||||||
(
|
(
|
||||||
FilterChain::reflect_uniform_location(program, param),
|
FilterChain::reflect_uniform_location(program, param),
|
||||||
|
@ -435,7 +434,7 @@ impl FilterChain {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (semantics, param) in &reflection.meta.texture_size_meta {
|
for (semantics, param) in &reflection.meta.texture_size_meta {
|
||||||
locations.insert(
|
variable_bindings.insert(
|
||||||
UniformBinding::TextureSize(*semantics),
|
UniformBinding::TextureSize(*semantics),
|
||||||
(
|
(
|
||||||
FilterChain::reflect_uniform_location(program, param),
|
FilterChain::reflect_uniform_location(program, param),
|
||||||
|
@ -461,15 +460,90 @@ impl FilterChain {
|
||||||
ubo_ring,
|
ubo_ring,
|
||||||
uniform_buffer,
|
uniform_buffer,
|
||||||
push_buffer,
|
push_buffer,
|
||||||
variable_bindings: locations,
|
variable_bindings,
|
||||||
source,
|
source,
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(filters)
|
Ok(filters.into_boxed_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn init_history(filters: &[FilterPass]) -> Box<[Framebuffer]> {
|
||||||
|
let mut required_images = 0;
|
||||||
|
|
||||||
|
for pass in filters {
|
||||||
|
// If a shader uses history size, but not history, we still need to keep the texture.
|
||||||
|
let texture_count = pass
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_meta
|
||||||
|
.iter()
|
||||||
|
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
|
||||||
|
.count();
|
||||||
|
let texture_size_count = pass
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_size_meta
|
||||||
|
.iter()
|
||||||
|
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
|
||||||
|
.count();
|
||||||
|
|
||||||
|
required_images = std::cmp::max(required_images, texture_count);
|
||||||
|
required_images = std::cmp::max(required_images, texture_size_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// not ussing frame history;
|
||||||
|
if required_images < 2 {
|
||||||
|
eprintln!("not using frame history");
|
||||||
|
return Vec::new().into_boxed_slice();
|
||||||
|
}
|
||||||
|
|
||||||
|
// history0 is aliased with the original
|
||||||
|
required_images -= 1;
|
||||||
|
|
||||||
|
let mut framebuffers = Vec::new();
|
||||||
|
framebuffers.resize_with(required_images, || Framebuffer::new(1));
|
||||||
|
framebuffers.into_boxed_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_feedback(filters: &[FilterPass]) -> Box<[Framebuffer]> {
|
||||||
|
let mut required_images = 0;
|
||||||
|
|
||||||
|
for pass in filters {
|
||||||
|
// If a shader uses history size, but not history, we still need to keep the texture.
|
||||||
|
let texture_count = pass
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_meta
|
||||||
|
.iter()
|
||||||
|
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
|
||||||
|
.count();
|
||||||
|
let texture_size_count = pass
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_size_meta
|
||||||
|
.iter()
|
||||||
|
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
|
||||||
|
.count();
|
||||||
|
|
||||||
|
required_images = std::cmp::max(required_images, texture_count);
|
||||||
|
required_images = std::cmp::max(required_images, texture_size_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// not ussing frame history;
|
||||||
|
if required_images < 2 {
|
||||||
|
eprintln!("not using frame history");
|
||||||
|
return Vec::new().into_boxed_slice();
|
||||||
|
}
|
||||||
|
|
||||||
|
// history0 is aliased with the original
|
||||||
|
required_images -= 1;
|
||||||
|
|
||||||
|
let mut framebuffers = Vec::new();
|
||||||
|
framebuffers.resize_with(required_images, || Framebuffer::new(1));
|
||||||
|
framebuffers.into_boxed_slice()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load(path: impl AsRef<Path>) -> Result<FilterChain, Box<dyn Error>> {
|
pub fn load(path: impl AsRef<Path>) -> Result<FilterChain, Box<dyn Error>> {
|
||||||
// load passes from preset
|
// load passes from preset
|
||||||
|
@ -482,10 +556,14 @@ impl FilterChain {
|
||||||
// initialize output framebuffers
|
// initialize output framebuffers
|
||||||
let mut output_framebuffers = Vec::new();
|
let mut output_framebuffers = Vec::new();
|
||||||
output_framebuffers.resize_with(filters.len(), || Framebuffer::new(1));
|
output_framebuffers.resize_with(filters.len(), || Framebuffer::new(1));
|
||||||
|
let mut output_textures = Vec::new();
|
||||||
|
output_textures.resize_with(filters.len(), Texture::default);
|
||||||
|
|
||||||
// load luts
|
// load luts
|
||||||
let luts = FilterChain::load_luts(&preset.textures)?;
|
let luts = FilterChain::load_luts(&preset.textures)?;
|
||||||
|
|
||||||
|
let original_history = FilterChain::init_history(&filters);
|
||||||
|
|
||||||
// create VBO objects
|
// create VBO objects
|
||||||
let mut quad_vbo = 0;
|
let mut quad_vbo = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -507,20 +585,26 @@ impl FilterChain {
|
||||||
|
|
||||||
Ok(FilterChain {
|
Ok(FilterChain {
|
||||||
passes: filters,
|
passes: filters,
|
||||||
|
output_framebuffers: output_framebuffers.into_boxed_slice(),
|
||||||
quad_vao,
|
quad_vao,
|
||||||
common: FilterCommon {
|
common: FilterCommon {
|
||||||
semantics,
|
semantics,
|
||||||
preset,
|
preset,
|
||||||
original_history: vec![],
|
original_history,
|
||||||
history: vec![],
|
history: vec![],
|
||||||
feedback: vec![],
|
feedback: vec![],
|
||||||
luts,
|
luts,
|
||||||
outputs: output_framebuffers,
|
output_textures: output_textures.into_boxed_slice(),
|
||||||
quad_vbo,
|
quad_vbo,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_output_texture(&self, index: usize) -> Texture {
|
||||||
|
let config = &self.passes[index].config;
|
||||||
|
self.output_framebuffers[index].as_texture(config.filter, config.wrap_mode)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn frame(&mut self, count: usize, vp: &Viewport, input: GlImage, _clear: bool) {
|
pub fn frame(&mut self, count: usize, vp: &Viewport, input: GlImage, _clear: bool) {
|
||||||
if self.passes.is_empty() {
|
if self.passes.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
@ -562,7 +646,7 @@ impl FilterChain {
|
||||||
|
|
||||||
for (index, pass) in pass.iter_mut().enumerate() {
|
for (index, pass) in pass.iter_mut().enumerate() {
|
||||||
{
|
{
|
||||||
let target = &mut self.common.outputs[index];
|
let target = &mut self.output_framebuffers[index];
|
||||||
let _framebuffer_size = target.scale(
|
let _framebuffer_size = target.scale(
|
||||||
pass.config.scaling.clone(),
|
pass.config.scaling.clone(),
|
||||||
pass.get_format(),
|
pass.get_format(),
|
||||||
|
@ -571,8 +655,10 @@ impl FilterChain {
|
||||||
&source,
|
&source,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let target = &self.common.outputs[index];
|
|
||||||
|
let target = &self.output_framebuffers[index];
|
||||||
pass.draw(
|
pass.draw(
|
||||||
|
index,
|
||||||
&self.common,
|
&self.common,
|
||||||
(count % pass.config.frame_count_mod as usize) as u32,
|
(count % pass.config.frame_count_mod as usize) as u32,
|
||||||
1,
|
1,
|
||||||
|
@ -581,11 +667,11 @@ impl FilterChain {
|
||||||
&source,
|
&source,
|
||||||
RenderTarget::new(target, None),
|
RenderTarget::new(target, None),
|
||||||
);
|
);
|
||||||
let target = target.as_texture(pass.config.filter, pass.config.wrap_mode);
|
|
||||||
|
|
||||||
// todo: update-pass-outputs
|
let target = target.as_texture(pass.config.filter, pass.config.wrap_mode);
|
||||||
|
self.common.output_textures[index] = target;
|
||||||
source = target;
|
source = target;
|
||||||
// passes.build_semantics(&self, None, count, 1, vp, &original, &source);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(last.len(), 1);
|
assert_eq!(last.len(), 1);
|
||||||
|
@ -593,6 +679,7 @@ impl FilterChain {
|
||||||
source.filter = pass.config.filter;
|
source.filter = pass.config.filter;
|
||||||
source.mip_filter = pass.config.filter;
|
source.mip_filter = pass.config.filter;
|
||||||
pass.draw(
|
pass.draw(
|
||||||
|
passes_len - 1,
|
||||||
&self.common,
|
&self.common,
|
||||||
(count % pass.config.frame_count_mod as usize) as u32,
|
(count % pass.config.frame_count_mod as usize) as u32,
|
||||||
1,
|
1,
|
||||||
|
|
|
@ -135,6 +135,7 @@ impl FilterPass {
|
||||||
// todo: fix rendertargets (i.e. non-final pass is internal, final pass is user provided fbo)
|
// todo: fix rendertargets (i.e. non-final pass is internal, final pass is user provided fbo)
|
||||||
pub fn draw(
|
pub fn draw(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
pass_index: usize,
|
||||||
parent: &FilterCommon,
|
parent: &FilterCommon,
|
||||||
frame_count: u32,
|
frame_count: u32,
|
||||||
frame_direction: i32,
|
frame_direction: i32,
|
||||||
|
@ -151,6 +152,7 @@ impl FilterPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.build_semantics(
|
self.build_semantics(
|
||||||
|
pass_index,
|
||||||
parent,
|
parent,
|
||||||
output.mvp,
|
output.mvp,
|
||||||
frame_count,
|
frame_count,
|
||||||
|
@ -256,6 +258,7 @@ impl FilterPass {
|
||||||
// framecount should be pre-modded
|
// framecount should be pre-modded
|
||||||
fn build_semantics(
|
fn build_semantics(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
pass_index: usize,
|
||||||
parent: &FilterCommon,
|
parent: &FilterCommon,
|
||||||
mvp: &[f32],
|
mvp: &[f32],
|
||||||
frame_count: u32,
|
frame_count: u32,
|
||||||
|
@ -265,6 +268,7 @@ impl FilterPass {
|
||||||
original: &Texture,
|
original: &Texture,
|
||||||
source: &Texture,
|
source: &Texture,
|
||||||
) {
|
) {
|
||||||
|
// Bind MVP
|
||||||
if let Some((_location, offset)) =
|
if let Some((_location, offset)) =
|
||||||
self.variable_bindings.get(&VariableSemantics::MVP.into())
|
self.variable_bindings.get(&VariableSemantics::MVP.into())
|
||||||
{
|
{
|
||||||
|
@ -276,6 +280,7 @@ impl FilterPass {
|
||||||
FilterPass::build_mvp(&mut buffer[offset..][..mvp_size], mvp)
|
FilterPass::build_mvp(&mut buffer[offset..][..mvp_size], mvp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bind OutputSize
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.variable_bindings
|
||||||
.get(&VariableSemantics::Output.into())
|
.get(&VariableSemantics::Output.into())
|
||||||
|
@ -288,6 +293,7 @@ impl FilterPass {
|
||||||
FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], fb_size)
|
FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], fb_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bind FinalViewportSize
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.variable_bindings
|
||||||
.get(&VariableSemantics::FinalViewport.into())
|
.get(&VariableSemantics::FinalViewport.into())
|
||||||
|
@ -303,6 +309,7 @@ impl FilterPass {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bind FrameCount
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.variable_bindings
|
||||||
.get(&VariableSemantics::FrameCount.into())
|
.get(&VariableSemantics::FrameCount.into())
|
||||||
|
@ -314,6 +321,7 @@ impl FilterPass {
|
||||||
FilterPass::build_uint(location.location(), &mut buffer[offset..][..4], frame_count)
|
FilterPass::build_uint(location.location(), &mut buffer[offset..][..4], frame_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bind FrameDirection
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.variable_bindings
|
||||||
.get(&VariableSemantics::FrameDirection.into())
|
.get(&VariableSemantics::FrameDirection.into())
|
||||||
|
@ -329,6 +337,7 @@ impl FilterPass {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bind Original sampler
|
||||||
if let Some(binding) = self
|
if let Some(binding) = self
|
||||||
.reflection
|
.reflection
|
||||||
.meta
|
.meta
|
||||||
|
@ -339,6 +348,7 @@ impl FilterPass {
|
||||||
FilterPass::bind_texture(binding, original);
|
FilterPass::bind_texture(binding, original);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bind OriginalSize
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.variable_bindings
|
||||||
.get(&TextureSemantics::Original.semantics(0).into())
|
.get(&TextureSemantics::Original.semantics(0).into())
|
||||||
|
@ -354,6 +364,7 @@ impl FilterPass {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bind Source sampler
|
||||||
if let Some(binding) = self
|
if let Some(binding) = self
|
||||||
.reflection
|
.reflection
|
||||||
.meta
|
.meta
|
||||||
|
@ -363,6 +374,8 @@ impl FilterPass {
|
||||||
// eprintln!("setting source binding to {}", binding.binding);
|
// eprintln!("setting source binding to {}", binding.binding);
|
||||||
FilterPass::bind_texture(binding, source);
|
FilterPass::bind_texture(binding, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bind SourceSize
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.variable_bindings
|
||||||
.get(&TextureSemantics::Source.semantics(0).into())
|
.get(&TextureSemantics::Source.semantics(0).into())
|
||||||
|
@ -378,6 +391,32 @@ impl FilterPass {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (index, output) in parent.output_textures[0..pass_index].iter().enumerate() {
|
||||||
|
if let Some(binding) = self
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_meta
|
||||||
|
.get(&TextureSemantics::PassOutput.semantics(index))
|
||||||
|
{
|
||||||
|
FilterPass::bind_texture(binding, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((location, offset)) = self
|
||||||
|
.variable_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..][..4],
|
||||||
|
output.image.size,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// // todo: history
|
// // todo: history
|
||||||
//
|
//
|
||||||
// // if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) {
|
// // if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) {
|
||||||
|
@ -392,6 +431,8 @@ impl FilterPass {
|
||||||
// // FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size);
|
// // FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size);
|
||||||
// // }
|
// // }
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// bind float parameters
|
||||||
for (id, (location, offset)) in
|
for (id, (location, offset)) in
|
||||||
self.variable_bindings
|
self.variable_bindings
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -426,30 +467,25 @@ impl FilterPass {
|
||||||
FilterPass::build_float(location.location(), &mut buffer[offset..][..4], value)
|
FilterPass::build_float(location.location(), &mut buffer[offset..][..4], value)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (id, (location, offset)) in
|
// bind luts
|
||||||
self.variable_bindings
|
for (index, lut) in &parent.luts {
|
||||||
.iter()
|
if let Some(binding) = self
|
||||||
.filter_map(|(binding, value)| match binding {
|
.reflection
|
||||||
UniformBinding::TextureSize(semantics) => {
|
.meta
|
||||||
if semantics.semantics == TextureSemantics::User {
|
.texture_meta
|
||||||
Some((semantics, value))
|
.get(&TextureSemantics::User.semantics(*index))
|
||||||
} else {
|
{
|
||||||
None
|
FilterPass::bind_texture(binding, lut);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
{
|
|
||||||
let (buffer, offset) = match offset {
|
|
||||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(lut) = parent.luts.get(&id.index) {
|
|
||||||
if let Some(binding) = self.reflection.meta.texture_meta.get(id) {
|
|
||||||
FilterPass::bind_texture(binding, lut);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if let Some((location, offset)) = self
|
||||||
|
.variable_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(
|
FilterPass::build_vec4(
|
||||||
location.location(),
|
location.location(),
|
||||||
&mut buffer[offset..][..4],
|
&mut buffer[offset..][..4],
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub fn calc_miplevel(width: u32, height: u32) -> u32 {
|
||||||
levels
|
levels
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Default, Debug, Copy, Clone)]
|
||||||
pub struct Texture {
|
pub struct Texture {
|
||||||
pub image: GlImage,
|
pub image: GlImage,
|
||||||
pub filter: FilterMode,
|
pub filter: FilterMode,
|
||||||
|
@ -35,7 +35,7 @@ pub struct Size {
|
||||||
pub height: u32,
|
pub height: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Default, Debug, Copy, Clone)]
|
||||||
pub struct GlImage {
|
pub struct GlImage {
|
||||||
pub handle: GLuint,
|
pub handle: GLuint,
|
||||||
pub format: GLenum,
|
pub format: GLenum,
|
||||||
|
|
Loading…
Reference in a new issue