diff --git a/librashader-runtime-d3d11/src/filter_chain.rs b/librashader-runtime-d3d11/src/filter_chain.rs index 193cead..db182f1 100644 --- a/librashader-runtime-d3d11/src/filter_chain.rs +++ b/librashader-runtime-d3d11/src/filter_chain.rs @@ -40,7 +40,6 @@ pub struct FilterMutable { pub(crate) parameters: FxHashMap, } -// todo: get rid of preset type ShaderPassMeta = ( ShaderPassConfig, ShaderSource, diff --git a/librashader-runtime-gl/src/binding.rs b/librashader-runtime-gl/src/binding.rs index e7c7588..55d4efe 100644 --- a/librashader-runtime-gl/src/binding.rs +++ b/librashader-runtime-gl/src/binding.rs @@ -35,7 +35,7 @@ impl UniformLocation { } } -pub(crate) type BufferStorage = UniformStorage>; +pub(crate) type GlUniformStorage = UniformStorage>; pub trait GlUniformScalar: UniformScalar { const FACTORY: unsafe fn(GLint, Self) -> (); diff --git a/librashader-runtime-gl/src/filter_chain/filter_impl.rs b/librashader-runtime-gl/src/filter_chain/filter_impl.rs index 369a288..f1a4a30 100644 --- a/librashader-runtime-gl/src/filter_chain/filter_impl.rs +++ b/librashader-runtime-gl/src/filter_chain/filter_impl.rs @@ -12,7 +12,7 @@ use librashader_common::{FilterMode, Size, WrapMode}; use std::collections::VecDeque; use librashader_reflect::reflect::ReflectShader; use crate::{error, GLImage, util, Viewport}; -use crate::binding::{BufferStorage, UniformLocation, VariableLocation}; +use crate::binding::{GlUniformStorage, UniformLocation, VariableLocation}; use crate::error::FilterChainError; use crate::filter_pass::FilterPass; use crate::gl::{DrawQuad, Framebuffer, FramebufferInterface, GLInterface, LoadLut, UboRing}; @@ -288,7 +288,7 @@ impl FilterChainImpl { None }; - let uniform_storage = BufferStorage::new( + let uniform_storage = GlUniformStorage::new( reflection .ubo .as_ref() diff --git a/librashader-runtime-gl/src/filter_pass.rs b/librashader-runtime-gl/src/filter_pass.rs index bcac59e..5379df2 100644 --- a/librashader-runtime-gl/src/filter_pass.rs +++ b/librashader-runtime-gl/src/filter_pass.rs @@ -11,7 +11,7 @@ use librashader_reflect::reflect::semantics::{ }; use rustc_hash::FxHashMap; -use crate::binding::{BufferStorage, UniformLocation, VariableLocation}; +use crate::binding::{GlUniformStorage, UniformLocation, VariableLocation}; use crate::filter_chain::FilterCommon; use crate::gl::{BindTexture, GLInterface, UboRing}; use crate::render_target::RenderTarget; @@ -25,7 +25,7 @@ pub struct FilterPass { pub program: GLuint, pub ubo_location: UniformLocation, pub ubo_ring: Option, - pub(crate) uniform_storage: BufferStorage, + pub(crate) uniform_storage: GlUniformStorage, pub uniform_bindings: FxHashMap, pub source: ShaderSource, pub config: ShaderPassConfig, diff --git a/librashader-runtime-gl/src/gl/gl3/ubo_ring.rs b/librashader-runtime-gl/src/gl/gl3/ubo_ring.rs index b4d43a7..750e7e0 100644 --- a/librashader-runtime-gl/src/gl/gl3/ubo_ring.rs +++ b/librashader-runtime-gl/src/gl/gl3/ubo_ring.rs @@ -1,8 +1,9 @@ use crate::binding::UniformLocation; use crate::gl::UboRing; -use crate::util::{InlineRingBuffer, RingBuffer}; +use librashader_runtime::ringbuffer::InlineRingBuffer; use gl::types::{GLsizei, GLsizeiptr, GLuint}; use librashader_reflect::reflect::semantics::UboReflection; +use librashader_runtime::ringbuffer::RingBuffer; use librashader_runtime::uniforms::UniformStorageAccess; pub struct Gl3UboRing { diff --git a/librashader-runtime-gl/src/gl/gl46/ubo_ring.rs b/librashader-runtime-gl/src/gl/gl46/ubo_ring.rs index c136cf0..9ef7df3 100644 --- a/librashader-runtime-gl/src/gl/gl46/ubo_ring.rs +++ b/librashader-runtime-gl/src/gl/gl46/ubo_ring.rs @@ -1,8 +1,9 @@ use crate::binding::UniformLocation; use crate::gl::UboRing; -use crate::util::{InlineRingBuffer, RingBuffer}; +use librashader_runtime::ringbuffer::InlineRingBuffer; use gl::types::{GLsizei, GLsizeiptr, GLuint}; use librashader_reflect::reflect::semantics::UboReflection; +use librashader_runtime::ringbuffer::RingBuffer; use librashader_runtime::uniforms::UniformStorageAccess; pub struct Gl46UboRing { diff --git a/librashader-runtime-gl/src/util.rs b/librashader-runtime-gl/src/util.rs index 7da59ce..3326d97 100644 --- a/librashader-runtime-gl/src/util.rs +++ b/librashader-runtime-gl/src/util.rs @@ -2,55 +2,6 @@ use gl::types::{GLenum, GLuint}; use librashader_reflect::back::cross::GlslVersion; -pub trait RingBuffer { - fn current(&self) -> &T; - fn current_mut(&mut self) -> &mut T; - fn next(&mut self); -} - -impl RingBuffer for InlineRingBuffer { - fn current(&self) -> &T { - &self.items[self.index] - } - - fn current_mut(&mut self) -> &mut T { - &mut self.items[self.index] - } - - fn next(&mut self) { - self.index += 1; - if self.index >= SIZE { - self.index = 0 - } - } -} - -pub struct InlineRingBuffer { - items: [T; SIZE], - index: usize, -} - -impl InlineRingBuffer -where - T: Copy, - T: Default, -{ - pub fn new() -> Self { - Self { - items: [T::default(); SIZE], - index: 0, - } - } - - pub fn items(&self) -> &[T; SIZE] { - &self.items - } - - pub fn items_mut(&mut self) -> &mut [T; SIZE] { - &mut self.items - } -} - pub unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint { let shader = gl::CreateShader(stage); gl::ShaderSource( diff --git a/librashader-runtime-vk/src/error.rs b/librashader-runtime-vk/src/error.rs new file mode 100644 index 0000000..9eb56e5 --- /dev/null +++ b/librashader-runtime-vk/src/error.rs @@ -0,0 +1,3 @@ +use std::error::Error; + +pub type Result = std::result::Result>; \ No newline at end of file diff --git a/librashader-runtime-vk/src/filter_chain.rs b/librashader-runtime-vk/src/filter_chain.rs new file mode 100644 index 0000000..5b2a592 --- /dev/null +++ b/librashader-runtime-vk/src/filter_chain.rs @@ -0,0 +1,182 @@ +use std::error::Error; +use std::path::Path; +use ash::vk; +use rustc_hash::FxHashMap; +use librashader_preprocess::ShaderSource; +use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; +use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation}; +use librashader_reflect::back::targets::SpirV; +use librashader_reflect::front::shaderc::GlslangCompilation; +use librashader_reflect::reflect::ReflectShader; +use librashader_reflect::reflect::semantics::{Semantic, ShaderSemantics, TextureSemantics, UniformBinding, UniformSemantic, UniqueSemantics}; +use librashader_runtime::uniforms::UniformStorage; +use crate::error; +use crate::filter_pass::FilterPass; + +pub struct Vulkan { + physical_device: vk::PhysicalDevice, + device: vk::Device, + queue: vk::Queue, + command_pool: vk::CommandPool, + pipelines: vk::PipelineCache, +} + +type ShaderPassMeta = ( + ShaderPassConfig, + ShaderSource, + CompilerBackend< + impl CompileShader, Context =()> + ReflectShader, + >, +); + + +#[derive(Clone)] +pub struct VulkanInfo<'a> { + physical_device: &'a vk::PhysicalDevice, + device: &'a vk::Device, + queue: &'a vk::Queue, + memory_properties: &'a vk::PhysicalDeviceMemoryProperties +} + +pub struct FilterChainVulkan { + pub(crate) common: FilterCommon, + pub(crate) passes: Vec, + // pub(crate) output_framebuffers: Box<[OwnedFramebuffer]>, + // pub(crate) feedback_framebuffers: Box<[OwnedFramebuffer]>, + // pub(crate) history_framebuffers: VecDeque, + // pub(crate) draw_quad: DrawQuad, +} + +pub(crate) struct FilterCommon { + // pub(crate) luts: FxHashMap, + // pub samplers: SamplerSet, + // pub output_textures: Box<[Option]>, + // pub feedback_textures: Box<[Option]>, + // pub history_textures: Box<[Option]>, + // pub config: FilterMutable, +} + +pub type FilterChainOptionsVulkan = (); + +impl FilterChainVulkan { + /// Load the shader preset at the given path into a filter chain. + pub fn load_from_path( + vulkan: VulkanInfo, + path: impl AsRef, + options: Option<&FilterChainOptionsVulkan>, + ) -> error::Result { + // load passes from preset + let preset = ShaderPreset::try_parse(path)?; + Self::load_from_preset(vulkan, preset, options) + } + + pub fn load_from_preset( + vulkan: VulkanInfo, + preset: ShaderPreset, + options: Option<&FilterChainOptionsVulkan>, + ) -> error::Result { + let (passes, semantics) = FilterChainVulkan::load_preset(preset.shaders, &preset.textures)?; + todo!(); + } + + fn load_preset( + passes: Vec, + textures: &[TextureConfig], + ) -> error::Result<(Vec, ShaderSemantics)> { + let mut uniform_semantics: FxHashMap = Default::default(); + let mut texture_semantics: FxHashMap> = + Default::default(); + + let passes = passes + .into_iter() + .map(|shader| { + eprintln!("[vk] loading {}", &shader.name.display()); + let source: ShaderSource = ShaderSource::load(&shader.name)?; + + let spirv = GlslangCompilation::compile(&source)?; + let reflect = SpirV::from_compilation(spirv)?; + + for parameter in source.parameters.iter() { + uniform_semantics.insert( + parameter.id.clone(), + UniformSemantic::Unique(Semantic { + semantics: UniqueSemantics::FloatParameter, + index: (), + }), + ); + } + Ok::<_, Box>((shader, source, reflect)) + }) + .into_iter() + .collect::)>>>()?; + + for details in &passes { + librashader_runtime::semantics::insert_pass_semantics( + &mut uniform_semantics, + &mut texture_semantics, + &details.0, + ) + } + librashader_runtime::semantics::insert_lut_semantics( + textures, + &mut uniform_semantics, + &mut texture_semantics, + ); + + let semantics = ShaderSemantics { + uniform_semantics, + texture_semantics, + }; + + Ok((passes, semantics)) + } + + fn init_passes( + passes: Vec, + semantics: &ShaderSemantics, + ) -> error::Result> { + let mut filters = Vec::new(); + + // initialize passes + for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() { + let reflection = reflect.reflect(index, semantics)?; + let spirv_words = reflect.compile(None)?; + + let uniform_storage = UniformStorage::new( + reflection + .ubo + .as_ref() + .map(|ubo| ubo.size as usize) + .unwrap_or(0), + reflection + .push_constant + .as_ref() + .map(|push| push.size as usize) + .unwrap_or(0), + ); + + let mut uniform_bindings = FxHashMap::default(); + for param in reflection.meta.parameter_meta.values() { + uniform_bindings.insert(UniformBinding::Parameter(param.id.clone()), param.offset); + } + + for (semantics, param) in &reflection.meta.unique_meta { + uniform_bindings.insert(UniformBinding::SemanticVariable(*semantics), param.offset); + } + + for (semantics, param) in &reflection.meta.texture_size_meta { + uniform_bindings.insert(UniformBinding::TextureSize(*semantics), param.offset); + } + + filters.push(FilterPass { + compiled: spirv_words, + uniform_storage, + uniform_bindings, + source, + config, + }); + } + + todo!(); + } +} \ No newline at end of file diff --git a/librashader-runtime-vk/src/filter_pass.rs b/librashader-runtime-vk/src/filter_pass.rs new file mode 100644 index 0000000..a47d443 --- /dev/null +++ b/librashader-runtime-vk/src/filter_pass.rs @@ -0,0 +1,14 @@ +use rustc_hash::FxHashMap; +use librashader_preprocess::ShaderSource; +use librashader_presets::ShaderPassConfig; +use librashader_reflect::back::ShaderCompilerOutput; +use librashader_reflect::reflect::semantics::{MemberOffset, UniformBinding}; +use librashader_runtime::uniforms::UniformStorage; + +pub struct FilterPass { + pub(crate) compiled: ShaderCompilerOutput>, + pub(crate) uniform_storage: UniformStorage, + pub uniform_bindings: FxHashMap, + pub source: ShaderSource, + pub config: ShaderPassConfig, +} \ No newline at end of file diff --git a/librashader-runtime-vk/src/hello_triangle.rs b/librashader-runtime-vk/src/hello_triangle.rs index 8a2dd79..5bf0d72 100644 --- a/librashader-runtime-vk/src/hello_triangle.rs +++ b/librashader-runtime-vk/src/hello_triangle.rs @@ -369,7 +369,7 @@ pub(crate) fn main() { let clear_values = [ vk::ClearValue { color: vk::ClearColorValue { - float32: [0.0, 0.0, 0.0, 0.0], + float32: [0.3, 0.3, 0.5, 0.0], }, }, vk::ClearValue { diff --git a/librashader-runtime-vk/src/lib.rs b/librashader-runtime-vk/src/lib.rs index 8457db0..86919fc 100644 --- a/librashader-runtime-vk/src/lib.rs +++ b/librashader-runtime-vk/src/lib.rs @@ -1,6 +1,9 @@ -mod hello_triangle; +#![feature(type_alias_impl_trait)] -use ash::vk::Framebuffer; +mod hello_triangle; +mod filter_chain; +mod filter_pass; +mod error; #[cfg(test)] mod tests { diff --git a/librashader-runtime/src/lib.rs b/librashader-runtime/src/lib.rs index 93cf8a8..e06b4b5 100644 --- a/librashader-runtime/src/lib.rs +++ b/librashader-runtime/src/lib.rs @@ -17,3 +17,6 @@ pub mod filter_chain; /// Image handling helpers. pub mod image; + +/// Ringbuffer helpers +pub mod ringbuffer; diff --git a/librashader-runtime/src/ringbuffer.rs b/librashader-runtime/src/ringbuffer.rs new file mode 100644 index 0000000..5d19c7e --- /dev/null +++ b/librashader-runtime/src/ringbuffer.rs @@ -0,0 +1,137 @@ +/// General trait for ring buffers. +pub trait RingBuffer { + /// Get a borrow the current item. + fn current(&self) -> &T; + + /// Get a mutable borrow to the current item. + fn current_mut(&mut self) -> &mut T; + + /// Move to the next item in the ring buffer. + fn next(&mut self); + + fn current_index(&self) -> usize; +} + +impl RingBuffer for InlineRingBuffer { + fn current(&self) -> &T { + &self.items[self.index] + } + + fn current_mut(&mut self) -> &mut T { + &mut self.items[self.index] + } + + fn next(&mut self) { + self.index += 1; + if self.index >= SIZE { + self.index = 0 + } + } + + fn current_index(&self) -> usize { + self.index + } +} + +/// A ring buffer that stores its contents inline. +pub struct InlineRingBuffer { + items: [T; SIZE], + index: usize, +} + +impl InlineRingBuffer +where + T: Copy, + T: Default, +{ + pub fn new() -> Self { + Self { + items: [T::default(); SIZE], + index: 0, + } + } + + /// Get a borrow to all the items in this ring buffer. + pub fn items(&self) -> &[T; SIZE] { + &self.items + } + + /// Get a mutable borrow to all the items in this ring buffer. + pub fn items_mut(&mut self) -> &mut [T; SIZE] { + &mut self.items + } +} + +/// A ring buffer that stores its contents in a box +pub struct BoxRingBuffer { + items: Box<[T]>, + index: usize, +} + +impl BoxRingBuffer + where + T: Copy, + T: Default, +{ + pub fn new(size: usize) -> Self { + Self { + items: vec![T::default(); size].into_boxed_slice(), + index: 0, + } + } + + /// Get a borrow to all the items in this ring buffer. + pub fn items(&self) -> &[T; SIZE] { + &self.items + } + + /// Get a mutable borrow to all the items in this ring buffer. + pub fn items_mut(&mut self) -> &mut [T; SIZE] { + &mut self.items + } +} + + +impl BoxRingBuffer { + pub fn from_vec(items: Vec) -> Self { + Self { + items: items.into_boxed_slice(), + index: 0 + } + } + + pub fn items(&self) -> &[T] { + &self.items + } + + pub fn items_mut(&mut self) -> &mut [T] { + &mut self.items + } +} + +impl From> for BoxRingBuffer { + fn from(value: Vec) -> Self { + BoxRingBuffer::from_vec(value) + } +} + +impl RingBuffer for BoxRingBuffer { + fn current(&self) -> &T { + &self.items[self.index] + } + + fn current_mut(&mut self) -> &mut T { + &mut self.items[self.index] + } + + fn next(&mut self) { + self.index += 1; + if self.index >= SIZE { + self.index = 0 + } + } + + fn current_index(&self) -> usize { + self.index + } +} \ No newline at end of file