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 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<T: D3D12HeapType> 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(
device: &ID3D12Device,
desc: D3D12_DESCRIPTOR_HEAP_DESC,
@ -210,7 +210,8 @@ impl<T> D3D12DescriptorHeap<T> {
pub unsafe fn suballocate(
self,
size: usize,
) -> (Vec<D3D12DescriptorHeap<T>>, ID3D12DescriptorHeap) {
reserved: usize,
) -> (Vec<D3D12DescriptorHeap<T>>, Option<D3D12DescriptorHeap<T>>, ID3D12DescriptorHeap) {
// has to be called right after creation.
assert_eq!(
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.")
.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<T> D3D12DescriptorHeap<T> {
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<T> D3D12DescriptorHeap<T> {
D3D12DescriptorHeap(Rc::new(RefCell::new(inner)), PhantomData::default())
})
.collect(),
reserved_heap.map(|inner| {
D3D12DescriptorHeap(Rc::new(RefCell::new(inner)), PhantomData::default())
}),
inner.heap,
)
}

View file

@ -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<impl CompileReflectShader<DXIL, GlslangCompilation> + Send>;
type HlslShaderPassMeta =
@ -66,7 +70,7 @@ pub struct FilterChainD3D12 {
staging_heap: D3D12DescriptorHeap<CpuStagingHeap>,
rtv_heap: D3D12DescriptorHeap<RenderTargetHeap>,
texture_heap: ID3D12DescriptorHeap,
work_heap: ID3D12DescriptorHeap,
sampler_heap: ID3D12DescriptorHeap,
residuals: Vec<OutputDescriptor>,
@ -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<ResourceWorkHeap> =
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<CpuStagingHeap>,
textures: &[TextureConfig],
mipmap_gen: &D3D12MipmapGen,
) -> error::Result<FxHashMap<usize, LutTexture>> {
// use separate mipgen to load luts.
let mipmap_gen = D3D12MipmapGen::new(device, true)?;
let mut work_heap: D3D12DescriptorHeap<ResourceWorkHeap> =
D3D12DescriptorHeap::new(device, u16::MAX as usize)?;
unsafe {
@ -339,20 +342,20 @@ impl FilterChainD3D12 {
hlsl_passes: Vec<HlslShaderPassMeta>,
semantics: &ShaderSemantics,
force_hlsl: bool,
) -> error::Result<(ID3D12DescriptorHeap, ID3D12DescriptorHeap, Vec<FilterPass>)> {
) -> error::Result<(ID3D12DescriptorHeap, ID3D12DescriptorHeap, Vec<FilterPass>, D3D12DescriptorHeap<ResourceWorkHeap>)> {
let shader_count = passes.len();
let work_heap = D3D12DescriptorHeap::<ResourceWorkHeap>::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<error::Result<_>> = passes.into_par_iter()
.zip(hlsl_passes)
@ -468,7 +471,8 @@ impl FilterChainD3D12 {
let filters: error::Result<Vec<_>> = 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()
}

View file

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

View file

@ -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<D3D12MipmapGen> {
pub fn new(device: &ID3D12Device, own_heaps: bool) -> error::Result<D3D12MipmapGen> {
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<F, E>(
&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)