dx11: begin to work on dx11 implementation
This commit is contained in:
parent
5d476d5229
commit
dadfb6ba33
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -426,6 +426,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gl",
|
"gl",
|
||||||
"image",
|
"image",
|
||||||
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -468,6 +469,7 @@ dependencies = [
|
||||||
name = "librashader-runtime-dx11"
|
name = "librashader-runtime-dx11"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
"gfx-maths",
|
"gfx-maths",
|
||||||
"librashader-common",
|
"librashader-common",
|
||||||
"librashader-preprocess",
|
"librashader-preprocess",
|
||||||
|
|
27
README.md
27
README.md
|
@ -22,23 +22,30 @@ of DirectX and OpenGL, as well as Metal, are not supported (but pull-requests ar
|
||||||
| DirectX 9 | ❌ | |
|
| DirectX 9 | ❌ | |
|
||||||
| Metal | ❌ | |
|
| Metal | ❌ | |
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
🚧 *`librashader_ld` is WIP* 🚧
|
||||||
|
|
||||||
|
librashader provides both a Rust API under the `librashader` crate, and a C API. Both APIs are first-class, fully supported.
|
||||||
|
|
||||||
|
The librashader C API is best used by linking statically with `librashader_ld`, which implements a loader that dynamically
|
||||||
|
loads the librashader (`librashader.so` or `rashader.dll`) implementation in the search path.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
The core parts of librashader such as the preprocessor, the preset parser,
|
The core parts of librashader such as the preprocessor, the preset parser,
|
||||||
the reflection library, and the runtimes, are all licensed under the Mozilla Public License version 2.0.
|
the reflection library, and the runtimes, are all licensed under the Mozilla Public License version 2.0.
|
||||||
|
|
||||||
The librashader C API, i.e. its headers and definitions, *not its implementation in `librashader_capi`*,
|
The librashader C API, i.e. its headers and definitions, *not its implementation in `librashader_capi`*,
|
||||||
are unique to librashader and are more permissively licensed, and may allow you to use librashader in your permissively
|
are more permissively licensed, and may allow you to use librashader in your permissively
|
||||||
licensed or proprietary project.
|
licensed or proprietary project.
|
||||||
|
|
||||||
While the code for `librashader_capi` (`librashader.so` and `rashader.dll`) is still under MPL-2.0,
|
To facilitate easier use of librashader in projects incompatible with MPL-2.0, `librashader_ld`
|
||||||
you may use librashader in proprietary works by linking against the MIT licensed `librashader_ld`,
|
implements a loader which thunks its calls to any `librashader.so` or `rashader.dll`
|
||||||
which implements the librashader C API, and thunks its calls to any `librashader.so` or `rashader.dll`
|
library found in the load path. A non-MPL-2.0 compatible project may link against
|
||||||
library found in the load path, *provided that `librashader.so` or `rashader.dll` are distributed under the restrictions
|
`librashader_ld` to use the librashader runtime, *provided that `librashader.so` or `rashader.dll`
|
||||||
of MPLv2*.
|
are distributed under the restrictions of MPLv2*.
|
||||||
|
|
||||||
Note that if your project is not compatible with MPLv2, you **can not distribute `librashader.so` or `rashader.dll`**
|
Note that this means that if your project is not compatible with MPL-2.0, you **can not distribute `librashader.so` or `rashader.dll`**
|
||||||
alongside your project, **only `librashader-ld.so` or `rashader-ld.dll`**, which will do nothing without a librashader
|
alongside your project. The end user must obtain the implementation of librashader themselves.
|
||||||
implementation in the load path. The end user must obtain the implementation of librashader themselves.
|
|
||||||
|
|
||||||
You may, at your discretion, choose to distribute `librashader` under the terms of MPL-2.0 instead of GPLv3.
|
At your discretion, you may instead choose to distribute `librashader` under the terms of GPLv3 rather than MPL-2.0
|
|
@ -8,7 +8,13 @@ edition = "2021"
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
opengl = ["gl"]
|
opengl = ["gl"]
|
||||||
|
directx = ["windows"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gl = { version = "0.14.0", optional = true }
|
gl = { version = "0.14.0", optional = true }
|
||||||
image = "0.24.5"
|
image = "0.24.5"
|
||||||
|
num-traits = "0.2.15"
|
||||||
|
#
|
||||||
|
#[dependencies.windows]
|
||||||
|
#optional = true
|
||||||
|
#version = "0.43.0"
|
||||||
|
|
39
librashader-common/src/dx.rs
Normal file
39
librashader-common/src/dx.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
use crate::{FilterMode, ShaderFormat, WrapMode};
|
||||||
|
//
|
||||||
|
// impl From<ShaderFormat> for gl::types::GLenum {
|
||||||
|
// fn from(format: ShaderFormat) -> Self {
|
||||||
|
// match format {
|
||||||
|
// ShaderFormat::Unknown => 0 as gl::types::GLenum,
|
||||||
|
// ShaderFormat::R8Unorm => gl::R8,
|
||||||
|
// ShaderFormat::R8Uint => gl::R8UI,
|
||||||
|
// ShaderFormat::R8Sint => gl::R8I,
|
||||||
|
// ShaderFormat::R8G8Unorm => gl::RG8,
|
||||||
|
// ShaderFormat::R8G8Uint => gl::RG8UI,
|
||||||
|
// ShaderFormat::R8G8Sint => gl::RG8I,
|
||||||
|
// ShaderFormat::R8G8B8A8Unorm => gl::RGBA8,
|
||||||
|
// ShaderFormat::R8G8B8A8Uint => gl::RGBA8UI,
|
||||||
|
// ShaderFormat::R8G8B8A8Sint => gl::RGBA8I,
|
||||||
|
// ShaderFormat::R8G8B8A8Srgb => gl::SRGB8_ALPHA8,
|
||||||
|
// ShaderFormat::A2B10G10R10UnormPack32 => gl::RGB10_A2,
|
||||||
|
// ShaderFormat::A2B10G10R10UintPack32 => gl::RGB10_A2UI,
|
||||||
|
// ShaderFormat::R16Uint => gl::R16UI,
|
||||||
|
// ShaderFormat::R16Sint => gl::R16I,
|
||||||
|
// ShaderFormat::R16Sfloat => gl::R16F,
|
||||||
|
// ShaderFormat::R16G16Uint => gl::RG16UI,
|
||||||
|
// ShaderFormat::R16G16Sint => gl::RG16I,
|
||||||
|
// ShaderFormat::R16G16Sfloat => gl::RG16F,
|
||||||
|
// ShaderFormat::R16G16B16A16Uint => gl::RGBA16UI,
|
||||||
|
// ShaderFormat::R16G16B16A16Sint => gl::RGBA16I,
|
||||||
|
// ShaderFormat::R16G16B16A16Sfloat => gl::RGBA16F,
|
||||||
|
// ShaderFormat::R32Uint => gl::R32UI,
|
||||||
|
// ShaderFormat::R32Sint => gl::R32I,
|
||||||
|
// ShaderFormat::R32Sfloat => gl::R32F,
|
||||||
|
// ShaderFormat::R32G32Uint => gl::RG32UI,
|
||||||
|
// ShaderFormat::R32G32Sint => gl::RG32I,
|
||||||
|
// ShaderFormat::R32G32Sfloat => gl::RG32F,
|
||||||
|
// ShaderFormat::R32G32B32A32Uint => gl::RGBA32UI,
|
||||||
|
// ShaderFormat::R32G32B32A32Sint => gl::RGBA32I,
|
||||||
|
// ShaderFormat::R32G32B32A32Sfloat => gl::RGBA32F,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
|
@ -2,8 +2,7 @@ use std::path::Path;
|
||||||
|
|
||||||
pub struct Image {
|
pub struct Image {
|
||||||
pub bytes: Vec<u8>,
|
pub bytes: Vec<u8>,
|
||||||
pub height: u32,
|
pub size: Size<u32>
|
||||||
pub width: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image {
|
impl Image {
|
||||||
|
@ -15,10 +14,13 @@ impl Image {
|
||||||
|
|
||||||
Ok(Image {
|
Ok(Image {
|
||||||
bytes: image.to_vec(),
|
bytes: image.to_vec(),
|
||||||
height,
|
size: Size {
|
||||||
width,
|
height,
|
||||||
|
width,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use image::ImageError as ImageError;
|
pub use image::ImageError as ImageError;
|
||||||
|
use crate::Size;
|
|
@ -1,9 +1,15 @@
|
||||||
#[cfg(feature = "opengl")]
|
#[cfg(feature = "opengl")]
|
||||||
pub mod gl;
|
pub mod gl;
|
||||||
|
#[cfg(feature = "dxgi")]
|
||||||
|
pub mod dx;
|
||||||
|
|
||||||
pub mod image;
|
pub mod image;
|
||||||
|
pub mod runtime;
|
||||||
|
|
||||||
|
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use num_traits::AsPrimitive;
|
||||||
|
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
@ -139,3 +145,16 @@ impl<T> Size<T> {
|
||||||
Size { width, height }
|
Size { width, height }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> From<Size<T>> for [f32; 4]
|
||||||
|
where T: Copy + AsPrimitive<f32>
|
||||||
|
{
|
||||||
|
fn from(value: Size<T>) -> Self {
|
||||||
|
[
|
||||||
|
value.width.as_(),
|
||||||
|
value.height.as_(),
|
||||||
|
1.0 / value.width.as_(),
|
||||||
|
1.0 / value.height.as_(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
0
librashader-common/src/runtime.rs
Normal file
0
librashader-common/src/runtime.rs
Normal file
|
@ -29,10 +29,15 @@ impl FromCompilation<GlslangCompilation> for GLSL {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct GlslangHlslContext {
|
||||||
|
pub compiler: CompiledAst<spirv_cross::hlsl::Target>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl FromCompilation<GlslangCompilation> for HLSL {
|
impl FromCompilation<GlslangCompilation> for HLSL {
|
||||||
type Target = HLSL;
|
type Target = HLSL;
|
||||||
type Options = Option<()>;
|
type Options = Option<()>;
|
||||||
type Context = ();
|
type Context = GlslangHlslContext;
|
||||||
type Output = impl CompileShader<Self::Target, Options = Self::Options, Context = Self::Context> + ReflectShader;
|
type Output = impl CompileShader<Self::Target, Options = Self::Options, Context = Self::Context> + ReflectShader;
|
||||||
|
|
||||||
fn from_compilation(
|
fn from_compilation(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::error::{SemanticsErrorKind, ShaderCompileError, ShaderReflectError};
|
use crate::error::{SemanticsErrorKind, ShaderCompileError, ShaderReflectError};
|
||||||
use crate::front::shaderc::GlslangCompilation;
|
use crate::front::shaderc::GlslangCompilation;
|
||||||
use crate::reflect::semantics::{BindingStage, MAX_BINDINGS_COUNT, MAX_PUSH_BUFFER_SIZE, MemberOffset, PushReflection, ReflectSemantics, ShaderReflection, TextureImage, TextureSemanticMap, TextureSemantics, TextureSizeMeta, TypeInfo, UboReflection, ValidateTypeSemantics, VariableMeta, VariableSemanticMap, VariableSemantics};
|
use crate::reflect::semantics::{BindingStage, MAX_BINDINGS_COUNT, MAX_PUSH_BUFFER_SIZE, MemberOffset, PushReflection, ReflectSemantics, ShaderReflection, TextureBinding, TextureSemanticMap, TextureSemantics, TextureSizeMeta, TypeInfo, UboReflection, ValidateTypeSemantics, VariableMeta, VariableSemanticMap, VariableSemantics};
|
||||||
use crate::reflect::{
|
use crate::reflect::{
|
||||||
ReflectMeta, ReflectShader,
|
ReflectMeta, ReflectShader,
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,7 @@ use spirv_cross::hlsl::ShaderModel;
|
||||||
use spirv_cross::spirv::{Ast, Decoration, Module, Resource, ShaderResources, Type};
|
use spirv_cross::spirv::{Ast, Decoration, Module, Resource, ShaderResources, Type};
|
||||||
use spirv_cross::{ErrorCode, glsl, hlsl};
|
use spirv_cross::{ErrorCode, glsl, hlsl};
|
||||||
|
|
||||||
use crate::back::cross::GlslangGlslContext;
|
use crate::back::cross::{GlslangGlslContext, GlslangHlslContext};
|
||||||
use crate::back::targets::{GLSL, HLSL};
|
use crate::back::targets::{GLSL, HLSL};
|
||||||
use crate::back::{CompileShader, ShaderCompilerOutput};
|
use crate::back::{CompileShader, ShaderCompilerOutput};
|
||||||
|
|
||||||
|
@ -492,7 +492,7 @@ where
|
||||||
|
|
||||||
meta.texture_meta.insert(
|
meta.texture_meta.insert(
|
||||||
semantic,
|
semantic,
|
||||||
TextureImage {
|
TextureBinding {
|
||||||
binding: texture.binding,
|
binding: texture.binding,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -819,12 +819,12 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
|
||||||
|
|
||||||
impl CompileShader<HLSL> for CrossReflect<hlsl::Target> {
|
impl CompileShader<HLSL> for CrossReflect<hlsl::Target> {
|
||||||
type Options = Option<()>;
|
type Options = Option<()>;
|
||||||
type Context = ();
|
type Context = GlslangHlslContext;
|
||||||
|
|
||||||
fn compile(
|
fn compile(
|
||||||
mut self,
|
mut self,
|
||||||
_options: Self::Options,
|
_options: Self::Options,
|
||||||
) -> Result<ShaderCompilerOutput<String>, ShaderCompileError> {
|
) -> Result<ShaderCompilerOutput<String, GlslangHlslContext>, ShaderCompileError> {
|
||||||
let mut options = hlsl::CompilerOptions::default();
|
let mut options = hlsl::CompilerOptions::default();
|
||||||
options.shader_model = ShaderModel::V5_0;
|
options.shader_model = ShaderModel::V5_0;
|
||||||
|
|
||||||
|
@ -834,7 +834,12 @@ impl CompileShader<HLSL> for CrossReflect<hlsl::Target> {
|
||||||
Ok(ShaderCompilerOutput {
|
Ok(ShaderCompilerOutput {
|
||||||
vertex: self.vertex.compile()?,
|
vertex: self.vertex.compile()?,
|
||||||
fragment: self.fragment.compile()?,
|
fragment: self.fragment.compile()?,
|
||||||
context: (),
|
context: GlslangHlslContext {
|
||||||
|
compiler: CompiledAst {
|
||||||
|
vertex: self.vertex,
|
||||||
|
fragment: self.fragment
|
||||||
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::error::ShaderReflectError;
|
use crate::error::ShaderReflectError;
|
||||||
use crate::reflect::semantics::{
|
use crate::reflect::semantics::{
|
||||||
SemanticMap, TextureImage, TextureSemantics, TextureSizeMeta, VariableMeta, VariableSemantics,
|
SemanticMap, TextureBinding, TextureSemantics, TextureSizeMeta, VariableMeta, VariableSemantics,
|
||||||
};
|
};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use semantics::ReflectSemantics;
|
use semantics::ReflectSemantics;
|
||||||
|
@ -26,7 +26,7 @@ pub trait ReflectShader {
|
||||||
pub struct ReflectMeta {
|
pub struct ReflectMeta {
|
||||||
pub parameter_meta: FxHashMap<String, VariableMeta>,
|
pub parameter_meta: FxHashMap<String, VariableMeta>,
|
||||||
pub variable_meta: FxHashMap<VariableSemantics, VariableMeta>,
|
pub variable_meta: FxHashMap<VariableSemantics, VariableMeta>,
|
||||||
pub texture_meta: FxHashMap<SemanticMap<TextureSemantics>, TextureImage>,
|
pub texture_meta: FxHashMap<SemanticMap<TextureSemantics>, TextureBinding>,
|
||||||
pub texture_size_meta: FxHashMap<SemanticMap<TextureSemantics>, TextureSizeMeta>,
|
pub texture_size_meta: FxHashMap<SemanticMap<TextureSemantics>, TextureSizeMeta>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ pub struct TextureSizeMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TextureImage {
|
pub struct TextureBinding {
|
||||||
pub binding: u32,
|
pub binding: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,3 +324,23 @@ pub struct ReflectSemantics {
|
||||||
pub uniform_semantics: FxHashMap<String, UniformSemantic>,
|
pub uniform_semantics: FxHashMap<String, UniformSemantic>,
|
||||||
pub non_uniform_semantics: FxHashMap<String, SemanticMap<TextureSemantics>>,
|
pub non_uniform_semantics: FxHashMap<String, SemanticMap<TextureSemantics>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
||||||
|
pub enum UniformBinding {
|
||||||
|
Parameter(String),
|
||||||
|
SemanticVariable(VariableSemantics),
|
||||||
|
TextureSize(SemanticMap<TextureSemantics>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<VariableSemantics> for UniformBinding {
|
||||||
|
fn from(value: VariableSemantics) -> Self {
|
||||||
|
UniformBinding::SemanticVariable(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SemanticMap<TextureSemantics>> for UniformBinding {
|
||||||
|
fn from(value: SemanticMap<TextureSemantics>) -> Self {
|
||||||
|
UniformBinding::TextureSize(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ edition = "2021"
|
||||||
"librashader-reflect" = { path = "../librashader-reflect" }
|
"librashader-reflect" = { path = "../librashader-reflect" }
|
||||||
rustc-hash = "1.1.0"
|
rustc-hash = "1.1.0"
|
||||||
gfx-maths = "0.2.8"
|
gfx-maths = "0.2.8"
|
||||||
|
bytemuck = "1.12.3"
|
||||||
|
|
||||||
[dependencies.windows]
|
[dependencies.windows]
|
||||||
version = "0.43.0"
|
version = "0.43.0"
|
||||||
|
|
|
@ -1,19 +1,25 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
use windows::Win32::Graphics::Direct3D11::{D3D11_BIND_SHADER_RESOURCE, D3D11_RESOURCE_MISC_GENERATE_MIPS, D3D11_SAMPLER_DESC, D3D11_TEXTURE2D_DESC, ID3D11Device, ID3D11DeviceContext};
|
||||||
|
use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SAMPLE_DESC};
|
||||||
|
use librashader_common::image::Image;
|
||||||
|
use librashader_common::Size;
|
||||||
use librashader_preprocess::ShaderSource;
|
use librashader_preprocess::ShaderSource;
|
||||||
use librashader_presets::{ShaderPassConfig, ShaderPreset};
|
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
|
||||||
use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation};
|
use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation};
|
||||||
|
use librashader_reflect::back::cross::GlslangHlslContext;
|
||||||
use librashader_reflect::back::targets::HLSL;
|
use librashader_reflect::back::targets::HLSL;
|
||||||
use librashader_reflect::front::shaderc::GlslangCompilation;
|
use librashader_reflect::front::shaderc::GlslangCompilation;
|
||||||
use librashader_reflect::reflect::ReflectShader;
|
use librashader_reflect::reflect::ReflectShader;
|
||||||
use librashader_reflect::reflect::semantics::{ReflectSemantics, SemanticMap, TextureSemantics, UniformSemantic, VariableSemantics};
|
use librashader_reflect::reflect::semantics::{ReflectSemantics, SemanticMap, TextureSemantics, UniformSemantic, VariableSemantics};
|
||||||
|
use crate::util::Texture;
|
||||||
|
|
||||||
type ShaderPassMeta<'a> = (
|
type ShaderPassMeta<'a> = (
|
||||||
&'a ShaderPassConfig,
|
&'a ShaderPassConfig,
|
||||||
ShaderSource,
|
ShaderSource,
|
||||||
CompilerBackend<
|
CompilerBackend<
|
||||||
impl CompileShader<HLSL, Options = Option<()>, Context = ()> + ReflectShader,
|
impl CompileShader<HLSL, Options = Option<()>, Context = GlslangHlslContext> + ReflectShader,
|
||||||
>,
|
>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -22,6 +28,12 @@ struct FilterChain {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct FilterCommon {
|
||||||
|
pub(crate) device_context: ID3D11DeviceContext,
|
||||||
|
pub(crate) preset: ShaderPreset,
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: d3d11.c 2097
|
||||||
type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
||||||
|
|
||||||
impl FilterChain {
|
impl FilterChain {
|
||||||
|
@ -100,7 +112,7 @@ impl FilterChain {
|
||||||
// feedback_textures.resize_with(filters.len(), Texture::default);
|
// feedback_textures.resize_with(filters.len(), Texture::default);
|
||||||
|
|
||||||
// load luts
|
// load luts
|
||||||
// let luts = FilterChain::load_luts(&preset.textures)?;
|
let luts = FilterChain::load_luts(&preset.textures)?;
|
||||||
|
|
||||||
// let (history_framebuffers, history_textures) =
|
// let (history_framebuffers, history_textures) =
|
||||||
// FilterChain::init_history(&filters, default_filter, default_wrap);
|
// FilterChain::init_history(&filters, default_filter, default_wrap);
|
||||||
|
@ -125,6 +137,31 @@ impl FilterChain {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_luts(device: &ID3D11Device, textures: &[TextureConfig]) -> Result<FxHashMap<usize, Texture>> {
|
||||||
|
let mut luts = FxHashMap::default();
|
||||||
|
|
||||||
|
for (index, texture) in textures.iter().enumerate() {
|
||||||
|
let image = Image::load(&texture.path)?;
|
||||||
|
let desc = D3D11_TEXTURE2D_DESC {
|
||||||
|
Width: image.width,
|
||||||
|
Height: image.height,
|
||||||
|
Format: DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
MiscFlags: if texture.mipmap {
|
||||||
|
D3D11_RESOURCE_MISC_GENERATE_MIPS
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut texture = Texture::new(device, image.size, desc);
|
||||||
|
// todo: update texture d3d11_common: 150
|
||||||
|
luts.insert(index, texture);
|
||||||
|
|
||||||
|
}
|
||||||
|
Ok(luts)
|
||||||
|
}
|
||||||
|
|
||||||
/// Load the shader preset at the given path into a filter chain.
|
/// Load the shader preset at the given path into a filter chain.
|
||||||
pub fn load_from_path(path: impl AsRef<Path>) -> Result<FilterChain> {
|
pub fn load_from_path(path: impl AsRef<Path>) -> Result<FilterChain> {
|
||||||
// load passes from preset
|
// load passes from preset
|
||||||
|
|
394
librashader-runtime-dx11/src/filter_pass.rs
Normal file
394
librashader-runtime-dx11/src/filter_pass.rs
Normal file
|
@ -0,0 +1,394 @@
|
||||||
|
use std::error::Error;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
use windows::Win32::Graphics::Direct3D11::{D3D11_MAP_WRITE_DISCARD, ID3D11Buffer, ID3D11PixelShader, ID3D11SamplerState, ID3D11ShaderResourceView, ID3D11VertexShader};
|
||||||
|
use windows::Win32::Graphics::Direct3D::ID3DBlob;
|
||||||
|
use librashader_common::Size;
|
||||||
|
use librashader_preprocess::ShaderSource;
|
||||||
|
use librashader_presets::ShaderPassConfig;
|
||||||
|
use librashader_reflect::back::cross::GlslangHlslContext;
|
||||||
|
use librashader_reflect::back::ShaderCompilerOutput;
|
||||||
|
use librashader_reflect::reflect::semantics::{BindingStage, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniformSemantic, VariableSemantics};
|
||||||
|
use librashader_reflect::reflect::ShaderReflection;
|
||||||
|
use crate::filter_chain::FilterCommon;
|
||||||
|
use crate::util::Texture;
|
||||||
|
|
||||||
|
pub struct DxShader<T> {
|
||||||
|
pub blob: ID3DBlob,
|
||||||
|
pub compiled: T
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ConstantBuffer {
|
||||||
|
pub binding: u32,
|
||||||
|
pub size: u32,
|
||||||
|
pub stage_mask: BindingStage,
|
||||||
|
pub buffer: ID3D11Buffer,
|
||||||
|
pub storage: Box<[u8]>
|
||||||
|
}
|
||||||
|
|
||||||
|
// slang_process.cpp 141
|
||||||
|
pub struct FilterPass {
|
||||||
|
pub reflection: ShaderReflection,
|
||||||
|
pub compiled: ShaderCompilerOutput<String, GlslangHlslContext>,
|
||||||
|
pub vertex_shader: DxShader<ID3D11VertexShader>,
|
||||||
|
pub pixel_shader: DxShader<ID3D11PixelShader>,
|
||||||
|
|
||||||
|
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
|
||||||
|
|
||||||
|
|
||||||
|
pub uniform_buffer: ConstantBuffer,
|
||||||
|
pub push_buffer: ConstantBuffer,
|
||||||
|
pub source: ShaderSource,
|
||||||
|
pub config: ShaderPassConfig,
|
||||||
|
}
|
||||||
|
// slang_process.cpp 229
|
||||||
|
impl FilterPass {
|
||||||
|
fn build_mvp(buffer: &mut [u8], mvp: &[f32]) {
|
||||||
|
let mvp = bytemuck::cast_slice(mvp);
|
||||||
|
buffer.copy_from_slice(mvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn build_uniform<T>(
|
||||||
|
buffer: &mut [u8],
|
||||||
|
value: T,
|
||||||
|
) where
|
||||||
|
T: Copy,
|
||||||
|
T: bytemuck::Pod,
|
||||||
|
{
|
||||||
|
let buffer = bytemuck::cast_slice_mut(buffer);
|
||||||
|
buffer[0] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_vec4(buffer: &mut [u8], size: impl Into<[f32; 4]>) {
|
||||||
|
let vec4 = size.into();
|
||||||
|
let vec4 = bytemuck::cast_slice(&vec4);
|
||||||
|
buffer.copy_from_slice(vec4);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bind_texture(texture_binding: &mut [Option<ID3D11ShaderResourceView>; 16],
|
||||||
|
sampler_binding: &mut [Option<ID3D11SamplerState>; 16],
|
||||||
|
binding: &TextureBinding,
|
||||||
|
texture: &Texture
|
||||||
|
)
|
||||||
|
{
|
||||||
|
texture_binding[binding.binding as usize] = Some(texture.srv.clone());
|
||||||
|
sampler_binding[binding.binding as usize] = Some(texture.sampler.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
// framecount should be pre-modded
|
||||||
|
fn build_semantics(
|
||||||
|
&mut self,
|
||||||
|
pass_index: usize,
|
||||||
|
parent: &FilterCommon,
|
||||||
|
mvp: &[f32],
|
||||||
|
frame_count: u32,
|
||||||
|
frame_direction: i32,
|
||||||
|
fb_size: Size<u32>,
|
||||||
|
// viewport: &Viewport,
|
||||||
|
original: &Texture,
|
||||||
|
source: &Texture,
|
||||||
|
) {
|
||||||
|
|
||||||
|
let mut textures: [Option<ID3D11ShaderResourceView>; 16] = std::array::from_fn(|_| None);
|
||||||
|
let mut samplers: [Option<ID3D11SamplerState>; 16] = std::array::from_fn(|_| None);
|
||||||
|
|
||||||
|
// Bind MVP
|
||||||
|
if let Some(offset) =
|
||||||
|
self.uniform_bindings.get(&VariableSemantics::MVP.into())
|
||||||
|
{
|
||||||
|
let mvp_size = mvp.len() * std::mem::size_of::<f32>();
|
||||||
|
let (buffer, offset) = match offset {
|
||||||
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||||
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||||
|
};
|
||||||
|
FilterPass::build_mvp(&mut buffer[offset..][..mvp_size], mvp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind OutputSize
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&VariableSemantics::Output.into())
|
||||||
|
{
|
||||||
|
let (buffer, offset) = match offset {
|
||||||
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||||
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||||
|
};
|
||||||
|
|
||||||
|
FilterPass::build_vec4(&mut buffer[offset..][..16], fb_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind FinalViewportSize
|
||||||
|
// if let Some(offset) = self
|
||||||
|
// .uniform_bindings
|
||||||
|
// .get(&VariableSemantics::FinalViewport.into())
|
||||||
|
// {
|
||||||
|
// let (buffer, offset) = match offset {
|
||||||
|
// MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||||
|
// MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||||
|
// };
|
||||||
|
// FilterPass::build_vec4(
|
||||||
|
// &mut buffer[offset..][..16],
|
||||||
|
// viewport.output.size,
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bind FrameCount
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&VariableSemantics::FrameCount.into())
|
||||||
|
{
|
||||||
|
let (buffer, offset) = match offset {
|
||||||
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||||
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||||
|
};
|
||||||
|
FilterPass::build_uniform(&mut buffer[offset..][..4], frame_count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind FrameDirection
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&VariableSemantics::FrameDirection.into())
|
||||||
|
{
|
||||||
|
let (buffer, offset) = match offset {
|
||||||
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||||
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||||
|
};
|
||||||
|
FilterPass::build_uniform(
|
||||||
|
&mut buffer[offset..][..4],
|
||||||
|
frame_direction,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind Original sampler
|
||||||
|
if let Some(binding) = self
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_meta
|
||||||
|
.get(&TextureSemantics::Original.semantics(0))
|
||||||
|
{
|
||||||
|
FilterPass::bind_texture(&mut textures, &mut samplers, binding, original);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// bind OriginalSize
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&TextureSemantics::Original.semantics(0).into())
|
||||||
|
{
|
||||||
|
let (buffer, offset) = match offset {
|
||||||
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||||
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||||
|
};
|
||||||
|
FilterPass::build_vec4(
|
||||||
|
&mut buffer[offset..][..16],
|
||||||
|
original.size,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind Source sampler
|
||||||
|
if let Some(binding) = self
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_meta
|
||||||
|
.get(&TextureSemantics::Source.semantics(0))
|
||||||
|
{
|
||||||
|
// eprintln!("setting source binding to {}", binding.binding);
|
||||||
|
FilterPass::bind_texture(&mut textures, &mut samplers, binding, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind SourceSize
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&TextureSemantics::Source.semantics(0).into())
|
||||||
|
{
|
||||||
|
let (buffer, offset) = match offset {
|
||||||
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||||
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||||
|
};
|
||||||
|
FilterPass::build_vec4(
|
||||||
|
&mut buffer[offset..][..16],
|
||||||
|
source.size,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(binding) = self
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_meta
|
||||||
|
.get(&TextureSemantics::OriginalHistory.semantics(0))
|
||||||
|
{
|
||||||
|
FilterPass::bind_texture(&mut textures, &mut samplers, binding, original);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&TextureSemantics::OriginalHistory.semantics(0).into())
|
||||||
|
{
|
||||||
|
let (buffer, offset) = match offset {
|
||||||
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||||
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||||
|
};
|
||||||
|
FilterPass::build_vec4(
|
||||||
|
&mut buffer[offset..][..16],
|
||||||
|
original.size,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for (index, output) in parent.history_textures.iter().enumerate() {
|
||||||
|
// // if let Some(binding) = self
|
||||||
|
// // .reflection
|
||||||
|
// // .meta
|
||||||
|
// // .texture_meta
|
||||||
|
// // .get(&TextureSemantics::OriginalHistory.semantics(index + 1))
|
||||||
|
// // {
|
||||||
|
// // FilterPass::bind_texture(binding, output);
|
||||||
|
// // }
|
||||||
|
//
|
||||||
|
// if let Some((location, offset)) = self.uniform_bindings.get(
|
||||||
|
// &TextureSemantics::OriginalHistory
|
||||||
|
// .semantics(index + 1)
|
||||||
|
// .into(),
|
||||||
|
// ) {
|
||||||
|
// let (buffer, offset) = match offset {
|
||||||
|
// MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||||
|
// MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||||
|
// };
|
||||||
|
// FilterPass::build_vec4(
|
||||||
|
// location.location(),
|
||||||
|
// &mut buffer[offset..][..16],
|
||||||
|
// output.image.size,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// PassOutput
|
||||||
|
// for (index, output) in parent.output_textures.iter().enumerate() {
|
||||||
|
// if let Some(binding) = self
|
||||||
|
// .reflection
|
||||||
|
// .meta
|
||||||
|
// .texture_meta
|
||||||
|
// .get(&TextureSemantics::PassOutput.semantics(index))
|
||||||
|
// {
|
||||||
|
// FilterPass::bind_texture(binding, output);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if let Some(offset) = self
|
||||||
|
// .uniform_bindings
|
||||||
|
// .get(&TextureSemantics::PassOutput.semantics(index).into())
|
||||||
|
// {
|
||||||
|
// let (buffer, offset) = match offset {
|
||||||
|
// MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||||
|
// MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||||
|
// };
|
||||||
|
// FilterPass::build_uniform(
|
||||||
|
// &mut buffer[offset..][..16],
|
||||||
|
// output.image.size,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// PassFeedback
|
||||||
|
// for (index, feedback) in parent.feedback_textures.iter().enumerate() {
|
||||||
|
// // if let Some(binding) = self
|
||||||
|
// // .reflection
|
||||||
|
// // .meta
|
||||||
|
// // .texture_meta
|
||||||
|
// // .get(&TextureSemantics::PassFeedback.semantics(index))
|
||||||
|
// // {
|
||||||
|
// // if feedback.image.handle == 0 {
|
||||||
|
// // eprintln!("[WARNING] trying to bind PassFeedback: {index} which has texture 0 to slot {} in pass {pass_index}", binding.binding)
|
||||||
|
// // }
|
||||||
|
// // FilterPass::bind_texture(binding, feedback);
|
||||||
|
// // }
|
||||||
|
//
|
||||||
|
// if let Some(offset) = self
|
||||||
|
// .uniform_bindings
|
||||||
|
// .get(&TextureSemantics::PassFeedback.semantics(index).into())
|
||||||
|
// {
|
||||||
|
// let (buffer, offset) = match offset {
|
||||||
|
// MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||||
|
// MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||||
|
// };
|
||||||
|
// FilterPass::build_uniform(
|
||||||
|
// &mut buffer[offset..][..16],
|
||||||
|
// feedback.image.size,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bind float parameters
|
||||||
|
for (id, offset) in
|
||||||
|
self.uniform_bindings
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(binding, value)| match binding {
|
||||||
|
UniformBinding::Parameter(id) => Some((id, value)),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
{
|
||||||
|
let id = id.as_str();
|
||||||
|
let (buffer, offset) = match offset {
|
||||||
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
|
||||||
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
|
||||||
|
};
|
||||||
|
|
||||||
|
// todo: cache parameters.
|
||||||
|
// presets override params
|
||||||
|
let default = self
|
||||||
|
.source
|
||||||
|
.parameters
|
||||||
|
.iter()
|
||||||
|
.find(|&p| p.id == id)
|
||||||
|
.map(|f| f.initial)
|
||||||
|
.unwrap_or(0f32);
|
||||||
|
|
||||||
|
let value = parent
|
||||||
|
.preset
|
||||||
|
.parameters
|
||||||
|
.iter()
|
||||||
|
.find(|&p| p.name == id)
|
||||||
|
.map(|p| p.value)
|
||||||
|
.unwrap_or(default);
|
||||||
|
|
||||||
|
FilterPass::build_uniform(&mut buffer[offset..][..4], value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind luts
|
||||||
|
// for (index, lut) in &parent.luts {
|
||||||
|
// if let Some(binding) = self
|
||||||
|
// .reflection
|
||||||
|
// .meta
|
||||||
|
// .texture_meta
|
||||||
|
// .get(&TextureSemantics::User.semantics(*index))
|
||||||
|
// {
|
||||||
|
// FilterPass::bind_texture(binding, lut);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if let Some((location, offset)) = self
|
||||||
|
// .uniform_bindings
|
||||||
|
// .get(&TextureSemantics::User.semantics(*index).into())
|
||||||
|
// {
|
||||||
|
// let (buffer, offset) = match offset {
|
||||||
|
// MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||||
|
// MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||||
|
// };
|
||||||
|
// FilterPass::build_vec4(
|
||||||
|
// location.location(),
|
||||||
|
// &mut buffer[offset..][..16],
|
||||||
|
// lut.image.size,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw(
|
||||||
|
&mut self,
|
||||||
|
pass_index: usize,
|
||||||
|
parent: &FilterCommon,
|
||||||
|
frame_count: u32,
|
||||||
|
frame_direction: i32,
|
||||||
|
) -> std::result::Result<(), Box<dyn Error>>
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -392,6 +392,10 @@ mod d3d11_hello_triangle {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.context.DrawIndexed(3, 0, 0);
|
self.context.DrawIndexed(3, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsafe {
|
||||||
resources.swapchain.Present(0, 0).ok()?;
|
resources.swapchain.Present(0, 0).ok()?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -17,6 +17,8 @@ use librashader_reflect::reflect::ReflectShader;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod hello_triangle;
|
mod hello_triangle;
|
||||||
|
mod filter_pass;
|
||||||
|
mod util;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
64
librashader-runtime-dx11/src/util.rs
Normal file
64
librashader-runtime-dx11/src/util.rs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
use windows::Win32::Graphics::Direct3D11::{D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE, D3D11_CPU_ACCESS_WRITE, D3D11_FORMAT_SUPPORT_RENDER_TARGET, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE, D3D11_FORMAT_SUPPORT_TEXTURE2D, D3D11_RESOURCE_MISC_GENERATE_MIPS, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DYNAMIC, ID3D11Device, ID3D11SamplerState, ID3D11ShaderResourceView, ID3D11Texture2D};
|
||||||
|
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
|
||||||
|
use librashader_common::{FilterMode, Size, WrapMode};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Texture {
|
||||||
|
pub handle: ID3D11Texture2D,
|
||||||
|
pub staging: ID3D11Texture2D,
|
||||||
|
pub srv: ID3D11ShaderResourceView,
|
||||||
|
pub sampler: ID3D11SamplerState,
|
||||||
|
pub desc: D3D11_TEXTURE2D_DESC,
|
||||||
|
pub size: Size<u32>
|
||||||
|
// pub image: GlImage,
|
||||||
|
// pub filter: FilterMode,
|
||||||
|
// pub mip_filter: FilterMode,
|
||||||
|
// pub wrap_mode: WrapMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Texture {
|
||||||
|
pub fn new(device: &ID3D11Device, size: Size<u32>, desc: D3D11_TEXTURE2D_DESC) -> Texture {
|
||||||
|
let mut desc = D3D11_TEXTURE2D_DESC {
|
||||||
|
Width: size.width,
|
||||||
|
Height: size.height,
|
||||||
|
MipLevels: 1,
|
||||||
|
ArraySize: 1,
|
||||||
|
SampleDesc: DXGI_SAMPLE_DESC {
|
||||||
|
Count: 1,
|
||||||
|
Quality: 0
|
||||||
|
},
|
||||||
|
CPUAccessFlags: if desc.Usage == D3D11_USAGE_DYNAMIC {
|
||||||
|
D3D11_CPU_ACCESS_WRITE
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
},
|
||||||
|
..desc
|
||||||
|
};
|
||||||
|
desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
|
||||||
|
|
||||||
|
// determine number of mipmaps required
|
||||||
|
if desc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS {
|
||||||
|
let mut width = desc.Width >> 5;
|
||||||
|
let mut height = desc.Height >> 5;
|
||||||
|
desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
|
||||||
|
|
||||||
|
while width != 0 && height != 0 {
|
||||||
|
width >>= 1;
|
||||||
|
height >>= 1;
|
||||||
|
desc.MipLevels += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine if format is supported.
|
||||||
|
let mut format_support = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
|
||||||
|
if desc.BindFlags |= D3D11_BIND_RENDER_TARGET {
|
||||||
|
format_support |= D3D11_FORMAT_SUPPORT_RENDER_TARGET;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: actually check format support
|
||||||
|
|
||||||
|
// d3d11_common: 83
|
||||||
|
todo!();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,22 +46,3 @@ pub enum MemberLocation {
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct TextureUnit<T>(T);
|
pub struct TextureUnit<T>(T);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
|
||||||
pub enum UniformBinding {
|
|
||||||
Parameter(String),
|
|
||||||
SemanticVariable(VariableSemantics),
|
|
||||||
TextureSize(SemanticMap<TextureSemantics>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<VariableSemantics> for UniformBinding {
|
|
||||||
fn from(value: VariableSemantics) -> Self {
|
|
||||||
UniformBinding::SemanticVariable(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<SemanticMap<TextureSemantics>> for UniformBinding {
|
|
||||||
fn from(value: SemanticMap<TextureSemantics>) -> Self {
|
|
||||||
UniformBinding::TextureSize(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::binding::{UniformBinding, UniformLocation, VariableLocation};
|
use crate::binding::{UniformLocation, VariableLocation};
|
||||||
use crate::filter_pass::FilterPass;
|
use crate::filter_pass::FilterPass;
|
||||||
use crate::framebuffer::{Framebuffer, GlImage, Viewport};
|
use crate::framebuffer::{Framebuffer, GlImage, Viewport};
|
||||||
use crate::quad_render::DrawQuad;
|
use crate::quad_render::DrawQuad;
|
||||||
|
@ -14,7 +14,7 @@ use librashader_preprocess::ShaderSource;
|
||||||
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
|
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
|
||||||
use librashader_reflect::back::cross::{GlslangGlslContext, GlVersion};
|
use librashader_reflect::back::cross::{GlslangGlslContext, GlVersion};
|
||||||
use librashader_reflect::back::targets::GLSL;
|
use librashader_reflect::back::targets::GLSL;
|
||||||
use librashader_reflect::reflect::semantics::{MemberOffset, ReflectSemantics, SemanticMap, TextureSemantics, UniformMeta, UniformSemantic, VariableSemantics};
|
use librashader_reflect::reflect::semantics::{MemberOffset, ReflectSemantics, SemanticMap, TextureSemantics, UniformBinding, UniformMeta, UniformSemantic, VariableSemantics};
|
||||||
use librashader_reflect::reflect::ReflectShader;
|
use librashader_reflect::reflect::ReflectShader;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use spirv_cross::spirv::Decoration;
|
use spirv_cross::spirv::Decoration;
|
||||||
|
@ -472,9 +472,9 @@ impl FilterChain {
|
||||||
.into_boxed_slice();
|
.into_boxed_slice();
|
||||||
|
|
||||||
// todo: reflect indexed parameters
|
// todo: reflect indexed parameters
|
||||||
let mut variable_bindings = FxHashMap::default();
|
let mut uniform_bindings = FxHashMap::default();
|
||||||
for param in reflection.meta.parameter_meta.values() {
|
for param in reflection.meta.parameter_meta.values() {
|
||||||
variable_bindings.insert(
|
uniform_bindings.insert(
|
||||||
UniformBinding::Parameter(param.id.clone()),
|
UniformBinding::Parameter(param.id.clone()),
|
||||||
(
|
(
|
||||||
FilterChain::reflect_uniform_location(program, param),
|
FilterChain::reflect_uniform_location(program, param),
|
||||||
|
@ -484,7 +484,7 @@ impl FilterChain {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (semantics, param) in &reflection.meta.variable_meta {
|
for (semantics, param) in &reflection.meta.variable_meta {
|
||||||
variable_bindings.insert(
|
uniform_bindings.insert(
|
||||||
UniformBinding::SemanticVariable(*semantics),
|
UniformBinding::SemanticVariable(*semantics),
|
||||||
(
|
(
|
||||||
FilterChain::reflect_uniform_location(program, param),
|
FilterChain::reflect_uniform_location(program, param),
|
||||||
|
@ -494,7 +494,7 @@ impl FilterChain {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (semantics, param) in &reflection.meta.texture_size_meta {
|
for (semantics, param) in &reflection.meta.texture_size_meta {
|
||||||
variable_bindings.insert(
|
uniform_bindings.insert(
|
||||||
UniformBinding::TextureSize(*semantics),
|
UniformBinding::TextureSize(*semantics),
|
||||||
(
|
(
|
||||||
FilterChain::reflect_uniform_location(program, param),
|
FilterChain::reflect_uniform_location(program, param),
|
||||||
|
@ -520,7 +520,7 @@ impl FilterChain {
|
||||||
ubo_ring,
|
ubo_ring,
|
||||||
uniform_buffer,
|
uniform_buffer,
|
||||||
push_buffer,
|
push_buffer,
|
||||||
variable_bindings,
|
uniform_bindings,
|
||||||
source,
|
source,
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,12 +6,10 @@ use librashader_reflect::reflect::ShaderReflection;
|
||||||
use librashader_common::{ShaderFormat, Size};
|
use librashader_common::{ShaderFormat, Size};
|
||||||
use librashader_preprocess::ShaderSource;
|
use librashader_preprocess::ShaderSource;
|
||||||
use librashader_presets::ShaderPassConfig;
|
use librashader_presets::ShaderPassConfig;
|
||||||
use librashader_reflect::reflect::semantics::{
|
use librashader_reflect::reflect::semantics::{MemberOffset, TextureBinding, TextureSemantics, UniformBinding, VariableSemantics};
|
||||||
MemberOffset, TextureImage, TextureSemantics, VariableSemantics,
|
|
||||||
};
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::binding::{UniformBinding, UniformLocation, VariableLocation};
|
use crate::binding::{UniformLocation, VariableLocation};
|
||||||
use crate::filter_chain::FilterCommon;
|
use crate::filter_chain::FilterCommon;
|
||||||
use crate::framebuffer::Viewport;
|
use crate::framebuffer::Viewport;
|
||||||
use crate::render_target::RenderTarget;
|
use crate::render_target::RenderTarget;
|
||||||
|
@ -25,7 +23,7 @@ pub struct FilterPass {
|
||||||
pub ubo_ring: Option<InlineRingBuffer<GLuint, 16>>,
|
pub ubo_ring: Option<InlineRingBuffer<GLuint, 16>>,
|
||||||
pub uniform_buffer: Box<[u8]>,
|
pub uniform_buffer: Box<[u8]>,
|
||||||
pub push_buffer: Box<[u8]>,
|
pub push_buffer: Box<[u8]>,
|
||||||
pub variable_bindings: FxHashMap<UniformBinding, (VariableLocation, MemberOffset)>,
|
pub uniform_bindings: FxHashMap<UniformBinding, (VariableLocation, MemberOffset)>,
|
||||||
pub source: ShaderSource,
|
pub source: ShaderSource,
|
||||||
pub config: ShaderPassConfig,
|
pub config: ShaderPassConfig,
|
||||||
}
|
}
|
||||||
|
@ -36,13 +34,8 @@ impl FilterPass {
|
||||||
buffer.copy_from_slice(mvp);
|
buffer.copy_from_slice(mvp);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_vec4(location: UniformLocation<GLint>, buffer: &mut [u8], size: Size<u32>) {
|
fn build_vec4(location: UniformLocation<GLint>, buffer: &mut [u8], size: impl Into<[f32; 4]>) {
|
||||||
let vec4 = [
|
let vec4 = size.into();
|
||||||
size.width as f32,
|
|
||||||
size.height as f32,
|
|
||||||
1.0 / size.width as f32,
|
|
||||||
1.0 / size.height as f32,
|
|
||||||
];
|
|
||||||
if location.fragment >= 0 || location.vertex >= 0 {
|
if location.fragment >= 0 || location.vertex >= 0 {
|
||||||
unsafe {
|
unsafe {
|
||||||
if location.vertex >= 0 {
|
if location.vertex >= 0 {
|
||||||
|
@ -95,7 +88,7 @@ impl FilterPass {
|
||||||
Self::build_uniform(location, buffer, value, gl::Uniform1f)
|
Self::build_uniform(location, buffer, value, gl::Uniform1f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bind_texture(binding: &TextureImage, texture: &Texture) {
|
fn bind_texture(binding: &TextureBinding, texture: &Texture) {
|
||||||
unsafe {
|
unsafe {
|
||||||
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
||||||
gl::ActiveTexture(gl::TEXTURE0 + binding.binding);
|
gl::ActiveTexture(gl::TEXTURE0 + binding.binding);
|
||||||
|
@ -269,7 +262,7 @@ impl FilterPass {
|
||||||
) {
|
) {
|
||||||
// Bind MVP
|
// Bind MVP
|
||||||
if let Some((_location, offset)) =
|
if let Some((_location, offset)) =
|
||||||
self.variable_bindings.get(&VariableSemantics::MVP.into())
|
self.uniform_bindings.get(&VariableSemantics::MVP.into())
|
||||||
{
|
{
|
||||||
let mvp_size = mvp.len() * std::mem::size_of::<f32>();
|
let mvp_size = mvp.len() * std::mem::size_of::<f32>();
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
|
@ -281,7 +274,7 @@ impl FilterPass {
|
||||||
|
|
||||||
// bind OutputSize
|
// bind OutputSize
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.uniform_bindings
|
||||||
.get(&VariableSemantics::Output.into())
|
.get(&VariableSemantics::Output.into())
|
||||||
{
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
|
@ -294,7 +287,7 @@ impl FilterPass {
|
||||||
|
|
||||||
// bind FinalViewportSize
|
// bind FinalViewportSize
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.uniform_bindings
|
||||||
.get(&VariableSemantics::FinalViewport.into())
|
.get(&VariableSemantics::FinalViewport.into())
|
||||||
{
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
|
@ -310,7 +303,7 @@ impl FilterPass {
|
||||||
|
|
||||||
// bind FrameCount
|
// bind FrameCount
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.uniform_bindings
|
||||||
.get(&VariableSemantics::FrameCount.into())
|
.get(&VariableSemantics::FrameCount.into())
|
||||||
{
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
|
@ -322,7 +315,7 @@ impl FilterPass {
|
||||||
|
|
||||||
// bind FrameDirection
|
// bind FrameDirection
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.uniform_bindings
|
||||||
.get(&VariableSemantics::FrameDirection.into())
|
.get(&VariableSemantics::FrameDirection.into())
|
||||||
{
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
|
@ -348,7 +341,7 @@ impl FilterPass {
|
||||||
|
|
||||||
// bind OriginalSize
|
// bind OriginalSize
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.uniform_bindings
|
||||||
.get(&TextureSemantics::Original.semantics(0).into())
|
.get(&TextureSemantics::Original.semantics(0).into())
|
||||||
{
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
|
@ -375,7 +368,7 @@ impl FilterPass {
|
||||||
|
|
||||||
// bind SourceSize
|
// bind SourceSize
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.uniform_bindings
|
||||||
.get(&TextureSemantics::Source.semantics(0).into())
|
.get(&TextureSemantics::Source.semantics(0).into())
|
||||||
{
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
|
@ -398,7 +391,7 @@ impl FilterPass {
|
||||||
FilterPass::bind_texture(binding, original);
|
FilterPass::bind_texture(binding, original);
|
||||||
}
|
}
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.uniform_bindings
|
||||||
.get(&TextureSemantics::OriginalHistory.semantics(0).into())
|
.get(&TextureSemantics::OriginalHistory.semantics(0).into())
|
||||||
{
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
|
@ -422,7 +415,7 @@ impl FilterPass {
|
||||||
FilterPass::bind_texture(binding, output);
|
FilterPass::bind_texture(binding, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((location, offset)) = self.variable_bindings.get(
|
if let Some((location, offset)) = self.uniform_bindings.get(
|
||||||
&TextureSemantics::OriginalHistory
|
&TextureSemantics::OriginalHistory
|
||||||
.semantics(index + 1)
|
.semantics(index + 1)
|
||||||
.into(),
|
.into(),
|
||||||
|
@ -451,7 +444,7 @@ impl FilterPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.uniform_bindings
|
||||||
.get(&TextureSemantics::PassOutput.semantics(index).into())
|
.get(&TextureSemantics::PassOutput.semantics(index).into())
|
||||||
{
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
|
@ -481,7 +474,7 @@ impl FilterPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.uniform_bindings
|
||||||
.get(&TextureSemantics::PassFeedback.semantics(index).into())
|
.get(&TextureSemantics::PassFeedback.semantics(index).into())
|
||||||
{
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
|
@ -498,7 +491,7 @@ impl FilterPass {
|
||||||
|
|
||||||
// bind float parameters
|
// bind float parameters
|
||||||
for (id, (location, offset)) in
|
for (id, (location, offset)) in
|
||||||
self.variable_bindings
|
self.uniform_bindings
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(binding, value)| match binding {
|
.filter_map(|(binding, value)| match binding {
|
||||||
UniformBinding::Parameter(id) => Some((id, value)),
|
UniformBinding::Parameter(id) => Some((id, value)),
|
||||||
|
@ -544,7 +537,7 @@ impl FilterPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.variable_bindings
|
.uniform_bindings
|
||||||
.get(&TextureSemantics::User.semantics(*index).into())
|
.get(&TextureSemantics::User.semantics(*index).into())
|
||||||
{
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
name = "librashader"
|
name = "librashader"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
Loading…
Reference in a new issue