d3d11/vk: render intermediate passes with identity matrix

This commit is contained in:
chyyran 2023-01-31 00:53:55 -05:00
parent b996d60e9b
commit 82ad516db0
11 changed files with 131 additions and 52 deletions

View file

@ -31,6 +31,7 @@ use windows::Win32::Graphics::Direct3D11::{
D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_USAGE_DYNAMIC, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_USAGE_DYNAMIC,
}; };
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R8G8B8A8_UNORM; use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R8G8B8A8_UNORM;
use librashader_runtime::quad::{IDENTITY_MVP, QuadType};
pub struct FilterMutable { pub struct FilterMutable {
pub(crate) passes_enabled: usize, pub(crate) passes_enabled: usize,
@ -521,7 +522,8 @@ impl FilterChainD3D11 {
viewport, viewport,
&original, &original,
&source, &source,
RenderTarget::new(target.as_output_framebuffer()?, None), RenderTarget::new(target.as_output_framebuffer()?, Some(IDENTITY_MVP)),
QuadType::Offscreen
)?; )?;
source = InputTexture { source = InputTexture {
@ -553,6 +555,7 @@ impl FilterChainD3D11 {
&original, &original,
&source, &source,
viewport.into(), viewport.into(),
QuadType::Final
)?; )?;
} }

View file

@ -17,6 +17,7 @@ use windows::Win32::Graphics::Direct3D11::{
ID3D11ShaderResourceView, ID3D11VertexShader, D3D11_MAPPED_SUBRESOURCE, ID3D11ShaderResourceView, ID3D11VertexShader, D3D11_MAPPED_SUBRESOURCE,
D3D11_MAP_WRITE_DISCARD, D3D11_MAP_WRITE_DISCARD,
}; };
use librashader_runtime::quad::QuadType;
use crate::render_target::RenderTarget; use crate::render_target::RenderTarget;
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
@ -147,6 +148,7 @@ impl FilterPass {
original: &InputTexture, original: &InputTexture,
source: &InputTexture, source: &InputTexture,
output: RenderTarget, output: RenderTarget,
vbo_type: QuadType,
) -> error::Result<()> { ) -> error::Result<()> {
let _device = &parent.d3d11.device; let _device = &parent.d3d11.device;
let context = &parent.d3d11.current_context; let context = &parent.d3d11.current_context;
@ -158,7 +160,7 @@ impl FilterPass {
} }
} }
unsafe { unsafe {
parent.draw_quad.bind_vertices(); parent.draw_quad.bind_vertices(vbo_type);
context.IASetInputLayout(&self.vertex_layout); context.IASetInputLayout(&self.vertex_layout);
context.VSSetShader(&self.vertex_shader, None); context.VSSetShader(&self.vertex_shader, None);
context.PSSetShader(&self.pixel_shader, None); context.PSSetShader(&self.pixel_shader, None);

View file

@ -9,6 +9,7 @@ use windows::Win32::Graphics::Direct3D11::{
D3D11_USAGE_IMMUTABLE, D3D11_USAGE_IMMUTABLE,
}; };
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R32G32_FLOAT; use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R32G32_FLOAT;
use librashader_runtime::quad::QuadType;
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone, Default)] #[derive(Debug, Copy, Clone, Default)]
@ -20,7 +21,30 @@ struct D3D11Vertex {
const CLEAR: [f32; 4] = [1.0, 1.0, 1.0, 1.0]; const CLEAR: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
static QUAD_VBO_DATA: &[D3D11Vertex; 4] = &[ static OFFSCREEN_VBO_DATA: &[D3D11Vertex; 4] = &[
D3D11Vertex {
position: [-1.0, -1.0],
texcoord: [0.0, 1.0],
color: CLEAR,
},
D3D11Vertex {
position: [-1.0, 1.0],
texcoord: [0.0, 0.0],
color: CLEAR,
},
D3D11Vertex {
position: [1.0, -1.0],
texcoord: [1.0, 1.0],
color: CLEAR,
},
D3D11Vertex {
position: [1.0, 1.0],
texcoord: [1.0, 0.0],
color: CLEAR,
},
];
static FINAL_VBO_DATA: &[D3D11Vertex; 4] = &[
D3D11Vertex { D3D11Vertex {
position: [0.0, 0.0], position: [0.0, 0.0],
texcoord: [0.0, 1.0], texcoord: [0.0, 1.0],
@ -44,16 +68,17 @@ static QUAD_VBO_DATA: &[D3D11Vertex; 4] = &[
]; ];
pub(crate) struct DrawQuad { pub(crate) struct DrawQuad {
buffer: ID3D11Buffer, final_vbo: ID3D11Buffer,
context: ID3D11DeviceContext, context: ID3D11DeviceContext,
offset: u32, offset: u32,
stride: u32, stride: u32,
offscreen_vbo: ID3D11Buffer,
} }
impl DrawQuad { impl DrawQuad {
pub fn new(device: &ID3D11Device, context: &ID3D11DeviceContext) -> error::Result<DrawQuad> { pub fn new(device: &ID3D11Device, context: &ID3D11DeviceContext) -> error::Result<DrawQuad> {
unsafe { unsafe {
let mut buffer = None; let mut final_vbo = None;
device.CreateBuffer( device.CreateBuffer(
&D3D11_BUFFER_DESC { &D3D11_BUFFER_DESC {
ByteWidth: std::mem::size_of::<[D3D11Vertex; 4]>() as u32, ByteWidth: std::mem::size_of::<[D3D11Vertex; 4]>() as u32,
@ -64,16 +89,36 @@ impl DrawQuad {
StructureByteStride: 0, StructureByteStride: 0,
}, },
Some(&D3D11_SUBRESOURCE_DATA { Some(&D3D11_SUBRESOURCE_DATA {
pSysMem: QUAD_VBO_DATA.as_ptr().cast(), pSysMem: FINAL_VBO_DATA.as_ptr().cast(),
SysMemPitch: 0, SysMemPitch: 0,
SysMemSlicePitch: 0, SysMemSlicePitch: 0,
}), }),
Some(&mut buffer), Some(&mut final_vbo),
)?; )?;
assume_d3d11_init!(buffer, "CreateBuffer"); assume_d3d11_init!(final_vbo, "CreateBuffer");
let mut offscreen_vbo = None;
device.CreateBuffer(
&D3D11_BUFFER_DESC {
ByteWidth: std::mem::size_of::<[D3D11Vertex; 4]>() as u32,
Usage: D3D11_USAGE_IMMUTABLE,
BindFlags: D3D11_BIND_VERTEX_BUFFER,
CPUAccessFlags: Default::default(),
MiscFlags: Default::default(),
StructureByteStride: 0,
},
Some(&D3D11_SUBRESOURCE_DATA {
pSysMem: OFFSCREEN_VBO_DATA.as_ptr().cast(),
SysMemPitch: 0,
SysMemSlicePitch: 0,
}),
Some(&mut offscreen_vbo),
)?;
assume_d3d11_init!(offscreen_vbo, "CreateBuffer");
Ok(DrawQuad { Ok(DrawQuad {
buffer, final_vbo,
offscreen_vbo,
context: context.clone(), context: context.clone(),
offset: 0, offset: 0,
stride: std::mem::size_of::<D3D11Vertex>() as u32, stride: std::mem::size_of::<D3D11Vertex>() as u32,
@ -81,14 +126,19 @@ impl DrawQuad {
} }
} }
pub fn bind_vertices(&self) { pub fn bind_vertices(&self, vbo_type: QuadType) {
unsafe { unsafe {
self.context self.context
.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); .IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
let buffer = match vbo_type {
QuadType::Offscreen => &self.offscreen_vbo,
QuadType::Final => &self.final_vbo,
};
self.context.IASetVertexBuffers( self.context.IASetVertexBuffers(
0, 0,
1, 1,
Some(&Some(self.buffer.clone())), Some(&Some(buffer.clone())),
Some(&self.stride), Some(&self.stride),
Some(&self.offset), Some(&self.offset),
); );

View file

@ -2,14 +2,7 @@ use crate::framebuffer::OutputFramebuffer;
use crate::D3D11OutputView; use crate::D3D11OutputView;
use librashader_common::Viewport; use librashader_common::Viewport;
use windows::Win32::Graphics::Direct3D11::D3D11_VIEWPORT; use windows::Win32::Graphics::Direct3D11::D3D11_VIEWPORT;
use librashader_runtime::quad::DEFAULT_MVP;
#[rustfmt::skip]
static DEFAULT_MVP: &[f32; 16] = &[
2f32, 0.0, 0.0, 0.0,
0.0, 2.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
-1.0, -1.0, 0.0, 1.0,
];
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct RenderTarget<'a> { pub(crate) struct RenderTarget<'a> {

View file

@ -1,10 +1,20 @@
use std::sync::Arc;
use ash::vk;
use librashader_runtime::quad::QuadType;
use crate::error; use crate::error;
use crate::vulkan_primitives::VulkanBuffer; use crate::vulkan_primitives::VulkanBuffer;
use ash::vk;
use std::sync::Arc;
#[rustfmt::skip] #[rustfmt::skip]
pub(crate) static VBO_DEFAULT_FINAL: &[f32; 16] = &[ static VBO_OFFSCREEN: &[f32; 16] = &[
// Offscreen
-1.0, -1.0, 0.0, 0.0,
-1.0, 1.0, 0.0, 1.0,
1.0, -1.0, 1.0, 0.0,
1.0, 1.0, 1.0, 1.0,
];
#[rustfmt::skip]
static VBO_DEFAULT_FINAL: &[f32; 16] = &[
// Final // Final
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0,
@ -14,37 +24,34 @@ pub(crate) static VBO_DEFAULT_FINAL: &[f32; 16] = &[
pub struct DrawQuad { pub struct DrawQuad {
buffer: VulkanBuffer, buffer: VulkanBuffer,
device: Arc<ash::Device>, device: Arc<ash::Device>
} }
impl DrawQuad { impl DrawQuad {
pub fn new( pub fn new(device: &Arc<ash::Device>, mem_props: &vk::PhysicalDeviceMemoryProperties) -> error::Result<DrawQuad> {
device: &Arc<ash::Device>, let mut buffer = VulkanBuffer::new(device, mem_props, vk::BufferUsageFlags::VERTEX_BUFFER, 2 * std::mem::size_of::<[f32; 16]>())?;
mem_props: &vk::PhysicalDeviceMemoryProperties,
) -> error::Result<DrawQuad> {
let mut buffer = VulkanBuffer::new(
device,
mem_props,
vk::BufferUsageFlags::VERTEX_BUFFER,
std::mem::size_of::<[f32; 16]>(),
)?;
{ {
let mut map = buffer.map()?; let mut map = buffer.map()?;
unsafe { unsafe {
map.copy_from(0, bytemuck::cast_slice(VBO_DEFAULT_FINAL)); map.copy_from(0, bytemuck::cast_slice(VBO_OFFSCREEN));
map.copy_from(std::mem::size_of::<[f32; 16]>(), bytemuck::cast_slice(VBO_DEFAULT_FINAL));
} }
} }
Ok(DrawQuad { Ok(DrawQuad {
buffer, buffer,
device: device.clone(), device: device.clone()
}) })
} }
pub fn bind_vbo(&self, cmd: vk::CommandBuffer) { pub fn bind_vbo(&self, cmd: vk::CommandBuffer, vbo: QuadType) {
let offset = match vbo {
QuadType::Offscreen => 0,
QuadType::Final => std::mem::size_of::<[f32; 16]>()
};
unsafe { unsafe {
self.device self.device.cmd_bind_vertex_buffers(cmd, 0, &[self.buffer.handle], &[offset as vk::DeviceSize])
.cmd_bind_vertex_buffers(cmd, 0, &[self.buffer.handle], &[0])
} }
} }
} }

View file

@ -1,11 +1,11 @@
use crate::draw_quad::DrawQuad; use crate::draw_quad::{DrawQuad, QuadType};
use crate::error::FilterChainError; use crate::error::FilterChainError;
use crate::filter_pass::FilterPass; use crate::filter_pass::FilterPass;
use crate::framebuffer::OutputImage; use crate::framebuffer::OutputImage;
use crate::luts::LutTexture; use crate::luts::LutTexture;
use crate::options::{FilterChainOptionsVulkan, FrameOptionsVulkan}; use crate::options::{FilterChainOptionsVulkan, FrameOptionsVulkan};
use crate::queue_selection::get_graphics_queue; use crate::queue_selection::get_graphics_queue;
use crate::render_target::{RenderTarget, DEFAULT_MVP}; use crate::render_target::RenderTarget;
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
use crate::texture::{InputImage, OwnedImage, OwnedImageLayout, VulkanImage}; use crate::texture::{InputImage, OwnedImage, OwnedImageLayout, VulkanImage};
// use crate::ubo_ring::VkUboRing; // use crate::ubo_ring::VkUboRing;
@ -28,6 +28,7 @@ use rustc_hash::FxHashMap;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::path::Path; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use librashader_runtime::quad::{DEFAULT_MVP, IDENTITY_MVP};
/// A Vulkan device and metadata that is required by the shader runtime. /// A Vulkan device and metadata that is required by the shader runtime.
pub struct VulkanObjects { pub struct VulkanObjects {
@ -719,7 +720,7 @@ impl FilterChainVulkan {
let out = RenderTarget { let out = RenderTarget {
x: 0.0, x: 0.0,
y: 0.0, y: 0.0,
mvp: DEFAULT_MVP, mvp: IDENTITY_MVP,
output: OutputImage::new(&self.vulkan, target.image.clone())?, output: OutputImage::new(&self.vulkan, target.image.clone())?,
}; };
@ -737,6 +738,7 @@ impl FilterChainVulkan {
&original, &original,
&source, &source,
&out, &out,
QuadType::Offscreen
)?; )?;
if target.max_miplevels > 1 && !self.disable_mipmaps { if target.max_miplevels > 1 && !self.disable_mipmaps {
@ -774,6 +776,7 @@ impl FilterChainVulkan {
&original, &original,
&source, &source,
&out, &out,
QuadType::Final
)?; )?;
intermediates.dispose_outputs(out.output); intermediates.dispose_outputs(out.output);

View file

@ -17,6 +17,7 @@ use librashader_runtime::binding::{BindSemantics, TextureInput};
use librashader_runtime::uniforms::{NoUniformBinder, UniformStorage, UniformStorageAccess}; use librashader_runtime::uniforms::{NoUniformBinder, UniformStorage, UniformStorageAccess};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::sync::Arc; use std::sync::Arc;
use crate::draw_quad::QuadType;
pub struct FilterPass { pub struct FilterPass {
pub device: Arc<ash::Device>, pub device: Arc<ash::Device>,
@ -95,6 +96,7 @@ impl FilterPass {
original: &InputImage, original: &InputImage,
source: &InputImage, source: &InputImage,
output: &RenderTarget, output: &RenderTarget,
vbo_type: QuadType,
) -> error::Result<Option<vk::Framebuffer>> { ) -> error::Result<Option<vk::Framebuffer>> {
let mut descriptor = self.graphics_pipeline.layout.descriptor_sets let mut descriptor = self.graphics_pipeline.layout.descriptor_sets
[(frame_count % self.frames_in_flight) as usize]; [(frame_count % self.frames_in_flight) as usize];
@ -170,7 +172,7 @@ impl FilterPass {
); );
} }
parent.draw_quad.bind_vbo(cmd); parent.draw_quad.bind_vbo(cmd, vbo_type);
parent.device.cmd_set_scissor( parent.device.cmd_set_scissor(
cmd, cmd,

View file

@ -52,7 +52,7 @@ mod tests {
Some(&FilterChainOptionsVulkan { Some(&FilterChainOptionsVulkan {
frames_in_flight: 3, frames_in_flight: 3,
force_no_mipmaps: false, force_no_mipmaps: false,
use_render_pass: true, use_render_pass: false,
}), }),
) )
.unwrap(); .unwrap();

View file

@ -1,13 +1,5 @@
use crate::framebuffer::OutputImage; use crate::framebuffer::OutputImage;
#[rustfmt::skip]
pub(crate) static DEFAULT_MVP: &[f32; 16] = &[
2f32, 0.0, 0.0, 0.0,
0.0, 2.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
-1.0, -1.0, 0.0, 1.0,
];
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct RenderTarget<'a> { pub(crate) struct RenderTarget<'a> {
pub x: f32, pub x: f32,

View file

@ -25,3 +25,4 @@ pub mod ringbuffer;
/// Generic implementation of semantics binding. /// Generic implementation of semantics binding.
pub mod binding; pub mod binding;
pub mod quad;

View file

@ -0,0 +1,26 @@
/// Different type of quad to render to depending on pass type
pub enum QuadType {
/// Offscreen, intermediate passes.
Offscreen,
/// Final pass to render target.
Final
}
/// Identity MVP for use in intermediate passes.
#[rustfmt::skip]
pub static IDENTITY_MVP: &[f32; 16] = &[
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
];
/// Default MVP for use when rendering to the render target.
#[rustfmt::skip]
pub static DEFAULT_MVP: &[f32; 16] = &[
2f32, 0.0, 0.0, 0.0,
0.0, 2.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
-1.0, -1.0, 0.0, 1.0,
];