rt: take ringbuffer out for reuse

This commit is contained in:
chyyran 2022-12-06 01:01:21 -05:00
parent 22f87aa7f8
commit e7351207cf
14 changed files with 354 additions and 60 deletions

View file

@ -40,7 +40,6 @@ pub struct FilterMutable {
pub(crate) parameters: FxHashMap<String, f32>,
}
// todo: get rid of preset
type ShaderPassMeta = (
ShaderPassConfig,
ShaderSource,

View file

@ -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) -> ();

View file

@ -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()

View file

@ -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,

View file

@ -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> {

View file

@ -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> {

View file

@ -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(

View file

@ -0,0 +1,3 @@
use std::error::Error;
pub type Result<T> = std::result::Result<T, Box<dyn Error>>;

View 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!();
}
}

View 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,
}

View file

@ -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 {

View file

@ -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 {

View file

@ -17,3 +17,6 @@ pub mod filter_chain;
/// Image handling helpers.
pub mod image;
/// Ringbuffer helpers
pub mod ringbuffer;

View 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
}
}