From 99954f011f437af0fb492d4fea647069c3f5d52d Mon Sep 17 00:00:00 2001 From: chyyran Date: Sun, 5 Feb 2023 23:18:13 -0500 Subject: [PATCH] dx12: fix mipmapping --- .../src/descriptor_heap.rs | 48 +++++++++--- librashader-runtime-d3d12/src/filter_chain.rs | 77 +++++++++---------- .../src/graphics_pipeline.rs | 41 +++++----- librashader-runtime-d3d12/src/mipmap.rs | 41 ++++++++-- 4 files changed, 134 insertions(+), 73 deletions(-) diff --git a/librashader-runtime-d3d12/src/descriptor_heap.rs b/librashader-runtime-d3d12/src/descriptor_heap.rs index 6c688a7..739c9a5 100644 --- a/librashader-runtime-d3d12/src/descriptor_heap.rs +++ b/librashader-runtime-d3d12/src/descriptor_heap.rs @@ -7,13 +7,7 @@ use std::ops::Deref; use std::rc::Rc; use crate::error::FilterChainError; -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, -}; +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}; #[const_trait] pub trait D3D12HeapType { @@ -169,6 +163,12 @@ impl D3D12DescriptorHeap { } impl D3D12DescriptorHeap { + /// 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( device: &ID3D12Device, desc: D3D12_DESCRIPTOR_HEAP_DESC, @@ -210,7 +210,8 @@ impl D3D12DescriptorHeap { pub unsafe fn suballocate( self, size: usize, - ) -> (Vec>, ID3D12DescriptorHeap) { + reserved: usize, + ) -> (Vec>, Option>, ID3D12DescriptorHeap) { // has to be called right after creation. assert_eq!( Rc::strong_count(&self.0), @@ -222,9 +223,11 @@ impl D3D12DescriptorHeap { .expect("[d3d12] undefined behaviour to suballocate a descriptor heap with live descriptors.") .into_inner(); + let num_descriptors = inner.num_descriptors - reserved; + // number of suballocated heaps - let num_heaps = inner.num_descriptors / size; - let remainder = inner.num_descriptors % size; + let num_heaps = num_descriptors / size; + let remainder = num_descriptors % size; assert_eq!( remainder, 0, @@ -259,6 +262,28 @@ impl D3D12DescriptorHeap { 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 .into_iter() @@ -266,6 +291,9 @@ impl D3D12DescriptorHeap { D3D12DescriptorHeap(Rc::new(RefCell::new(inner)), PhantomData::default()) }) .collect(), + reserved_heap.map(|inner| { + D3D12DescriptorHeap(Rc::new(RefCell::new(inner)), PhantomData::default()) + }), inner.heap, ) } diff --git a/librashader-runtime-d3d12/src/filter_chain.rs b/librashader-runtime-d3d12/src/filter_chain.rs index a121b4c..16dd164 100644 --- a/librashader-runtime-d3d12/src/filter_chain.rs +++ b/librashader-runtime-d3d12/src/filter_chain.rs @@ -47,6 +47,10 @@ use windows::Win32::System::Threading::{CreateEventA, ResetEvent, WaitForSingleO use windows::Win32::System::WindowsProgramming::INFINITE; use rayon::prelude::*; +use librashader_runtime::scaling::MipmapSize; + +const MIPMAP_RESERVED_WORKHEAP_DESCRIPTORS: usize = 1024; + type DxilShaderPassMeta = ShaderPassArtifact + Send>; type HlslShaderPassMeta = @@ -66,7 +70,7 @@ pub struct FilterChainD3D12 { staging_heap: D3D12DescriptorHeap, rtv_heap: D3D12DescriptorHeap, - texture_heap: ID3D12DescriptorHeap, + work_heap: ID3D12DescriptorHeap, sampler_heap: ID3D12DescriptorHeap, residuals: Vec, @@ -123,7 +127,7 @@ impl FilterChainD3D12 { )?; 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 mut staging_heap = D3D12DescriptorHeap::new( @@ -136,11 +140,11 @@ impl FilterChainD3D12 { )?; 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 (texture_heap, sampler_heap, filters) = FilterChainD3D12::init_passes( + let (texture_heap, sampler_heap, filters, mipmap_heap) = FilterChainD3D12::init_passes( device, &root_signature, passes, @@ -181,8 +185,6 @@ impl FilterChainD3D12 { let (history_framebuffers, history_textures) = FilterChainD3D12::init_history(device, &filters)?; - let mipmap_heap: D3D12DescriptorHeap = - D3D12DescriptorHeap::new(device, u16::MAX as usize)?; Ok(FilterChainD3D12 { common: FilterCommon { d3d12: device.clone(), @@ -209,7 +211,7 @@ impl FilterChainD3D12 { output_framebuffers: output_framebuffers.into_boxed_slice(), feedback_framebuffers: feedback_framebuffers.into_boxed_slice(), history_framebuffers, - texture_heap, + work_heap: texture_heap, sampler_heap, mipmap_heap, disable_mipmaps: options.map_or(false, |o| o.force_no_mipmaps), @@ -252,8 +254,9 @@ impl FilterChainD3D12 { device: &ID3D12Device, heap: &mut D3D12DescriptorHeap, textures: &[TextureConfig], - mipmap_gen: &D3D12MipmapGen, ) -> error::Result> { + // use separate mipgen to load luts. + let mipmap_gen = D3D12MipmapGen::new(device, true)?; let mut work_heap: D3D12DescriptorHeap = D3D12DescriptorHeap::new(device, u16::MAX as usize)?; unsafe { @@ -339,20 +342,20 @@ impl FilterChainD3D12 { hlsl_passes: Vec, semantics: &ShaderSemantics, force_hlsl: bool, - ) -> error::Result<(ID3D12DescriptorHeap, ID3D12DescriptorHeap, Vec)> { + ) -> error::Result<(ID3D12DescriptorHeap, ID3D12DescriptorHeap, Vec, D3D12DescriptorHeap)> { let shader_count = passes.len(); let work_heap = D3D12DescriptorHeap::::new( 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) = - unsafe { work_heap.suballocate(MAX_BINDINGS_COUNT as usize) }; + let (work_heaps, mipmap_heap, texture_heap_handle) = + unsafe { work_heap.suballocate(MAX_BINDINGS_COUNT as usize, MIPMAP_RESERVED_WORKHEAP_DESCRIPTORS) }; let sampler_work_heap = D3D12DescriptorHeap::new(device, (MAX_BINDINGS_COUNT as usize) * shader_count)?; - let (sampler_work_heaps, sampler_heap_handle) = - unsafe { sampler_work_heap.suballocate(MAX_BINDINGS_COUNT as usize) }; + let (sampler_work_heaps, _, sampler_heap_handle) = + unsafe { sampler_work_heap.suballocate(MAX_BINDINGS_COUNT as usize, 0) }; let filters: Vec> = passes.into_par_iter() .zip(hlsl_passes) @@ -468,7 +471,8 @@ impl FilterChainD3D12 { let filters: error::Result> = filters.into_iter().collect(); 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( @@ -595,32 +599,32 @@ impl FilterChainD3D12 { let (pass, last) = passes.split_at_mut(passes_len - 1); 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.SetGraphicsRootSignature(&self.common.root_signature.handle); + self.common.mipmap_gen.pin_root_signature(cmd); } for (index, pass) in pass.iter_mut().enumerate() { source.filter = pass.config.filter; source.wrap_mode = pass.config.wrap_mode; - // if pass.config.mipmap_input && !self.disable_mipmaps { - // unsafe { - // // this is so bad. - // self.common.mipmap_gen.mipmapping_context( - // cmd, - // &mut self.mipmap_heap, - // |ctx| { - // ctx.generate_mipmaps( - // &source.resource, - // source.size().calculate_miplevels() as u16, - // source.size, - // source.format, - // )?; - // Ok::<(), FilterChainError>(()) - // }, - // )?; - // } - // } + if pass.config.mipmap_input && !self.disable_mipmaps { + unsafe { + self.common.mipmap_gen.mipmapping_context( + cmd, + &mut self.mipmap_heap, + |ctx| { + ctx.generate_mipmaps( + &source.resource, + source.size().calculate_miplevels() as u16, + source.size, + source.format, + )?; + Ok::<(), FilterChainError>(()) + }, + )?; + } + } let target = &self.output_framebuffers[index]; util::d3d12_resource_transition( @@ -666,11 +670,6 @@ impl FilterChainD3D12 { 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); source = self.common.output_textures[index].as_ref().unwrap().clone() } diff --git a/librashader-runtime-d3d12/src/graphics_pipeline.rs b/librashader-runtime-d3d12/src/graphics_pipeline.rs index 8d6ef3d..d50ac06 100644 --- a/librashader-runtime-d3d12/src/graphics_pipeline.rs +++ b/librashader-runtime-d3d12/src/graphics_pipeline.rs @@ -8,25 +8,26 @@ use librashader_reflect::back::ShaderCompilerOutput; use librashader_reflect::reflect::semantics::BindingStage; use windows::Win32::Foundation::BOOL; 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}; pub struct D3D12GraphicsPipeline { pub(crate) handle: ID3D12PipelineState, } -const D3D12_SLANG_ROOT_PARAMETERS: &[D3D12_ROOT_PARAMETER; 4] = &[ +const D3D12_SLANG_ROOT_PARAMETERS: &[D3D12_ROOT_PARAMETER1; 4] = &[ // srvs - D3D12_ROOT_PARAMETER { + D3D12_ROOT_PARAMETER1 { ParameterType: D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, - Anonymous: D3D12_ROOT_PARAMETER_0 { - DescriptorTable: D3D12_ROOT_DESCRIPTOR_TABLE { + Anonymous: D3D12_ROOT_PARAMETER1_0 { + DescriptorTable: D3D12_ROOT_DESCRIPTOR_TABLE1 { NumDescriptorRanges: 1, - pDescriptorRanges: &D3D12_DESCRIPTOR_RANGE { + pDescriptorRanges: &D3D12_DESCRIPTOR_RANGE1 { RangeType: D3D12_DESCRIPTOR_RANGE_TYPE_SRV, NumDescriptors: 16, BaseShaderRegister: 0, RegisterSpace: 0, + Flags: D3D12_DESCRIPTOR_RANGE_FLAGS(D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE.0 | D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE.0), OffsetInDescriptorsFromTableStart: 0, }, }, @@ -34,16 +35,17 @@ const D3D12_SLANG_ROOT_PARAMETERS: &[D3D12_ROOT_PARAMETER; 4] = &[ ShaderVisibility: D3D12_SHADER_VISIBILITY_PIXEL, }, // samplers - D3D12_ROOT_PARAMETER { + D3D12_ROOT_PARAMETER1 { ParameterType: D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, - Anonymous: D3D12_ROOT_PARAMETER_0 { - DescriptorTable: D3D12_ROOT_DESCRIPTOR_TABLE { + Anonymous: D3D12_ROOT_PARAMETER1_0 { + DescriptorTable: D3D12_ROOT_DESCRIPTOR_TABLE1 { NumDescriptorRanges: 1, - pDescriptorRanges: &D3D12_DESCRIPTOR_RANGE { + pDescriptorRanges: &D3D12_DESCRIPTOR_RANGE1 { RangeType: D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, NumDescriptors: 16, BaseShaderRegister: 0, RegisterSpace: 0, + Flags: D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE, OffsetInDescriptorsFromTableStart: 0, }, }, @@ -51,22 +53,25 @@ const D3D12_SLANG_ROOT_PARAMETERS: &[D3D12_ROOT_PARAMETER; 4] = &[ ShaderVisibility: D3D12_SHADER_VISIBILITY_PIXEL, }, // UBO - D3D12_ROOT_PARAMETER { + D3D12_ROOT_PARAMETER1 { ParameterType: D3D12_ROOT_PARAMETER_TYPE_CBV, - Anonymous: D3D12_ROOT_PARAMETER_0 { - Descriptor: D3D12_ROOT_DESCRIPTOR { + Anonymous: D3D12_ROOT_PARAMETER1_0 { + Descriptor: D3D12_ROOT_DESCRIPTOR1 { ShaderRegister: 0, RegisterSpace: 0, + Flags: D3D12_ROOT_DESCRIPTOR_FLAG_NONE, }, }, ShaderVisibility: D3D12_SHADER_VISIBILITY_ALL, }, - D3D12_ROOT_PARAMETER { + // push + D3D12_ROOT_PARAMETER1 { ParameterType: D3D12_ROOT_PARAMETER_TYPE_CBV, - Anonymous: D3D12_ROOT_PARAMETER_0 { - Descriptor: D3D12_ROOT_DESCRIPTOR { + Anonymous: D3D12_ROOT_PARAMETER1_0 { + Descriptor: D3D12_ROOT_DESCRIPTOR1 { ShaderRegister: 1, RegisterSpace: 0, + Flags: D3D12_ROOT_DESCRIPTOR_FLAG_NONE, }, }, 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 { - Version: D3D_ROOT_SIGNATURE_VERSION_1_0, + Version: D3D_ROOT_SIGNATURE_VERSION_1_1, 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, pParameters: D3D12_SLANG_ROOT_PARAMETERS.as_ptr(), NumStaticSamplers: 0, diff --git a/librashader-runtime-d3d12/src/mipmap.rs b/librashader-runtime-d3d12/src/mipmap.rs index b9f449c..59c73d0 100644 --- a/librashader-runtime-d3d12/src/mipmap.rs +++ b/librashader-runtime-d3d12/src/mipmap.rs @@ -30,8 +30,8 @@ static GENERATE_MIPS_SRC: &[u8] = b" \" DENY_GEOMETRY_SHADER_ROOT_ACCESS |\" \\ \" DENY_HULL_SHADER_ROOT_ACCESS |\" \\ \" DENY_PIXEL_SHADER_ROOT_ACCESS ),\" \\ -\"DescriptorTable ( SRV(t0, flags=DATA_VOLATILE) ),\" \\ -\"DescriptorTable ( UAV(u0, flags=DATA_VOLATILE) ),\" \\ +\"DescriptorTable ( SRV(t0, flags=DATA_VOLATILE|DESCRIPTORS_VOLATILE) ),\" \\ +\"DescriptorTable ( UAV(u0, flags=DATA_VOLATILE|DESCRIPTORS_VOLATILE) ),\" \\ \"RootConstants(num32BitConstants=3, b0),\" \\ \"StaticSampler(s0,\"\\ \" filter = FILTER_MIN_MAG_LINEAR_MIP_POINT,\"\\ @@ -66,6 +66,8 @@ pub struct D3D12MipmapGen { device: ID3D12Device, root_signature: ID3D12RootSignature, pipeline: ID3D12PipelineState, + own_heaps: bool, + root_index_offset: usize, } #[derive(Copy, Clone, Zeroable, Pod)] @@ -121,7 +123,7 @@ impl<'a> MipmapGenContext<'a> { } impl D3D12MipmapGen { - pub fn new(device: &ID3D12Device) -> error::Result { + pub fn new(device: &ID3D12Device, own_heaps: bool) -> error::Result { unsafe { let blob = fxc_compile_shader(GENERATE_MIPS_SRC, b"main\0", b"cs_5_1\0")?; let blob = @@ -144,13 +146,29 @@ impl D3D12MipmapGen { device: device.clone(), root_signature, 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. - /// 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. + /// + /// 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( &self, cmd: &ID3D12GraphicsCommandList, @@ -162,9 +180,12 @@ impl D3D12MipmapGen { { let heap: ID3D12DescriptorHeap = (&(*work_heap)).into(); unsafe { - cmd.SetComputeRootSignature(&self.root_signature); 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); @@ -291,6 +312,14 @@ impl D3D12MipmapGen { D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, i, ); + + util::d3d12_resource_transition_subresource( + cmd, + resource, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + i - 1, + ); } Ok(heap_slots)