Skip to content

Commit

Permalink
feat: add staging buffers
Browse files Browse the repository at this point in the history
  • Loading branch information
SkillerRaptor committed Sep 8, 2024
1 parent f4fc2d1 commit 0e18e3a
Show file tree
Hide file tree
Showing 11 changed files with 514 additions and 187 deletions.
260 changes: 99 additions & 161 deletions crates/hyper_rhi/src/d3d12/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,25 @@ use gpu_allocator::{
MemoryLocation,
};
use hyper_core::alignment::Alignment;
use windows::{
core::Interface,
Win32::{
Graphics::{
Direct3D12::{
ID3D12CommandAllocator,
ID3D12Fence,
ID3D12GraphicsCommandList,
D3D12_COMMAND_LIST_TYPE_DIRECT,
D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
D3D12_FENCE_FLAG_NONE,
D3D12_HEAP_FLAG_NONE,
D3D12_HEAP_PROPERTIES,
D3D12_HEAP_TYPE_DEFAULT,
D3D12_HEAP_TYPE_UPLOAD,
D3D12_MEMORY_POOL_UNKNOWN,
D3D12_RANGE,
D3D12_RESOURCE_DESC,
D3D12_RESOURCE_DIMENSION_BUFFER,
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
D3D12_RESOURCE_FLAG_NONE,
D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_GENERIC_READ,
D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
},
Dxgi::Common::{DXGI_FORMAT_UNKNOWN, DXGI_SAMPLE_DESC},
},
System::Threading::{CreateEventA, WaitForSingleObject, INFINITE},
use windows::Win32::Graphics::{
Direct3D12::{
D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
D3D12_HEAP_FLAG_NONE,
D3D12_HEAP_PROPERTIES,
D3D12_HEAP_TYPE_DEFAULT,
D3D12_HEAP_TYPE_UPLOAD,
D3D12_MEMORY_POOL_UNKNOWN,
D3D12_RANGE,
D3D12_RESOURCE_DESC,
D3D12_RESOURCE_DIMENSION_BUFFER,
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
D3D12_RESOURCE_FLAG_NONE,
D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_GENERIC_READ,
D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
},
Dxgi::Common::{DXGI_FORMAT_UNKNOWN, DXGI_SAMPLE_DESC},
};

use crate::{
Expand All @@ -67,6 +56,67 @@ impl Buffer {
let size = descriptor.data.len();
let aligned_size = size.align_up(buffer::ALIGNMENT);

let resource = Self::create_resoure(graphics_device, aligned_size, false);

graphics_device.upload_buffer(descriptor.data, &resource.resource());

let resource_handle_pair =
graphics_device.allocate_buffer_handle(resource.resource(), size);

tracing::debug!(
size,
aligned_size,
srv_index = resource_handle_pair.srv().0,
uav_index = resource_handle_pair.uav().0,
"Buffer created"
);

Self {
resource_handle_pair,

size: size as usize,
resource,

resource_handler: Arc::clone(graphics_device.resource_handler()),
}
}

pub(crate) fn new_staging(
graphics_device: &GraphicsDevice,
descriptor: &BufferDescriptor,
) -> Self {
let size = descriptor.data.len();
let aligned_size = size.align_up(buffer::ALIGNMENT);

let resource = Self::create_resoure(graphics_device, aligned_size, true);

unsafe {
let mut data = std::ptr::null_mut();
resource
.resource()
.Map(0, Some(&D3D12_RANGE { Begin: 0, End: 0 }), Some(&mut data))
.unwrap();
std::ptr::copy_nonoverlapping(descriptor.data.as_ptr(), data as *mut u8, size);
resource.resource().Unmap(0, None);
}

tracing::trace!(size, aligned_size, "Staging Buffer created");

Self {
resource_handle_pair: ResourceHandlePair::default(),

size: size as usize,
resource,

resource_handler: Arc::clone(graphics_device.resource_handler()),
}
}

fn create_resoure(
graphics_device: &GraphicsDevice,
aligned_size: usize,
staging: bool,
) -> gpu_allocator::d3d12::Resource {
let create_info = ResourceCreateDesc {
name: "",
memory_location: MemoryLocation::CpuToGpu,
Expand All @@ -84,16 +134,26 @@ impl Buffer {
Quality: 0,
},
Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
Flags: D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
Flags: if staging {
D3D12_RESOURCE_FLAG_NONE
} else {
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS
},
},
castable_formats: &[],
clear_value: None,
initial_state_or_layout: ResourceStateOrBarrierLayout::ResourceState(
D3D12_RESOURCE_STATE_COPY_DEST,
),
initial_state_or_layout: ResourceStateOrBarrierLayout::ResourceState(if staging {
D3D12_RESOURCE_STATE_GENERIC_READ
} else {
D3D12_RESOURCE_STATE_COPY_DEST
}),
resource_type: &ResourceType::Committed {
heap_properties: &D3D12_HEAP_PROPERTIES {
Type: D3D12_HEAP_TYPE_DEFAULT,
Type: if staging {
D3D12_HEAP_TYPE_UPLOAD
} else {
D3D12_HEAP_TYPE_DEFAULT
},
CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
CreationNodeMask: 1,
Expand All @@ -103,143 +163,21 @@ impl Buffer {
},
};

let resource = graphics_device
graphics_device
.allocator()
.lock()
.unwrap()
.create_resource(&create_info)
.unwrap();

let upload_create_info = ResourceCreateDesc {
name: "",
memory_location: MemoryLocation::CpuToGpu,
resource_category: ResourceCategory::Buffer,
resource_desc: &D3D12_RESOURCE_DESC {
Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
Alignment: D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT as u64,
Width: aligned_size as u64,
Height: 1,
DepthOrArraySize: 1,
MipLevels: 1,
Format: DXGI_FORMAT_UNKNOWN,
SampleDesc: DXGI_SAMPLE_DESC {
Count: 1,
Quality: 0,
},
Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
Flags: D3D12_RESOURCE_FLAG_NONE,
},
castable_formats: &[],
clear_value: None,
initial_state_or_layout: ResourceStateOrBarrierLayout::ResourceState(
D3D12_RESOURCE_STATE_GENERIC_READ,
),
resource_type: &ResourceType::Committed {
heap_properties: &D3D12_HEAP_PROPERTIES {
Type: D3D12_HEAP_TYPE_UPLOAD,
CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
CreationNodeMask: 1,
VisibleNodeMask: 1,
},
heap_flags: D3D12_HEAP_FLAG_NONE,
},
};

let upload_resource = graphics_device
.allocator()
.lock()
.unwrap()
.create_resource(&upload_create_info)
.unwrap();

unsafe {
let mut data = std::ptr::null_mut();
upload_resource
.resource()
.Map(0, Some(&D3D12_RANGE { Begin: 0, End: 0 }), Some(&mut data))
.unwrap();
std::ptr::copy_nonoverlapping(descriptor.data.as_ptr(), data as *mut u8, size);
upload_resource.resource().Unmap(0, None);
}

// Upload
{
let command_allocator: ID3D12CommandAllocator = unsafe {
graphics_device
.device()
.CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT)
.unwrap()
};
let command_list: ID3D12GraphicsCommandList = unsafe {
graphics_device
.device()
.CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, &command_allocator, None)
.unwrap()
};
unsafe {
command_list.Close().unwrap();
}
let fence: ID3D12Fence = unsafe {
graphics_device
.device()
.CreateFence(0, D3D12_FENCE_FLAG_NONE)
}
.unwrap();
let fence_event = unsafe { CreateEventA(None, false, false, None) }.unwrap();

let mut fence_value = 0;
unsafe {
command_allocator.Reset().unwrap();
command_list.Reset(&command_allocator, None).unwrap();

command_list.CopyResource(resource.resource(), upload_resource.resource());

command_list.Close().unwrap();

graphics_device
.command_queue()
.ExecuteCommandLists(&[Some(command_list.cast().unwrap())]);

fence_value += 1;
graphics_device
.command_queue()
.Signal(&fence, fence_value as u64)
.unwrap();

if fence.GetCompletedValue() < fence_value as u64 {
fence
.SetEventOnCompletion(fence_value as u64, fence_event)
.unwrap();
WaitForSingleObject(fence_event, INFINITE);
}
}
}

let resource_handle_pair =
graphics_device.allocate_buffer_handle(resource.resource(), size);

tracing::debug!(
size,
aligned_size,
srv_index = resource_handle_pair.srv().0,
uav_index = resource_handle_pair.uav().0,
"Buffer created"
);

Self {
resource_handle_pair,

size: size as usize,
resource,

resource_handler: Arc::clone(graphics_device.resource_handler()),
}
}

pub(crate) fn gpu_address(&self) -> u64 {
unsafe { self.resource.resource().GetGPUVirtualAddress() }
}

pub(crate) fn resource(&self) -> &gpu_allocator::d3d12::Resource {
&self.resource
}
}

impl Drop for Buffer {
Expand Down
4 changes: 3 additions & 1 deletion crates/hyper_rhi/src/d3d12/descriptor_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ impl DescriptorManager {
}

pub(crate) fn retire_handle(&self, handle: ResourceHandle) {
self.recycled_descriptors.lock().unwrap().push_back(handle);
if handle.0 != u32::MAX {
self.recycled_descriptors.lock().unwrap().push_back(handle);
}
}

pub(crate) fn cbv_srv_uav_heap(&self) -> &ResourceHeap {
Expand Down
11 changes: 11 additions & 0 deletions crates/hyper_rhi/src/d3d12/graphics_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ use crate::{
shader_module::ShaderModule,
surface::Surface,
texture::Texture,
upload_manager::UploadManager,
},
graphics_device::GraphicsDeviceDescriptor,
graphics_pipeline::GraphicsPipelineDescriptor,
Expand Down Expand Up @@ -104,6 +105,8 @@ pub(crate) struct GraphicsDevice {
fence_event: HANDLE,
fence: ID3D12Fence,

upload_manager: UploadManager,

root_signature: ID3D12RootSignature,

_dsv_heap: ResourceHeap,
Expand Down Expand Up @@ -158,6 +161,8 @@ impl GraphicsDevice {

let root_signature = Self::create_root_signature(&device);

let upload_manager = UploadManager::new(&device);

let (fence, fence_event) = Self::create_fence(&device);

let mut frames = Vec::new();
Expand All @@ -182,6 +187,8 @@ impl GraphicsDevice {
fence_event,
fence,

upload_manager,

root_signature,

_dsv_heap: dsv_heap,
Expand Down Expand Up @@ -357,6 +364,10 @@ impl GraphicsDevice {
.allocate_buffer_handle(&self.device, resource, size)
}

pub(crate) fn upload_buffer(&self, source: &[u8], destination: &ID3D12Resource) {
self.upload_manager.upload_buffer(self, source, destination);
}

pub(crate) fn factory(&self) -> &IDXGIFactory7 {
&self.factory
}
Expand Down
1 change: 1 addition & 0 deletions crates/hyper_rhi/src/d3d12/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ mod resource_heap;
mod shader_module;
mod surface;
mod texture;
mod upload_manager;

pub(crate) mod graphics_device;
Loading

0 comments on commit 0e18e3a

Please sign in to comment.