rt(d3d12): use gpu_allocator instead of CreateCommittedResource

This commit is contained in:
chyyran 2024-08-25 01:24:05 -04:00 committed by Ronny Chan
parent e90c27ebbd
commit 2e7c3b3273
9 changed files with 267 additions and 150 deletions

3
Cargo.lock generated
View file

@ -1265,6 +1265,7 @@ dependencies = [
"log",
"presser",
"thiserror",
"windows 0.58.0",
]
[[package]]
@ -1774,6 +1775,7 @@ dependencies = [
"bitvec",
"bytemuck",
"gfx-maths",
"gpu-allocator 0.27.0",
"librashader-cache",
"librashader-common",
"librashader-preprocess",
@ -1781,6 +1783,7 @@ dependencies = [
"librashader-reflect",
"librashader-runtime",
"mach-siegbert-vogt-dxcsa",
"parking_lot",
"rayon",
"thiserror",
"widestring",

View file

@ -29,6 +29,8 @@ array-concat = "0.5.2"
mach-siegbert-vogt-dxcsa = "0.1.3"
rayon = "1.6.1"
gpu-allocator = { version = "0.27.0", features = ["d3d12"], default-features = false}
parking_lot = "0.12.3"
[target.'cfg(windows)'.dependencies.windows]
workspace = true

View file

@ -1,19 +1,25 @@
use crate::error;
use crate::error::assume_d3d12_init;
use gpu_allocator::d3d12::{
Allocator, Resource, ResourceCategory, ResourceCreateDesc, ResourceStateOrBarrierLayout,
ResourceType,
};
use gpu_allocator::MemoryLocation;
use parking_lot::Mutex;
use std::ffi::c_void;
use std::mem::ManuallyDrop;
use std::ops::{Deref, DerefMut, Range};
use std::ptr::NonNull;
use std::sync::Arc;
use windows::Win32::Graphics::Direct3D12::{
ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
D3D12_HEAP_FLAG_NONE, D3D12_HEAP_PROPERTIES, D3D12_HEAP_TYPE_UPLOAD, D3D12_MEMORY_POOL_UNKNOWN,
D3D12_RANGE, D3D12_RESOURCE_DESC, D3D12_RESOURCE_DIMENSION_BUFFER,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
ID3D12GraphicsCommandList, ID3D12Resource, D3D12_RANGE, D3D12_RESOURCE_DESC,
D3D12_RESOURCE_DIMENSION_BUFFER, D3D12_RESOURCE_STATE_GENERIC_READ,
D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
};
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
pub struct D3D12Buffer {
handle: ID3D12Resource,
resource: ManuallyDrop<Resource>,
allocator: Arc<Mutex<Allocator>>,
size: usize,
}
@ -28,51 +34,51 @@ impl<'a> Drop for D3D12BufferMapHandle<'a> {
}
}
impl D3D12Buffer {
pub fn new(device: &ID3D12Device, size: usize) -> error::Result<D3D12Buffer> {
unsafe {
let mut buffer: Option<ID3D12Resource> = None;
device.CreateCommittedResource(
&D3D12_HEAP_PROPERTIES {
Type: D3D12_HEAP_TYPE_UPLOAD,
CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
..Default::default()
},
D3D12_HEAP_FLAG_NONE,
&D3D12_RESOURCE_DESC {
Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
Width: size as u64,
Height: 1,
DepthOrArraySize: 1,
MipLevels: 1,
Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
SampleDesc: DXGI_SAMPLE_DESC {
Count: 1,
Quality: 0,
},
..Default::default()
},
D3D12_RESOURCE_STATE_GENERIC_READ,
None,
&mut buffer,
)?;
assume_d3d12_init!(buffer, "CreateCommittedResource");
Ok(D3D12Buffer {
handle: buffer,
size,
})
impl Drop for D3D12Buffer {
fn drop(&mut self) {
let resource = unsafe { ManuallyDrop::take(&mut self.resource) };
if let Err(e) = self.allocator.lock().free_resource(resource) {
println!("librashader-runtime-d3d12: [warn] failed to deallocate buffer memory {e}")
}
}
}
impl D3D12Buffer {
pub fn new(allocator: &Arc<Mutex<Allocator>>, size: usize) -> error::Result<D3D12Buffer> {
let resource = allocator.lock().create_resource(&ResourceCreateDesc {
name: "d3d12buffer",
memory_location: MemoryLocation::CpuToGpu,
resource_category: ResourceCategory::Buffer,
resource_desc: &D3D12_RESOURCE_DESC {
Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
Width: size as u64,
Height: 1,
DepthOrArraySize: 1,
MipLevels: 1,
Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
SampleDesc: DXGI_SAMPLE_DESC {
Count: 1,
Quality: 0,
},
..Default::default()
},
castable_formats: &[],
clear_value: None,
initial_state_or_layout: ResourceStateOrBarrierLayout::ResourceState(
D3D12_RESOURCE_STATE_GENERIC_READ,
),
resource_type: &ResourceType::Placed,
})?;
Ok(Self {
resource: ManuallyDrop::new(resource),
size,
allocator: Arc::clone(&allocator),
})
}
pub fn gpu_address(&self) -> u64 {
unsafe { self.handle.GetGPUVirtualAddress() }
}
pub fn into_raw(self) -> ID3D12Resource {
self.handle
unsafe { self.resource.resource().GetGPUVirtualAddress() }
}
pub fn map(&mut self, range: Option<Range<usize>>) -> error::Result<D3D12BufferMapHandle> {
@ -88,10 +94,12 @@ impl D3D12Buffer {
unsafe {
let mut ptr = std::ptr::null_mut();
self.handle.Map(0, Some(&range), Some(&mut ptr))?;
self.resource
.resource()
.Map(0, Some(&range), Some(&mut ptr))?;
let slice = std::slice::from_raw_parts_mut(ptr.cast(), size);
Ok(D3D12BufferMapHandle {
handle: &self.handle,
handle: &self.resource.resource(),
slice,
})
}
@ -115,7 +123,10 @@ impl RawD3D12Buffer {
let range = D3D12_RANGE { Begin: 0, End: 0 };
let mut ptr = std::ptr::null_mut();
unsafe {
buffer.handle.Map(0, Some(&range), Some(&mut ptr))?;
buffer
.resource
.resource()
.Map(0, Some(&range), Some(&mut ptr))?;
}
// panic-safety: If Map returns Ok then ptr is not null
@ -134,7 +145,7 @@ impl RawD3D12Buffer {
impl Drop for RawD3D12Buffer {
fn drop(&mut self) {
unsafe {
self.buffer.handle.Unmap(0, None);
self.buffer.resource.resource().Unmap(0, None);
ManuallyDrop::drop(&mut self.buffer);
}
}

View file

@ -2,11 +2,14 @@ use crate::buffer::D3D12Buffer;
use crate::error;
use array_concat::concat_arrays;
use bytemuck::offset_of;
use gpu_allocator::d3d12::Allocator;
use librashader_runtime::quad::{QuadType, VertexInput};
use parking_lot::Mutex;
use std::sync::Arc;
use windows::core::PCSTR;
use windows::Win32::Graphics::Direct3D::D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
use windows::Win32::Graphics::Direct3D12::{
ID3D12Device, ID3D12GraphicsCommandList, ID3D12GraphicsCommandList4, ID3D12Resource,
ID3D12GraphicsCommandList, ID3D12GraphicsCommandList4,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, D3D12_INPUT_ELEMENT_DESC, D3D12_VERTEX_BUFFER_VIEW,
};
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R32G32_FLOAT;
@ -52,15 +55,15 @@ const FINAL_VBO_DATA: [VertexInput; 4] = [
static VBO_DATA: &[VertexInput; 8] = &concat_arrays!(OFFSCREEN_VBO_DATA, FINAL_VBO_DATA);
pub(crate) struct DrawQuad {
_buffer: ID3D12Resource,
_buffer: D3D12Buffer,
view: D3D12_VERTEX_BUFFER_VIEW,
}
impl DrawQuad {
pub fn new(device: &ID3D12Device) -> error::Result<DrawQuad> {
pub fn new(allocator: &Arc<Mutex<Allocator>>) -> error::Result<DrawQuad> {
let stride = std::mem::size_of::<VertexInput>() as u32;
let size = 2 * std::mem::size_of::<[VertexInput; 4]>() as u32;
let mut buffer = D3D12Buffer::new(device, size as usize)?;
let mut buffer = D3D12Buffer::new(allocator, size as usize)?;
buffer
.map(None)?
.slice
@ -72,7 +75,6 @@ impl DrawQuad {
StrideInBytes: stride,
};
let buffer = buffer.into_raw();
Ok(DrawQuad {
_buffer: buffer,
view,

View file

@ -5,7 +5,7 @@ use thiserror::Error;
/// Cumulative error type for Direct3D12 filter chains.
#[derive(Error, Debug)]
pub enum FilterChainError {
#[error("invariant assumption about d3d11 did not hold. report this as an issue.")]
#[error("invariant assumption about d3d12 did not hold. report this as an issue.")]
Direct3DOperationError(&'static str),
#[error("direct3d driver error")]
Direct3DError(#[from] windows::core::Error),
@ -21,6 +21,8 @@ pub enum FilterChainError {
LutLoadError(#[from] ImageError),
#[error("heap overflow")]
DescriptorHeapOverflow(usize),
#[error("allocation error")]
AllocationError(#[from] gpu_allocator::AllocationError),
}
/// Result type for Direct3D 12 filter chains.

View file

@ -14,6 +14,7 @@ use crate::options::{FilterChainOptionsD3D12, FrameOptionsD3D12};
use crate::samplers::SamplerSet;
use crate::texture::{D3D12InputImage, D3D12OutputView, InputTexture, OutputDescriptor};
use crate::{error, util};
use gpu_allocator::d3d12::{Allocator, AllocatorCreateDesc, ID3D12DeviceVersion};
use librashader_common::map::FastHashMap;
use librashader_common::{ImageFormat, Size, Viewport};
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
@ -27,9 +28,11 @@ use librashader_runtime::binding::{BindingUtil, TextureInput};
use librashader_runtime::image::{Image, ImageError, UVDirection};
use librashader_runtime::quad::QuadType;
use librashader_runtime::uniforms::UniformStorage;
use parking_lot::Mutex;
use std::collections::VecDeque;
use std::mem::ManuallyDrop;
use std::path::Path;
use std::sync::Arc;
use windows::core::Interface;
use windows::Win32::Foundation::CloseHandle;
use windows::Win32::Graphics::Direct3D::Dxc::{
@ -93,6 +96,7 @@ pub(crate) struct FilterCommon {
pub mipmap_gen: D3D12MipmapGen,
pub root_signature: D3D12RootSignature,
pub draw_quad: DrawQuad,
allocator: Arc<Mutex<Allocator>>,
}
pub(crate) struct FrameResiduals {
@ -275,7 +279,13 @@ impl FilterChainD3D12 {
let samplers = SamplerSet::new(device)?;
let mipmap_gen = D3D12MipmapGen::new(device, false)?;
let draw_quad = DrawQuad::new(device)?;
let allocator = Arc::new(Mutex::new(Allocator::new(&AllocatorCreateDesc {
device: ID3D12DeviceVersion::Device(device.clone()),
debug_settings: Default::default(),
allocation_sizes: Default::default(),
})?));
let draw_quad = DrawQuad::new(&allocator)?;
let mut staging_heap = D3D12DescriptorHeap::new(
device,
(MAX_BINDINGS_COUNT as usize) * shader_count
@ -294,6 +304,7 @@ impl FilterChainD3D12 {
let (texture_heap, sampler_heap, filters, mut mipmap_heap) = FilterChainD3D12::init_passes(
device,
&root_signature,
&allocator,
passes,
hlsl_passes,
&semantics,
@ -306,6 +317,7 @@ impl FilterChainD3D12 {
let luts = FilterChainD3D12::load_luts(
device,
cmd,
&allocator,
&mut staging_heap,
&mut mipmap_heap,
&mut residuals,
@ -315,6 +327,7 @@ impl FilterChainD3D12 {
let framebuffer_gen = || {
OwnedImage::new(
device,
&allocator,
Size::new(1, 1),
ImageFormat::R8G8B8A8Unorm.into(),
false,
@ -341,6 +354,7 @@ impl FilterChainD3D12 {
common: FilterCommon {
d3d12: device.clone(),
samplers,
allocator: allocator,
output_textures,
feedback_textures,
luts,
@ -375,6 +389,7 @@ impl FilterChainD3D12 {
fn load_luts(
device: &ID3D12Device,
cmd: &ID3D12GraphicsCommandList,
allocator: &Arc<Mutex<Allocator>>,
staging_heap: &mut D3D12DescriptorHeap<CpuStagingHeap>,
mipmap_heap: &mut D3D12DescriptorHeap<ResourceWorkHeap>,
gc: &mut FrameResiduals,
@ -392,6 +407,7 @@ impl FilterChainD3D12 {
for (index, (texture, image)) in textures.iter().zip(images).enumerate() {
let texture = LutTexture::new(
device,
allocator,
staging_heap,
cmd,
&image,
@ -425,6 +441,7 @@ impl FilterChainD3D12 {
fn init_passes(
device: &ID3D12Device,
root_signature: &D3D12RootSignature,
allocator: &Arc<Mutex<Allocator>>,
passes: Vec<DxilShaderPassMeta>,
hlsl_passes: Vec<HlslShaderPassMeta>,
semantics: &ShaderSemantics,
@ -535,8 +552,8 @@ impl FilterChainD3D12 {
.map_or(1, |push| push.size as usize);
let uniform_storage = UniformStorage::new_with_storage(
RawD3D12Buffer::new(D3D12Buffer::new(device, ubo_size)?)?,
RawD3D12Buffer::new(D3D12Buffer::new(device, push_size)?)?,
RawD3D12Buffer::new(D3D12Buffer::new(allocator, ubo_size)?)?,
RawD3D12Buffer::new(D3D12Buffer::new(allocator, push_size)?)?,
);
let uniform_bindings =
@ -584,7 +601,13 @@ impl FilterChainD3D12 {
// old back will get dropped.. do we need to defer?
let _old_back = std::mem::replace(
&mut back,
OwnedImage::new(&self.common.d3d12, input.size, input.format, false)?,
OwnedImage::new(
&self.common.d3d12,
&self.common.allocator,
input.size,
input.format,
false,
)?,
);
}
unsafe {
@ -731,7 +754,7 @@ impl FilterChainD3D12 {
util::d3d12_resource_transition(
cmd,
&target.handle,
&target.handle.resource(),
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_RENDER_TARGET,
);
@ -754,7 +777,7 @@ impl FilterChainD3D12 {
util::d3d12_resource_transition(
cmd,
&target.handle,
&target.handle.resource(),
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
);
@ -765,7 +788,7 @@ impl FilterChainD3D12 {
&mut self.mipmap_heap,
|ctx| {
ctx.generate_mipmaps(
&target.handle,
&target.handle.resource(),
target.max_mipmap,
target.size,
target.format.into(),

View file

@ -1,22 +1,27 @@
use crate::descriptor_heap::{CpuStagingHeap, D3D12DescriptorHeap, RenderTargetHeap};
use crate::error::{assume_d3d12_init, FilterChainError};
use crate::error::FilterChainError;
use crate::filter_chain::FrameResiduals;
use crate::texture::{D3D12OutputView, InputTexture};
use crate::util::d3d12_get_closest_format;
use crate::{error, util};
use gpu_allocator::d3d12::{
Allocator, Resource, ResourceCategory, ResourceCreateDesc, ResourceStateOrBarrierLayout,
ResourceType,
};
use gpu_allocator::MemoryLocation;
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_presets::Scale2D;
use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize};
use parking_lot::Mutex;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::sync::Arc;
use windows::Win32::Graphics::Direct3D12::{
ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_BOX,
D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
ID3D12Device, ID3D12GraphicsCommandList, D3D12_BOX, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FORMAT_SUPPORT1_MIP,
D3D12_FORMAT_SUPPORT1_RENDER_TARGET, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE,
D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD,
D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE, D3D12_HEAP_FLAG_NONE, D3D12_HEAP_PROPERTIES,
D3D12_HEAP_TYPE_DEFAULT, D3D12_MEMORY_POOL_UNKNOWN, D3D12_RENDER_TARGET_VIEW_DESC,
D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE, D3D12_RENDER_TARGET_VIEW_DESC,
D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_DESC,
D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST,
@ -28,13 +33,14 @@ use windows::Win32::Graphics::Direct3D12::{
};
use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_SAMPLE_DESC};
#[derive(Debug, Clone)]
#[derive(Debug)]
pub(crate) struct OwnedImage {
pub(crate) handle: ID3D12Resource,
pub(crate) handle: ManuallyDrop<Resource>,
pub(crate) size: Size<u32>,
pub(crate) format: DXGI_FORMAT,
pub(crate) max_mipmap: u16,
device: ID3D12Device,
allocator: Arc<Mutex<Allocator>>,
}
static CLEAR: &[f32; 4] = &[0.0, 0.0, 0.0, 0.0];
@ -64,6 +70,7 @@ impl OwnedImage {
pub fn new(
device: &ID3D12Device,
allocator: &Arc<Mutex<Allocator>>,
size: Size<u32>,
format: DXGI_FORMAT,
mipmap: bool,
@ -105,31 +112,46 @@ impl OwnedImage {
}
desc.Format = d3d12_get_closest_format(device, format_support);
let mut resource: Option<ID3D12Resource> = None;
unsafe {
device.CreateCommittedResource(
&D3D12_HEAP_PROPERTIES {
Type: D3D12_HEAP_TYPE_DEFAULT,
CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
CreationNodeMask: 1,
VisibleNodeMask: 1,
},
D3D12_HEAP_FLAG_NONE,
&desc,
let resource = allocator.lock().create_resource(&ResourceCreateDesc {
name: "ownedimage",
memory_location: MemoryLocation::GpuOnly,
resource_category: ResourceCategory::RtvDsvTexture,
resource_desc: &desc,
castable_formats: &[],
clear_value: None,
initial_state_or_layout: ResourceStateOrBarrierLayout::ResourceState(
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
None,
&mut resource,
)?;
}
assume_d3d12_init!(resource, "CreateCommittedResource");
),
resource_type: &ResourceType::Placed,
})?;
// let mut resource: Option<ID3D12Resource> = None;
// unsafe {
// device.CreateCommittedResource(
// &D3D12_HEAP_PROPERTIES {
// Type: D3D12_HEAP_TYPE_DEFAULT,
// CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
// MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
// CreationNodeMask: 1,
// VisibleNodeMask: 1,
// },
// D3D12_HEAP_FLAG_NONE,
// &desc,
// D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
// None,
// &mut resource,
// )?;
// }
// assume_d3d12_init!(resource, "CreateCommittedResource");
Ok(OwnedImage {
handle: resource,
handle: ManuallyDrop::new(resource),
size,
format: desc.Format,
device: device.clone(),
max_mipmap: miplevels as u16,
allocator: Arc::clone(&allocator),
})
}
@ -149,7 +171,7 @@ impl OwnedImage {
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
),
util::d3d12_get_resource_transition_subresource(
&self.handle,
&self.handle.resource(),
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
@ -160,7 +182,7 @@ impl OwnedImage {
cmd.ResourceBarrier(&barriers);
let dst = D3D12_TEXTURE_COPY_LOCATION {
pResource: ManuallyDrop::new(Some(self.handle.clone())),
pResource: ManuallyDrop::new(Some(self.handle.resource().clone())),
Type: D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
SubresourceIndex: 0,
@ -203,7 +225,7 @@ impl OwnedImage {
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
),
util::d3d12_get_resource_transition_subresource(
&self.handle,
&self.handle.resource(),
D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
@ -224,7 +246,7 @@ impl OwnedImage {
) -> error::Result<()> {
util::d3d12_resource_transition(
cmd,
&self.handle,
&self.handle.resource(),
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_RENDER_TARGET,
);
@ -235,7 +257,7 @@ impl OwnedImage {
util::d3d12_resource_transition(
cmd,
&self.handle,
&self.handle.resource(),
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
);
@ -265,14 +287,14 @@ impl OwnedImage {
};
self.device.CreateShaderResourceView(
&self.handle,
self.handle.resource(),
Some(&srv_desc),
*descriptor.deref().as_ref(),
);
}
Ok(InputTexture::new(
self.handle.clone(),
self.handle.resource().clone(),
descriptor,
self.size,
self.format,
@ -300,7 +322,7 @@ impl OwnedImage {
};
self.device.CreateRenderTargetView(
&self.handle,
self.handle.resource(),
Some(&rtv_desc),
*descriptor.deref().as_ref(),
);
@ -330,7 +352,7 @@ impl OwnedImage {
|| (!mipmap && self.max_mipmap != 1)
|| format != self.format
{
let mut new = OwnedImage::new(&self.device, size, format, mipmap)?;
let mut new = OwnedImage::new(&self.device, &self.allocator, size, format, mipmap)?;
std::mem::swap(self, &mut new);
}
Ok(size)
@ -361,3 +383,12 @@ impl ScaleFramebuffer for OwnedImage {
)
}
}
impl Drop for OwnedImage {
fn drop(&mut self) {
let resource = unsafe { ManuallyDrop::take(&mut self.handle) };
if let Err(e) = self.allocator.lock().free_resource(resource) {
println!("librashader-runtime-d3d12: [warn] failed to deallocate owned image buffer memory {e}")
}
}
}

View file

@ -1,20 +1,25 @@
use crate::descriptor_heap::{CpuStagingHeap, D3D12DescriptorHeap};
use crate::error;
use crate::error::assume_d3d12_init;
use crate::filter_chain::FrameResiduals;
use crate::mipmap::MipmapGenContext;
use crate::texture::InputTexture;
use crate::util::{d3d12_get_closest_format, d3d12_resource_transition, d3d12_update_subresources};
use gpu_allocator::d3d12::{
Allocator, Resource, ResourceCategory, ResourceCreateDesc, ResourceStateOrBarrierLayout,
ResourceType,
};
use gpu_allocator::MemoryLocation;
use librashader_common::{FilterMode, ImageFormat, WrapMode};
use librashader_runtime::image::Image;
use librashader_runtime::scaling::MipmapSize;
use parking_lot::Mutex;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::sync::Arc;
use windows::Win32::Graphics::Direct3D12::{
ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_FEATURE_DATA_FORMAT_SUPPORT,
D3D12_FORMAT_SUPPORT1_MIP, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE,
D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_HEAP_FLAG_NONE, D3D12_HEAP_PROPERTIES,
D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_TYPE_UPLOAD, D3D12_MEMORY_POOL_UNKNOWN,
ID3D12Device, ID3D12GraphicsCommandList, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FORMAT_SUPPORT1_MIP,
D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE, D3D12_FORMAT_SUPPORT1_TEXTURE2D,
D3D12_PLACED_SUBRESOURCE_FOOTPRINT, D3D12_RESOURCE_DESC, D3D12_RESOURCE_DIMENSION_BUFFER,
D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ,
@ -25,15 +30,19 @@ use windows::Win32::Graphics::Direct3D12::{
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
pub struct LutTexture {
resource: ID3D12Resource,
resource: ManuallyDrop<Resource>,
view: InputTexture,
miplevels: Option<u16>,
_staging: ID3D12Resource,
// Staging heap needs to be kept alive until the command list is submitted, which is
// really annoying. We could probably do better but it's safer to keep it around.
staging: ManuallyDrop<Resource>,
allocator: Arc<Mutex<Allocator>>,
}
impl LutTexture {
pub(crate) fn new(
device: &ID3D12Device,
allocator: &Arc<Mutex<Allocator>>,
heap: &mut D3D12DescriptorHeap<CpuStagingHeap>,
cmd: &ID3D12GraphicsCommandList,
source: &Image,
@ -74,24 +83,19 @@ impl LutTexture {
let descriptor = heap.alloc_slot()?;
// create handles on GPU
let mut resource: Option<ID3D12Resource> = None;
unsafe {
device.CreateCommittedResource(
&D3D12_HEAP_PROPERTIES {
Type: D3D12_HEAP_TYPE_DEFAULT,
CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
CreationNodeMask: 1,
VisibleNodeMask: 1,
},
D3D12_HEAP_FLAG_NONE,
&desc,
let resource = allocator.lock().create_resource(&ResourceCreateDesc {
name: "lut alloc",
memory_location: MemoryLocation::GpuOnly,
resource_category: ResourceCategory::OtherTexture,
resource_desc: &desc,
castable_formats: &[],
clear_value: None,
initial_state_or_layout: ResourceStateOrBarrierLayout::ResourceState(
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
None,
&mut resource,
)?;
}
assume_d3d12_init!(resource, "CreateCommittedResource");
),
resource_type: &ResourceType::Placed,
})?;
unsafe {
let srv_desc = D3D12_SHADER_RESOURCE_VIEW_DESC {
Format: desc.Format,
@ -106,7 +110,7 @@ impl LutTexture {
};
device.CreateShaderResourceView(
&resource,
resource.resource(),
Some(&srv_desc),
*descriptor.deref().as_ref(),
);
@ -139,25 +143,40 @@ impl LutTexture {
buffer_desc.SampleDesc.Count = 1;
buffer_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
}
let mut upload: Option<ID3D12Resource> = None;
unsafe {
device.CreateCommittedResource(
&D3D12_HEAP_PROPERTIES {
Type: D3D12_HEAP_TYPE_UPLOAD,
CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
CreationNodeMask: 1,
VisibleNodeMask: 1,
},
D3D12_HEAP_FLAG_NONE,
&buffer_desc,
let upload = allocator.lock().create_resource(&ResourceCreateDesc {
name: "lut staging",
memory_location: MemoryLocation::CpuToGpu,
resource_category: ResourceCategory::Buffer,
resource_desc: &buffer_desc,
castable_formats: &[],
clear_value: None,
initial_state_or_layout: ResourceStateOrBarrierLayout::ResourceState(
D3D12_RESOURCE_STATE_GENERIC_READ,
None,
&mut upload,
)?;
}
assume_d3d12_init!(upload, "CreateCommittedResource");
),
resource_type: &ResourceType::Placed,
})?;
//
// let mut upload: Option<ID3D12Resource> = None;
//
// unsafe {
// device.CreateCommittedResource(
// &D3D12_HEAP_PROPERTIES {
// Type: D3D12_HEAP_TYPE_UPLOAD,
// CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
// MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
// CreationNodeMask: 1,
// VisibleNodeMask: 1,
// },
// D3D12_HEAP_FLAG_NONE,
// &buffer_desc,
// D3D12_RESOURCE_STATE_GENERIC_READ,
// None,
// &mut upload,
// )?;
// }
// assume_d3d12_init!(upload, "CreateCommittedResource");
let subresource = [D3D12_SUBRESOURCE_DATA {
pData: source.bytes.as_ptr().cast(),
@ -167,22 +186,31 @@ impl LutTexture {
d3d12_resource_transition(
cmd,
&resource,
&resource.resource(),
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_COPY_DEST,
);
d3d12_update_subresources(cmd, &resource, &upload, 0, 0, 1, &subresource, gc)?;
d3d12_update_subresources(
cmd,
&resource.resource(),
&upload.resource(),
0,
0,
1,
&subresource,
gc,
)?;
d3d12_resource_transition(
cmd,
&resource,
&resource.resource(),
D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
);
let view = InputTexture::new(
resource.clone(),
resource.resource().clone(),
descriptor,
source.size,
ImageFormat::R8G8B8A8Unorm.into(),
@ -190,17 +218,18 @@ impl LutTexture {
wrap_mode,
);
Ok(LutTexture {
resource,
_staging: upload,
resource: ManuallyDrop::new(resource),
staging: ManuallyDrop::new(upload),
view,
miplevels: if mipmap { Some(miplevels) } else { None },
allocator: Arc::clone(&allocator),
})
}
pub fn generate_mipmaps(&self, gen_mips: &mut MipmapGenContext) -> error::Result<()> {
if let Some(miplevels) = self.miplevels {
gen_mips.generate_mipmaps(
&self.resource,
&self.resource.resource(),
miplevels,
self.view.size,
ImageFormat::R8G8B8A8Unorm.into(),
@ -216,3 +245,17 @@ impl AsRef<InputTexture> for LutTexture {
&self.view
}
}
impl Drop for LutTexture {
fn drop(&mut self) {
let resource = unsafe { ManuallyDrop::take(&mut self.resource) };
if let Err(e) = self.allocator.lock().free_resource(resource) {
println!("librashader-runtime-d3d12: [warn] failed to deallocate lut buffer memory {e}")
}
let staging = unsafe { ManuallyDrop::take(&mut self.staging) };
if let Err(e) = self.allocator.lock().free_resource(staging) {
println!("librashader-runtime-d3d12: [warn] failed to deallocate lut staging buffer memory {e}")
}
}
}

View file

@ -6,11 +6,11 @@ use crate::hello_triangle::{DXSample, SampleCommandLine};
fn triangle_d3d12() {
let sample = hello_triangle::d3d12_hello_triangle::Sample::new(
// "../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
"../test/shaders_slang/crt/crt-lottes.slangp",
// "../test/shaders_slang/crt/crt-lottes.slangp",
// "../test/basic.slangp",
// "../test/shaders_slang/handheld/console-border/gbc-lcd-grid-v2.slangp",
// "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID]-[Night].slangp",
// "../test/slang-shaders/test/feedback.slangp",
"../test/shaders_slang/test/feedback.slangp",
// "../test/shaders_slang/test/history.slangp",
// "../test/shaders_slang/crt/crt-royale.slangp",
// "../test/slang-shaders/vhs/VHSPro.slangp",