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(
&mut self,
pass_number: u32,
pass_number: usize,
semantics: &ReflectSemantics,
) -> Result<ShaderReflection, ShaderReflectError> {
self.backend.reflect(pass_number, semantics)

View file

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

View file

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

View file

@ -13,7 +13,7 @@ pub mod semantics;
pub trait ReflectShader {
fn reflect(
&mut self,
pass_number: u32,
pass_number: usize,
semantics: &ReflectSemantics,
) -> Result<ShaderReflection, ShaderReflectError>;
}
@ -69,7 +69,7 @@ impl TextureSemanticMap<UniformSemantic> for FxHashMap<String, UniformSemantic>
{
if semantics.is_array() {
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 Some(SemanticMap {
@ -101,7 +101,7 @@ impl TextureSemanticMap<UniformSemantic> for FxHashMap<String, SemanticMap<Textu
{
if semantics.is_array() {
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 {
semantics: *semantics,
index,

View file

@ -5,6 +5,15 @@ pub const BASE_SEMANTICS_COUNT: usize = 5;
pub const MAX_BINDINGS_COUNT: u32 = 16;
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)]
#[repr(i32)]
pub enum VariableSemantics {
@ -29,6 +38,17 @@ impl VariableSemantics {
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)]
@ -78,7 +98,7 @@ impl TextureSemantics {
!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 {
semantics: self,
index
@ -95,7 +115,7 @@ pub trait ValidateTypeSemantics<T> {
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct SemanticMap<T, I=u32> {
pub struct SemanticMap<T, I=usize> {
pub semantics: T,
pub index: I,
}
@ -160,3 +180,28 @@ pub struct ShaderReflection {
pub push_constant: Option<PushReflection>,
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 gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint};
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 crate::{FilterChain, FilterCommon};
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 reflection: ShaderReflection,
pub compiled: ShaderCompilerOutput<String, GlslangGlslContext>,
pub program: GLuint,
pub ubo_location: Location<GLuint>,
pub ubo_location: UniformLocation<GLuint>,
pub ubo_ring: Option<RingBuffer<GLuint, 16>>,
pub uniform_buffer: Box<[u8]>,
pub push_buffer: Box<[u8]>,
pub locations: FxHashMap<String, VariableLocation>,
pub variable_bindings: FxHashMap<UniformBinding, (VariableLocation, MemberOffset)>,
pub framebuffer: Framebuffer,
pub feedback_framebuffer: Framebuffer,
pub source: ShaderSource,
@ -34,7 +36,7 @@ impl FilterPass {
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];
if location.fragment >= 0 || location.vertex >= 0 {
unsafe {
@ -52,7 +54,7 @@ impl FilterPass {
}
#[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
{
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)
}
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)
}
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)
}
fn set_texture(binding: &TextureImage, texture: &Texture) {
fn bind_texture(binding: &TextureImage, texture: &Texture) {
unsafe {
// eprintln!("binding {} = texture {}", binding.binding, texture.image.handle);
gl::ActiveTexture((gl::TEXTURE0 + binding.binding) as GLenum);
@ -158,7 +160,8 @@ impl FilterPass {
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;
if self.config.srgb_framebuffer {
fb_format = ShaderFormat::R8G8B8A8Srgb;
@ -247,134 +250,148 @@ impl FilterPass {
}
// 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) {
if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::MVP) {
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()) {
let mvp = mvp.unwrap_or(&[
2f32, 0.0, 0.0, 0.0,
0.0, 2.0, 0.0, 0.0,
0.0, 0.0, 2.0, 0.0,
-1.0, -1.0, 0.0, 1.0
]);
let mvp_size = mvp.len() * std::mem::size_of::<f32>();
let (buffer, offset) = match variable.offset {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
let (buffer, offset) = match 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)
}
if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::Output) {
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], 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)
if let Some((location, offset)) = self.variable_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_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)) {
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();
let (buffer, offset) = match variable.offset {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
if let Some((location, offset)) = self.variable_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, &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)) {
// 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)) {
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)
if let Some((location, offset)) = self.variable_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, &mut buffer[offset..][..4], source.image.size);
FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], source.image.size);
}
// todo: history
// if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) {
// FilterPass::set_texture(binding, original);
// }
// 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 (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], original.image.size);
// }
for variable in self.reflection.meta.parameter_meta.values() {
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)
// // todo: history
//
// // if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) {
// // FilterPass::set_texture(binding, original);
// // }
// // 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 (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], original.image.size);
// // }
//
for (id, (location, offset)) in self.variable_bindings.iter()
.filter_map(|(binding, value)| match binding {
UniformBinding::Parameter(id) => {
Some((id, value))
}
_ => 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
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)
.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)
.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 (index, lut) in parent.luts.values().enumerate() {
// // todo: sort out order
// if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::User.semantics(index as u32)) {
// }
//
// }
// todo history
for (id, (location, offset)) in self.variable_bindings.iter()
.filter_map(|(binding, value)| match binding {
UniformBinding::TextureSize(semantics) => {
if semantics.semantics == TextureSemantics::User {
Some((semantics, value))
} else {
None
}
}
_ => 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 util;
mod framebuffer;
mod binding;
use std::collections::HashMap;
use std::error::Error;
@ -26,9 +27,11 @@ use librashader_reflect::back::targets::{FromCompilation, GLSL};
use librashader_reflect::front::shaderc::GlslangCompilation;
use librashader_reflect::reflect::cross::CrossReflect;
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 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 {
let shader = gl::CreateShader(stage);
@ -63,7 +66,7 @@ impl FilterChain {
return;
}
let index = config.id as u32;
let index = config.id as usize;
// PassOutput
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: fix this.
match meta.offset {
match meta.offset() {
MemberOffset::Ubo(_) => {
let vert_name = format!("RARCH_UBO_VERTEX_INSTANCE.{}\0", meta.id);
let frag_name = format!("RARCH_UBO_FRAGMENT_INSTANCE.{}\0", meta.id);
let vert_name = format!("LIBRA_UBO_VERTEX_INSTANCE.{}\0", meta.id());
let frag_name = format!("LIBRA_UBO_FRAGMENT_INSTANCE.{}\0", meta.id());
unsafe {
let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast());
let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast());
VariableLocation::Ubo(Location {
VariableLocation::Ubo(UniformLocation {
vertex,
fragment
})
}
}
MemberOffset::PushConstant(_) => {
let vert_name = format!("RARCH_PUSH_VERTEX_INSTANCE.{}\0", meta.id);
let frag_name = format!("RARCH_PUSH_FRAGMENT_INSTANCE.{}\0", meta.id);
let vert_name = format!("LIBRA_PUSH_VERTEX_INSTANCE.{}\0", meta.id());
let frag_name = format!("LIBRA_PUSH_FRAGMENT_INSTANCE.{}\0", meta.id());
unsafe {
let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast());
let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast());
VariableLocation::Push(Location {
VariableLocation::Push(UniformLocation {
vertex,
fragment
})
@ -133,7 +136,7 @@ pub struct FilterCommon {
original_history: Vec<Framebuffer>,
history: Vec<Texture>,
feedback: Vec<Texture>,
luts: FxHashMap<String, Texture>,
luts: FxHashMap<usize, Texture>,
pub quad_vbo: GLuint,
pub input_framebuffer: Framebuffer,
}
@ -174,12 +177,12 @@ impl FilterChain {
for (index, texture) in preset.textures.iter().enumerate() {
texture_semantics.insert(texture.name.clone(), SemanticMap {
semantics: TextureSemantics::User,
index: index as u32
index
});
uniform_semantics.insert(format!("{}Size", texture.name), UniformSemantic::Texture(SemanticMap {
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() {
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 vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?;
@ -210,7 +213,7 @@ impl FilterChain {
for res in &vertex_resources.stage_inputs {
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}");
gl::BindAttribLocation(program, loc, loc_name.as_str().as_ptr().cast())
}
@ -225,7 +228,7 @@ impl FilterChain {
}
for binding in &glsl.context.texture_fixups {
let loc_name = format!("RARCH_TEXTURE_{}\0", *binding);
let loc_name = format!("LIBRA_TEXTURE_{}\0", *binding);
unsafe {
let location = gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast());
if location >= 0 {
@ -236,9 +239,9 @@ impl FilterChain {
unsafe {
gl::UseProgram(0);
(program, Location {
vertex: gl::GetUniformBlockIndex(program, b"RARCH_UBO_VERTEX\0".as_ptr().cast()),
fragment: gl::GetUniformBlockIndex(program, b"RARCH_UBO_FRAGMENT\0".as_ptr().cast()),
(program, UniformLocation {
vertex: gl::GetUniformBlockIndex(program, b"LIBRA_UBO_VERTEX\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
let mut locations = FxHashMap::default();
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() {
locations.insert(param.id.clone(), FilterChain::reflect_parameter(program, param));
for (semantics, param) in &reflection.meta.variable_meta {
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!("{:#?}", reflection.meta);
@ -290,7 +301,7 @@ impl FilterChain {
ubo_ring,
uniform_buffer,
push_buffer,
locations,
variable_bindings: locations,
source,
// no idea if this works.
// retroarch checks if feedback frames are used but we'll just init it tbh.
@ -323,7 +334,7 @@ impl FilterChain {
// load luts
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 levels = if texture.mipmap {
util::calc_miplevel(image.width, image.height)
@ -374,7 +385,7 @@ impl FilterChain {
gl::BindTexture(gl::TEXTURE_2D, 0);
}
luts.insert(texture.name.clone(), Texture {
luts.insert(index, Texture {
image: GlImage {
handle,
format: gl::RGBA8,

View file

@ -1,26 +1,6 @@
use gl::types::{GLenum, GLint, GLuint};
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 {
let mut size = std::cmp::max(width, height);
let mut levels = 0;