d3d11: make error unboxed
This commit is contained in:
parent
759cd4bc28
commit
6519a78df2
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -491,6 +491,8 @@ dependencies = [
|
|||
"librashader-reflect",
|
||||
"librashader-runtime",
|
||||
"rustc-hash",
|
||||
"spirv_cross",
|
||||
"thiserror",
|
||||
"windows",
|
||||
]
|
||||
|
||||
|
|
|
@ -11,9 +11,10 @@ librashader-presets = { path = "../librashader-presets" }
|
|||
librashader-preprocess = { path = "../librashader-preprocess" }
|
||||
librashader-reflect = { path = "../librashader-reflect" }
|
||||
librashader-runtime = { path = "../librashader-runtime" }
|
||||
thiserror = "1.0.37"
|
||||
spirv_cross = "0.23.1"
|
||||
|
||||
rustc-hash = "1.1.0"
|
||||
gfx-maths = "0.2.8"
|
||||
bytemuck = "1.12.3"
|
||||
|
||||
[dependencies.windows]
|
||||
|
@ -33,3 +34,4 @@ features = [
|
|||
]
|
||||
|
||||
[dev-dependencies]
|
||||
gfx-maths = "0.2.8"
|
||||
|
|
25
librashader-runtime-d3d11/src/error.rs
Normal file
25
librashader-runtime-d3d11/src/error.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use librashader_common::image::ImageError;
|
||||
use librashader_preprocess::PreprocessError;
|
||||
use librashader_presets::ParsePresetError;
|
||||
use librashader_reflect::error::{ShaderCompileError, ShaderReflectError};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum FilterChainError {
|
||||
#[error("unable to get direct3d context")]
|
||||
Direct3DContextError,
|
||||
#[error("direct3d driver error")]
|
||||
Direct3DError(#[from] windows::core::Error),
|
||||
#[error("SPIRV reflection error")]
|
||||
SpirvCrossReflectError(#[from] spirv_cross::ErrorCode),
|
||||
#[error("shader preset parse error")]
|
||||
ShaderPresetError(#[from] ParsePresetError),
|
||||
#[error("shader preprocess error")]
|
||||
ShaderPreprocessError(#[from] PreprocessError),
|
||||
#[error("shader compile error")]
|
||||
ShaderCompileError(#[from] ShaderCompileError),
|
||||
#[error("shader reflect error")]
|
||||
ShaderReflectError(#[from] ShaderReflectError),
|
||||
#[error("lut loading error")]
|
||||
LutLoadError(#[from] ImageError),
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::texture::{DxImageView, OwnedTexture, Texture};
|
||||
use crate::texture::{DxImageView, LutTexture, Texture};
|
||||
use librashader_common::image::Image;
|
||||
use librashader_common::{ImageFormat, Size};
|
||||
use librashader_preprocess::ShaderSource;
|
||||
|
@ -31,10 +31,16 @@ use windows::Win32::Graphics::Direct3D11::{
|
|||
D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_USAGE_DYNAMIC,
|
||||
};
|
||||
use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_FORMAT_R8G8B8A8_UNORM};
|
||||
use crate::error::FilterChainError;
|
||||
|
||||
pub struct FilterMutable {
|
||||
pub(crate) passes_enabled: usize,
|
||||
pub(crate) parameters: FxHashMap<String, f32>,
|
||||
}
|
||||
|
||||
// todo: get rid of preset
|
||||
type ShaderPassMeta<'a> = (
|
||||
&'a ShaderPassConfig,
|
||||
type ShaderPassMeta = (
|
||||
ShaderPassConfig,
|
||||
ShaderSource,
|
||||
CompilerBackend<
|
||||
impl CompileShader<HLSL, Options = Option<()>, Context = GlslangHlslContext> + ReflectShader,
|
||||
|
@ -53,16 +59,17 @@ pub struct FilterChain {
|
|||
pub struct Direct3D11 {
|
||||
pub(crate) device: ID3D11Device,
|
||||
pub(crate) device_context: ID3D11DeviceContext,
|
||||
pub context_is_deferred: bool
|
||||
}
|
||||
|
||||
pub struct FilterCommon {
|
||||
pub(crate) d3d11: Direct3D11,
|
||||
pub(crate) preset: ShaderPreset,
|
||||
pub(crate) luts: FxHashMap<usize, OwnedTexture>,
|
||||
pub(crate) luts: FxHashMap<usize, LutTexture>,
|
||||
pub samplers: SamplerSet,
|
||||
pub output_textures: Box<[Option<Texture>]>,
|
||||
pub feedback_textures: Box<[Option<Texture>]>,
|
||||
pub history_textures: Box<[Option<Texture>]>,
|
||||
pub config: FilterMutable
|
||||
}
|
||||
|
||||
impl FilterChain {
|
||||
|
@ -188,17 +195,18 @@ impl FilterChain {
|
|||
device: &ID3D11Device,
|
||||
preset: ShaderPreset,
|
||||
) -> util::Result<FilterChain> {
|
||||
let (passes, semantics) = FilterChain::load_preset(&preset)?;
|
||||
let (passes, semantics) = FilterChain::load_preset(preset.shaders, &preset.textures)?;
|
||||
|
||||
let samplers = SamplerSet::new(device)?;
|
||||
|
||||
// initialize passes
|
||||
let filters = FilterChain::init_passes(device, passes, &semantics).unwrap();
|
||||
let filters = FilterChain::init_passes(device, passes, &semantics)?;
|
||||
|
||||
let mut device_context = None;
|
||||
unsafe {
|
||||
device.GetImmediateContext(&mut device_context);
|
||||
}
|
||||
|
||||
let device_context = device_context.unwrap();
|
||||
|
||||
let device_context =
|
||||
|
@ -214,8 +222,12 @@ impl FilterChain {
|
|||
Size::new(1, 1),
|
||||
ImageFormat::R8G8B8A8Unorm,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
// resolve all results
|
||||
let output_framebuffers = output_framebuffers
|
||||
.into_iter().collect::<util::Result<Vec<OwnedFramebuffer>>>()?;
|
||||
|
||||
let mut output_textures = Vec::new();
|
||||
output_textures.resize_with(filters.len(), || None);
|
||||
//
|
||||
|
@ -228,16 +240,20 @@ impl FilterChain {
|
|||
Size::new(1, 1),
|
||||
ImageFormat::R8G8B8A8Unorm,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
// resolve all results
|
||||
let feedback_framebuffers = feedback_framebuffers
|
||||
.into_iter().collect::<util::Result<Vec<OwnedFramebuffer>>>()?;
|
||||
|
||||
let mut feedback_textures = Vec::new();
|
||||
feedback_textures.resize_with(filters.len(), || None);
|
||||
|
||||
// load luts
|
||||
let luts = FilterChain::load_luts(device, &preset.textures)?;
|
||||
let luts = FilterChain::load_luts(device,
|
||||
&device_context, &preset.textures)?;
|
||||
|
||||
let (history_framebuffers, history_textures) =
|
||||
FilterChain::init_history(device, &device_context, &filters);
|
||||
FilterChain::init_history(device, &device_context, &filters)?;
|
||||
|
||||
let draw_quad = DrawQuad::new(device, &device_context)?;
|
||||
|
||||
|
@ -252,12 +268,18 @@ impl FilterChain {
|
|||
d3d11: Direct3D11 {
|
||||
device: device.clone(),
|
||||
device_context,
|
||||
context_is_deferred: false
|
||||
},
|
||||
config: FilterMutable {
|
||||
passes_enabled: preset.shader_count as usize,
|
||||
parameters: preset
|
||||
.parameters
|
||||
.into_iter()
|
||||
.map(|param| (param.name, param.value))
|
||||
.collect(),
|
||||
},
|
||||
luts,
|
||||
samplers,
|
||||
// we don't need the reflect semantics once all locations have been bound per pass.
|
||||
// semantics,
|
||||
preset,
|
||||
output_textures: output_textures.into_boxed_slice(),
|
||||
feedback_textures: feedback_textures.into_boxed_slice(),
|
||||
history_textures,
|
||||
|
@ -269,7 +291,7 @@ impl FilterChain {
|
|||
device: &ID3D11Device,
|
||||
context: &ID3D11DeviceContext,
|
||||
filters: &[FilterPass],
|
||||
) -> (VecDeque<OwnedFramebuffer>, Box<[Option<Texture>]>) {
|
||||
) -> util::Result<(VecDeque<OwnedFramebuffer>, Box<[Option<Texture>]>)> {
|
||||
let mut required_images = 0;
|
||||
|
||||
for pass in filters {
|
||||
|
@ -296,7 +318,7 @@ impl FilterChain {
|
|||
// not using frame history;
|
||||
if required_images <= 1 {
|
||||
println!("[history] not using frame history");
|
||||
return (VecDeque::new(), Box::new([]));
|
||||
return Ok((VecDeque::new(), Box::new([])));
|
||||
}
|
||||
|
||||
// history0 is aliased with the original
|
||||
|
@ -305,13 +327,15 @@ impl FilterChain {
|
|||
let mut framebuffers = VecDeque::with_capacity(required_images);
|
||||
framebuffers.resize_with(required_images, || {
|
||||
OwnedFramebuffer::new(device, context, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
let framebuffers = framebuffers
|
||||
.into_iter().collect::<util::Result<VecDeque<OwnedFramebuffer>>>()?;
|
||||
|
||||
let mut history_textures = Vec::new();
|
||||
history_textures.resize_with(required_images, || None);
|
||||
|
||||
(framebuffers, history_textures.into_boxed_slice())
|
||||
Ok((framebuffers, history_textures.into_boxed_slice()))
|
||||
}
|
||||
|
||||
fn push_history(&mut self, input: &DxImageView) -> util::Result<()> {
|
||||
|
@ -325,8 +349,9 @@ impl FilterChain {
|
|||
|
||||
fn load_luts(
|
||||
device: &ID3D11Device,
|
||||
context: &ID3D11DeviceContext,
|
||||
textures: &[TextureConfig],
|
||||
) -> util::Result<FxHashMap<usize, OwnedTexture>> {
|
||||
) -> util::Result<FxHashMap<usize, LutTexture>> {
|
||||
let mut luts = FxHashMap::default();
|
||||
|
||||
for (index, texture) in textures.iter().enumerate() {
|
||||
|
@ -345,7 +370,7 @@ impl FilterChain {
|
|||
};
|
||||
|
||||
let texture =
|
||||
OwnedTexture::new(device, &image, desc, texture.filter_mode, texture.wrap_mode)?;
|
||||
LutTexture::new(device, context,&image, desc, texture.filter_mode, texture.wrap_mode)?;
|
||||
luts.insert(index, texture);
|
||||
}
|
||||
Ok(luts)
|
||||
|
@ -361,14 +386,15 @@ impl FilterChain {
|
|||
Self::load_from_preset(device, preset)
|
||||
}
|
||||
|
||||
fn load_preset(preset: &ShaderPreset) -> util::Result<(Vec<ShaderPassMeta>, ReflectSemantics)> {
|
||||
fn load_preset( passes: Vec<ShaderPassConfig>,
|
||||
textures: &[TextureConfig],
|
||||
) -> util::Result<(Vec<ShaderPassMeta>, ReflectSemantics)> {
|
||||
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
|
||||
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> =
|
||||
Default::default();
|
||||
|
||||
let passes = preset
|
||||
.shaders
|
||||
.iter()
|
||||
let passes = passes
|
||||
.into_iter()
|
||||
.map(|shader| {
|
||||
eprintln!("[dx11] loading {}", &shader.name.display());
|
||||
let source: ShaderSource = ShaderSource::load(&shader.name)?;
|
||||
|
@ -385,21 +411,21 @@ impl FilterChain {
|
|||
}),
|
||||
);
|
||||
}
|
||||
Ok::<_, Box<dyn Error>>((shader, source, reflect))
|
||||
Ok::<_, FilterChainError>((shader, source, reflect))
|
||||
})
|
||||
.into_iter()
|
||||
.collect::<util::Result<Vec<(&ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>(
|
||||
.collect::<util::Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>(
|
||||
)?;
|
||||
|
||||
for details in &passes {
|
||||
librashader_runtime::semantics::insert_pass_semantics(
|
||||
&mut uniform_semantics,
|
||||
&mut texture_semantics,
|
||||
details.0,
|
||||
&details.0,
|
||||
)
|
||||
}
|
||||
librashader_runtime::semantics::insert_lut_semantics(
|
||||
&preset.textures,
|
||||
&textures,
|
||||
&mut uniform_semantics,
|
||||
&mut texture_semantics,
|
||||
);
|
||||
|
@ -476,12 +502,12 @@ impl FilterChain {
|
|||
viewport,
|
||||
&original,
|
||||
&source,
|
||||
RenderTarget::new(target.as_output_framebuffer().unwrap(), None),
|
||||
RenderTarget::new(target.as_output_framebuffer()?, None),
|
||||
)?;
|
||||
|
||||
source = Texture {
|
||||
view: DxImageView {
|
||||
handle: target.create_shader_resource_view().unwrap(),
|
||||
handle: target.create_shader_resource_view()?,
|
||||
size,
|
||||
},
|
||||
filter,
|
||||
|
|
|
@ -20,6 +20,7 @@ use windows::Win32::Graphics::Direct3D11::{
|
|||
use crate::render_target::RenderTarget;
|
||||
use crate::samplers::SamplerSet;
|
||||
use librashader_runtime::uniforms::UniformStorage;
|
||||
use crate::util;
|
||||
|
||||
pub struct ConstantBufferBinding {
|
||||
pub binding: u32,
|
||||
|
@ -310,13 +311,7 @@ impl FilterPass {
|
|||
.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);
|
||||
let value = *parent.config.parameters.get(id).unwrap_or(&default);
|
||||
|
||||
self.uniform_storage.bind_scalar(*offset, value, None);
|
||||
}
|
||||
|
@ -360,7 +355,7 @@ impl FilterPass {
|
|||
original: &Texture,
|
||||
source: &Texture,
|
||||
output: RenderTarget,
|
||||
) -> std::result::Result<(), Box<dyn Error>> {
|
||||
) -> util::Result<()> {
|
||||
let _device = &parent.d3d11.device;
|
||||
let context = &parent.d3d11.device_context;
|
||||
unsafe {
|
||||
|
|
|
@ -155,9 +155,10 @@ impl OwnedFramebuffer {
|
|||
let resource: ID3D11Texture2D = unsafe {
|
||||
let mut resource = None;
|
||||
image.handle.GetResource(&mut resource);
|
||||
|
||||
// todo: make panic-free
|
||||
resource.unwrap().cast()?
|
||||
let Some(resource) = resource else {
|
||||
return Ok(())
|
||||
};
|
||||
resource.cast()?
|
||||
};
|
||||
|
||||
let format = unsafe {
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(let_chains)]
|
||||
|
||||
mod filter_chain;
|
||||
|
||||
mod filter_pass;
|
||||
mod framebuffer;
|
||||
#[cfg(test)]
|
||||
mod hello_triangle;
|
||||
|
||||
mod filter_chain;
|
||||
mod filter_pass;
|
||||
mod framebuffer;
|
||||
mod quad_render;
|
||||
mod render_target;
|
||||
mod samplers;
|
||||
mod texture;
|
||||
mod util;
|
||||
pub mod error;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
|
@ -1,48 +1,40 @@
|
|||
use librashader_common::image::Image;
|
||||
use librashader_common::{FilterMode, Size, WrapMode};
|
||||
use windows::Win32::Graphics::Direct3D::D3D_SRV_DIMENSION_TEXTURE2D;
|
||||
use windows::Win32::Graphics::Direct3D11::{
|
||||
ID3D11Device, ID3D11ShaderResourceView, ID3D11Texture2D, D3D11_BIND_FLAG,
|
||||
D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE, D3D11_BOX, D3D11_CPU_ACCESS_FLAG,
|
||||
D3D11_CPU_ACCESS_WRITE, D3D11_FORMAT_SUPPORT_RENDER_TARGET, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE,
|
||||
D3D11_FORMAT_SUPPORT_TEXTURE2D, D3D11_RESOURCE_MISC_FLAG, D3D11_RESOURCE_MISC_GENERATE_MIPS,
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC, D3D11_SHADER_RESOURCE_VIEW_DESC_0, D3D11_SUBRESOURCE_DATA,
|
||||
D3D11_TEX2D_SRV, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DYNAMIC, D3D11_USAGE_STAGING,
|
||||
};
|
||||
use windows::Win32::Graphics::Direct3D11::{ID3D11Device, ID3D11ShaderResourceView, ID3D11Texture2D, D3D11_BIND_FLAG, D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE, D3D11_BOX, D3D11_CPU_ACCESS_FLAG, D3D11_CPU_ACCESS_WRITE, D3D11_FORMAT_SUPPORT_RENDER_TARGET, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE, D3D11_FORMAT_SUPPORT_TEXTURE2D, D3D11_RESOURCE_MISC_FLAG, D3D11_RESOURCE_MISC_GENERATE_MIPS, D3D11_SHADER_RESOURCE_VIEW_DESC, D3D11_SHADER_RESOURCE_VIEW_DESC_0, D3D11_SUBRESOURCE_DATA, D3D11_TEX2D_SRV, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DYNAMIC, D3D11_USAGE_STAGING, ID3D11DeviceContext};
|
||||
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
|
||||
use crate::filter_chain::Direct3D11;
|
||||
|
||||
use crate::util::Result;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DxImageView {
|
||||
pub handle: ID3D11ShaderResourceView,
|
||||
pub size: Size<u32>, // pub image: GlImage,
|
||||
pub size: Size<u32>,
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Texture {
|
||||
pub view: DxImageView,
|
||||
pub filter: FilterMode,
|
||||
pub wrap_mode: WrapMode,
|
||||
// pub mip_filter: FilterMode,
|
||||
// pub wrap_mode: WrapMode,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OwnedTexture {
|
||||
pub struct LutTexture {
|
||||
pub handle: ID3D11Texture2D,
|
||||
// pub staging: ID3D11Texture2D,
|
||||
pub desc: D3D11_TEXTURE2D_DESC,
|
||||
pub image: Texture,
|
||||
}
|
||||
|
||||
impl OwnedTexture {
|
||||
impl LutTexture {
|
||||
pub fn new(
|
||||
device: &ID3D11Device,
|
||||
context: &ID3D11DeviceContext,
|
||||
source: &Image,
|
||||
desc: D3D11_TEXTURE2D_DESC,
|
||||
filter: FilterMode,
|
||||
wrap_mode: WrapMode,
|
||||
) -> Result<OwnedTexture> {
|
||||
) -> Result<LutTexture> {
|
||||
let mut desc = D3D11_TEXTURE2D_DESC {
|
||||
Width: source.size.width,
|
||||
Height: source.size.height,
|
||||
|
@ -107,12 +99,6 @@ impl OwnedTexture {
|
|||
}),
|
||||
)?;
|
||||
|
||||
let mut context = None;
|
||||
device.GetImmediateContext(&mut context);
|
||||
|
||||
// todo: make this fallible
|
||||
let context = context.unwrap();
|
||||
|
||||
// need a staging texture to defer mipmap generation
|
||||
let staging = device.CreateTexture2D(
|
||||
&D3D11_TEXTURE2D_DESC {
|
||||
|
@ -158,7 +144,7 @@ impl OwnedTexture {
|
|||
// let mut subresource = context.Map(staging, 0, D3D11_MAP_WRITE, 0)?;
|
||||
// staging.Upd
|
||||
|
||||
Ok(OwnedTexture {
|
||||
Ok(LutTexture {
|
||||
handle,
|
||||
// staging,
|
||||
desc,
|
||||
|
|
|
@ -167,4 +167,4 @@ pub fn d3d11_create_input_layout(
|
|||
}
|
||||
|
||||
// todo: d3d11.c 2097
|
||||
pub type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
||||
pub type Result<T> = std::result::Result<T, crate::error::FilterChainError>;
|
||||
|
|
|
@ -32,7 +32,6 @@ pub struct FilterPass<T: GLInterface> {
|
|||
}
|
||||
|
||||
impl<T: GLInterface> FilterPass<T> {
|
||||
// todo: fix rendertargets (i.e. non-final pass is internal, final pass is user provided fbo)
|
||||
pub(crate) fn draw(
|
||||
&mut self,
|
||||
pass_index: usize,
|
||||
|
|
|
@ -89,6 +89,11 @@ impl FramebufferInterface for Gl46Framebuffer {
|
|||
}
|
||||
}
|
||||
fn copy_from(fb: &mut Framebuffer, image: &GLImage) -> Result<()> {
|
||||
// todo: confirm this behaviour for unbound image.
|
||||
if image.handle == 0 {
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
// todo: may want to use a shader and draw a quad to be faster.
|
||||
if image.size != fb.size || image.format != fb.format {
|
||||
Self::init(
|
||||
|
|
Loading…
Reference in a new issue