rt: take ringbuffer out for reuse
This commit is contained in:
parent
22f87aa7f8
commit
e7351207cf
|
@ -40,7 +40,6 @@ pub struct FilterMutable {
|
|||
pub(crate) parameters: FxHashMap<String, f32>,
|
||||
}
|
||||
|
||||
// todo: get rid of preset
|
||||
type ShaderPassMeta = (
|
||||
ShaderPassConfig,
|
||||
ShaderSource,
|
||||
|
|
|
@ -35,7 +35,7 @@ impl UniformLocation<GLint> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) type BufferStorage = UniformStorage<GlUniformBinder, UniformLocation<GLint>>;
|
||||
pub(crate) type GlUniformStorage = UniformStorage<GlUniformBinder, UniformLocation<GLint>>;
|
||||
|
||||
pub trait GlUniformScalar: UniformScalar {
|
||||
const FACTORY: unsafe fn(GLint, Self) -> ();
|
||||
|
|
|
@ -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<T: GLInterface> FilterChainImpl<T> {
|
|||
None
|
||||
};
|
||||
|
||||
let uniform_storage = BufferStorage::new(
|
||||
let uniform_storage = GlUniformStorage::new(
|
||||
reflection
|
||||
.ubo
|
||||
.as_ref()
|
||||
|
|
|
@ -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<T: GLInterface> {
|
|||
pub program: GLuint,
|
||||
pub ubo_location: UniformLocation<GLuint>,
|
||||
pub ubo_ring: Option<T::UboRing>,
|
||||
pub(crate) uniform_storage: BufferStorage,
|
||||
pub(crate) uniform_storage: GlUniformStorage,
|
||||
pub uniform_bindings: FxHashMap<UniformBinding, (VariableLocation, MemberOffset)>,
|
||||
pub source: ShaderSource,
|
||||
pub config: ShaderPassConfig,
|
||||
|
|
|
@ -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<const SIZE: usize> {
|
||||
|
|
|
@ -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<const SIZE: usize> {
|
||||
|
|
|
@ -2,55 +2,6 @@ use gl::types::{GLenum, GLuint};
|
|||
|
||||
use librashader_reflect::back::cross::GlslVersion;
|
||||
|
||||
pub trait RingBuffer<T> {
|
||||
fn current(&self) -> &T;
|
||||
fn current_mut(&mut self) -> &mut T;
|
||||
fn next(&mut self);
|
||||
}
|
||||
|
||||
impl<T, const SIZE: usize> RingBuffer<T> for InlineRingBuffer<T, SIZE> {
|
||||
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<T, const SIZE: usize> {
|
||||
items: [T; SIZE],
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<T, const SIZE: usize> InlineRingBuffer<T, SIZE>
|
||||
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(
|
||||
|
|
3
librashader-runtime-vk/src/error.rs
Normal file
3
librashader-runtime-vk/src/error.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
use std::error::Error;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
182
librashader-runtime-vk/src/filter_chain.rs
Normal file
182
librashader-runtime-vk/src/filter_chain.rs
Normal file
|
@ -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<SpirV, Options = Option<()>, 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<FilterPass>,
|
||||
// pub(crate) output_framebuffers: Box<[OwnedFramebuffer]>,
|
||||
// pub(crate) feedback_framebuffers: Box<[OwnedFramebuffer]>,
|
||||
// pub(crate) history_framebuffers: VecDeque<OwnedFramebuffer>,
|
||||
// pub(crate) draw_quad: DrawQuad,
|
||||
}
|
||||
|
||||
pub(crate) struct FilterCommon {
|
||||
// pub(crate) luts: FxHashMap<usize, LutTexture>,
|
||||
// pub samplers: SamplerSet,
|
||||
// pub output_textures: Box<[Option<Texture>]>,
|
||||
// pub feedback_textures: Box<[Option<Texture>]>,
|
||||
// pub history_textures: Box<[Option<Texture>]>,
|
||||
// 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<Path>,
|
||||
options: Option<&FilterChainOptionsVulkan>,
|
||||
) -> error::Result<FilterChainVulkan> {
|
||||
// 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<FilterChainVulkan> {
|
||||
let (passes, semantics) = FilterChainVulkan::load_preset(preset.shaders, &preset.textures)?;
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn load_preset(
|
||||
passes: Vec<ShaderPassConfig>,
|
||||
textures: &[TextureConfig],
|
||||
) -> error::Result<(Vec<ShaderPassMeta>, ShaderSemantics)> {
|
||||
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
|
||||
let mut texture_semantics: FxHashMap<String, Semantic<TextureSemantics>> =
|
||||
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<dyn Error>>((shader, source, reflect))
|
||||
})
|
||||
.into_iter()
|
||||
.collect::<error::Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>()?;
|
||||
|
||||
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<ShaderPassMeta>,
|
||||
semantics: &ShaderSemantics,
|
||||
) -> error::Result<Box<[FilterPass]>> {
|
||||
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!();
|
||||
}
|
||||
}
|
14
librashader-runtime-vk/src/filter_pass.rs
Normal file
14
librashader-runtime-vk/src/filter_pass.rs
Normal file
|
@ -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<Vec<u32>>,
|
||||
pub(crate) uniform_storage: UniformStorage,
|
||||
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
|
||||
pub source: ShaderSource,
|
||||
pub config: ShaderPassConfig,
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -17,3 +17,6 @@ pub mod filter_chain;
|
|||
|
||||
/// Image handling helpers.
|
||||
pub mod image;
|
||||
|
||||
/// Ringbuffer helpers
|
||||
pub mod ringbuffer;
|
||||
|
|
137
librashader-runtime/src/ringbuffer.rs
Normal file
137
librashader-runtime/src/ringbuffer.rs
Normal file
|
@ -0,0 +1,137 @@
|
|||
/// General trait for ring buffers.
|
||||
pub trait RingBuffer<T> {
|
||||
/// 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<T, const SIZE: usize> RingBuffer<T> for InlineRingBuffer<T, SIZE> {
|
||||
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<T, const SIZE: usize> {
|
||||
items: [T; SIZE],
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<T, const SIZE: usize> InlineRingBuffer<T, SIZE>
|
||||
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<T> {
|
||||
items: Box<[T]>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<T> BoxRingBuffer<T>
|
||||
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<T> BoxRingBuffer<T> {
|
||||
pub fn from_vec(items: Vec<T>) -> 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<T> From<Vec<T>> for BoxRingBuffer<T> {
|
||||
fn from(value: Vec<T>) -> Self {
|
||||
BoxRingBuffer::from_vec(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> RingBuffer<T> for BoxRingBuffer<T> {
|
||||
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
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue