doc: general add docs and clean up
This commit is contained in:
parent
a64d0b0a96
commit
acab02e401
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -416,6 +416,7 @@ dependencies = [
|
||||||
"librashader-preprocess",
|
"librashader-preprocess",
|
||||||
"librashader-presets",
|
"librashader-presets",
|
||||||
"librashader-reflect",
|
"librashader-reflect",
|
||||||
|
"librashader-runtime",
|
||||||
"librashader-runtime-d3d11",
|
"librashader-runtime-d3d11",
|
||||||
"librashader-runtime-gl",
|
"librashader-runtime-gl",
|
||||||
]
|
]
|
||||||
|
|
|
@ -59,6 +59,7 @@ impl From<FilterMode> for gl::types::GLenum {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FilterMode {
|
impl FilterMode {
|
||||||
|
/// Get the mipmap filtering mode for the given combination.
|
||||||
pub fn gl_mip(&self, mip: FilterMode) -> gl::types::GLenum {
|
pub fn gl_mip(&self, mip: FilterMode) -> gl::types::GLenum {
|
||||||
match (self, mip) {
|
match (self, mip) {
|
||||||
(FilterMode::Linear, FilterMode::Linear) => gl::LINEAR_MIPMAP_LINEAR,
|
(FilterMode::Linear, FilterMode::Linear) => gl::LINEAR_MIPMAP_LINEAR,
|
||||||
|
|
|
@ -6,9 +6,20 @@ pub struct Image {
|
||||||
pub pitch: usize,
|
pub pitch: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum UVDirection {
|
||||||
|
TopLeft,
|
||||||
|
BottomLeft,
|
||||||
|
}
|
||||||
impl Image {
|
impl Image {
|
||||||
pub fn load(path: impl AsRef<Path>) -> Result<Self, ImageError> {
|
pub fn load(path: impl AsRef<Path>, direction: UVDirection) -> Result<Self, ImageError> {
|
||||||
let image = image::open(path.as_ref())?.flipv().to_rgba8();
|
let mut image = image::open(path.as_ref())?;
|
||||||
|
|
||||||
|
if direction == BottomLeft {
|
||||||
|
image = image.flipv();
|
||||||
|
}
|
||||||
|
|
||||||
|
let image = image.to_rgba8();
|
||||||
|
|
||||||
let height = image.height();
|
let height = image.height();
|
||||||
let width = image.width();
|
let width = image.width();
|
||||||
|
@ -27,3 +38,4 @@ impl Image {
|
||||||
|
|
||||||
use crate::Size;
|
use crate::Size;
|
||||||
pub use image::ImageError;
|
pub use image::ImageError;
|
||||||
|
use crate::image::UVDirection::BottomLeft;
|
||||||
|
|
|
@ -1,20 +1,25 @@
|
||||||
#[cfg(feature = "d3d11")]
|
/// OpenGL common conversions.
|
||||||
pub mod d3d11;
|
|
||||||
#[cfg(feature = "opengl")]
|
#[cfg(feature = "opengl")]
|
||||||
pub mod gl;
|
pub mod gl;
|
||||||
|
|
||||||
pub mod image;
|
/// DXGI common conversions.
|
||||||
pub mod runtime;
|
|
||||||
|
|
||||||
#[cfg(feature = "dxgi")]
|
#[cfg(feature = "dxgi")]
|
||||||
pub mod dxgi;
|
pub mod dxgi;
|
||||||
|
|
||||||
|
/// Direct3D 11 common conversions.
|
||||||
|
#[cfg(feature = "d3d11")]
|
||||||
|
pub mod d3d11;
|
||||||
|
|
||||||
|
/// Image handing helpers.
|
||||||
|
pub mod image;
|
||||||
|
|
||||||
use num_traits::AsPrimitive;
|
use num_traits::AsPrimitive;
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
/// Supported image formats for textures.
|
||||||
pub enum ImageFormat {
|
pub enum ImageFormat {
|
||||||
#[default]
|
#[default]
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
|
@ -60,9 +65,13 @@ pub enum ImageFormat {
|
||||||
|
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash)]
|
||||||
|
/// The filtering mode for a texture sampler.
|
||||||
pub enum FilterMode {
|
pub enum FilterMode {
|
||||||
#[default]
|
#[default]
|
||||||
|
/// Linear filtering.
|
||||||
Linear = 0,
|
Linear = 0,
|
||||||
|
|
||||||
|
/// Nearest-neighbour (point) filtering.
|
||||||
Nearest,
|
Nearest,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,11 +91,16 @@ impl FromStr for WrapMode {
|
||||||
|
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash)]
|
||||||
|
/// The wrapping (address) mode for a texture sampler.
|
||||||
pub enum WrapMode {
|
pub enum WrapMode {
|
||||||
#[default]
|
#[default]
|
||||||
|
/// Clamp txture to border.
|
||||||
ClampToBorder = 0,
|
ClampToBorder = 0,
|
||||||
|
/// Clamp texture to edge.
|
||||||
ClampToEdge,
|
ClampToEdge,
|
||||||
|
/// Repeat addressing mode.
|
||||||
Repeat,
|
Repeat,
|
||||||
|
/// Mirrored repeat addressing mode.
|
||||||
MirroredRepeat,
|
MirroredRepeat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +149,7 @@ impl FromStr for ImageFormat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A size with a width and height.
|
||||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct Size<T> {
|
pub struct Size<T> {
|
||||||
pub width: T,
|
pub width: T,
|
||||||
|
@ -142,6 +157,7 @@ pub struct Size<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Size<T> {
|
impl<T> Size<T> {
|
||||||
|
/// Create a new `Size<T>` with the given width and height.
|
||||||
pub fn new(width: T, height: T) -> Self {
|
pub fn new(width: T, height: T) -> Self {
|
||||||
Size { width, height }
|
Size { width, height }
|
||||||
}
|
}
|
||||||
|
@ -151,6 +167,7 @@ impl<T> From<Size<T>> for [f32; 4]
|
||||||
where
|
where
|
||||||
T: Copy + AsPrimitive<f32>,
|
T: Copy + AsPrimitive<f32>,
|
||||||
{
|
{
|
||||||
|
/// Convert a `Size<T>` to a `vec4` uniform.
|
||||||
fn from(value: Size<T>) -> Self {
|
fn from(value: Size<T>) -> Self {
|
||||||
[
|
[
|
||||||
value.width.as_(),
|
value.width.as_(),
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -2,22 +2,31 @@ use std::convert::Infallible;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
/// Error type for source preprocessing.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum PreprocessError {
|
pub enum PreprocessError {
|
||||||
|
/// The version header was not found in the source file.
|
||||||
#[error("the version header was missing")]
|
#[error("the version header was missing")]
|
||||||
MissingVersionHeader,
|
MissingVersionHeader,
|
||||||
|
/// An IO error occurred when reading the source file.
|
||||||
#[error("the file was not found during resolution")]
|
#[error("the file was not found during resolution")]
|
||||||
IOError(PathBuf, std::io::Error),
|
IOError(PathBuf, std::io::Error),
|
||||||
|
/// Unexpected EOF when reading the source file.
|
||||||
#[error("unexpected end of file")]
|
#[error("unexpected end of file")]
|
||||||
UnexpectedEof,
|
UnexpectedEof,
|
||||||
|
/// Unexpected end of line when reading the source file.
|
||||||
#[error("unexpected end of line")]
|
#[error("unexpected end of line")]
|
||||||
UnexpectedEol(usize),
|
UnexpectedEol(usize),
|
||||||
|
/// An error occurred when parsing a pragma statement.
|
||||||
#[error("error parsing pragma")]
|
#[error("error parsing pragma")]
|
||||||
PragmaParseError(String),
|
PragmaParseError(String),
|
||||||
|
/// The given pragma was declared multiple times with differing values.
|
||||||
#[error("duplicate pragma found")]
|
#[error("duplicate pragma found")]
|
||||||
DuplicatePragmaError(String),
|
DuplicatePragmaError(String),
|
||||||
|
/// The imaged format requested by the shader was unknown or not supported.
|
||||||
#[error("shader format is unknown or not found")]
|
#[error("shader format is unknown or not found")]
|
||||||
UnknownShaderFormat,
|
UnknownImageFormat,
|
||||||
|
/// The stage declared by the shader source was not `vertex` or `fragment`.
|
||||||
#[error("stage must be either vertex or fragment")]
|
#[error("stage must be either vertex or fragment")]
|
||||||
InvalidStage,
|
InvalidStage,
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,26 +8,45 @@ pub use error::*;
|
||||||
use librashader_common::ImageFormat;
|
use librashader_common::ImageFormat;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
/// The source file for a single shader pass.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct ShaderSource {
|
pub struct ShaderSource {
|
||||||
|
/// The source contents for the vertex shader.
|
||||||
pub vertex: String,
|
pub vertex: String,
|
||||||
|
|
||||||
|
/// The source contents for the fragment shader.
|
||||||
pub fragment: String,
|
pub fragment: String,
|
||||||
|
|
||||||
|
/// The alias of the shader if available.
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
|
|
||||||
|
/// The list of shader parameters found in the shader source.
|
||||||
pub parameters: Vec<ShaderParameter>,
|
pub parameters: Vec<ShaderParameter>,
|
||||||
|
|
||||||
|
/// The image format the shader expects.
|
||||||
pub format: ImageFormat,
|
pub format: ImageFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A user tweakable parameter for the shader as declared in source.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct ShaderParameter {
|
pub struct ShaderParameter {
|
||||||
|
/// The name of the parameter.
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
/// The description of the parameter.
|
||||||
pub description: String,
|
pub description: String,
|
||||||
|
/// The initial value the parameter is set to.
|
||||||
pub initial: f32,
|
pub initial: f32,
|
||||||
|
/// The minimum value that the parameter can be set to.
|
||||||
pub minimum: f32,
|
pub minimum: f32,
|
||||||
|
/// The maximum value that the parameter can be set to.
|
||||||
pub maximum: f32,
|
pub maximum: f32,
|
||||||
|
/// The step by which this parameter can be incremented or decremented.
|
||||||
pub step: f32,
|
pub step: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShaderSource {
|
impl ShaderSource {
|
||||||
|
/// Load the source file at the given path, resolving includes relative to the location of the
|
||||||
|
/// source file.
|
||||||
pub fn load(path: impl AsRef<Path>) -> Result<ShaderSource, PreprocessError> {
|
pub fn load(path: impl AsRef<Path>) -> Result<ShaderSource, PreprocessError> {
|
||||||
load_shader_source(path)
|
load_shader_source(path)
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ pub(crate) fn parse_pragma_meta(source: impl AsRef<str>) -> Result<ShaderMeta, P
|
||||||
format = ImageFormat::from_str(format_string)?;
|
format = ImageFormat::from_str(format_string)?;
|
||||||
|
|
||||||
if format == ImageFormat::Unknown {
|
if format == ImageFormat::Unknown {
|
||||||
return Err(PreprocessError::UnknownShaderFormat);
|
return Err(PreprocessError::UnknownImageFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
/// Error type for preset parsing.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum ParsePresetError {
|
pub enum ParsePresetError {
|
||||||
|
/// An error occurred when tokenizing the preset file.
|
||||||
#[error("shader preset lexing error")]
|
#[error("shader preset lexing error")]
|
||||||
LexerError { offset: usize, row: u32, col: usize },
|
LexerError { offset: usize, row: u32, col: usize },
|
||||||
|
/// An error occurred when parsing the preset file.
|
||||||
#[error("shader preset parse error")]
|
#[error("shader preset parse error")]
|
||||||
ParserError {
|
ParserError {
|
||||||
offset: usize,
|
offset: usize,
|
||||||
|
@ -12,23 +15,34 @@ pub enum ParsePresetError {
|
||||||
col: usize,
|
col: usize,
|
||||||
kind: ParseErrorKind,
|
kind: ParseErrorKind,
|
||||||
},
|
},
|
||||||
|
/// The scale type was invalid.
|
||||||
#[error("invalid scale type")]
|
#[error("invalid scale type")]
|
||||||
InvalidScaleType(String),
|
InvalidScaleType(String),
|
||||||
|
/// The preset reference depth exceeded 16.
|
||||||
#[error("exceeded maximum reference depth (16)")]
|
#[error("exceeded maximum reference depth (16)")]
|
||||||
ExceededReferenceDepth,
|
ExceededReferenceDepth,
|
||||||
#[error("shader presents must be resolved against an absolute path")]
|
/// An absolute path could not be found to resolve the shader preset against.
|
||||||
|
#[error("shader presets must be resolved against an absolute path")]
|
||||||
RootPathWasNotAbsolute,
|
RootPathWasNotAbsolute,
|
||||||
|
/// An IO error occurred when reading the shader preset.
|
||||||
#[error("the file was not found during resolution")]
|
#[error("the file was not found during resolution")]
|
||||||
IOError(PathBuf, std::io::Error),
|
IOError(PathBuf, std::io::Error),
|
||||||
|
/// The shader preset did not contain valid UTF-8 bytes.
|
||||||
#[error("expected utf8 bytes but got invalid utf8")]
|
#[error("expected utf8 bytes but got invalid utf8")]
|
||||||
Utf8Error(Vec<u8>),
|
Utf8Error(Vec<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The kind of error that may occur in parsing.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ParseErrorKind {
|
pub enum ParseErrorKind {
|
||||||
|
/// Expected an indexed key (i.e. `shader0`, `shader1`, ...)
|
||||||
Index(&'static str),
|
Index(&'static str),
|
||||||
|
/// Expected a signed integer.
|
||||||
Int,
|
Int,
|
||||||
|
/// Expected an unsigned integer.
|
||||||
UnsignedInt,
|
UnsignedInt,
|
||||||
|
/// Expected a float.
|
||||||
Float,
|
Float,
|
||||||
|
/// Expected a boolean.
|
||||||
Bool,
|
Bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,16 +4,26 @@ use std::ops::Mul;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
/// The configuration for a single shader pass.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ShaderPassConfig {
|
pub struct ShaderPassConfig {
|
||||||
|
/// The index of the shader pass relative to its parent preset.
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
|
/// The path to the shader pass source file.
|
||||||
pub name: PathBuf,
|
pub name: PathBuf,
|
||||||
|
/// The alias of the shader pass if available.
|
||||||
pub alias: Option<String>,
|
pub alias: Option<String>,
|
||||||
|
/// The filtering mode that this shader pass should expect.
|
||||||
pub filter: FilterMode,
|
pub filter: FilterMode,
|
||||||
|
/// The texture addressing (wrap) mode that this shader pass expects.
|
||||||
pub wrap_mode: WrapMode,
|
pub wrap_mode: WrapMode,
|
||||||
|
/// The number to which to wrap the frame count before passing it to the uniforms.
|
||||||
pub frame_count_mod: u32,
|
pub frame_count_mod: u32,
|
||||||
|
/// Whether or not this shader pass expects an SRGB framebuffer output.
|
||||||
pub srgb_framebuffer: bool,
|
pub srgb_framebuffer: bool,
|
||||||
|
/// Whether or not this shader pass expects an float framebuffer output.
|
||||||
pub float_framebuffer: bool,
|
pub float_framebuffer: bool,
|
||||||
|
/// Whether or not to generate mipm
|
||||||
pub mipmap_input: bool,
|
pub mipmap_input: bool,
|
||||||
pub scaling: Scale2D,
|
pub scaling: Scale2D,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
/// Shader codegen backends.
|
||||||
pub mod back;
|
pub mod back;
|
||||||
|
/// Error types.
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
/// Shader frontend parsers.
|
||||||
pub mod front;
|
pub mod front;
|
||||||
|
/// Shader reflection.
|
||||||
pub mod reflect;
|
pub mod reflect;
|
||||||
|
|
|
@ -3,7 +3,6 @@ use bitflags::bitflags;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
pub const BASE_SEMANTICS_COUNT: usize = 5;
|
|
||||||
pub const MAX_BINDINGS_COUNT: u32 = 16;
|
pub const MAX_BINDINGS_COUNT: u32 = 16;
|
||||||
pub const MAX_PUSH_BUFFER_SIZE: u32 = 128;
|
pub const MAX_PUSH_BUFFER_SIZE: u32 = 128;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::texture::{DxImageView, LutTexture, Texture};
|
use crate::texture::{DxImageView, LutTexture, Texture};
|
||||||
use librashader_common::image::Image;
|
use librashader_common::image::{Image, UVDirection};
|
||||||
use librashader_common::{ImageFormat, Size};
|
use librashader_common::{ImageFormat, Size};
|
||||||
use librashader_preprocess::ShaderSource;
|
use librashader_preprocess::ShaderSource;
|
||||||
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
|
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
|
||||||
|
@ -123,6 +123,7 @@ impl FilterChain {
|
||||||
OwnedFramebuffer::new(
|
OwnedFramebuffer::new(
|
||||||
device,
|
device,
|
||||||
Size::new(1, 1),
|
Size::new(1, 1),
|
||||||
|
0,
|
||||||
ImageFormat::R8G8B8A8Unorm,
|
ImageFormat::R8G8B8A8Unorm,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -141,6 +142,7 @@ impl FilterChain {
|
||||||
OwnedFramebuffer::new(
|
OwnedFramebuffer::new(
|
||||||
device,
|
device,
|
||||||
Size::new(1, 1),
|
Size::new(1, 1),
|
||||||
|
1,
|
||||||
ImageFormat::R8G8B8A8Unorm,
|
ImageFormat::R8G8B8A8Unorm,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -349,7 +351,7 @@ impl FilterChain {
|
||||||
eprintln!("[history] using frame history with {required_images} images");
|
eprintln!("[history] using frame history with {required_images} images");
|
||||||
let mut framebuffers = VecDeque::with_capacity(required_images);
|
let mut framebuffers = VecDeque::with_capacity(required_images);
|
||||||
framebuffers.resize_with(required_images, || {
|
framebuffers.resize_with(required_images, || {
|
||||||
OwnedFramebuffer::new(device, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm)
|
OwnedFramebuffer::new(device, Size::new(1, 1), 1, ImageFormat::R8G8B8A8Unorm)
|
||||||
});
|
});
|
||||||
|
|
||||||
let framebuffers = framebuffers
|
let framebuffers = framebuffers
|
||||||
|
@ -379,7 +381,7 @@ impl FilterChain {
|
||||||
let mut luts = FxHashMap::default();
|
let mut luts = FxHashMap::default();
|
||||||
|
|
||||||
for (index, texture) in textures.iter().enumerate() {
|
for (index, texture) in textures.iter().enumerate() {
|
||||||
let image = Image::load(&texture.path)?;
|
let image = Image::load(&texture.path, UVDirection::TopLeft)?;
|
||||||
let desc = D3D11_TEXTURE2D_DESC {
|
let desc = D3D11_TEXTURE2D_DESC {
|
||||||
Width: image.size.width,
|
Width: image.size.width,
|
||||||
Height: image.size.height,
|
Height: image.size.height,
|
||||||
|
@ -459,6 +461,7 @@ impl FilterChain {
|
||||||
Ok((passes, semantics))
|
Ok((passes, semantics))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Process a frame with the input image.
|
||||||
pub fn frame(
|
pub fn frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: DxImageView,
|
input: DxImageView,
|
||||||
|
@ -544,6 +547,7 @@ impl FilterChain {
|
||||||
self.common.output_textures[index] = Some(source.clone());
|
self.common.output_textures[index] = Some(source.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try to hint the optimizer
|
||||||
assert_eq!(last.len(), 1);
|
assert_eq!(last.len(), 1);
|
||||||
for pass in last {
|
for pass in last {
|
||||||
source.filter = pass.config.filter;
|
source.filter = pass.config.filter;
|
||||||
|
@ -590,3 +594,14 @@ impl FilterChain {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl librashader_runtime::filter_chain::FilterChain for FilterChain {
|
||||||
|
type Error = FilterChainError;
|
||||||
|
type Input<'a> = DxImageView;
|
||||||
|
type Viewport<'a> = Viewport<'a>;
|
||||||
|
type FrameOptions = FrameOptions;
|
||||||
|
|
||||||
|
fn frame<'a>(&mut self, input: Self::Input<'a>, viewport: &Self::Viewport<'a>, frame_count: usize, options: Option<&Self::FrameOptions>) -> Result<(), Self::Error> {
|
||||||
|
self.frame(input, viewport, frame_count, options)
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ use crate::error;
|
||||||
use crate::render_target::RenderTarget;
|
use crate::render_target::RenderTarget;
|
||||||
use crate::samplers::SamplerSet;
|
use crate::samplers::SamplerSet;
|
||||||
use crate::viewport::Viewport;
|
use crate::viewport::Viewport;
|
||||||
use librashader_runtime::uniforms::UniformStorage;
|
use librashader_runtime::uniforms::{UniformStorage, UniformStorageAccess};
|
||||||
|
|
||||||
pub struct ConstantBufferBinding {
|
pub struct ConstantBufferBinding {
|
||||||
pub binding: u32,
|
pub binding: u32,
|
||||||
|
@ -379,7 +379,7 @@ impl FilterPass {
|
||||||
unsafe {
|
unsafe {
|
||||||
let map = context.Map(&ubo.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0)?;
|
let map = context.Map(&ubo.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0)?;
|
||||||
std::ptr::copy_nonoverlapping(
|
std::ptr::copy_nonoverlapping(
|
||||||
self.uniform_storage.ubo.as_ptr(),
|
self.uniform_storage.ubo_pointer(),
|
||||||
map.pData.cast(),
|
map.pData.cast(),
|
||||||
ubo.size as usize,
|
ubo.size as usize,
|
||||||
);
|
);
|
||||||
|
@ -403,7 +403,7 @@ impl FilterPass {
|
||||||
unsafe {
|
unsafe {
|
||||||
let map = context.Map(&push.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0)?;
|
let map = context.Map(&push.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0)?;
|
||||||
std::ptr::copy_nonoverlapping(
|
std::ptr::copy_nonoverlapping(
|
||||||
self.uniform_storage.push.as_ptr(),
|
self.uniform_storage.push_pointer(),
|
||||||
map.pData.cast(),
|
map.pData.cast(),
|
||||||
push.size as usize,
|
push.size as usize,
|
||||||
);
|
);
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub(crate) struct OwnedFramebuffer {
|
||||||
pub texture: ID3D11Texture2D,
|
pub texture: ID3D11Texture2D,
|
||||||
pub size: Size<u32>,
|
pub size: Size<u32>,
|
||||||
pub format: DXGI_FORMAT,
|
pub format: DXGI_FORMAT,
|
||||||
|
pub max_levels: u32,
|
||||||
device: ID3D11Device,
|
device: ID3D11Device,
|
||||||
is_raw: bool,
|
is_raw: bool,
|
||||||
}
|
}
|
||||||
|
@ -29,6 +30,7 @@ impl OwnedFramebuffer {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
device: &ID3D11Device,
|
device: &ID3D11Device,
|
||||||
size: Size<u32>,
|
size: Size<u32>,
|
||||||
|
mip_levels: u32,
|
||||||
format: ImageFormat,
|
format: ImageFormat,
|
||||||
) -> error::Result<OwnedFramebuffer> {
|
) -> error::Result<OwnedFramebuffer> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -39,7 +41,7 @@ impl OwnedFramebuffer {
|
||||||
| D3D11_FORMAT_SUPPORT_SHADER_SAMPLE.0
|
| D3D11_FORMAT_SUPPORT_SHADER_SAMPLE.0
|
||||||
| D3D11_FORMAT_SUPPORT_RENDER_TARGET.0,
|
| D3D11_FORMAT_SUPPORT_RENDER_TARGET.0,
|
||||||
);
|
);
|
||||||
let desc = default_desc(size, format);
|
let desc = default_desc(size, format, mip_levels);
|
||||||
let texture = device.CreateTexture2D(&desc, None)?;
|
let texture = device.CreateTexture2D(&desc, None)?;
|
||||||
|
|
||||||
Ok(OwnedFramebuffer {
|
Ok(OwnedFramebuffer {
|
||||||
|
@ -47,18 +49,20 @@ impl OwnedFramebuffer {
|
||||||
size,
|
size,
|
||||||
format,
|
format,
|
||||||
device: device.clone(),
|
device: device.clone(),
|
||||||
|
max_levels: mip_levels,
|
||||||
is_raw: false,
|
is_raw: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub(crate) fn scale(
|
pub(crate) fn scale(
|
||||||
&mut self,
|
&mut self,
|
||||||
scaling: Scale2D,
|
scaling: Scale2D,
|
||||||
format: ImageFormat,
|
format: ImageFormat,
|
||||||
viewport_size: &Size<u32>,
|
viewport_size: &Size<u32>,
|
||||||
_original: &Texture,
|
_original: &Texture,
|
||||||
source: &Texture,
|
source: &Texture
|
||||||
) -> error::Result<Size<u32>> {
|
) -> error::Result<Size<u32>> {
|
||||||
if self.is_raw {
|
if self.is_raw {
|
||||||
return Ok(self.size);
|
return Ok(self.size);
|
||||||
|
@ -94,7 +98,7 @@ impl OwnedFramebuffer {
|
||||||
| D3D11_FORMAT_SUPPORT_RENDER_TARGET.0,
|
| D3D11_FORMAT_SUPPORT_RENDER_TARGET.0,
|
||||||
);
|
);
|
||||||
|
|
||||||
let desc = default_desc(size, format);
|
let desc = default_desc(size, format, self.max_levels);
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut texture = self.device.CreateTexture2D(&desc, None)?;
|
let mut texture = self.device.CreateTexture2D(&desc, None)?;
|
||||||
std::mem::swap(&mut self.texture, &mut texture);
|
std::mem::swap(&mut self.texture, &mut texture);
|
||||||
|
@ -179,11 +183,11 @@ pub(crate) struct OutputFramebuffer {
|
||||||
pub viewport: D3D11_VIEWPORT,
|
pub viewport: D3D11_VIEWPORT,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_desc(size: Size<u32>, format: DXGI_FORMAT) -> D3D11_TEXTURE2D_DESC {
|
fn default_desc(size: Size<u32>, format: DXGI_FORMAT, mip_levels: u32) -> D3D11_TEXTURE2D_DESC {
|
||||||
D3D11_TEXTURE2D_DESC {
|
D3D11_TEXTURE2D_DESC {
|
||||||
Width: size.width,
|
Width: size.width,
|
||||||
Height: size.height,
|
Height: size.height,
|
||||||
MipLevels: 1,
|
MipLevels: mip_levels,
|
||||||
ArraySize: 1,
|
ArraySize: 1,
|
||||||
Format: format,
|
Format: format,
|
||||||
SampleDesc: DXGI_SAMPLE_DESC {
|
SampleDesc: DXGI_SAMPLE_DESC {
|
||||||
|
|
|
@ -221,6 +221,7 @@ struct TriangleUniforms {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod d3d11_hello_triangle {
|
pub mod d3d11_hello_triangle {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ mod samplers;
|
||||||
mod texture;
|
mod texture;
|
||||||
mod util;
|
mod util;
|
||||||
mod viewport;
|
mod viewport;
|
||||||
|
mod parameters;
|
||||||
|
|
||||||
pub use filter_chain::FilterChain;
|
pub use filter_chain::FilterChain;
|
||||||
pub use viewport::Viewport;
|
pub use viewport::Viewport;
|
||||||
|
@ -28,7 +29,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn triangle_d3d11() {
|
fn triangle_d3d11() {
|
||||||
let sample = hello_triangle::d3d11_hello_triangle::Sample::new(
|
let sample = hello_triangle::d3d11_hello_triangle::Sample::new(
|
||||||
"../test/slang-shaders/crt/crt-royale.slangp",
|
"../test/slang-shaders/border/gameboy-player/gameboy-player-crt-royale.slangp",
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
31
librashader-runtime-d3d11/src/parameters.rs
Normal file
31
librashader-runtime-d3d11/src/parameters.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
use std::collections::hash_map::Iter;
|
||||||
|
use librashader_runtime::parameters::FilterChainParameters;
|
||||||
|
use crate::FilterChain;
|
||||||
|
|
||||||
|
impl FilterChainParameters for FilterChain {
|
||||||
|
fn get_enabled_pass_count(&self) -> usize {
|
||||||
|
self.common.config.passes_enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_enabled_pass_count(&mut self, count: usize) {
|
||||||
|
self.common.config.passes_enabled = count
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enumerate_parameters(&self) -> Iter<String, f32> {
|
||||||
|
self.common.config.parameters.iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_parameter(&self, parameter: &str) -> Option<f32> {
|
||||||
|
self.common.config.parameters.get::<str>(parameter.as_ref()).map(|f| *f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parameter(&mut self, parameter: &str, new_value: f32) -> Option<f32> {
|
||||||
|
if let Some(value) = self.common.config.parameters.get_mut::<str>(parameter.as_ref()) {
|
||||||
|
let old = *value;
|
||||||
|
*value = new_value;
|
||||||
|
Some(old)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,95 +1,31 @@
|
||||||
use crate::binding::{UniformLocation, VariableLocation};
|
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
|
||||||
use crate::error::{FilterChainError, Result};
|
use librashader_reflect::reflect::semantics::{MemberOffset, ReflectSemantics, SemanticMap, TextureSemantics, UniformBinding, UniformMeta, UniformSemantic, VariableSemantics};
|
||||||
use crate::filter_pass::FilterPass;
|
use rustc_hash::FxHashMap;
|
||||||
use crate::framebuffer::GLImage;
|
use librashader_preprocess::ShaderSource;
|
||||||
use crate::render_target::RenderTarget;
|
use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation};
|
||||||
use crate::util;
|
use librashader_reflect::back::cross::{GlslangGlslContext, GlVersion};
|
||||||
use crate::util::{gl_get_version, gl_u16_to_version};
|
use librashader_reflect::back::targets::GLSL;
|
||||||
|
use librashader_reflect::front::shaderc::GlslangCompilation;
|
||||||
|
use spirv_cross::spirv::Decoration;
|
||||||
use gl::types::{GLint, GLuint};
|
use gl::types::{GLint, GLuint};
|
||||||
|
use librashader_common::{FilterMode, WrapMode};
|
||||||
use crate::binding::BufferStorage;
|
use std::collections::VecDeque;
|
||||||
|
use librashader_reflect::reflect::ReflectShader;
|
||||||
|
use crate::{error, GLImage, util, Viewport};
|
||||||
|
use crate::binding::{BufferStorage, UniformLocation, VariableLocation};
|
||||||
|
use crate::error::FilterChainError;
|
||||||
|
use crate::filter_pass::FilterPass;
|
||||||
use crate::gl::{DrawQuad, Framebuffer, FramebufferInterface, GLInterface, LoadLut, UboRing};
|
use crate::gl::{DrawQuad, Framebuffer, FramebufferInterface, GLInterface, LoadLut, UboRing};
|
||||||
use crate::options::{FilterChainOptions, FrameOptions};
|
use crate::options::{FilterChainOptions, FrameOptions};
|
||||||
|
use crate::render_target::RenderTarget;
|
||||||
use crate::samplers::SamplerSet;
|
use crate::samplers::SamplerSet;
|
||||||
use crate::texture::Texture;
|
use crate::texture::Texture;
|
||||||
use crate::viewport::Viewport;
|
use crate::util::{gl_get_version, gl_u16_to_version};
|
||||||
use librashader_common::{FilterMode, WrapMode};
|
|
||||||
use librashader_preprocess::ShaderSource;
|
|
||||||
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
|
|
||||||
use librashader_reflect::back::cross::{GlVersion, GlslangGlslContext};
|
|
||||||
use librashader_reflect::back::targets::GLSL;
|
|
||||||
use librashader_reflect::back::{CompileShader, CompilerBackend, FromCompilation};
|
|
||||||
use librashader_reflect::front::shaderc::GlslangCompilation;
|
|
||||||
use librashader_reflect::reflect::semantics::{
|
|
||||||
MemberOffset, ReflectSemantics, SemanticMap, TextureSemantics, UniformBinding, UniformMeta,
|
|
||||||
UniformSemantic, VariableSemantics,
|
|
||||||
};
|
|
||||||
use librashader_reflect::reflect::ReflectShader;
|
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use spirv_cross::spirv::Decoration;
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
pub struct FilterChain {
|
pub(crate) struct FilterChainImpl<T: GLInterface> {
|
||||||
filter: FilterChainInner,
|
pub(crate) common: FilterCommon,
|
||||||
}
|
|
||||||
|
|
||||||
impl FilterChain {
|
|
||||||
pub fn load_from_preset(
|
|
||||||
preset: ShaderPreset,
|
|
||||||
options: Option<&FilterChainOptions>,
|
|
||||||
) -> Result<Self> {
|
|
||||||
if let Some(options) = options && options.use_dsa {
|
|
||||||
return Ok(Self {
|
|
||||||
filter: FilterChainInner::DirectStateAccess(FilterChainImpl::load_from_preset(preset, Some(options))?)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Ok(Self {
|
|
||||||
filter: FilterChainInner::Compatibility(FilterChainImpl::load_from_preset(
|
|
||||||
preset, options,
|
|
||||||
)?),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Load the shader preset at the given path into a filter chain.
|
|
||||||
pub fn load_from_path(
|
|
||||||
path: impl AsRef<Path>,
|
|
||||||
options: Option<&FilterChainOptions>,
|
|
||||||
) -> Result<Self> {
|
|
||||||
// load passes from preset
|
|
||||||
let preset = ShaderPreset::try_parse(path)?;
|
|
||||||
Self::load_from_preset(preset, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Process a frame with the input image.
|
|
||||||
///
|
|
||||||
/// When this frame returns, GL_FRAMEBUFFER is bound to 0.
|
|
||||||
pub fn frame(
|
|
||||||
&mut self,
|
|
||||||
input: &GLImage,
|
|
||||||
viewport: &Viewport,
|
|
||||||
frame_count: usize,
|
|
||||||
options: Option<&FrameOptions>,
|
|
||||||
) -> Result<()> {
|
|
||||||
match &mut self.filter {
|
|
||||||
FilterChainInner::DirectStateAccess(p) => {
|
|
||||||
p.frame(frame_count, viewport, input, options)
|
|
||||||
}
|
|
||||||
FilterChainInner::Compatibility(p) => p.frame(frame_count, viewport, input, options),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum FilterChainInner {
|
|
||||||
DirectStateAccess(FilterChainImpl<crate::gl::gl46::DirectStateAccessGL>),
|
|
||||||
Compatibility(FilterChainImpl<crate::gl::gl3::CompatibilityGL>),
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FilterChainImpl<T: GLInterface> {
|
|
||||||
passes: Box<[FilterPass<T>]>,
|
passes: Box<[FilterPass<T>]>,
|
||||||
common: FilterCommon,
|
draw_quad: T::DrawQuad,
|
||||||
pub(crate) draw_quad: T::DrawQuad,
|
|
||||||
output_framebuffers: Box<[Framebuffer]>,
|
output_framebuffers: Box<[Framebuffer]>,
|
||||||
feedback_framebuffers: Box<[Framebuffer]>,
|
feedback_framebuffers: Box<[Framebuffer]>,
|
||||||
history_framebuffers: VecDeque<Framebuffer>,
|
history_framebuffers: VecDeque<Framebuffer>,
|
||||||
|
@ -152,7 +88,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
||||||
pub(crate) fn load_from_preset(
|
pub(crate) fn load_from_preset(
|
||||||
preset: ShaderPreset,
|
preset: ShaderPreset,
|
||||||
options: Option<&FilterChainOptions>,
|
options: Option<&FilterChainOptions>,
|
||||||
) -> Result<Self> {
|
) -> error::Result<Self> {
|
||||||
let (passes, semantics) = Self::load_preset(preset.shaders, &preset.textures)?;
|
let (passes, semantics) = Self::load_preset(preset.shaders, &preset.textures)?;
|
||||||
|
|
||||||
let version = options
|
let version = options
|
||||||
|
@ -218,7 +154,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
||||||
fn load_preset(
|
fn load_preset(
|
||||||
passes: Vec<ShaderPassConfig>,
|
passes: Vec<ShaderPassConfig>,
|
||||||
textures: &[TextureConfig],
|
textures: &[TextureConfig],
|
||||||
) -> Result<(Vec<ShaderPassMeta>, ReflectSemantics)> {
|
) -> error::Result<(Vec<ShaderPassMeta>, ReflectSemantics)> {
|
||||||
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
|
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
|
||||||
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> =
|
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> =
|
||||||
Default::default();
|
Default::default();
|
||||||
|
@ -244,7 +180,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
||||||
Ok::<_, FilterChainError>((shader, source, reflect))
|
Ok::<_, FilterChainError>((shader, source, reflect))
|
||||||
})
|
})
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>()?;
|
.collect::<error::Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>()?;
|
||||||
|
|
||||||
for details in &passes {
|
for details in &passes {
|
||||||
librashader_runtime::semantics::insert_pass_semantics(
|
librashader_runtime::semantics::insert_pass_semantics(
|
||||||
|
@ -272,7 +208,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
||||||
version: GlVersion,
|
version: GlVersion,
|
||||||
passes: Vec<ShaderPassMeta>,
|
passes: Vec<ShaderPassMeta>,
|
||||||
semantics: &ReflectSemantics,
|
semantics: &ReflectSemantics,
|
||||||
) -> Result<Box<[FilterPass<T>]>> {
|
) -> error::Result<Box<[FilterPass<T>]>> {
|
||||||
let mut filters = Vec::new();
|
let mut filters = Vec::new();
|
||||||
|
|
||||||
// initialize passes
|
// initialize passes
|
||||||
|
@ -456,7 +392,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
||||||
(framebuffers, history_textures.into_boxed_slice())
|
(framebuffers, history_textures.into_boxed_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_history(&mut self, input: &GLImage) -> Result<()> {
|
fn push_history(&mut self, input: &GLImage) -> error::Result<()> {
|
||||||
if let Some(mut back) = self.history_framebuffers.pop_back() {
|
if let Some(mut back) = self.history_framebuffers.pop_back() {
|
||||||
if back.size != input.size || (input.format != 0 && input.format != back.format) {
|
if back.size != input.size || (input.format != 0 && input.format != back.format) {
|
||||||
eprintln!("[history] resizing");
|
eprintln!("[history] resizing");
|
||||||
|
@ -480,7 +416,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
input: &GLImage,
|
input: &GLImage,
|
||||||
options: Option<&FrameOptions>,
|
options: Option<&FrameOptions>,
|
||||||
) -> Result<()> {
|
) -> error::Result<()> {
|
||||||
// limit number of passes to those enabled.
|
// limit number of passes to those enabled.
|
||||||
let passes = &mut self.passes[0..self.common.config.passes_enabled];
|
let passes = &mut self.passes[0..self.common.config.passes_enabled];
|
||||||
if let Some(options) = options {
|
if let Some(options) = options {
|
||||||
|
@ -579,6 +515,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
||||||
source = target;
|
source = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try to hint the optimizer
|
||||||
assert_eq!(last.len(), 1);
|
assert_eq!(last.len(), 1);
|
||||||
for pass in last {
|
for pass in last {
|
||||||
source.filter = pass.config.filter;
|
source.filter = pass.config.filter;
|
6
librashader-runtime-gl/src/filter_chain/inner.rs
Normal file
6
librashader-runtime-gl/src/filter_chain/inner.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
use crate::filter_chain::filter_impl::FilterChainImpl;
|
||||||
|
|
||||||
|
pub(in crate::filter_chain) enum FilterChainDispatch {
|
||||||
|
DirectStateAccess(FilterChainImpl<crate::gl::gl46::DirectStateAccessGL>),
|
||||||
|
Compatibility(FilterChainImpl<crate::gl::gl3::CompatibilityGL>),
|
||||||
|
}
|
82
librashader-runtime-gl/src/filter_chain/mod.rs
Normal file
82
librashader-runtime-gl/src/filter_chain/mod.rs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use librashader_presets::ShaderPreset;
|
||||||
|
use crate::filter_chain::filter_impl::FilterChainImpl;
|
||||||
|
use crate::filter_chain::inner::FilterChainDispatch;
|
||||||
|
use crate::{GLImage, Viewport};
|
||||||
|
use crate::error::{Result, FilterChainError};
|
||||||
|
use crate::options::{FilterChainOptions, FrameOptions};
|
||||||
|
|
||||||
|
mod filter_impl;
|
||||||
|
mod inner;
|
||||||
|
mod parameters;
|
||||||
|
|
||||||
|
pub(crate) use filter_impl::FilterCommon;
|
||||||
|
|
||||||
|
pub struct FilterChain {
|
||||||
|
pub(in crate::filter_chain) filter: FilterChainDispatch,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FilterChain {
|
||||||
|
pub fn load_from_preset(
|
||||||
|
preset: ShaderPreset,
|
||||||
|
options: Option<&FilterChainOptions>,
|
||||||
|
) -> Result<Self> {
|
||||||
|
if let Some(options) = options && options.use_dsa {
|
||||||
|
return Ok(Self {
|
||||||
|
filter: FilterChainDispatch::DirectStateAccess(FilterChainImpl::load_from_preset(preset, Some(options))?)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
filter: FilterChainDispatch::Compatibility(FilterChainImpl::load_from_preset(
|
||||||
|
preset, options,
|
||||||
|
)?),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load the shader preset at the given path into a filter chain.
|
||||||
|
pub fn load_from_path(
|
||||||
|
path: impl AsRef<Path>,
|
||||||
|
options: Option<&FilterChainOptions>,
|
||||||
|
) -> Result<Self> {
|
||||||
|
// load passes from preset
|
||||||
|
let preset = ShaderPreset::try_parse(path)?;
|
||||||
|
Self::load_from_preset(preset, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process a frame with the input image.
|
||||||
|
///
|
||||||
|
/// When this frame returns, GL_FRAMEBUFFER is bound to 0 if not using Direct State Access.
|
||||||
|
pub(crate) fn frame(
|
||||||
|
&mut self,
|
||||||
|
input: &GLImage,
|
||||||
|
viewport: &Viewport,
|
||||||
|
frame_count: usize,
|
||||||
|
options: Option<&FrameOptions>,
|
||||||
|
) -> Result<()> {
|
||||||
|
match &mut self.filter {
|
||||||
|
FilterChainDispatch::DirectStateAccess(p) => {
|
||||||
|
p.frame(frame_count, viewport, input, options)
|
||||||
|
}
|
||||||
|
FilterChainDispatch::Compatibility(p) => p.frame(frame_count, viewport, input, options),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl librashader_runtime::filter_chain::FilterChain for FilterChain {
|
||||||
|
type Error = FilterChainError;
|
||||||
|
type Input<'a> = &'a GLImage;
|
||||||
|
type Viewport<'a> = Viewport<'a>;
|
||||||
|
type FrameOptions = FrameOptions;
|
||||||
|
|
||||||
|
fn frame<'a>(
|
||||||
|
&mut self,
|
||||||
|
input: Self::Input<'a>,
|
||||||
|
viewport: &Self::Viewport<'a>,
|
||||||
|
frame_count: usize,
|
||||||
|
options: Option<&Self::FrameOptions>,
|
||||||
|
) -> std::result::Result<(), Self::Error> {
|
||||||
|
self.frame(input, viewport, frame_count, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
74
librashader-runtime-gl/src/filter_chain/parameters.rs
Normal file
74
librashader-runtime-gl/src/filter_chain/parameters.rs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
use std::collections::hash_map::Iter;
|
||||||
|
use librashader_runtime::parameters::FilterChainParameters;
|
||||||
|
use crate::filter_chain::filter_impl::FilterChainImpl;
|
||||||
|
use crate::filter_chain::inner::FilterChainDispatch;
|
||||||
|
use crate::FilterChain;
|
||||||
|
use crate::gl::GLInterface;
|
||||||
|
|
||||||
|
impl AsRef<dyn FilterChainParameters + 'static> for FilterChainDispatch {
|
||||||
|
fn as_ref<'a>(&'a self) -> &'a (dyn FilterChainParameters + 'static) {
|
||||||
|
match self {
|
||||||
|
FilterChainDispatch::DirectStateAccess(p) => p,
|
||||||
|
FilterChainDispatch::Compatibility(p) => p,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsMut<dyn FilterChainParameters + 'static> for FilterChainDispatch {
|
||||||
|
fn as_mut<'a>(&'a mut self) -> &'a mut (dyn FilterChainParameters + 'static) {
|
||||||
|
match self {
|
||||||
|
FilterChainDispatch::DirectStateAccess(p) => p,
|
||||||
|
FilterChainDispatch::Compatibility(p) => p,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FilterChainParameters for FilterChain {
|
||||||
|
fn get_enabled_pass_count(&self) -> usize {
|
||||||
|
self.filter.as_ref().get_enabled_pass_count()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_enabled_pass_count(&mut self, count: usize) {
|
||||||
|
self.filter.as_mut().set_enabled_pass_count(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enumerate_parameters(&self) -> Iter<String, f32> {
|
||||||
|
self.filter.as_ref().enumerate_parameters()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_parameter(&self, parameter: &str) -> Option<f32> {
|
||||||
|
self.filter.as_ref().get_parameter(parameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parameter(&mut self, parameter: &str, new_value: f32) -> Option<f32> {
|
||||||
|
self.filter.as_mut().set_parameter(parameter, new_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T: GLInterface> FilterChainParameters for FilterChainImpl<T> {
|
||||||
|
fn get_enabled_pass_count(&self) -> usize {
|
||||||
|
self.common.config.passes_enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_enabled_pass_count(&mut self, count: usize) {
|
||||||
|
self.common.config.passes_enabled = count
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enumerate_parameters(&self) -> Iter<String, f32> {
|
||||||
|
self.common.config.parameters.iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_parameter(&self, parameter: &str) -> Option<f32> {
|
||||||
|
self.common.config.parameters.get::<str>(parameter.as_ref()).map(|f| *f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parameter(&mut self, parameter: &str, new_value: f32) -> Option<f32> {
|
||||||
|
if let Some(value) = self.common.config.parameters.get_mut::<str>(parameter.as_ref()) {
|
||||||
|
let old = *value;
|
||||||
|
*value = new_value;
|
||||||
|
Some(old)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::binding::{BufferStorage, UniformLocation, VariableLocation};
|
use crate::binding::{BufferStorage, UniformLocation, VariableLocation};
|
||||||
use crate::filter_chain::FilterCommon;
|
use crate::filter_chain::FilterCommon;
|
||||||
use crate::gl::{BindTexture, FramebufferInterface, GLInterface, UboRing};
|
use crate::gl::{BindTexture, GLInterface, UboRing};
|
||||||
use crate::render_target::RenderTarget;
|
use crate::render_target::RenderTarget;
|
||||||
use crate::viewport::Viewport;
|
use crate::viewport::Viewport;
|
||||||
|
|
||||||
|
|
|
@ -74,3 +74,17 @@ impl DrawQuad for Gl3DrawQuad {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for Gl3DrawQuad {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
if self.vbo != 0 {
|
||||||
|
gl::DeleteBuffers(1, &self.vbo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.vao != 0 {
|
||||||
|
gl::DeleteVertexArrays(1, &self.vao)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::framebuffer::GLImage;
|
||||||
use crate::gl::LoadLut;
|
use crate::gl::LoadLut;
|
||||||
use crate::texture::Texture;
|
use crate::texture::Texture;
|
||||||
use gl::types::{GLsizei, GLuint};
|
use gl::types::{GLsizei, GLuint};
|
||||||
use librashader_common::image::Image;
|
use librashader_common::image::{Image, UVDirection};
|
||||||
use librashader_common::Size;
|
use librashader_common::Size;
|
||||||
use librashader_presets::TextureConfig;
|
use librashader_presets::TextureConfig;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
@ -19,7 +19,7 @@ impl LoadLut for Gl3LutLoad {
|
||||||
};
|
};
|
||||||
|
|
||||||
for (index, texture) in textures.iter().enumerate() {
|
for (index, texture) in textures.iter().enumerate() {
|
||||||
let image = Image::load(&texture.path)?;
|
let image = Image::load(&texture.path, UVDirection::BottomLeft)?;
|
||||||
let levels = if texture.mipmap {
|
let levels = if texture.mipmap {
|
||||||
librashader_runtime::scaling::calc_miplevel(image.size)
|
librashader_runtime::scaling::calc_miplevel(image.size)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -63,3 +63,17 @@ impl DrawQuad for Gl46DrawQuad {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for Gl46DrawQuad {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
if self.vbo != 0 {
|
||||||
|
gl::DeleteBuffers(1, &self.vbo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.vao != 0 {
|
||||||
|
gl::DeleteVertexArrays(1, &self.vao)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ use crate::framebuffer::GLImage;
|
||||||
use crate::gl::LoadLut;
|
use crate::gl::LoadLut;
|
||||||
use crate::texture::Texture;
|
use crate::texture::Texture;
|
||||||
use gl::types::{GLsizei, GLuint};
|
use gl::types::{GLsizei, GLuint};
|
||||||
use librashader_common::image::Image;
|
use librashader_common::image::{Image, UVDirection};
|
||||||
use librashader_common::Size;
|
use librashader_common::Size;
|
||||||
use librashader_presets::TextureConfig;
|
use librashader_presets::TextureConfig;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
@ -23,7 +23,7 @@ impl LoadLut for Gl46LutLoad {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index, texture) in textures.iter().enumerate() {
|
for (index, texture) in textures.iter().enumerate() {
|
||||||
let image = Image::load(&texture.path)?;
|
let image = Image::load(&texture.path, UVDirection::BottomLeft)?;
|
||||||
let levels = if texture.mipmap {
|
let levels = if texture.mipmap {
|
||||||
librashader_runtime::scaling::calc_miplevel(image.size)
|
librashader_runtime::scaling::calc_miplevel(image.size)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -31,7 +31,7 @@ mod tests {
|
||||||
fn triangle_gl() {
|
fn triangle_gl() {
|
||||||
let (glfw, window, events, shader, vao) = gl::gl3::hello_triangle::setup();
|
let (glfw, window, events, shader, vao) = gl::gl3::hello_triangle::setup();
|
||||||
let mut filter = FilterChain::load_from_path(
|
let mut filter = FilterChain::load_from_path(
|
||||||
"../test/slang-shaders/vhs/VHSPro.slangp",
|
"../test/slang-shaders/border/gameboy-player/gameboy-player-crt-royale.slangp",
|
||||||
Some(&FilterChainOptions {
|
Some(&FilterChainOptions {
|
||||||
gl_version: 0,
|
gl_version: 0,
|
||||||
use_dsa: false,
|
use_dsa: false,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::gl::{Framebuffer, FramebufferInterface};
|
use crate::gl::Framebuffer;
|
||||||
use crate::viewport::Viewport;
|
use crate::viewport::Viewport;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
|
30
librashader-runtime/src/filter_chain.rs
Normal file
30
librashader-runtime/src/filter_chain.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
/// Common trait for filter chains.
|
||||||
|
pub trait FilterChain {
|
||||||
|
/// The error type for a filter chain.
|
||||||
|
type Error: Error;
|
||||||
|
|
||||||
|
/// The type for the input surface to apply a filter chain to.
|
||||||
|
type Input<'a>;
|
||||||
|
|
||||||
|
/// The type for the output surface, including viewport information, to output the result of a
|
||||||
|
/// filter chain to.
|
||||||
|
type Viewport<'a>;
|
||||||
|
|
||||||
|
/// The per-frame options to pass to the filter chain.
|
||||||
|
type FrameOptions;
|
||||||
|
|
||||||
|
/// Process a frame with the input image.
|
||||||
|
///
|
||||||
|
/// The output image should be written to the viewport. It is expected that the viewport
|
||||||
|
/// contains some sort of handle with interior mutability to a GPU buffer, e.g. a
|
||||||
|
/// `RenderTargetView`, `vkImage`, or a texture `GLuint`.
|
||||||
|
fn frame<'a>(
|
||||||
|
&mut self,
|
||||||
|
input: Self::Input<'a>,
|
||||||
|
viewport: &Self::Viewport<'a>,
|
||||||
|
frame_count: usize,
|
||||||
|
options: Option<&Self::FrameOptions>,
|
||||||
|
) -> Result<(), Self::Error>;
|
||||||
|
}
|
|
@ -1,3 +1,16 @@
|
||||||
|
//! Helpers and shared logic for librashader runtime implementations.
|
||||||
|
|
||||||
|
/// Scaling helpers.
|
||||||
pub mod scaling;
|
pub mod scaling;
|
||||||
|
|
||||||
|
/// Semantics helpers.
|
||||||
pub mod semantics;
|
pub mod semantics;
|
||||||
|
|
||||||
|
/// Uniform binding helpers.
|
||||||
pub mod uniforms;
|
pub mod uniforms;
|
||||||
|
|
||||||
|
/// Parameter reflection helpers and traits.
|
||||||
|
pub mod parameters;
|
||||||
|
|
||||||
|
/// Filter chain helpers and traits.
|
||||||
|
pub mod filter_chain;
|
||||||
|
|
19
librashader-runtime/src/parameters.rs
Normal file
19
librashader-runtime/src/parameters.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/// Trait for filter chains that allow runtime reflection of shader parameters.
|
||||||
|
pub trait FilterChainParameters {
|
||||||
|
/// Gets the number of shader passes enabled at runtime.
|
||||||
|
fn get_enabled_pass_count(&self) -> usize;
|
||||||
|
|
||||||
|
/// Sets the number of shader passes enabled at runtime.
|
||||||
|
fn set_enabled_pass_count(&mut self, count: usize);
|
||||||
|
|
||||||
|
/// Enumerates the active parameters as well as their values in the current filter chain.
|
||||||
|
fn enumerate_parameters(&self) -> std::collections::hash_map::Iter<String, f32>;
|
||||||
|
|
||||||
|
/// Get the value of the given parameter if present.
|
||||||
|
fn get_parameter(&self, parameter: &str) -> Option<f32>;
|
||||||
|
|
||||||
|
/// Set the value of the given parameter if present.
|
||||||
|
///
|
||||||
|
/// Returns `None` if the parameter did not exist, or the old value if successful.
|
||||||
|
fn set_parameter(&mut self, parameter: &str, new_value: f32) -> Option<f32>;
|
||||||
|
}
|
|
@ -3,42 +3,40 @@ use librashader_presets::{Scale2D, ScaleFactor, ScaleType, Scaling};
|
||||||
use num_traits::AsPrimitive;
|
use num_traits::AsPrimitive;
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
|
|
||||||
|
/// Produce a `Size<T>` scaled with the input scaling options.
|
||||||
pub fn scale<T>(scaling: Scale2D, source: Size<T>, viewport: Size<T>) -> Size<T>
|
pub fn scale<T>(scaling: Scale2D, source: Size<T>, viewport: Size<T>) -> Size<T>
|
||||||
where
|
where
|
||||||
T: Mul<ScaleFactor, Output = f32> + Copy + 'static,
|
T: Mul<ScaleFactor, Output = f32> + Copy + 'static,
|
||||||
f32: AsPrimitive<T>,
|
f32: AsPrimitive<T>,
|
||||||
{
|
{
|
||||||
let width: f32;
|
let width = match scaling.x {
|
||||||
let height: f32;
|
|
||||||
|
|
||||||
match scaling.x {
|
|
||||||
Scaling {
|
Scaling {
|
||||||
scale_type: ScaleType::Input,
|
scale_type: ScaleType::Input,
|
||||||
factor,
|
factor,
|
||||||
} => width = source.width * factor,
|
} => source.width * factor,
|
||||||
Scaling {
|
Scaling {
|
||||||
scale_type: ScaleType::Absolute,
|
scale_type: ScaleType::Absolute,
|
||||||
factor,
|
factor,
|
||||||
} => width = factor.into(),
|
} => factor.into(),
|
||||||
Scaling {
|
Scaling {
|
||||||
scale_type: ScaleType::Viewport,
|
scale_type: ScaleType::Viewport,
|
||||||
factor,
|
factor,
|
||||||
} => width = viewport.width * factor,
|
} => viewport.width * factor,
|
||||||
};
|
};
|
||||||
|
|
||||||
match scaling.y {
|
let height = match scaling.y {
|
||||||
Scaling {
|
Scaling {
|
||||||
scale_type: ScaleType::Input,
|
scale_type: ScaleType::Input,
|
||||||
factor,
|
factor,
|
||||||
} => height = source.height * factor,
|
} => source.height * factor,
|
||||||
Scaling {
|
Scaling {
|
||||||
scale_type: ScaleType::Absolute,
|
scale_type: ScaleType::Absolute,
|
||||||
factor,
|
factor,
|
||||||
} => height = factor.into(),
|
} => factor.into(),
|
||||||
Scaling {
|
Scaling {
|
||||||
scale_type: ScaleType::Viewport,
|
scale_type: ScaleType::Viewport,
|
||||||
factor,
|
factor,
|
||||||
} => height = viewport.height * factor,
|
} => viewport.height * factor,
|
||||||
};
|
};
|
||||||
|
|
||||||
Size {
|
Size {
|
||||||
|
@ -47,6 +45,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate the number of mipmap levels for a given size.
|
||||||
pub fn calc_miplevel(size: Size<u32>) -> u32 {
|
pub fn calc_miplevel(size: Size<u32>) -> u32 {
|
||||||
let mut size = std::cmp::max(size.width, size.height);
|
let mut size = std::cmp::max(size.width, size.height);
|
||||||
let mut levels = 0;
|
let mut levels = 0;
|
||||||
|
|
|
@ -2,9 +2,13 @@ use librashader_presets::{ShaderPassConfig, TextureConfig};
|
||||||
use librashader_reflect::reflect::semantics::{SemanticMap, TextureSemantics, UniformSemantic};
|
use librashader_reflect::reflect::semantics::{SemanticMap, TextureSemantics, UniformSemantic};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
/// A map for variable names and uniform semantics
|
||||||
pub type UniformSemanticsMap = FxHashMap<String, UniformSemantic>;
|
pub type UniformSemanticsMap = FxHashMap<String, UniformSemantic>;
|
||||||
|
|
||||||
|
/// A map for sampler names and texture semantics.
|
||||||
pub type TextureSemanticsMap = FxHashMap<String, SemanticMap<TextureSemantics>>;
|
pub type TextureSemanticsMap = FxHashMap<String, SemanticMap<TextureSemantics>>;
|
||||||
|
|
||||||
|
/// Insert the available semantics for the input pass config into the provided semantic maps.
|
||||||
pub fn insert_pass_semantics(
|
pub fn insert_pass_semantics(
|
||||||
uniform_semantics: &mut UniformSemanticsMap,
|
uniform_semantics: &mut UniformSemanticsMap,
|
||||||
texture_semantics: &mut TextureSemanticsMap,
|
texture_semantics: &mut TextureSemanticsMap,
|
||||||
|
@ -54,6 +58,7 @@ pub fn insert_pass_semantics(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// /// Insert the available semantics for the input texture config into the provided semantic maps.
|
||||||
pub fn insert_lut_semantics(
|
pub fn insert_lut_semantics(
|
||||||
textures: &[TextureConfig],
|
textures: &[TextureConfig],
|
||||||
uniform_semantics: &mut UniformSemanticsMap,
|
uniform_semantics: &mut UniformSemanticsMap,
|
||||||
|
|
|
@ -1,24 +1,30 @@
|
||||||
use librashader_reflect::reflect::semantics::MemberOffset;
|
use librashader_reflect::reflect::semantics::MemberOffset;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
/// A scalar value that is valid as a uniform member
|
||||||
pub trait UniformScalar: Copy + bytemuck::Pod {}
|
pub trait UniformScalar: Copy + bytemuck::Pod {}
|
||||||
impl UniformScalar for f32 {}
|
impl UniformScalar for f32 {}
|
||||||
impl UniformScalar for i32 {}
|
impl UniformScalar for i32 {}
|
||||||
impl UniformScalar for u32 {}
|
impl UniformScalar for u32 {}
|
||||||
|
|
||||||
pub struct NoUniformBinder;
|
/// A trait for a binder that binds the given value and context into the uniform for a shader pass.
|
||||||
impl<T> BindUniform<Option<()>, T> for NoUniformBinder {
|
|
||||||
fn bind_uniform(_: T, _: Option<()>) -> Option<()> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait BindUniform<C, T> {
|
pub trait BindUniform<C, T> {
|
||||||
|
/// Bind the given value to the shader uniforms given the input context.
|
||||||
|
///
|
||||||
|
/// A `BindUniform` implementation should not write to a backing buffer from a [`UniformStorage`](crate::uniforms::UniformStorage).
|
||||||
|
/// If the binding is successful and no writes to a backing buffer is necessary, this function should return `Some(())`.
|
||||||
|
/// If this function returns `None`, then the value will instead be written to the backing buffer.
|
||||||
fn bind_uniform(value: T, ctx: C) -> Option<()>;
|
fn bind_uniform(value: T, ctx: C) -> Option<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait to access the raw pointer to a backing uniform storage.
|
||||||
pub trait UniformStorageAccess {
|
pub trait UniformStorageAccess {
|
||||||
|
/// Get a pointer to the backing UBO storage. This pointer must be valid for the lifetime
|
||||||
|
/// of the implementing struct.
|
||||||
fn ubo_pointer(&self) -> *const u8;
|
fn ubo_pointer(&self) -> *const u8;
|
||||||
|
|
||||||
|
/// Get a pointer to the backing Push Constant buffer storage.
|
||||||
|
/// This pointer must be valid for the lifetime of the implementing struct.
|
||||||
fn push_pointer(&self) -> *const u8;
|
fn push_pointer(&self) -> *const u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,9 +38,19 @@ impl<T, H> UniformStorageAccess for UniformStorage<T, H> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A uniform binder that always returns `None`, and does not do any binding of uniforms.
|
||||||
|
/// All uniform data is thus written into the backing buffer storage.
|
||||||
|
pub struct NoUniformBinder;
|
||||||
|
impl<T> BindUniform<Option<()>, T> for NoUniformBinder {
|
||||||
|
fn bind_uniform(_: T, _: Option<()>) -> Option<()> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A helper to bind uniform variables to UBO or Push Constant Buffers.
|
||||||
pub struct UniformStorage<H = NoUniformBinder, C = Option<()>> {
|
pub struct UniformStorage<H = NoUniformBinder, C = Option<()>> {
|
||||||
pub ubo: Box<[u8]>,
|
ubo: Box<[u8]>,
|
||||||
pub push: Box<[u8]>,
|
push: Box<[u8]>,
|
||||||
_h: PhantomData<H>,
|
_h: PhantomData<H>,
|
||||||
_c: PhantomData<C>,
|
_c: PhantomData<C>,
|
||||||
}
|
}
|
||||||
|
@ -47,6 +63,8 @@ where
|
||||||
H: for<'a> BindUniform<C, &'a [f32; 4]>,
|
H: for<'a> BindUniform<C, &'a [f32; 4]>,
|
||||||
H: for<'a> BindUniform<C, &'a [f32; 16]>,
|
H: for<'a> BindUniform<C, &'a [f32; 16]>,
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// Create a new `UniformStorage` with the given size for UBO and Push Constant Buffer sizes.
|
||||||
pub fn new(ubo_size: usize, push_size: usize) -> Self {
|
pub fn new(ubo_size: usize, push_size: usize) -> Self {
|
||||||
UniformStorage {
|
UniformStorage {
|
||||||
ubo: vec![0u8; ubo_size].into_boxed_slice(),
|
ubo: vec![0u8; ubo_size].into_boxed_slice(),
|
||||||
|
@ -67,6 +85,7 @@ where
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
fn write_mat4_inner(buffer: &mut [u8], mat4: &[f32; 16], ctx: C) {
|
fn write_mat4_inner(buffer: &mut [u8], mat4: &[f32; 16], ctx: C) {
|
||||||
if H::bind_uniform(mat4, ctx).is_none() {
|
if H::bind_uniform(mat4, ctx).is_none() {
|
||||||
let mat4 = bytemuck::cast_slice(mat4);
|
let mat4 = bytemuck::cast_slice(mat4);
|
||||||
|
@ -74,6 +93,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
fn write_vec4_inner(buffer: &mut [u8], vec4: impl Into<[f32; 4]>, ctx: C) {
|
fn write_vec4_inner(buffer: &mut [u8], vec4: impl Into<[f32; 4]>, ctx: C) {
|
||||||
let vec4 = vec4.into();
|
let vec4 = vec4.into();
|
||||||
if H::bind_uniform(&vec4, ctx).is_none() {
|
if H::bind_uniform(&vec4, ctx).is_none() {
|
||||||
|
@ -82,6 +102,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Bind a `mat4` to the given offset.
|
||||||
pub fn bind_mat4(&mut self, offset: MemberOffset, value: &[f32; 16], ctx: C) {
|
pub fn bind_mat4(&mut self, offset: MemberOffset, value: &[f32; 16], ctx: C) {
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.ubo, offset),
|
MemberOffset::Ubo(offset) => (&mut self.ubo, offset),
|
||||||
|
@ -94,6 +115,7 @@ where
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Bind a `vec4` to the given offset.
|
||||||
pub fn bind_vec4(&mut self, offset: MemberOffset, value: impl Into<[f32; 4]>, ctx: C) {
|
pub fn bind_vec4(&mut self, offset: MemberOffset, value: impl Into<[f32; 4]>, ctx: C) {
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.ubo, offset),
|
MemberOffset::Ubo(offset) => (&mut self.ubo, offset),
|
||||||
|
@ -107,6 +129,7 @@ where
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Bind a scalar to the given offset.
|
||||||
pub fn bind_scalar<T: UniformScalar>(&mut self, offset: MemberOffset, value: T, ctx: C)
|
pub fn bind_scalar<T: UniformScalar>(&mut self, offset: MemberOffset, value: T, ctx: C)
|
||||||
where
|
where
|
||||||
H: BindUniform<C, T>,
|
H: BindUniform<C, T>,
|
||||||
|
|
|
@ -9,6 +9,7 @@ librashader-common = { path = "../librashader-common" }
|
||||||
librashader-presets = { path = "../librashader-presets" }
|
librashader-presets = { path = "../librashader-presets" }
|
||||||
librashader-preprocess = { path = "../librashader-preprocess" }
|
librashader-preprocess = { path = "../librashader-preprocess" }
|
||||||
librashader-reflect = { path = "../librashader-reflect" }
|
librashader-reflect = { path = "../librashader-reflect" }
|
||||||
|
librashader-runtime = { path = "../librashader-runtime" }
|
||||||
librashader-runtime-d3d11 = { path = "../librashader-runtime-d3d11" }
|
librashader-runtime-d3d11 = { path = "../librashader-runtime-d3d11" }
|
||||||
librashader-runtime-gl = { path = "../librashader-runtime-gl" }
|
librashader-runtime-gl = { path = "../librashader-runtime-gl" }
|
||||||
|
|
||||||
|
|
|
@ -1,68 +1,17 @@
|
||||||
//! Re-exports for usage of librashader in consuming libraries.
|
//! Re-exports for usage of librashader in consuming libraries.
|
||||||
//!
|
//!
|
||||||
//! Runtime implementations should depend directly on constituent crates.
|
//! Runtime implementations should depend directly on constituent crates.
|
||||||
|
|
||||||
|
|
||||||
|
/// Parsing and usage of shader presets.
|
||||||
|
///
|
||||||
|
/// Shader presets contain shader and texture parameters, and the order in which to apply a set of shaders
|
||||||
|
/// in a filter chain.
|
||||||
pub mod presets {
|
pub mod presets {
|
||||||
pub use librashader_presets::*;
|
pub use librashader_presets::*;
|
||||||
}
|
|
||||||
|
|
||||||
pub mod preprocess {
|
|
||||||
pub use librashader_preprocess::*;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod reflect {
|
|
||||||
pub use librashader_reflect::error::*;
|
|
||||||
|
|
||||||
pub use librashader_reflect::reflect::{
|
|
||||||
semantics, ReflectMeta, ReflectShader, ShaderReflection,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub use librashader_reflect::back::{
|
|
||||||
targets::OutputTarget, CompileShader, CompilerBackend, FromCompilation,
|
|
||||||
ShaderCompilerOutput,
|
|
||||||
};
|
|
||||||
pub use librashader_reflect::front::shaderc::GlslangCompilation;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod targets {
|
|
||||||
/// Shader compiler targets and runtime for OpenGL 3.3+.
|
|
||||||
pub mod gl {
|
|
||||||
/// Shader compiler target for GLSL.
|
|
||||||
pub use librashader_reflect::back::targets::GLSL;
|
|
||||||
|
|
||||||
/// Shader runtime for OpenGL.
|
|
||||||
pub mod runtime {
|
|
||||||
pub use librashader_runtime_gl::*;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Shader compiler targets and runtime for DirectX.
|
|
||||||
pub mod d3d {
|
|
||||||
/// Shader compiler target for HLSL.
|
|
||||||
pub use librashader_reflect::back::targets::HLSL;
|
|
||||||
|
|
||||||
/// Shader runtime for DirectX.
|
|
||||||
pub mod runtime {
|
|
||||||
|
|
||||||
/// Shader runtime for DirectX 11.
|
|
||||||
pub mod d3d11 {
|
|
||||||
pub use librashader_runtime_d3d11::*;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Shader compiler targets and runtime for Vulkan.
|
|
||||||
pub mod vk {
|
|
||||||
/// Shader compiler target for SPIR-V.
|
|
||||||
pub use librashader_reflect::back::targets::SPIRV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
|
||||||
|
|
||||||
pub mod util {
|
|
||||||
use librashader_preprocess::{PreprocessError, ShaderParameter, ShaderSource};
|
use librashader_preprocess::{PreprocessError, ShaderParameter, ShaderSource};
|
||||||
use librashader_presets::ShaderPreset;
|
use librashader_presets::ShaderPreset;
|
||||||
|
/// Get full parameter metadata from a shader preset.
|
||||||
pub fn get_parameter_meta(
|
pub fn get_parameter_meta(
|
||||||
preset: &ShaderPreset,
|
preset: &ShaderPreset,
|
||||||
) -> Result<impl Iterator<Item = ShaderParameter>, PreprocessError> {
|
) -> Result<impl Iterator<Item = ShaderParameter>, PreprocessError> {
|
||||||
|
@ -76,3 +25,61 @@ pub mod util {
|
||||||
Ok(iters.into_iter().flatten())
|
Ok(iters.into_iter().flatten())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Loading and preprocessing of 'slang' shader source files.
|
||||||
|
///
|
||||||
|
/// Shader sources files must be loaded with imports resolved before being able to be compiled.
|
||||||
|
/// Shader parameters are also defined in `#pragma`s within shader source files which must be parsed.
|
||||||
|
pub mod preprocess {
|
||||||
|
pub use librashader_preprocess::*;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shader compilation and reflection.
|
||||||
|
pub mod reflect {
|
||||||
|
/// Supported shader compiler targets.
|
||||||
|
pub mod targets {
|
||||||
|
/// Shader compiler target for GLSL.
|
||||||
|
pub use librashader_reflect::back::targets::GLSL;
|
||||||
|
|
||||||
|
/// Shader compiler target for HLSL.
|
||||||
|
pub use librashader_reflect::back::targets::HLSL;
|
||||||
|
|
||||||
|
/// Shader compiler target for SPIR-V.
|
||||||
|
pub use librashader_reflect::back::targets::SPIRV;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use librashader_reflect::error::*;
|
||||||
|
|
||||||
|
pub use librashader_reflect::reflect::{
|
||||||
|
semantics, ReflectMeta, ReflectShader, ShaderReflection,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub use librashader_reflect::back::{
|
||||||
|
targets::OutputTarget, CompileShader, CompilerBackend, FromCompilation,
|
||||||
|
ShaderCompilerOutput,
|
||||||
|
};
|
||||||
|
pub use librashader_reflect::front::shaderc::GlslangCompilation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shader runtimes to execute a filter chain on a GPU surface.
|
||||||
|
pub mod runtime {
|
||||||
|
pub use librashader_runtime::parameters::FilterChainParameters;
|
||||||
|
pub use librashader_runtime::filter_chain::FilterChain;
|
||||||
|
|
||||||
|
/// Shader runtime for OpenGL 3.3+.
|
||||||
|
pub mod gl {
|
||||||
|
pub use librashader_runtime_gl::*;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shader runtime for Direct3D11
|
||||||
|
pub mod d3d11 {
|
||||||
|
pub use librashader_runtime_d3d11::*;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shader compiler targets and runtime for Vulkan.
|
||||||
|
pub mod vk {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
||||||
|
|
Loading…
Reference in a new issue