d3d12: bind logic

This commit is contained in:
chyyran 2023-01-31 19:23:57 -05:00 committed by Ronny Chan
parent 3506e1a3da
commit 10cd240868
5 changed files with 142 additions and 43 deletions

View file

@ -420,7 +420,8 @@ impl FilterChainD3D12 {
pipeline: graphics_pipeline,
config: config.clone(),
texture_heap,
sampler_heap
sampler_heap,
source,
})
}

View file

@ -1,13 +1,18 @@
use rustc_hash::FxHashMap;
use librashader_common::Size;
use windows::Win32::Graphics::Direct3D11::ID3D11Device;
use windows::Win32::Graphics::Direct3D12::ID3D12Device;
use librashader_common::{ImageFormat, Size};
use librashader_preprocess::ShaderSource;
use librashader_presets::ShaderPassConfig;
use librashader_reflect::reflect::semantics::{MemberOffset, UniformBinding};
use librashader_reflect::reflect::semantics::{MemberOffset, TextureBinding, UniformBinding};
use librashader_reflect::reflect::ShaderReflection;
use librashader_runtime::binding::TextureInput;
use librashader_runtime::binding::{BindSemantics, TextureInput};
use librashader_runtime::uniforms::UniformStorage;
use crate::buffer::D3D12ConstantBuffer;
use crate::filter_chain::FilterCommon;
use crate::graphics_pipeline::D3D12GraphicsPipeline;
use crate::heap::{D3D12DescriptorHeap, ResourceWorkHeap, SamplerWorkHeap};
use crate::heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot, ResourceWorkHeap, SamplerWorkHeap};
use crate::samplers::SamplerSet;
use crate::texture::InputTexture;
pub(crate) struct FilterPass {
@ -20,6 +25,8 @@ pub(crate) struct FilterPass {
pub(crate) ubo_cbuffer: Option<D3D12ConstantBuffer>,
pub(crate) texture_heap: D3D12DescriptorHeap<ResourceWorkHeap>,
pub(crate) sampler_heap: D3D12DescriptorHeap<SamplerWorkHeap>,
pub source: ShaderSource,
}
impl TextureInput for InputTexture {
@ -27,3 +34,88 @@ impl TextureInput for InputTexture {
self.size
}
}
//
impl BindSemantics for FilterPass {
type InputTexture = InputTexture;
type SamplerSet = SamplerSet;
type DescriptorSet<'a> =
(
&'a mut [D3D12DescriptorHeapSlot<ResourceWorkHeap>; 16],
&'a mut [D3D12DescriptorHeapSlot<SamplerWorkHeap>; 16],
);
type DeviceContext = ();
type UniformOffset = MemberOffset;
fn bind_texture<'a>(
descriptors: &mut Self::DescriptorSet<'a>,
samplers: &Self::SamplerSet,
binding: &TextureBinding,
texture: &Self::InputTexture,
_device: &Self::DeviceContext,
) {
let (texture_binding,
sampler_binding) = descriptors;
unsafe {
texture_binding[binding.binding as usize]
.copy_descriptor(*texture.descriptor.as_ref());
sampler_binding[binding.binding as usize]
.copy_descriptor(*samplers.get(texture.wrap_mode, texture.filter).as_ref())
}
}
}
impl FilterPass {
pub fn get_format(&self) -> ImageFormat {
let fb_format = self.source.format;
if let Some(format) = self.config.get_format_override() {
format
} else if fb_format == ImageFormat::Unknown {
ImageFormat::R8G8B8A8Unorm
} else {
fb_format
}
}
// framecount should be pre-modded
fn build_semantics<'a>(
&mut self,
pass_index: usize,
parent: &FilterCommon,
mvp: &[f32; 16],
frame_count: u32,
frame_direction: i32,
fb_size: Size<u32>,
viewport_size: Size<u32>,
mut descriptors: (
&'a mut [D3D12DescriptorHeapSlot<ResourceWorkHeap>; 16],
&'a mut [D3D12DescriptorHeapSlot<SamplerWorkHeap>; 16],
),
original: &InputTexture,
source: &InputTexture,
) {
Self::bind_semantics(
&(),
&parent.samplers,
&mut self.uniform_storage,
&mut descriptors,
mvp,
frame_count,
frame_direction,
fb_size,
viewport_size,
original,
source,
&self.uniform_bindings,
&self.reflection.meta.texture_meta,
parent.output_textures[0..pass_index]
.iter()
.map(|o| o.as_ref()),
parent.feedback_textures.iter().map(|o| o.as_ref()),
parent.history_textures.iter().map(|o| o.as_ref()),
parent.luts.iter().map(|(u, i)| (*u, i.as_ref())),
&self.source.parameters,
&parent.config.parameters,
);
}
}

View file

@ -1,6 +1,7 @@
use crate::error;
use std::cell::RefCell;
use std::marker::PhantomData;
use std::ops::Deref;
use std::sync::Arc;
use windows::Win32::Graphics::Direct3D12::{ID3D12DescriptorHeap, ID3D12Device, D3D12_CPU_DESCRIPTOR_HANDLE, D3D12_DESCRIPTOR_HEAP_DESC, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_GPU_DESCRIPTOR_HANDLE, D3D12_DESCRIPTOR_HEAP_TYPE};
@ -22,7 +23,6 @@ pub struct ResourceWorkHeap;
#[derive(Clone)]
pub struct SamplerWorkHeap;
impl const D3D12HeapType for SamplerPaletteHeap {
// sampler palettes just get set directly
fn get_desc(size: usize) -> D3D12_DESCRIPTOR_HEAP_DESC {
@ -87,6 +87,21 @@ impl<T> D3D12DescriptorHeapSlot<T> {
pub fn index(&self) -> usize {
self.slot
}
/// unsafe because type must match
pub unsafe fn copy_descriptor(&mut self, source: D3D12_CPU_DESCRIPTOR_HANDLE) {
unsafe {
let heap = self.heap.deref()
.borrow();
heap.device.CopyDescriptorsSimple(
1,
self.cpu_handle,
source,
heap.ty
)
}
}
}
impl<T> AsRef<D3D12_CPU_DESCRIPTOR_HANDLE> for D3D12DescriptorHeapSlot<T> {
@ -258,23 +273,8 @@ impl<T> D3D12DescriptorHeap<T> {
todo!("error need to fail");
}
pub fn copy_descriptors<const NUM_DESC: usize>(&mut self,
source: &[&D3D12_CPU_DESCRIPTOR_HANDLE; NUM_DESC])
-> error::Result<[D3D12DescriptorHeapSlot<T>; NUM_DESC]> {
pub fn alloc_range<const NUM_DESC: usize>(&mut self)-> error::Result<[D3D12DescriptorHeapSlot<T>; NUM_DESC]> {
let dest = array_init::try_array_init(|_| self.alloc_slot())?;
let inner = self.0.borrow_mut();
unsafe {
// unfortunately we can't guarantee that the source and dest descriptors are contiguous so...
for i in 0..NUM_DESC {
inner.device.CopyDescriptorsSimple(
1,
*dest[i].as_ref(),
*source[i],
inner.ty
);
}
}
Ok(dest)
}
}

View file

@ -13,10 +13,7 @@ use crate::texture::InputTexture;
pub struct LutTexture {
resource: ID3D12Resource,
descriptor: D3D12DescriptorHeapSlot<CpuStagingHeap>,
size: Size<u32>,
filter: FilterMode,
wrap_mode: WrapMode,
view: InputTexture,
miplevels: Option<u16>,
}
@ -160,12 +157,16 @@ impl LutTexture {
d3d12_resource_transition(cmd, &resource, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)
}
let view = InputTexture::new(
descriptor,
source.size,
ImageFormat::R8G8B8A8Unorm,
wrap_mode,
filter,
);
Ok((LutTexture {
resource,
descriptor,
size: source.size,
filter,
wrap_mode,
view,
miplevels: if mipmap { Some(miplevels) } else { None }
}, upload))
}
@ -174,16 +175,15 @@ impl LutTexture {
if let Some(miplevels) = self.miplevels {
gen_mips.generate_mipmaps(&self.resource,
miplevels,
self.size, ImageFormat::R8G8B8A8Unorm.into())?
self.view.size, ImageFormat::R8G8B8A8Unorm.into())?
}
Ok(())
}
pub fn as_input(&self)
-> InputTexture {
InputTexture::new(self.descriptor.clone(),
self.size, ImageFormat::R8G8B8A8Unorm,
self.wrap_mode, self.filter)
}
}
impl AsRef<InputTexture> for LutTexture {
fn as_ref(&self) -> &InputTexture {
&self.view
}
}

View file

@ -2,12 +2,12 @@ use windows::Win32::Graphics::Direct3D12::{D3D12_CPU_DESCRIPTOR_HANDLE};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use crate::heap::{CpuStagingHeap, D3D12DescriptorHeapSlot};
enum InputDescriptor {
pub(crate) enum InputDescriptor {
Owned(D3D12DescriptorHeapSlot<CpuStagingHeap>),
Raw(D3D12_CPU_DESCRIPTOR_HANDLE)
}
enum OutputDescriptor {
pub(crate) enum OutputDescriptor {
Owned(D3D12DescriptorHeapSlot<CpuStagingHeap>),
Raw(D3D12_CPU_DESCRIPTOR_HANDLE)
}
@ -59,11 +59,11 @@ impl OutputTexture {
}
pub struct InputTexture {
descriptor: InputDescriptor,
pub(crate) descriptor: InputDescriptor,
pub(crate) size: Size<u32>,
format: ImageFormat,
wrap_mode: WrapMode,
filter: FilterMode
pub(crate) wrap_mode: WrapMode,
pub(crate) filter: FilterMode
}
impl InputTexture {
@ -100,3 +100,9 @@ impl InputTexture {
}
}
impl AsRef<InputTexture> for InputTexture {
fn as_ref(&self) -> &InputTexture {
self
}
}