d3d11: sketch out filterpass

This commit is contained in:
chyyran 2022-11-27 02:21:36 -05:00
parent 0806114e12
commit 4e242bf25e
6 changed files with 206 additions and 67 deletions

View file

@ -45,6 +45,7 @@ pub struct FilterChain {
pub struct Direct3D11 { pub struct Direct3D11 {
pub(crate) device: ID3D11Device, pub(crate) device: ID3D11Device,
pub(crate) device_context: ID3D11DeviceContext,
} }
pub struct FilterCommon { pub struct FilterCommon {
@ -267,6 +268,13 @@ impl FilterChain {
// 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);
let mut device_context = None;
unsafe {
device.GetImmediateContext(&mut device_context);
}
// todo: make vbo: d3d11.c 1376
Ok(FilterChain { Ok(FilterChain {
passes: filters, passes: filters,
// output_framebuffers: output_framebuffers.into_boxed_slice(), // output_framebuffers: output_framebuffers.into_boxed_slice(),
@ -276,6 +284,7 @@ impl FilterChain {
common: FilterCommon { common: FilterCommon {
d3d11: Direct3D11 { d3d11: Direct3D11 {
device: device.clone(), device: device.clone(),
device_context: device_context.unwrap()
}, },
luts, luts,
samplers, samplers,
@ -311,8 +320,8 @@ impl FilterChain {
..Default::default() ..Default::default()
}; };
let mut texture = OwnedTexture::new(device, &image, desc)?; let mut texture = OwnedTexture::new(device, &image, desc,
// todo: update texture d3d11_common: 150 texture.filter_mode, texture.wrap_mode)?;
luts.insert(index, texture); luts.insert(index, texture);
} }
Ok(luts) Ok(luts)

View file

@ -1,20 +1,19 @@
use crate::filter_chain::FilterCommon; use crate::filter_chain::FilterCommon;
use crate::texture::{ExternalTexture, OwnedTexture}; use crate::texture::{Texture, OwnedTexture};
use librashader_common::Size; use librashader_common::Size;
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use librashader_presets::ShaderPassConfig; use librashader_presets::ShaderPassConfig;
use librashader_reflect::back::cross::GlslangHlslContext; use librashader_reflect::back::cross::GlslangHlslContext;
use librashader_reflect::back::ShaderCompilerOutput; use librashader_reflect::back::ShaderCompilerOutput;
use librashader_reflect::reflect::semantics::{ use librashader_reflect::reflect::semantics::{BindingStage, MAX_BINDINGS_COUNT, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniformSemantic, VariableSemantics};
BindingStage, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniformSemantic,
VariableSemantics,
};
use librashader_reflect::reflect::ShaderReflection; use librashader_reflect::reflect::ShaderReflection;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::error::Error; use std::error::Error;
use windows::core::ConstBuffer; use windows::core::ConstBuffer;
use windows::Win32::Graphics::Direct3D::ID3DBlob; use windows::Win32::Graphics::Direct3D::ID3DBlob;
use windows::Win32::Graphics::Direct3D11::{ID3D11Buffer, ID3D11PixelShader, ID3D11SamplerState, ID3D11ShaderResourceView, ID3D11VertexShader, D3D11_MAP_WRITE_DISCARD, ID3D11InputLayout}; 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 struct ConstantBufferBinding {
pub binding: u32, pub binding: u32,
@ -77,14 +76,14 @@ impl FilterPass {
} }
fn bind_texture( fn bind_texture(
samplers: &SamplerSet,
texture_binding: &mut [Option<ID3D11ShaderResourceView>; 16], texture_binding: &mut [Option<ID3D11ShaderResourceView>; 16],
sampler_binding: &mut [Option<ID3D11SamplerState>; 16], sampler_binding: &mut [Option<ID3D11SamplerState>; 16],
binding: &TextureBinding, binding: &TextureBinding,
texture: &ExternalTexture, texture: &Texture,
) { ) {
texture_binding[binding.binding as usize] = Some(texture.srv.clone()); texture_binding[binding.binding as usize] = Some(texture.handle.clone());
// todo: make samplers for all wrapmode/filtermode combos. sampler_binding[binding.binding as usize] = Some(samplers.get(texture.wrap_mode, texture.filter).clone());
// sampler_binding[binding.binding as usize] = Some(texture.sampler.clone());
} }
// framecount should be pre-modded // framecount should be pre-modded
@ -96,10 +95,10 @@ impl FilterPass {
frame_count: u32, frame_count: u32,
frame_direction: i32, frame_direction: i32,
fb_size: Size<u32>, fb_size: Size<u32>,
// viewport: &Viewport, viewport_size: Size<u32>,
original: &ExternalTexture, original: &Texture,
source: &ExternalTexture, source: &Texture,
) { ) -> ([Option<ID3D11ShaderResourceView>; 16], [Option<ID3D11SamplerState>; 16]){
let mut textures: [Option<ID3D11ShaderResourceView>; 16] = std::array::from_fn(|_| None); let mut textures: [Option<ID3D11ShaderResourceView>; 16] = std::array::from_fn(|_| None);
let mut samplers: [Option<ID3D11SamplerState>; 16] = std::array::from_fn(|_| None); let mut samplers: [Option<ID3D11SamplerState>; 16] = std::array::from_fn(|_| None);
@ -124,19 +123,19 @@ impl FilterPass {
} }
// bind FinalViewportSize // bind FinalViewportSize
// if let Some(offset) = self if let Some(offset) = self
// .uniform_bindings .uniform_bindings
// .get(&VariableSemantics::FinalViewport.into()) .get(&VariableSemantics::FinalViewport.into())
// { {
// let (buffer, offset) = match offset { let (buffer, offset) = match offset {
// MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
// MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset), MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
// }; };
// FilterPass::build_vec4( FilterPass::build_vec4(
// &mut buffer[offset..][..16], &mut buffer[offset..][..16],
// viewport.output.size, viewport_size,
// ) )
// } }
// bind FrameCount // bind FrameCount
if let Some(offset) = self if let Some(offset) = self
@ -169,7 +168,7 @@ impl FilterPass {
.texture_meta .texture_meta
.get(&TextureSemantics::Original.semantics(0)) .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 // bind OriginalSize
@ -192,7 +191,7 @@ impl FilterPass {
.get(&TextureSemantics::Source.semantics(0)) .get(&TextureSemantics::Source.semantics(0))
{ {
// eprintln!("setting source binding to {}", binding.binding); // 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 // bind SourceSize
@ -213,7 +212,7 @@ impl FilterPass {
.texture_meta .texture_meta
.get(&TextureSemantics::OriginalHistory.semantics(0)) .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 if let Some(offset) = self
@ -346,31 +345,32 @@ impl FilterPass {
} }
// bind luts // bind luts
// for (index, lut) in &parent.luts { for (index, lut) in &parent.luts {
// if let Some(binding) = self if let Some(binding) = self
// .reflection .reflection
// .meta .meta
// .texture_meta .texture_meta
// .get(&TextureSemantics::User.semantics(*index)) .get(&TextureSemantics::User.semantics(*index))
// { {
// FilterPass::bind_texture(binding, lut); FilterPass::bind_texture(&parent.samplers, &mut textures, &mut samplers, binding, &lut.image);
// } }
//
// if let Some((location, offset)) = self if let Some(offset) = self
// .uniform_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 {
// MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer.storage, *offset),
// MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset), MemberOffset::PushConstant(offset) => (&mut self.push_buffer.storage, *offset),
// }; };
// FilterPass::build_vec4( FilterPass::build_vec4(
// location.location(), &mut buffer[offset..][..16],
// &mut buffer[offset..][..16], lut.image.size,
// lut.image.size, );
// ); }
// } }
// }
(textures, samplers)
} }
pub fn draw( pub fn draw(
@ -379,7 +379,81 @@ impl FilterPass {
parent: &FilterCommon, parent: &FilterCommon,
frame_count: u32, frame_count: u32,
frame_direction: i32, frame_direction: i32,
viewport: &Size<u32>,
original: &Texture,
source: &Texture,
output: RenderTarget,
) -> std::result::Result<(), Box<dyn Error>> { ) -> std::result::Result<(), Box<dyn Error>> {
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(()) Ok(())
} }
} }

View file

@ -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<u32>,
pub viewport: D3D11_VIEWPORT
}

View file

@ -23,6 +23,8 @@ mod hello_triangle;
mod texture; mod texture;
mod util; mod util;
mod samplers; mod samplers;
mod render_target;
mod framebuffer;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

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

View file

@ -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::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::Direct3D::D3D_SRV_DIMENSION_TEXTURE2D;
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC; use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
@ -7,25 +7,25 @@ use crate::util::d3d11_get_closest_format;
use crate::util::Result; use crate::util::Result;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ExternalTexture { pub struct Texture {
pub srv: ID3D11ShaderResourceView, pub handle: ID3D11ShaderResourceView,
pub size: Size<u32>, // pub image: GlImage, pub size: Size<u32>, // pub image: GlImage,
pub filter: FilterMode,
pub wrap_mode: WrapMode,
// pub mip_filter: FilterMode,
// pub wrap_mode: WrapMode,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct OwnedTexture { pub struct OwnedTexture {
pub handle: ID3D11Texture2D, pub handle: ID3D11Texture2D,
// pub staging: ID3D11Texture2D, // pub staging: ID3D11Texture2D,
pub srv: ID3D11ShaderResourceView,
pub desc: D3D11_TEXTURE2D_DESC, pub desc: D3D11_TEXTURE2D_DESC,
pub size: Size<u32>, // pub image: GlImage, pub image: Texture,
// pub filter: FilterMode,
// pub mip_filter: FilterMode,
// pub wrap_mode: WrapMode,
} }
impl OwnedTexture { impl OwnedTexture {
pub fn new(device: &ID3D11Device, source: &Image, desc: D3D11_TEXTURE2D_DESC) -> Result<OwnedTexture> { pub fn new(device: &ID3D11Device, source: &Image, desc: D3D11_TEXTURE2D_DESC, filter: FilterMode, wrap_mode: WrapMode) -> Result<OwnedTexture> {
let mut desc = D3D11_TEXTURE2D_DESC { let mut desc = D3D11_TEXTURE2D_DESC {
Width: source.size.width, Width: source.size.width,
Height: source.size.height, Height: source.size.height,
@ -133,9 +133,13 @@ impl OwnedTexture {
Ok(OwnedTexture { Ok(OwnedTexture {
handle, handle,
// staging, // staging,
srv,
desc, desc,
size: source.size, image: Texture {
handle: srv,
size: source.size,
filter,
wrap_mode
}
}) })
} }
} }