From 4e242bf25e33b04306c7793789c8ab986b6f7925 Mon Sep 17 00:00:00 2001 From: chyyran Date: Sun, 27 Nov 2022 02:21:36 -0500 Subject: [PATCH] d3d11: sketch out filterpass --- librashader-runtime-d3d11/src/filter_chain.rs | 13 +- librashader-runtime-d3d11/src/filter_pass.rs | 182 ++++++++++++------ librashader-runtime-d3d11/src/framebuffer.rs | 16 ++ librashader-runtime-d3d11/src/lib.rs | 2 + .../src/render_target.rs | 34 ++++ librashader-runtime-d3d11/src/texture.rs | 26 +-- 6 files changed, 206 insertions(+), 67 deletions(-) create mode 100644 librashader-runtime-d3d11/src/framebuffer.rs create mode 100644 librashader-runtime-d3d11/src/render_target.rs diff --git a/librashader-runtime-d3d11/src/filter_chain.rs b/librashader-runtime-d3d11/src/filter_chain.rs index 5835f0a..37885f1 100644 --- a/librashader-runtime-d3d11/src/filter_chain.rs +++ b/librashader-runtime-d3d11/src/filter_chain.rs @@ -45,6 +45,7 @@ pub struct FilterChain { pub struct Direct3D11 { pub(crate) device: ID3D11Device, + pub(crate) device_context: ID3D11DeviceContext, } pub struct FilterCommon { @@ -267,6 +268,13 @@ impl FilterChain { // let (history_framebuffers, history_textures) = // FilterChain::init_history(&filters, default_filter, default_wrap); + let mut device_context = None; + + unsafe { + device.GetImmediateContext(&mut device_context); + } + + // todo: make vbo: d3d11.c 1376 Ok(FilterChain { passes: filters, // output_framebuffers: output_framebuffers.into_boxed_slice(), @@ -276,6 +284,7 @@ impl FilterChain { common: FilterCommon { d3d11: Direct3D11 { device: device.clone(), + device_context: device_context.unwrap() }, luts, samplers, @@ -311,8 +320,8 @@ impl FilterChain { ..Default::default() }; - let mut texture = OwnedTexture::new(device, &image, desc)?; - // todo: update texture d3d11_common: 150 + let mut texture = OwnedTexture::new(device, &image, desc, + texture.filter_mode, texture.wrap_mode)?; luts.insert(index, texture); } Ok(luts) diff --git a/librashader-runtime-d3d11/src/filter_pass.rs b/librashader-runtime-d3d11/src/filter_pass.rs index ce7faba..5264749 100644 --- a/librashader-runtime-d3d11/src/filter_pass.rs +++ b/librashader-runtime-d3d11/src/filter_pass.rs @@ -1,20 +1,19 @@ use crate::filter_chain::FilterCommon; -use crate::texture::{ExternalTexture, OwnedTexture}; +use crate::texture::{Texture, OwnedTexture}; 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::semantics::{BindingStage, MAX_BINDINGS_COUNT, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniformSemantic, VariableSemantics}; use librashader_reflect::reflect::ShaderReflection; use rustc_hash::FxHashMap; use std::error::Error; use windows::core::ConstBuffer; use windows::Win32::Graphics::Direct3D::ID3DBlob; use windows::Win32::Graphics::Direct3D11::{ID3D11Buffer, ID3D11PixelShader, ID3D11SamplerState, ID3D11ShaderResourceView, ID3D11VertexShader, D3D11_MAP_WRITE_DISCARD, ID3D11InputLayout}; +use crate::render_target::RenderTarget; +use crate::samplers::SamplerSet; pub struct ConstantBufferBinding { pub binding: u32, @@ -77,14 +76,14 @@ impl FilterPass { } fn bind_texture( + samplers: &SamplerSet, texture_binding: &mut [Option; 16], sampler_binding: &mut [Option; 16], binding: &TextureBinding, - texture: &ExternalTexture, + texture: &Texture, ) { - texture_binding[binding.binding as usize] = Some(texture.srv.clone()); - // todo: make samplers for all wrapmode/filtermode combos. - // sampler_binding[binding.binding as usize] = Some(texture.sampler.clone()); + texture_binding[binding.binding as usize] = Some(texture.handle.clone()); + sampler_binding[binding.binding as usize] = Some(samplers.get(texture.wrap_mode, texture.filter).clone()); } // framecount should be pre-modded @@ -96,10 +95,10 @@ impl FilterPass { frame_count: u32, frame_direction: i32, fb_size: Size, - // viewport: &Viewport, - original: &ExternalTexture, - source: &ExternalTexture, - ) { + viewport_size: Size, + original: &Texture, + source: &Texture, + ) -> ([Option; 16], [Option; 16]){ let mut textures: [Option; 16] = std::array::from_fn(|_| None); let mut samplers: [Option; 16] = std::array::from_fn(|_| None); @@ -124,19 +123,19 @@ impl FilterPass { } // 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, - // ) - // } + 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_size, + ) + } // bind FrameCount if let Some(offset) = self @@ -169,7 +168,7 @@ impl FilterPass { .texture_meta .get(&TextureSemantics::Original.semantics(0)) { - FilterPass::bind_texture(&mut textures, &mut samplers, binding, original); + FilterPass::bind_texture(&parent.samplers, &mut textures, &mut samplers, binding, original); } // // bind OriginalSize @@ -192,7 +191,7 @@ impl FilterPass { .get(&TextureSemantics::Source.semantics(0)) { // eprintln!("setting source binding to {}", binding.binding); - FilterPass::bind_texture(&mut textures, &mut samplers, binding, source); + FilterPass::bind_texture(&parent.samplers, &mut textures, &mut samplers, binding, source); } // bind SourceSize @@ -213,7 +212,7 @@ impl FilterPass { .texture_meta .get(&TextureSemantics::OriginalHistory.semantics(0)) { - FilterPass::bind_texture(&mut textures, &mut samplers, binding, original); + FilterPass::bind_texture(&parent.samplers, &mut textures, &mut samplers, binding, original); } if let Some(offset) = self @@ -346,31 +345,32 @@ impl FilterPass { } // 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, - // ); - // } - // } + for (index, lut) in &parent.luts { + if let Some(binding) = self + .reflection + .meta + .texture_meta + .get(&TextureSemantics::User.semantics(*index)) + { + FilterPass::bind_texture(&parent.samplers, &mut textures, &mut samplers, binding, &lut.image); + } + + if let Some(offset) = self + .uniform_bindings + .get(&TextureSemantics::User.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_vec4( + &mut buffer[offset..][..16], + lut.image.size, + ); + } + } + + (textures, samplers) } pub fn draw( @@ -379,7 +379,81 @@ impl FilterPass { parent: &FilterCommon, frame_count: u32, frame_direction: i32, + viewport: &Size, + original: &Texture, + source: &Texture, + output: RenderTarget, ) -> std::result::Result<(), Box> { + let device = &parent.d3d11.device; + let context = &parent.d3d11.device_context; + unsafe { + context.IASetInputLayout(&self.vertex_layout); + context.VSSetShader(&self.vertex_shader, None); + context.PSSetShader(&self.pixel_shader, None); + } + + let (textures, samplers) = self.build_semantics(pass_index, parent, output.mvp, frame_count, frame_direction, + output.output.size, *viewport, original, source); + + + + if let Some(ubo) = &self.uniform_buffer.binding { + // upload uniforms + unsafe { + let map = context.Map(&ubo.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0)?; + std::ptr::copy_nonoverlapping(self.uniform_buffer.storage.as_ptr(), map.pData.cast(), ubo.size as usize); + context.Unmap(&ubo.buffer, 0); + } + + if ubo.stage_mask.contains(BindingStage::VERTEX) { + unsafe { + context.VSSetConstantBuffers(ubo.binding, Some(&[Some(ubo.buffer.clone())])) + } + } + if ubo.stage_mask.contains(BindingStage::FRAGMENT) { + unsafe { + context.PSSetConstantBuffers(ubo.binding, Some(&[Some(ubo.buffer.clone())])) + } + } + } + + if let Some(push) = &self.push_buffer.binding { + // upload push constants + unsafe { + let map = context.Map(&push.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0)?; + std::ptr::copy_nonoverlapping(self.push_buffer.storage.as_ptr(), map.pData.cast(), push.size as usize); + context.Unmap(&push.buffer, 0); + } + + if push.stage_mask.contains(BindingStage::VERTEX) { + unsafe { + context.VSSetConstantBuffers(push.binding, Some(&[Some(push.buffer.clone())])) + } + } + if push.stage_mask.contains(BindingStage::FRAGMENT) { + unsafe { + context.PSSetConstantBuffers(push.binding, Some(&[Some(push.buffer.clone())])) + } + } + } + + unsafe { + // reset RTVs + context.OMSetRenderTargets(None, None); + } + + unsafe { + context.PSSetShaderResources(0, Some(&textures)); + context.PSSetSamplers(0, Some(&samplers)); + + context.OMSetRenderTargets(Some(&[Some(output.output.rtv.clone())]), None); + context.RSSetViewports(Some(&[output.output.viewport.clone()])) + } + + unsafe { + // must be under primitive topology trianglestrip with quad + context.Draw(4, 0); + } Ok(()) } } diff --git a/librashader-runtime-d3d11/src/framebuffer.rs b/librashader-runtime-d3d11/src/framebuffer.rs new file mode 100644 index 0000000..4e5e22b --- /dev/null +++ b/librashader-runtime-d3d11/src/framebuffer.rs @@ -0,0 +1,16 @@ +use windows::Win32::Graphics::Direct3D11::{D3D11_VIEWPORT, ID3D11RenderTargetView, ID3D11ShaderResourceView, ID3D11Texture2D}; +use librashader_common::Size; +#[derive(Debug, Clone)] +pub struct OwnedFramebuffer { + pub srv: ID3D11ShaderResourceView, + pub rtv: ID3D11RenderTargetView, + pub texture: ID3D11Texture2D, +} + +#[derive(Debug, Clone)] + +pub struct OutputFramebuffer { + pub rtv: ID3D11RenderTargetView, + pub size: Size, + pub viewport: D3D11_VIEWPORT +} \ No newline at end of file diff --git a/librashader-runtime-d3d11/src/lib.rs b/librashader-runtime-d3d11/src/lib.rs index b208d74..37d6867 100644 --- a/librashader-runtime-d3d11/src/lib.rs +++ b/librashader-runtime-d3d11/src/lib.rs @@ -23,6 +23,8 @@ mod hello_triangle; mod texture; mod util; mod samplers; +mod render_target; +mod framebuffer; #[cfg(test)] mod tests { diff --git a/librashader-runtime-d3d11/src/render_target.rs b/librashader-runtime-d3d11/src/render_target.rs new file mode 100644 index 0000000..86d4940 --- /dev/null +++ b/librashader-runtime-d3d11/src/render_target.rs @@ -0,0 +1,34 @@ +use windows::Win32::Graphics::Direct3D11::ID3D11RenderTargetView; +use librashader_common::Size; +use crate::framebuffer::{OutputFramebuffer}; + +#[rustfmt::skip] +static DEFAULT_MVP: &[f32] = &[ + 2f32, 0.0, 0.0, 0.0, + 0.0, 2.0, 0.0, 0.0, + 0.0, 0.0, 2.0, 0.0, + -1.0, -1.0, 0.0, 1.0, +]; + +#[derive(Debug, Clone)] +pub struct RenderTarget<'a> { + pub mvp: &'a [f32], + pub output: OutputFramebuffer +} + +impl<'a> RenderTarget<'a> { + pub fn new(backbuffer: OutputFramebuffer, mvp: Option<&'a [f32]>) -> Self { + if let Some(mvp) = mvp { + RenderTarget { + output: backbuffer, + mvp, + } + } else { + RenderTarget { + output: backbuffer, + mvp: DEFAULT_MVP, + } + } + } +} + diff --git a/librashader-runtime-d3d11/src/texture.rs b/librashader-runtime-d3d11/src/texture.rs index d9fbc8f..a33a17f 100644 --- a/librashader-runtime-d3d11/src/texture.rs +++ b/librashader-runtime-d3d11/src/texture.rs @@ -1,4 +1,4 @@ -use librashader_common::Size; +use librashader_common::{FilterMode, Size, WrapMode}; use windows::Win32::Graphics::Direct3D11::{ID3D11Device, ID3D11SamplerState, ID3D11ShaderResourceView, ID3D11Texture2D, D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE, 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_GENERATE_MIPS, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DYNAMIC, D3D11_SHADER_RESOURCE_VIEW_DESC, D3D11_SHADER_RESOURCE_VIEW_DESC_0, D3D11_TEX2D_SRV, D3D11_BIND_FLAG, D3D11_RESOURCE_MISC_FLAG, D3D11_USAGE_STAGING, ID3D11DeviceContext, D3D11_SUBRESOURCE_DATA, D3D11_MAP_WRITE, D3D11_BOX}; use windows::Win32::Graphics::Direct3D::D3D_SRV_DIMENSION_TEXTURE2D; use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC; @@ -7,25 +7,25 @@ use crate::util::d3d11_get_closest_format; use crate::util::Result; #[derive(Debug, Clone)] -pub struct ExternalTexture { - pub srv: ID3D11ShaderResourceView, +pub struct Texture { + pub handle: ID3D11ShaderResourceView, pub size: Size, // pub image: GlImage, + pub filter: FilterMode, + pub wrap_mode: WrapMode, + // pub mip_filter: FilterMode, + // pub wrap_mode: WrapMode, } #[derive(Debug, Clone)] pub struct OwnedTexture { pub handle: ID3D11Texture2D, // pub staging: ID3D11Texture2D, - pub srv: ID3D11ShaderResourceView, pub desc: D3D11_TEXTURE2D_DESC, - pub size: Size, // pub image: GlImage, - // pub filter: FilterMode, - // pub mip_filter: FilterMode, - // pub wrap_mode: WrapMode, + pub image: Texture, } impl OwnedTexture { - pub fn new(device: &ID3D11Device, source: &Image, desc: D3D11_TEXTURE2D_DESC) -> Result { + pub fn new(device: &ID3D11Device, source: &Image, desc: D3D11_TEXTURE2D_DESC, filter: FilterMode, wrap_mode: WrapMode) -> Result { let mut desc = D3D11_TEXTURE2D_DESC { Width: source.size.width, Height: source.size.height, @@ -133,9 +133,13 @@ impl OwnedTexture { Ok(OwnedTexture { handle, // staging, - srv, desc, - size: source.size, + image: Texture { + handle: srv, + size: source.size, + filter, + wrap_mode + } }) } }