gl: clean up uniform binding storage

This commit is contained in:
chyyran 2022-11-19 18:48:54 -05:00
parent 2c8f2685f2
commit d49fa5307a
9 changed files with 296 additions and 177 deletions

View file

@ -51,7 +51,7 @@ where
{ {
fn reflect( fn reflect(
&mut self, &mut self,
pass_number: u32, pass_number: usize,
semantics: &ReflectSemantics, semantics: &ReflectSemantics,
) -> Result<ShaderReflection, ShaderReflectError> { ) -> Result<ShaderReflection, ShaderReflectError> {
self.backend.reflect(pass_number, semantics) self.backend.reflect(pass_number, semantics)

View file

@ -46,7 +46,7 @@ pub enum ShaderReflectError {
#[error("vertx and fragment shader must have same binding")] #[error("vertx and fragment shader must have same binding")]
MismatchedUniformBuffer { vertex: u32, fragment: u32 }, MismatchedUniformBuffer { vertex: u32, fragment: u32 },
#[error("filter chain is non causal")] #[error("filter chain is non causal")]
NonCausalFilterChain { pass: u32, target: u32 }, NonCausalFilterChain { pass: usize, target: usize },
#[error("mismatched offset")] #[error("mismatched offset")]
MismatchedOffset { MismatchedOffset {
semantic: String, semantic: String,

View file

@ -284,7 +284,7 @@ where
fn reflect_buffer_range_metas( fn reflect_buffer_range_metas(
ast: &Ast<T>, ast: &Ast<T>,
resource: &Resource, resource: &Resource,
pass_number: u32, pass_number: usize,
semantics: &ReflectSemantics, semantics: &ReflectSemantics,
meta: &mut ReflectMeta, meta: &mut ReflectMeta,
offset_type: impl Fn(usize) -> MemberOffset, offset_type: impl Fn(usize) -> MemberOffset,
@ -478,7 +478,7 @@ where
fn reflect_texture_metas( fn reflect_texture_metas(
&self, &self,
texture: TextureData, texture: TextureData,
pass_number: u32, pass_number: usize,
semantics: &ReflectSemantics, semantics: &ReflectSemantics,
meta: &mut ReflectMeta, meta: &mut ReflectMeta,
) -> Result<(), ShaderReflectError> { ) -> Result<(), ShaderReflectError> {
@ -594,7 +594,7 @@ where
{ {
fn reflect( fn reflect(
&mut self, &mut self,
pass_number: u32, pass_number: usize,
semantics: &ReflectSemantics, semantics: &ReflectSemantics,
) -> Result<ShaderReflection, ShaderReflectError> { ) -> Result<ShaderReflection, ShaderReflectError> {
let vertex_res = self.vertex.get_shader_resources()?; let vertex_res = self.vertex.get_shader_resources()?;
@ -707,19 +707,19 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
for res in &vertex_resources.stage_inputs { for res in &vertex_resources.stage_inputs {
let location = self.vertex.get_decoration(res.id, Decoration::Location)?; let location = self.vertex.get_decoration(res.id, Decoration::Location)?;
self.vertex self.vertex
.set_name(res.id, &format!("RARCH_ATTRIBUTE_{location}"))?; .set_name(res.id, &format!("LIBRA_ATTRIBUTE_{location}"))?;
self.vertex.unset_decoration(res.id, Decoration::Location)?; self.vertex.unset_decoration(res.id, Decoration::Location)?;
} }
for res in &vertex_resources.stage_outputs { for res in &vertex_resources.stage_outputs {
let location = self.vertex.get_decoration(res.id, Decoration::Location)?; let location = self.vertex.get_decoration(res.id, Decoration::Location)?;
self.vertex self.vertex
.set_name(res.id, &format!("RARCH_VARYING_{location}"))?; .set_name(res.id, &format!("LIBRA_VARYING_{location}"))?;
self.vertex.unset_decoration(res.id, Decoration::Location)?; self.vertex.unset_decoration(res.id, Decoration::Location)?;
} }
for res in &fragment_resources.stage_inputs { for res in &fragment_resources.stage_inputs {
let location = self.fragment.get_decoration(res.id, Decoration::Location)?; let location = self.fragment.get_decoration(res.id, Decoration::Location)?;
self.fragment self.fragment
.set_name(res.id, &format!("RARCH_VARYING_{location}"))?; .set_name(res.id, &format!("LIBRA_VARYING_{location}"))?;
self.fragment self.fragment
.unset_decoration(res.id, Decoration::Location)?; .unset_decoration(res.id, Decoration::Location)?;
} }
@ -732,9 +732,9 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
)); ));
} }
for res in &vertex_resources.push_constant_buffers { for res in &vertex_resources.push_constant_buffers {
self.vertex.set_name(res.id, "RARCH_PUSH_VERTEX_INSTANCE")?; self.vertex.set_name(res.id, "LIBRA_PUSH_VERTEX_INSTANCE")?;
self.vertex self.vertex
.set_name(res.base_type_id, "RARCH_PUSH_VERTEX")?; .set_name(res.base_type_id, "LIBRA_PUSH_VERTEX")?;
} }
// todo: options // todo: options
@ -751,8 +751,8 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
// if flatten { // if flatten {
// self.vertex.flatten_buffer_block(res.id)?; // self.vertex.flatten_buffer_block(res.id)?;
// } // }
self.vertex.set_name(res.id, "RARCH_UBO_VERTEX_INSTANCE")?; self.vertex.set_name(res.id, "LIBRA_UBO_VERTEX_INSTANCE")?;
self.vertex.set_name(res.base_type_id, "RARCH_UBO_VERTEX")?; self.vertex.set_name(res.base_type_id, "LIBRA_UBO_VERTEX")?;
self.vertex self.vertex
.unset_decoration(res.id, Decoration::DescriptorSet)?; .unset_decoration(res.id, Decoration::DescriptorSet)?;
self.vertex.unset_decoration(res.id, Decoration::Binding)?; self.vertex.unset_decoration(res.id, Decoration::Binding)?;
@ -767,9 +767,9 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
} }
for res in &fragment_resources.push_constant_buffers { for res in &fragment_resources.push_constant_buffers {
self.fragment self.fragment
.set_name(res.id, "RARCH_PUSH_FRAGMENT_INSTANCE")?; .set_name(res.id, "LIBRA_PUSH_FRAGMENT_INSTANCE")?;
self.fragment self.fragment
.set_name(res.base_type_id, "RARCH_PUSH_FRAGMENT")?; .set_name(res.base_type_id, "LIBRA_PUSH_FRAGMENT")?;
} }
if fragment_resources.uniform_buffers.len() > 1 { if fragment_resources.uniform_buffers.len() > 1 {
@ -785,9 +785,9 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
// self.fragment.flatten_buffer_block(res.id)?; // self.fragment.flatten_buffer_block(res.id)?;
// } // }
self.fragment self.fragment
.set_name(res.id, "RARCH_UBO_FRAGMENT_INSTANCE")?; .set_name(res.id, "LIBRA_UBO_FRAGMENT_INSTANCE")?;
self.fragment self.fragment
.set_name(res.base_type_id, "RARCH_UBO_FRAGMENT")?; .set_name(res.base_type_id, "LIBRA_UBO_FRAGMENT")?;
self.fragment self.fragment
.unset_decoration(res.id, Decoration::DescriptorSet)?; .unset_decoration(res.id, Decoration::DescriptorSet)?;
self.fragment self.fragment
@ -798,7 +798,7 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
for res in &fragment_resources.sampled_images { for res in &fragment_resources.sampled_images {
let binding = self.fragment.get_decoration(res.id, Decoration::Binding)?; let binding = self.fragment.get_decoration(res.id, Decoration::Binding)?;
self.fragment self.fragment
.set_name(res.id, &format!("RARCH_TEXTURE_{binding}"))?; .set_name(res.id, &format!("LIBRA_TEXTURE_{binding}"))?;
self.fragment self.fragment
.unset_decoration(res.id, Decoration::DescriptorSet)?; .unset_decoration(res.id, Decoration::DescriptorSet)?;
self.fragment self.fragment

View file

@ -13,7 +13,7 @@ pub mod semantics;
pub trait ReflectShader { pub trait ReflectShader {
fn reflect( fn reflect(
&mut self, &mut self,
pass_number: u32, pass_number: usize,
semantics: &ReflectSemantics, semantics: &ReflectSemantics,
) -> Result<ShaderReflection, ShaderReflectError>; ) -> Result<ShaderReflection, ShaderReflectError>;
} }
@ -69,7 +69,7 @@ impl TextureSemanticMap<UniformSemantic> for FxHashMap<String, UniformSemantic>
{ {
if semantics.is_array() { if semantics.is_array() {
let index = &name[semantics.size_uniform_name().len()..]; let index = &name[semantics.size_uniform_name().len()..];
let Ok(index) = u32::from_str(index) else { let Ok(index) = usize::from_str(index) else {
return None; return None;
}; };
return Some(SemanticMap { return Some(SemanticMap {
@ -101,7 +101,7 @@ impl TextureSemanticMap<UniformSemantic> for FxHashMap<String, SemanticMap<Textu
{ {
if semantics.is_array() { if semantics.is_array() {
let index = &name[semantics.texture_name().len()..]; let index = &name[semantics.texture_name().len()..];
let Ok(index) = u32::from_str(index) else {return None}; let Ok(index) = usize::from_str(index) else {return None};
return Some(SemanticMap { return Some(SemanticMap {
semantics: *semantics, semantics: *semantics,
index, index,

View file

@ -5,6 +5,15 @@ pub const BASE_SEMANTICS_COUNT: usize = 5;
pub const MAX_BINDINGS_COUNT: u32 = 16; pub const MAX_BINDINGS_COUNT: u32 = 16;
pub const MAX_PUSH_BUFFER_SIZE: u32 = 128; pub const MAX_PUSH_BUFFER_SIZE: u32 = 128;
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
pub enum UniformType {
MVP,
Size,
Unsigned,
Signed,
Float
}
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)] #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
#[repr(i32)] #[repr(i32)]
pub enum VariableSemantics { pub enum VariableSemantics {
@ -29,6 +38,17 @@ impl VariableSemantics {
index: () index: ()
} }
} }
pub const fn binding_type(&self) -> UniformType {
match self {
VariableSemantics::MVP => UniformType::MVP,
VariableSemantics::Output => UniformType::Size,
VariableSemantics::FinalViewport => UniformType::Size,
VariableSemantics::FrameCount => UniformType::Unsigned,
VariableSemantics::FrameDirection => UniformType::Signed,
VariableSemantics::FloatParameter => UniformType::Float
}
}
} }
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)] #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
@ -78,7 +98,7 @@ impl TextureSemantics {
!matches!(self, TextureSemantics::Original | TextureSemantics::Source) !matches!(self, TextureSemantics::Original | TextureSemantics::Source)
} }
pub const fn semantics(self, index: u32) -> SemanticMap<TextureSemantics, u32> { pub const fn semantics(self, index: usize) -> SemanticMap<TextureSemantics> {
SemanticMap { SemanticMap {
semantics: self, semantics: self,
index index
@ -95,7 +115,7 @@ pub trait ValidateTypeSemantics<T> {
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct SemanticMap<T, I=u32> { pub struct SemanticMap<T, I=usize> {
pub semantics: T, pub semantics: T,
pub index: I, pub index: I,
} }
@ -160,3 +180,28 @@ pub struct ShaderReflection {
pub push_constant: Option<PushReflection>, pub push_constant: Option<PushReflection>,
pub meta: ReflectMeta, pub meta: ReflectMeta,
} }
pub trait UniformMeta {
fn offset(&self) -> MemberOffset;
fn id(&self) -> &str;
}
impl UniformMeta for VariableMeta {
fn offset(&self) -> MemberOffset {
self.offset
}
fn id(&self) -> &str {
&self.id
}
}
impl UniformMeta for TextureSizeMeta {
fn offset(&self) -> MemberOffset {
self.offset
}
fn id(&self) -> &str {
&self.id
}
}

View file

@ -0,0 +1,66 @@
use std::borrow::Borrow;
use std::hash::{Hash, Hasher};
use gl::types::GLint;
use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureSemantics, VariableSemantics};
#[derive(Debug)]
pub enum VariableLocation {
Ubo(UniformLocation<GLint>),
Push(UniformLocation<GLint>),
}
impl VariableLocation {
pub fn location(&self) -> UniformLocation<GLint> {
match self {
VariableLocation::Ubo(l) | VariableLocation::Push(l) => *l
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct UniformLocation<T> {
pub vertex: T,
pub fragment: T,
}
impl UniformLocation<GLint> {
pub fn is_fragment_valid(&self) -> bool {
self.fragment >= 0
}
pub fn is_vertex_valid(&self) -> bool {
self.vertex >= 0
}
pub fn is_valid(&self) -> bool {
self.is_fragment_valid() || self.is_vertex_valid()
}
}
#[derive(Debug, Copy, Clone)]
pub enum MemberLocation {
Offset(MemberOffset),
Uniform(UniformLocation<GLint>)
}
#[derive(Debug, Copy, Clone)]
pub struct TextureUnit<T>(T);
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub enum UniformBinding {
Parameter(String),
SemanticVariable(VariableSemantics),
TextureSize(SemanticMap<TextureSemantics>),
}
impl From<VariableSemantics> for UniformBinding {
fn from(value: VariableSemantics) -> Self {
UniformBinding::SemanticVariable(value)
}
}
impl From<SemanticMap<TextureSemantics>> for UniformBinding {
fn from(value: SemanticMap<TextureSemantics>) -> Self {
UniformBinding::TextureSize(value)
}
}

View file

@ -1,3 +1,4 @@
use std::borrow::Borrow;
use std::iter::Filter; use std::iter::Filter;
use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint}; use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint};
use librashader_reflect::back::cross::GlslangGlslContext; use librashader_reflect::back::cross::GlslangGlslContext;
@ -11,17 +12,18 @@ use librashader_presets::{Scale2D, ScaleType, Scaling, ShaderPassConfig, ShaderP
use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureImage, TextureSemantics, VariableMeta, VariableSemantics}; use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureImage, TextureSemantics, VariableMeta, VariableSemantics};
use crate::{FilterChain, FilterCommon}; use crate::{FilterChain, FilterCommon};
use crate::framebuffer::Framebuffer; use crate::framebuffer::Framebuffer;
use crate::util::{Location, VariableLocation, RingBuffer, Size, GlImage, Texture, Viewport}; use crate::binding::{UniformBinding, UniformLocation, VariableLocation};
use crate::util::{GlImage, RingBuffer, Size, Texture, Viewport};
pub struct FilterPass { pub struct FilterPass {
pub reflection: ShaderReflection, pub reflection: ShaderReflection,
pub compiled: ShaderCompilerOutput<String, GlslangGlslContext>, pub compiled: ShaderCompilerOutput<String, GlslangGlslContext>,
pub program: GLuint, pub program: GLuint,
pub ubo_location: Location<GLuint>, pub ubo_location: UniformLocation<GLuint>,
pub ubo_ring: Option<RingBuffer<GLuint, 16>>, pub ubo_ring: Option<RingBuffer<GLuint, 16>>,
pub uniform_buffer: Box<[u8]>, pub uniform_buffer: Box<[u8]>,
pub push_buffer: Box<[u8]>, pub push_buffer: Box<[u8]>,
pub locations: FxHashMap<String, VariableLocation>, pub variable_bindings: FxHashMap<UniformBinding, (VariableLocation, MemberOffset)>,
pub framebuffer: Framebuffer, pub framebuffer: Framebuffer,
pub feedback_framebuffer: Framebuffer, pub feedback_framebuffer: Framebuffer,
pub source: ShaderSource, pub source: ShaderSource,
@ -34,7 +36,7 @@ impl FilterPass {
buffer.copy_from_slice(mvp); buffer.copy_from_slice(mvp);
} }
fn build_vec4(location: Location<GLint>, buffer: &mut [u8], size: Size) { fn build_vec4(location: UniformLocation<GLint>, buffer: &mut [u8], size: Size) {
let vec4 = [size.width as f32, size.height as f32, 1.0 / size.width as f32, 1.0/ size.height as f32]; let vec4 = [size.width as f32, size.height as f32, 1.0 / size.width as f32, 1.0/ size.height as f32];
if location.fragment >= 0 || location.vertex >= 0 { if location.fragment >= 0 || location.vertex >= 0 {
unsafe { unsafe {
@ -52,7 +54,7 @@ impl FilterPass {
} }
#[inline(always)] #[inline(always)]
fn build_uniform<T>(location: Location<GLint>, buffer: &mut [u8], value: T, glfn: unsafe fn(GLint, T) -> ()) fn build_uniform<T>(location: UniformLocation<GLint>, buffer: &mut [u8], value: T, glfn: unsafe fn(GLint, T) -> ())
where T: Copy, T: bytemuck::Pod where T: Copy, T: bytemuck::Pod
{ {
if location.fragment >= 0 || location.vertex >= 0 { if location.fragment >= 0 || location.vertex >= 0 {
@ -70,19 +72,19 @@ impl FilterPass {
} }
} }
fn build_uint(location: Location<GLint>, buffer: &mut [u8], value: u32) { fn build_uint(location: UniformLocation<GLint>, buffer: &mut [u8], value: u32) {
Self::build_uniform(location, buffer, value, gl::Uniform1ui) Self::build_uniform(location, buffer, value, gl::Uniform1ui)
} }
fn build_sint(location: Location<GLint>, buffer: &mut [u8], value: i32) { fn build_sint(location: UniformLocation<GLint>, buffer: &mut [u8], value: i32) {
Self::build_uniform(location, buffer, value, gl::Uniform1i) Self::build_uniform(location, buffer, value, gl::Uniform1i)
} }
fn build_float(location: Location<GLint>, buffer: &mut [u8], value: f32) { fn build_float(location: UniformLocation<GLint>, buffer: &mut [u8], value: f32) {
Self::build_uniform(location, buffer, value, gl::Uniform1f) Self::build_uniform(location, buffer, value, gl::Uniform1f)
} }
fn set_texture(binding: &TextureImage, texture: &Texture) { fn bind_texture(binding: &TextureImage, texture: &Texture) {
unsafe { unsafe {
// eprintln!("binding {} = texture {}", binding.binding, texture.image.handle); // eprintln!("binding {} = texture {}", binding.binding, texture.image.handle);
gl::ActiveTexture((gl::TEXTURE0 + binding.binding) as GLenum); gl::ActiveTexture((gl::TEXTURE0 + binding.binding) as GLenum);
@ -158,7 +160,8 @@ impl FilterPass {
size size
} }
pub fn build_commands(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, viewport: &Viewport, original: &Texture, source: &Texture) { // todo: fix rendertargets (i.e. non-final pass is internal, final pass is user provided fbo)
pub fn build_commands(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: i32, viewport: &Viewport, original: &Texture, source: &Texture) {
let mut fb_format = ShaderFormat::R8G8B8A8Unorm; let mut fb_format = ShaderFormat::R8G8B8A8Unorm;
if self.config.srgb_framebuffer { if self.config.srgb_framebuffer {
fb_format = ShaderFormat::R8G8B8A8Srgb; fb_format = ShaderFormat::R8G8B8A8Srgb;
@ -247,134 +250,148 @@ impl FilterPass {
} }
// framecount should be pre-modded // framecount should be pre-modded
fn build_semantics(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, fb_size: Size, viewport: &Viewport, original: &Texture, source: &Texture) { fn build_semantics(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: i32, fb_size: Size, viewport: &Viewport, original: &Texture, source: &Texture) {
if let Some((_location, offset)) = self.variable_bindings.get(&VariableSemantics::MVP.into()) {
if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::MVP) { let mvp = mvp.unwrap_or(&[
let mvp = mvp.unwrap_or(&[ 2f32, 0.0, 0.0, 0.0,
2f32, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0,
0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0,
0.0, 0.0, 2.0, 0.0, -1.0, -1.0, 0.0, 1.0
-1.0, -1.0, 0.0, 1.0 ]);
]); let mvp_size = mvp.len() * std::mem::size_of::<f32>();
let (buffer, offset) = match offset {
let mvp_size = mvp.len() * std::mem::size_of::<f32>(); MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
let (buffer, offset) = match variable.offset { MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), };
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) FilterPass::build_mvp(&mut buffer[offset..][..mvp_size], mvp)
};
FilterPass::build_mvp(&mut buffer[offset..][..mvp_size], mvp)
} }
if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::Output) { if let Some((location, offset)) = self.variable_bindings.get(&VariableSemantics::Output.into()) {
let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); let (buffer, offset) = match offset {
let (buffer, offset) = match variable.offset { MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
};
FilterPass::build_vec4(location, &mut buffer[offset..][..4], fb_size)
}
if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::FinalViewport) {
// todo: do all variables have location..?
let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location();
let (buffer, offset) = match variable.offset {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
};
FilterPass::build_vec4(location, &mut buffer[offset..][..4], viewport.size)
}
if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::FrameCount) {
// todo: do all variables have location..?
let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location();
let (buffer, offset) = match variable.offset {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
};
FilterPass::build_uint(location, &mut buffer[offset..][..4], frame_count)
}
if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::FrameDirection) {
// todo: do all variables have location..?
let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location();
let (buffer, offset) = match variable.offset {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
}; };
FilterPass::build_uint(location, &mut buffer[offset..][..4], frame_direction) FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], fb_size)
} }
if let Some((location, offset)) = self.variable_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..][..4], viewport.size)
}
if let Some((location, offset)) = self.variable_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)
}
if let Some((location, offset)) = self.variable_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)
}
if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Original.semantics(0)) { if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Original.semantics(0)) {
eprintln!("setting original binding to {}", binding.binding); eprintln!("setting original binding to {}", binding.binding);
FilterPass::set_texture(binding, original); FilterPass::bind_texture(binding, original);
} }
if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::Original.semantics(0)) {
let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); if let Some((location, offset)) = self.variable_bindings.get(&TextureSemantics::Original.semantics(0).into()) {
let (buffer, offset) = match variable.offset { let (buffer, offset) = match offset {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
}; };
FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size); FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], original.image.size);
} }
if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Source.semantics(0)) { if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Source.semantics(0)) {
// eprintln!("setting source binding to {}", binding.binding); // eprintln!("setting source binding to {}", binding.binding);
FilterPass::set_texture(binding, source); FilterPass::bind_texture(binding, source);
} }
if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::Source.semantics(0)) { if let Some((location, offset)) = self.variable_bindings.get(&TextureSemantics::Source.semantics(0).into()) {
let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); let (buffer, offset) = match offset {
let (buffer, offset) = match variable.offset { MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
}; };
FilterPass::build_vec4(location, &mut buffer[offset..][..4], source.image.size); FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], source.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)) { // // FilterPass::set_texture(binding, original);
// FilterPass::set_texture(binding, original); // // }
// } // // if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) {
// if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) { // // let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location();
// let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); // // let (buffer, offset) = match variable.offset {
// let (buffer, offset) = match variable.offset { // // MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
// MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), // // MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
// MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) // // };
// }; // // FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size);
// FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size); // // }
// } //
for (id, (location, offset)) in self.variable_bindings.iter()
for variable in self.reflection.meta.parameter_meta.values() { .filter_map(|(binding, value)| match binding {
let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); UniformBinding::Parameter(id) => {
let (buffer, offset) = match variable.offset { Some((id, value))
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), }
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) _ => None
})
{
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)
}; };
// presets override params // presets override params
let default = self.source.parameters.iter().find(|&p| p.id == variable.id) let default = self.source.parameters.iter().find(|&p| p.id == id)
.map(|f| f.initial) .map(|f| f.initial)
.unwrap_or(0f32); .unwrap_or(0f32);
let value = parent.preset.parameters.iter().find(|&p| p.name == variable.id) let value = parent.preset.parameters.iter().find(|&p| p.name == id)
.map(|p| p.value) .map(|p| p.value)
.unwrap_or(default); .unwrap_or(default);
FilterPass::build_float(location, &mut buffer[offset..][..4], value) FilterPass::build_float(location.location(), &mut buffer[offset..][..4], value)
} }
// todo: deal with both lut name and index for (id, (location, offset)) in self.variable_bindings.iter()
// for (index, lut) in parent.luts.values().enumerate() { .filter_map(|(binding, value)| match binding {
// // todo: sort out order UniformBinding::TextureSize(semantics) => {
// if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::User.semantics(index as u32)) { if semantics.semantics == TextureSemantics::User {
// } Some((semantics, value))
// } else {
// } None
// todo history }
}
_ => 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);
}
FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4],
lut.image.size);
}
}
// // todo history
} }
} }

View file

@ -5,6 +5,7 @@ mod filter;
mod filter_pass; mod filter_pass;
mod util; mod util;
mod framebuffer; mod framebuffer;
mod binding;
use std::collections::HashMap; use std::collections::HashMap;
use std::error::Error; use std::error::Error;
@ -26,9 +27,11 @@ use librashader_reflect::back::targets::{FromCompilation, GLSL};
use librashader_reflect::front::shaderc::GlslangCompilation; use librashader_reflect::front::shaderc::GlslangCompilation;
use librashader_reflect::reflect::cross::CrossReflect; use librashader_reflect::reflect::cross::CrossReflect;
use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, ShaderReflection, UniformSemantic}; use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, ShaderReflection, UniformSemantic};
use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureSemantics, VariableMeta, VariableSemantics}; use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureSemantics, UniformMeta, VariableMeta, VariableSemantics};
use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap}; use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap};
use util::{Location, VariableLocation, RingBuffer, Size, GlImage, Texture, Viewport}; use binding::{UniformLocation, VariableLocation};
use util::{GlImage, RingBuffer, Size, Texture, Viewport};
use crate::binding::UniformBinding;
unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint { unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint {
let shader = gl::CreateShader(stage); let shader = gl::CreateShader(stage);
@ -63,7 +66,7 @@ impl FilterChain {
return; return;
} }
let index = config.id as u32; let index = config.id as usize;
// PassOutput // PassOutput
texture_semantics.insert(alias.clone(), SemanticMap { texture_semantics.insert(alias.clone(), SemanticMap {
@ -86,31 +89,31 @@ impl FilterChain {
})); }));
} }
fn reflect_parameter(pipeline: GLuint, meta: &VariableMeta) -> VariableLocation { fn reflect_uniform_location(pipeline: GLuint, meta: &impl UniformMeta) -> VariableLocation {
// todo: support both ubo and pushco // todo: support both ubo and pushco
// todo: fix this. // todo: fix this.
match meta.offset { match meta.offset() {
MemberOffset::Ubo(_) => { MemberOffset::Ubo(_) => {
let vert_name = format!("RARCH_UBO_VERTEX_INSTANCE.{}\0", meta.id); let vert_name = format!("LIBRA_UBO_VERTEX_INSTANCE.{}\0", meta.id());
let frag_name = format!("RARCH_UBO_FRAGMENT_INSTANCE.{}\0", meta.id); let frag_name = format!("LIBRA_UBO_FRAGMENT_INSTANCE.{}\0", meta.id());
unsafe { unsafe {
let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast()); let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast());
let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast()); let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast());
VariableLocation::Ubo(Location { VariableLocation::Ubo(UniformLocation {
vertex, vertex,
fragment fragment
}) })
} }
} }
MemberOffset::PushConstant(_) => { MemberOffset::PushConstant(_) => {
let vert_name = format!("RARCH_PUSH_VERTEX_INSTANCE.{}\0", meta.id); let vert_name = format!("LIBRA_PUSH_VERTEX_INSTANCE.{}\0", meta.id());
let frag_name = format!("RARCH_PUSH_FRAGMENT_INSTANCE.{}\0", meta.id); let frag_name = format!("LIBRA_PUSH_FRAGMENT_INSTANCE.{}\0", meta.id());
unsafe { unsafe {
let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast()); let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast());
let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast()); let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast());
VariableLocation::Push(Location { VariableLocation::Push(UniformLocation {
vertex, vertex,
fragment fragment
}) })
@ -133,7 +136,7 @@ pub struct FilterCommon {
original_history: Vec<Framebuffer>, original_history: Vec<Framebuffer>,
history: Vec<Texture>, history: Vec<Texture>,
feedback: Vec<Texture>, feedback: Vec<Texture>,
luts: FxHashMap<String, Texture>, luts: FxHashMap<usize, Texture>,
pub quad_vbo: GLuint, pub quad_vbo: GLuint,
pub input_framebuffer: Framebuffer, pub input_framebuffer: Framebuffer,
} }
@ -174,12 +177,12 @@ impl FilterChain {
for (index, texture) in preset.textures.iter().enumerate() { for (index, texture) in preset.textures.iter().enumerate() {
texture_semantics.insert(texture.name.clone(), SemanticMap { texture_semantics.insert(texture.name.clone(), SemanticMap {
semantics: TextureSemantics::User, semantics: TextureSemantics::User,
index: index as u32 index
}); });
uniform_semantics.insert(format!("{}Size", texture.name), UniformSemantic::Texture(SemanticMap { uniform_semantics.insert(format!("{}Size", texture.name), UniformSemantic::Texture(SemanticMap {
semantics: TextureSemantics::User, semantics: TextureSemantics::User,
index: index as u32 index
})); }));
} }
@ -194,7 +197,7 @@ impl FilterChain {
for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() { for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() {
let mut semantics = semantics.clone(); let mut semantics = semantics.clone();
let reflection = reflect.reflect(index as u32, &semantics)?; let reflection = reflect.reflect(index, &semantics)?;
let glsl = reflect.compile(GlVersion::V4_60)?; let glsl = reflect.compile(GlVersion::V4_60)?;
let vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?; let vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?;
@ -210,7 +213,7 @@ impl FilterChain {
for res in &vertex_resources.stage_inputs { for res in &vertex_resources.stage_inputs {
let loc = glsl.context.compiler.vertex.get_decoration(res.id, Decoration::Location)?; let loc = glsl.context.compiler.vertex.get_decoration(res.id, Decoration::Location)?;
let loc_name = format!("RARCH_ATTRIBUTE_{loc}\0"); let loc_name = format!("LIBRA_ATTRIBUTE_{loc}\0");
eprintln!("{loc_name}"); eprintln!("{loc_name}");
gl::BindAttribLocation(program, loc, loc_name.as_str().as_ptr().cast()) gl::BindAttribLocation(program, loc, loc_name.as_str().as_ptr().cast())
} }
@ -225,7 +228,7 @@ impl FilterChain {
} }
for binding in &glsl.context.texture_fixups { for binding in &glsl.context.texture_fixups {
let loc_name = format!("RARCH_TEXTURE_{}\0", *binding); let loc_name = format!("LIBRA_TEXTURE_{}\0", *binding);
unsafe { unsafe {
let location = gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast()); let location = gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast());
if location >= 0 { if location >= 0 {
@ -236,9 +239,9 @@ impl FilterChain {
unsafe { unsafe {
gl::UseProgram(0); gl::UseProgram(0);
(program, Location { (program, UniformLocation {
vertex: gl::GetUniformBlockIndex(program, b"RARCH_UBO_VERTEX\0".as_ptr().cast()), vertex: gl::GetUniformBlockIndex(program, b"LIBRA_UBO_VERTEX\0".as_ptr().cast()),
fragment: gl::GetUniformBlockIndex(program, b"RARCH_UBO_FRAGMENT\0".as_ptr().cast()), fragment: gl::GetUniformBlockIndex(program, b"LIBRA_UBO_FRAGMENT\0".as_ptr().cast()),
}) })
} }
}; };
@ -265,13 +268,21 @@ impl FilterChain {
// todo: reflect indexed parameters // todo: reflect indexed parameters
let mut locations = FxHashMap::default(); let mut locations = FxHashMap::default();
for param in reflection.meta.parameter_meta.values() { for param in reflection.meta.parameter_meta.values() {
locations.insert(param.id.clone(), FilterChain::reflect_parameter(program, param)); locations.insert(UniformBinding::Parameter(param.id.clone()),
(FilterChain::reflect_uniform_location(program, param), param.offset));
} }
for param in reflection.meta.variable_meta.values() { for (semantics, param) in &reflection.meta.variable_meta {
locations.insert(param.id.clone(), FilterChain::reflect_parameter(program, param)); locations.insert(UniformBinding::SemanticVariable(semantics.clone()),
(FilterChain::reflect_uniform_location(program, param), param.offset));
} }
for (semantics, param) in &reflection.meta.texture_size_meta {
locations.insert(UniformBinding::TextureSize(semantics.clone()),
(FilterChain::reflect_uniform_location(program, param), param.offset));
}
// eprintln!("{:#?}", semantics); // eprintln!("{:#?}", semantics);
eprintln!("{:#?}", reflection.meta); eprintln!("{:#?}", reflection.meta);
@ -290,7 +301,7 @@ impl FilterChain {
ubo_ring, ubo_ring,
uniform_buffer, uniform_buffer,
push_buffer, push_buffer,
locations, variable_bindings: locations,
source, source,
// no idea if this works. // no idea if this works.
// retroarch checks if feedback frames are used but we'll just init it tbh. // retroarch checks if feedback frames are used but we'll just init it tbh.
@ -323,7 +334,7 @@ impl FilterChain {
// load luts // load luts
let mut luts = FxHashMap::default(); let mut luts = FxHashMap::default();
for texture in &preset.textures { for (index, texture) in preset.textures.iter().enumerate() {
let image = Image::load(&texture.path)?; let image = Image::load(&texture.path)?;
let levels = if texture.mipmap { let levels = if texture.mipmap {
util::calc_miplevel(image.width, image.height) util::calc_miplevel(image.width, image.height)
@ -374,7 +385,7 @@ impl FilterChain {
gl::BindTexture(gl::TEXTURE_2D, 0); gl::BindTexture(gl::TEXTURE_2D, 0);
} }
luts.insert(texture.name.clone(), Texture { luts.insert(index, Texture {
image: GlImage { image: GlImage {
handle, handle,
format: gl::RGBA8, format: gl::RGBA8,

View file

@ -1,26 +1,6 @@
use gl::types::{GLenum, GLint, GLuint}; use gl::types::{GLenum, GLint, GLuint};
use librashader::{FilterMode, WrapMode}; use librashader::{FilterMode, WrapMode};
#[derive(Debug, Copy, Clone)]
pub struct Location<T> {
pub vertex: T,
pub fragment: T,
}
#[derive(Debug)]
pub enum VariableLocation {
Ubo(Location<GLint>),
Push(Location<GLint>),
}
impl VariableLocation {
pub fn location(&self) -> Location<GLint> {
match self {
VariableLocation::Ubo(l) | VariableLocation::Push(l) => *l
}
}
}
pub fn calc_miplevel(width: u32, height: u32) -> u32 { pub fn calc_miplevel(width: u32, height: u32) -> u32 {
let mut size = std::cmp::max(width, height); let mut size = std::cmp::max(width, height);
let mut levels = 0; let mut levels = 0;