gl: clean up uniform binding storage
This commit is contained in:
parent
2c8f2685f2
commit
d49fa5307a
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
66
librashader-runtime-gl/src/binding.rs
Normal file
66
librashader-runtime-gl/src/binding.rs
Normal 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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue