dx12: fix mipmapping

This commit is contained in:
chyyran 2023-02-05 23:18:13 -05:00
parent 1fe4b47981
commit 99954f011f
4 changed files with 134 additions and 73 deletions

View file

@ -7,13 +7,7 @@ use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use crate::error::FilterChainError; use crate::error::FilterChainError;
use windows::Win32::Graphics::Direct3D12::{ 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, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_GPU_DESCRIPTOR_HANDLE, ID3D12Resource};
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, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
D3D12_GPU_DESCRIPTOR_HANDLE,
};
#[const_trait] #[const_trait]
pub trait D3D12HeapType { pub trait D3D12HeapType {
@ -169,6 +163,12 @@ impl<T: D3D12HeapType> D3D12DescriptorHeap<T> {
} }
impl<T> D3D12DescriptorHeap<T> { impl<T> D3D12DescriptorHeap<T> {
/// Gets a cloned handle to the inner heap
pub fn handle(&self) -> ID3D12DescriptorHeap {
let inner = self.0.borrow();
inner.heap.clone()
}
pub unsafe fn new_with_desc( pub unsafe fn new_with_desc(
device: &ID3D12Device, device: &ID3D12Device,
desc: D3D12_DESCRIPTOR_HEAP_DESC, desc: D3D12_DESCRIPTOR_HEAP_DESC,
@ -210,7 +210,8 @@ impl<T> D3D12DescriptorHeap<T> {
pub unsafe fn suballocate( pub unsafe fn suballocate(
self, self,
size: usize, size: usize,
) -> (Vec<D3D12DescriptorHeap<T>>, ID3D12DescriptorHeap) { reserved: usize,
) -> (Vec<D3D12DescriptorHeap<T>>, Option<D3D12DescriptorHeap<T>>, ID3D12DescriptorHeap) {
// has to be called right after creation. // has to be called right after creation.
assert_eq!( assert_eq!(
Rc::strong_count(&self.0), Rc::strong_count(&self.0),
@ -222,9 +223,11 @@ impl<T> D3D12DescriptorHeap<T> {
.expect("[d3d12] undefined behaviour to suballocate a descriptor heap with live descriptors.") .expect("[d3d12] undefined behaviour to suballocate a descriptor heap with live descriptors.")
.into_inner(); .into_inner();
let num_descriptors = inner.num_descriptors - reserved;
// number of suballocated heaps // number of suballocated heaps
let num_heaps = inner.num_descriptors / size; let num_heaps = num_descriptors / size;
let remainder = inner.num_descriptors % size; let remainder = num_descriptors % size;
assert_eq!( assert_eq!(
remainder, 0, remainder, 0,
@ -259,6 +262,28 @@ impl<T> D3D12DescriptorHeap<T> {
start += size; start += size;
} }
let mut reserved_heap = None;
if reserved != 0 {
assert_eq!(reserved, inner.num_descriptors - start, "The input heap could not fit the number of requested reserved descriptors.");
let new_cpu_start = root_cpu_ptr + (start * inner.handle_size);
let new_gpu_start = root_gpu_ptr.map(|r| D3D12_GPU_DESCRIPTOR_HANDLE {
ptr: r + (start as u64 * inner.handle_size as u64),
});
reserved_heap = Some(D3D12DescriptorHeapInner {
device: inner.device.clone(),
heap: inner.heap.clone(),
ty: inner.ty,
cpu_start: D3D12_CPU_DESCRIPTOR_HANDLE { ptr: new_cpu_start },
gpu_start: new_gpu_start,
handle_size: inner.handle_size,
start: 0,
num_descriptors: reserved,
map: bitvec![0; reserved].into_boxed_bitslice(),
});
}
( (
heaps heaps
.into_iter() .into_iter()
@ -266,6 +291,9 @@ impl<T> D3D12DescriptorHeap<T> {
D3D12DescriptorHeap(Rc::new(RefCell::new(inner)), PhantomData::default()) D3D12DescriptorHeap(Rc::new(RefCell::new(inner)), PhantomData::default())
}) })
.collect(), .collect(),
reserved_heap.map(|inner| {
D3D12DescriptorHeap(Rc::new(RefCell::new(inner)), PhantomData::default())
}),
inner.heap, inner.heap,
) )
} }

View file

@ -47,6 +47,10 @@ use windows::Win32::System::Threading::{CreateEventA, ResetEvent, WaitForSingleO
use windows::Win32::System::WindowsProgramming::INFINITE; use windows::Win32::System::WindowsProgramming::INFINITE;
use rayon::prelude::*; use rayon::prelude::*;
use librashader_runtime::scaling::MipmapSize;
const MIPMAP_RESERVED_WORKHEAP_DESCRIPTORS: usize = 1024;
type DxilShaderPassMeta = type DxilShaderPassMeta =
ShaderPassArtifact<impl CompileReflectShader<DXIL, GlslangCompilation> + Send>; ShaderPassArtifact<impl CompileReflectShader<DXIL, GlslangCompilation> + Send>;
type HlslShaderPassMeta = type HlslShaderPassMeta =
@ -66,7 +70,7 @@ pub struct FilterChainD3D12 {
staging_heap: D3D12DescriptorHeap<CpuStagingHeap>, staging_heap: D3D12DescriptorHeap<CpuStagingHeap>,
rtv_heap: D3D12DescriptorHeap<RenderTargetHeap>, rtv_heap: D3D12DescriptorHeap<RenderTargetHeap>,
texture_heap: ID3D12DescriptorHeap, work_heap: ID3D12DescriptorHeap,
sampler_heap: ID3D12DescriptorHeap, sampler_heap: ID3D12DescriptorHeap,
residuals: Vec<OutputDescriptor>, residuals: Vec<OutputDescriptor>,
@ -123,7 +127,7 @@ impl FilterChainD3D12 {
)?; )?;
let samplers = SamplerSet::new(device)?; let samplers = SamplerSet::new(device)?;
let mipmap_gen = D3D12MipmapGen::new(device)?; let mipmap_gen = D3D12MipmapGen::new(device, false)?;
let draw_quad = DrawQuad::new(device)?; let draw_quad = DrawQuad::new(device)?;
let mut staging_heap = D3D12DescriptorHeap::new( let mut staging_heap = D3D12DescriptorHeap::new(
@ -136,11 +140,11 @@ impl FilterChainD3D12 {
)?; )?;
let luts = let luts =
FilterChainD3D12::load_luts(device, &mut staging_heap, &preset.textures, &mipmap_gen)?; FilterChainD3D12::load_luts(device, &mut staging_heap, &preset.textures)?;
let root_signature = D3D12RootSignature::new(device)?; let root_signature = D3D12RootSignature::new(device)?;
let (texture_heap, sampler_heap, filters) = FilterChainD3D12::init_passes( let (texture_heap, sampler_heap, filters, mipmap_heap) = FilterChainD3D12::init_passes(
device, device,
&root_signature, &root_signature,
passes, passes,
@ -181,8 +185,6 @@ impl FilterChainD3D12 {
let (history_framebuffers, history_textures) = let (history_framebuffers, history_textures) =
FilterChainD3D12::init_history(device, &filters)?; FilterChainD3D12::init_history(device, &filters)?;
let mipmap_heap: D3D12DescriptorHeap<ResourceWorkHeap> =
D3D12DescriptorHeap::new(device, u16::MAX as usize)?;
Ok(FilterChainD3D12 { Ok(FilterChainD3D12 {
common: FilterCommon { common: FilterCommon {
d3d12: device.clone(), d3d12: device.clone(),
@ -209,7 +211,7 @@ impl FilterChainD3D12 {
output_framebuffers: output_framebuffers.into_boxed_slice(), output_framebuffers: output_framebuffers.into_boxed_slice(),
feedback_framebuffers: feedback_framebuffers.into_boxed_slice(), feedback_framebuffers: feedback_framebuffers.into_boxed_slice(),
history_framebuffers, history_framebuffers,
texture_heap, work_heap: texture_heap,
sampler_heap, sampler_heap,
mipmap_heap, mipmap_heap,
disable_mipmaps: options.map_or(false, |o| o.force_no_mipmaps), disable_mipmaps: options.map_or(false, |o| o.force_no_mipmaps),
@ -252,8 +254,9 @@ impl FilterChainD3D12 {
device: &ID3D12Device, device: &ID3D12Device,
heap: &mut D3D12DescriptorHeap<CpuStagingHeap>, heap: &mut D3D12DescriptorHeap<CpuStagingHeap>,
textures: &[TextureConfig], textures: &[TextureConfig],
mipmap_gen: &D3D12MipmapGen,
) -> error::Result<FxHashMap<usize, LutTexture>> { ) -> error::Result<FxHashMap<usize, LutTexture>> {
// use separate mipgen to load luts.
let mipmap_gen = D3D12MipmapGen::new(device, true)?;
let mut work_heap: D3D12DescriptorHeap<ResourceWorkHeap> = let mut work_heap: D3D12DescriptorHeap<ResourceWorkHeap> =
D3D12DescriptorHeap::new(device, u16::MAX as usize)?; D3D12DescriptorHeap::new(device, u16::MAX as usize)?;
unsafe { unsafe {
@ -339,20 +342,20 @@ impl FilterChainD3D12 {
hlsl_passes: Vec<HlslShaderPassMeta>, hlsl_passes: Vec<HlslShaderPassMeta>,
semantics: &ShaderSemantics, semantics: &ShaderSemantics,
force_hlsl: bool, force_hlsl: bool,
) -> error::Result<(ID3D12DescriptorHeap, ID3D12DescriptorHeap, Vec<FilterPass>)> { ) -> error::Result<(ID3D12DescriptorHeap, ID3D12DescriptorHeap, Vec<FilterPass>, D3D12DescriptorHeap<ResourceWorkHeap>)> {
let shader_count = passes.len(); let shader_count = passes.len();
let work_heap = D3D12DescriptorHeap::<ResourceWorkHeap>::new( let work_heap = D3D12DescriptorHeap::<ResourceWorkHeap>::new(
device, device,
(MAX_BINDINGS_COUNT as usize) * shader_count, (MAX_BINDINGS_COUNT as usize) * shader_count + MIPMAP_RESERVED_WORKHEAP_DESCRIPTORS,
)?; )?;
let (work_heaps, texture_heap_handle) = let (work_heaps, mipmap_heap, texture_heap_handle) =
unsafe { work_heap.suballocate(MAX_BINDINGS_COUNT as usize) }; unsafe { work_heap.suballocate(MAX_BINDINGS_COUNT as usize, MIPMAP_RESERVED_WORKHEAP_DESCRIPTORS) };
let sampler_work_heap = let sampler_work_heap =
D3D12DescriptorHeap::new(device, (MAX_BINDINGS_COUNT as usize) * shader_count)?; D3D12DescriptorHeap::new(device, (MAX_BINDINGS_COUNT as usize) * shader_count)?;
let (sampler_work_heaps, sampler_heap_handle) = let (sampler_work_heaps, _, sampler_heap_handle) =
unsafe { sampler_work_heap.suballocate(MAX_BINDINGS_COUNT as usize) }; unsafe { sampler_work_heap.suballocate(MAX_BINDINGS_COUNT as usize, 0) };
let filters: Vec<error::Result<_>> = passes.into_par_iter() let filters: Vec<error::Result<_>> = passes.into_par_iter()
.zip(hlsl_passes) .zip(hlsl_passes)
@ -468,7 +471,8 @@ impl FilterChainD3D12 {
let filters: error::Result<Vec<_>> = filters.into_iter().collect(); let filters: error::Result<Vec<_>> = filters.into_iter().collect();
let filters = filters?; let filters = filters?;
Ok((texture_heap_handle, sampler_heap_handle, filters)) // Panic SAFETY: mipmap_heap is always 1024 descriptors.
Ok((texture_heap_handle, sampler_heap_handle, filters, mipmap_heap.unwrap()))
} }
fn push_history( fn push_history(
@ -595,32 +599,32 @@ impl FilterChainD3D12 {
let (pass, last) = passes.split_at_mut(passes_len - 1); let (pass, last) = passes.split_at_mut(passes_len - 1);
unsafe { unsafe {
let heaps = [self.texture_heap.clone(), self.sampler_heap.clone()]; let heaps = [self.work_heap.clone(), self.sampler_heap.clone()];
cmd.SetDescriptorHeaps(&heaps); cmd.SetDescriptorHeaps(&heaps);
cmd.SetGraphicsRootSignature(&self.common.root_signature.handle); cmd.SetGraphicsRootSignature(&self.common.root_signature.handle);
self.common.mipmap_gen.pin_root_signature(cmd);
} }
for (index, pass) in pass.iter_mut().enumerate() { for (index, pass) in pass.iter_mut().enumerate() {
source.filter = pass.config.filter; source.filter = pass.config.filter;
source.wrap_mode = pass.config.wrap_mode; source.wrap_mode = pass.config.wrap_mode;
// if pass.config.mipmap_input && !self.disable_mipmaps { if pass.config.mipmap_input && !self.disable_mipmaps {
// unsafe { unsafe {
// // this is so bad. self.common.mipmap_gen.mipmapping_context(
// self.common.mipmap_gen.mipmapping_context( cmd,
// cmd, &mut self.mipmap_heap,
// &mut self.mipmap_heap, |ctx| {
// |ctx| { ctx.generate_mipmaps(
// ctx.generate_mipmaps( &source.resource,
// &source.resource, source.size().calculate_miplevels() as u16,
// source.size().calculate_miplevels() as u16, source.size,
// source.size, source.format,
// source.format, )?;
// )?; Ok::<(), FilterChainError>(())
// Ok::<(), FilterChainError>(()) },
// }, )?;
// )?; }
// } }
// }
let target = &self.output_framebuffers[index]; let target = &self.output_framebuffers[index];
util::d3d12_resource_transition( util::d3d12_resource_transition(
@ -666,11 +670,6 @@ impl FilterChainD3D12 {
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
); );
// let target_handle = target.create_shader_resource_view(
// &mut self.staging_heap,
// pass.config.filter,
// pass.config.wrap_mode,
// )?;
self.residuals.push(out.output.descriptor); self.residuals.push(out.output.descriptor);
source = self.common.output_textures[index].as_ref().unwrap().clone() source = self.common.output_textures[index].as_ref().unwrap().clone()
} }

View file

@ -8,25 +8,26 @@ use librashader_reflect::back::ShaderCompilerOutput;
use librashader_reflect::reflect::semantics::BindingStage; use librashader_reflect::reflect::semantics::BindingStage;
use windows::Win32::Foundation::BOOL; use windows::Win32::Foundation::BOOL;
use windows::Win32::Graphics::Direct3D::Dxc::{IDxcBlob, IDxcCompiler, IDxcUtils, IDxcValidator}; use windows::Win32::Graphics::Direct3D::Dxc::{IDxcBlob, IDxcCompiler, IDxcUtils, IDxcValidator};
use windows::Win32::Graphics::Direct3D12::{ID3D12Device, ID3D12PipelineState, ID3D12RootSignature, D3D12_BLEND_DESC, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, D3D12_BLEND_SRC_ALPHA, D3D12_COLOR_WRITE_ENABLE_ALL, D3D12_CULL_MODE_NONE, D3D12_DESCRIPTOR_RANGE, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, D3D12_FILL_MODE_SOLID, D3D12_GRAPHICS_PIPELINE_STATE_DESC, D3D12_INPUT_LAYOUT_DESC, D3D12_LOGIC_OP_NOOP, D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, D3D12_RASTERIZER_DESC, D3D12_RENDER_TARGET_BLEND_DESC, D3D12_ROOT_DESCRIPTOR, D3D12_ROOT_DESCRIPTOR_TABLE, D3D12_ROOT_PARAMETER, D3D12_ROOT_PARAMETER_0, D3D12_ROOT_PARAMETER_TYPE_CBV, D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, D3D12_ROOT_SIGNATURE_DESC, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT, D3D12_SHADER_BYTECODE, D3D12_SHADER_VISIBILITY_ALL, D3D12_SHADER_VISIBILITY_PIXEL, D3D_ROOT_SIGNATURE_VERSION_1, D3D12SerializeVersionedRootSignature, D3D12_VERSIONED_ROOT_SIGNATURE_DESC, D3D_ROOT_SIGNATURE_VERSION_1_0, D3D12_VERSIONED_ROOT_SIGNATURE_DESC_0}; use windows::Win32::Graphics::Direct3D12::{ID3D12Device, ID3D12PipelineState, ID3D12RootSignature, D3D12_BLEND_DESC, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, D3D12_BLEND_SRC_ALPHA, D3D12_COLOR_WRITE_ENABLE_ALL, D3D12_CULL_MODE_NONE, D3D12_DESCRIPTOR_RANGE, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, D3D12_FILL_MODE_SOLID, D3D12_GRAPHICS_PIPELINE_STATE_DESC, D3D12_INPUT_LAYOUT_DESC, D3D12_LOGIC_OP_NOOP, D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, D3D12_RASTERIZER_DESC, D3D12_RENDER_TARGET_BLEND_DESC, D3D12_ROOT_DESCRIPTOR, D3D12_ROOT_DESCRIPTOR_TABLE, D3D12_ROOT_PARAMETER, D3D12_ROOT_PARAMETER_0, D3D12_ROOT_PARAMETER_TYPE_CBV, D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, D3D12_ROOT_SIGNATURE_DESC, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT, D3D12_SHADER_BYTECODE, D3D12_SHADER_VISIBILITY_ALL, D3D12_SHADER_VISIBILITY_PIXEL, D3D_ROOT_SIGNATURE_VERSION_1, D3D12SerializeVersionedRootSignature, D3D12_VERSIONED_ROOT_SIGNATURE_DESC, D3D_ROOT_SIGNATURE_VERSION_1_0, D3D12_VERSIONED_ROOT_SIGNATURE_DESC_0, D3D_ROOT_SIGNATURE_VERSION_1_1, D3D12_ROOT_SIGNATURE_DESC1, D3D12_ROOT_PARAMETER1, D3D12_ROOT_PARAMETER1_0, D3D12_ROOT_DESCRIPTOR1, D3D12_ROOT_DESCRIPTOR_TABLE1, D3D12_DESCRIPTOR_RANGE1, D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE, D3D12_DESCRIPTOR_RANGE_FLAG_NONE, D3D12_ROOT_DESCRIPTOR_FLAG_NONE, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE, D3D12_DESCRIPTOR_RANGE_FLAGS};
use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_FORMAT_UNKNOWN, DXGI_SAMPLE_DESC}; use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_FORMAT_UNKNOWN, DXGI_SAMPLE_DESC};
pub struct D3D12GraphicsPipeline { pub struct D3D12GraphicsPipeline {
pub(crate) handle: ID3D12PipelineState, pub(crate) handle: ID3D12PipelineState,
} }
const D3D12_SLANG_ROOT_PARAMETERS: &[D3D12_ROOT_PARAMETER; 4] = &[ const D3D12_SLANG_ROOT_PARAMETERS: &[D3D12_ROOT_PARAMETER1; 4] = &[
// srvs // srvs
D3D12_ROOT_PARAMETER { D3D12_ROOT_PARAMETER1 {
ParameterType: D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, ParameterType: D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
Anonymous: D3D12_ROOT_PARAMETER_0 { Anonymous: D3D12_ROOT_PARAMETER1_0 {
DescriptorTable: D3D12_ROOT_DESCRIPTOR_TABLE { DescriptorTable: D3D12_ROOT_DESCRIPTOR_TABLE1 {
NumDescriptorRanges: 1, NumDescriptorRanges: 1,
pDescriptorRanges: &D3D12_DESCRIPTOR_RANGE { pDescriptorRanges: &D3D12_DESCRIPTOR_RANGE1 {
RangeType: D3D12_DESCRIPTOR_RANGE_TYPE_SRV, RangeType: D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
NumDescriptors: 16, NumDescriptors: 16,
BaseShaderRegister: 0, BaseShaderRegister: 0,
RegisterSpace: 0, RegisterSpace: 0,
Flags: D3D12_DESCRIPTOR_RANGE_FLAGS(D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE.0 | D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE.0),
OffsetInDescriptorsFromTableStart: 0, OffsetInDescriptorsFromTableStart: 0,
}, },
}, },
@ -34,16 +35,17 @@ const D3D12_SLANG_ROOT_PARAMETERS: &[D3D12_ROOT_PARAMETER; 4] = &[
ShaderVisibility: D3D12_SHADER_VISIBILITY_PIXEL, ShaderVisibility: D3D12_SHADER_VISIBILITY_PIXEL,
}, },
// samplers // samplers
D3D12_ROOT_PARAMETER { D3D12_ROOT_PARAMETER1 {
ParameterType: D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, ParameterType: D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
Anonymous: D3D12_ROOT_PARAMETER_0 { Anonymous: D3D12_ROOT_PARAMETER1_0 {
DescriptorTable: D3D12_ROOT_DESCRIPTOR_TABLE { DescriptorTable: D3D12_ROOT_DESCRIPTOR_TABLE1 {
NumDescriptorRanges: 1, NumDescriptorRanges: 1,
pDescriptorRanges: &D3D12_DESCRIPTOR_RANGE { pDescriptorRanges: &D3D12_DESCRIPTOR_RANGE1 {
RangeType: D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, RangeType: D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
NumDescriptors: 16, NumDescriptors: 16,
BaseShaderRegister: 0, BaseShaderRegister: 0,
RegisterSpace: 0, RegisterSpace: 0,
Flags: D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE,
OffsetInDescriptorsFromTableStart: 0, OffsetInDescriptorsFromTableStart: 0,
}, },
}, },
@ -51,22 +53,25 @@ const D3D12_SLANG_ROOT_PARAMETERS: &[D3D12_ROOT_PARAMETER; 4] = &[
ShaderVisibility: D3D12_SHADER_VISIBILITY_PIXEL, ShaderVisibility: D3D12_SHADER_VISIBILITY_PIXEL,
}, },
// UBO // UBO
D3D12_ROOT_PARAMETER { D3D12_ROOT_PARAMETER1 {
ParameterType: D3D12_ROOT_PARAMETER_TYPE_CBV, ParameterType: D3D12_ROOT_PARAMETER_TYPE_CBV,
Anonymous: D3D12_ROOT_PARAMETER_0 { Anonymous: D3D12_ROOT_PARAMETER1_0 {
Descriptor: D3D12_ROOT_DESCRIPTOR { Descriptor: D3D12_ROOT_DESCRIPTOR1 {
ShaderRegister: 0, ShaderRegister: 0,
RegisterSpace: 0, RegisterSpace: 0,
Flags: D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
}, },
}, },
ShaderVisibility: D3D12_SHADER_VISIBILITY_ALL, ShaderVisibility: D3D12_SHADER_VISIBILITY_ALL,
}, },
D3D12_ROOT_PARAMETER { // push
D3D12_ROOT_PARAMETER1 {
ParameterType: D3D12_ROOT_PARAMETER_TYPE_CBV, ParameterType: D3D12_ROOT_PARAMETER_TYPE_CBV,
Anonymous: D3D12_ROOT_PARAMETER_0 { Anonymous: D3D12_ROOT_PARAMETER1_0 {
Descriptor: D3D12_ROOT_DESCRIPTOR { Descriptor: D3D12_ROOT_DESCRIPTOR1 {
ShaderRegister: 1, ShaderRegister: 1,
RegisterSpace: 0, RegisterSpace: 0,
Flags: D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
}, },
}, },
ShaderVisibility: D3D12_SHADER_VISIBILITY_ALL, ShaderVisibility: D3D12_SHADER_VISIBILITY_ALL,
@ -74,9 +79,9 @@ const D3D12_SLANG_ROOT_PARAMETERS: &[D3D12_ROOT_PARAMETER; 4] = &[
]; ];
const D3D12_SLANG_VERSIONED_ROOT_SIGNATURE: &D3D12_VERSIONED_ROOT_SIGNATURE_DESC = &D3D12_VERSIONED_ROOT_SIGNATURE_DESC { const D3D12_SLANG_VERSIONED_ROOT_SIGNATURE: &D3D12_VERSIONED_ROOT_SIGNATURE_DESC = &D3D12_VERSIONED_ROOT_SIGNATURE_DESC {
Version: D3D_ROOT_SIGNATURE_VERSION_1_0, Version: D3D_ROOT_SIGNATURE_VERSION_1_1,
Anonymous: D3D12_VERSIONED_ROOT_SIGNATURE_DESC_0 { Anonymous: D3D12_VERSIONED_ROOT_SIGNATURE_DESC_0 {
Desc_1_0: D3D12_ROOT_SIGNATURE_DESC { Desc_1_1: D3D12_ROOT_SIGNATURE_DESC1 {
NumParameters: D3D12_SLANG_ROOT_PARAMETERS.len() as u32, NumParameters: D3D12_SLANG_ROOT_PARAMETERS.len() as u32,
pParameters: D3D12_SLANG_ROOT_PARAMETERS.as_ptr(), pParameters: D3D12_SLANG_ROOT_PARAMETERS.as_ptr(),
NumStaticSamplers: 0, NumStaticSamplers: 0,

View file

@ -30,8 +30,8 @@ static GENERATE_MIPS_SRC: &[u8] = b"
\" DENY_GEOMETRY_SHADER_ROOT_ACCESS |\" \\ \" DENY_GEOMETRY_SHADER_ROOT_ACCESS |\" \\
\" DENY_HULL_SHADER_ROOT_ACCESS |\" \\ \" DENY_HULL_SHADER_ROOT_ACCESS |\" \\
\" DENY_PIXEL_SHADER_ROOT_ACCESS ),\" \\ \" DENY_PIXEL_SHADER_ROOT_ACCESS ),\" \\
\"DescriptorTable ( SRV(t0, flags=DATA_VOLATILE) ),\" \\ \"DescriptorTable ( SRV(t0, flags=DATA_VOLATILE|DESCRIPTORS_VOLATILE) ),\" \\
\"DescriptorTable ( UAV(u0, flags=DATA_VOLATILE) ),\" \\ \"DescriptorTable ( UAV(u0, flags=DATA_VOLATILE|DESCRIPTORS_VOLATILE) ),\" \\
\"RootConstants(num32BitConstants=3, b0),\" \\ \"RootConstants(num32BitConstants=3, b0),\" \\
\"StaticSampler(s0,\"\\ \"StaticSampler(s0,\"\\
\" filter = FILTER_MIN_MAG_LINEAR_MIP_POINT,\"\\ \" filter = FILTER_MIN_MAG_LINEAR_MIP_POINT,\"\\
@ -66,6 +66,8 @@ pub struct D3D12MipmapGen {
device: ID3D12Device, device: ID3D12Device,
root_signature: ID3D12RootSignature, root_signature: ID3D12RootSignature,
pipeline: ID3D12PipelineState, pipeline: ID3D12PipelineState,
own_heaps: bool,
root_index_offset: usize,
} }
#[derive(Copy, Clone, Zeroable, Pod)] #[derive(Copy, Clone, Zeroable, Pod)]
@ -121,7 +123,7 @@ impl<'a> MipmapGenContext<'a> {
} }
impl D3D12MipmapGen { impl D3D12MipmapGen {
pub fn new(device: &ID3D12Device) -> error::Result<D3D12MipmapGen> { pub fn new(device: &ID3D12Device, own_heaps: bool) -> error::Result<D3D12MipmapGen> {
unsafe { unsafe {
let blob = fxc_compile_shader(GENERATE_MIPS_SRC, b"main\0", b"cs_5_1\0")?; let blob = fxc_compile_shader(GENERATE_MIPS_SRC, b"main\0", b"cs_5_1\0")?;
let blob = let blob =
@ -144,13 +146,29 @@ impl D3D12MipmapGen {
device: device.clone(), device: device.clone(),
root_signature, root_signature,
pipeline, pipeline,
own_heaps,
root_index_offset: 0
}) })
} }
} }
/// If own_heap is false, this sets the compute root signature.
/// Otherwise, this does nothing and the root signature is set upon entering a
/// Mipmapping Context
pub fn pin_root_signature(&self, cmd: &ID3D12GraphicsCommandList) {
if !self.own_heaps {
unsafe {
cmd.SetComputeRootSignature(&self.root_signature);
}
}
}
/// Enters a mipmapping compute context. /// Enters a mipmapping compute context.
/// This is a relatively expensive operation /// This is a relatively expensive operation if set_heap is true,
/// and should only be done at most a few times per frame. /// and should only be done at most a few times per frame.
///
/// If own_heap is false, then you must ensure that the compute root signature
/// is already bound before entering the context.
pub fn mipmapping_context<F, E>( pub fn mipmapping_context<F, E>(
&self, &self,
cmd: &ID3D12GraphicsCommandList, cmd: &ID3D12GraphicsCommandList,
@ -162,9 +180,12 @@ impl D3D12MipmapGen {
{ {
let heap: ID3D12DescriptorHeap = (&(*work_heap)).into(); let heap: ID3D12DescriptorHeap = (&(*work_heap)).into();
unsafe { unsafe {
cmd.SetComputeRootSignature(&self.root_signature);
cmd.SetPipelineState(&self.pipeline); cmd.SetPipelineState(&self.pipeline);
cmd.SetDescriptorHeaps(&[heap]);
if self.own_heaps {
cmd.SetComputeRootSignature(&self.root_signature);
cmd.SetDescriptorHeaps(&[heap]);
}
} }
let mut context = MipmapGenContext::new(self, cmd, work_heap); let mut context = MipmapGenContext::new(self, cmd, work_heap);
@ -291,6 +312,14 @@ impl D3D12MipmapGen {
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
i, i,
); );
util::d3d12_resource_transition_subresource(
cmd,
resource,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
i - 1,
);
} }
Ok(heap_slots) Ok(heap_slots)