-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for dedicated allocations and committed resource tracking #148
Conversation
…urces to the dx12 allocator. Add dedicated allocation information to the visualizer.
…e same functions. Add information about committed resources per heap type to the visualizer in d3d12.
…cated allocations to be ignored.
Remove old heap type information that was leftover from before an API change. Implement several pull request suggestions, and fix a bug that would wrongly display dedicated block information in the vulkan visualizer.
…w an allocation should be managed. Remove the BlockType enum that previously fulfilled the same task under the hood.
#[derive(Copy, Clone, Debug, Eq, PartialEq)] | ||
pub enum AllocationScheme { | ||
/// This allocation will be for a buffer, and it will be driver managed using vulkans DedicatedAllocation feature. | ||
/// The driver will be able to perform optimizations in some cases with this type of allocation. | ||
DedicatedBuffer { buffer: vk::Buffer }, | ||
/// This allocation will be for a image, and it will be driver managed using vulkans DedicatedAllocation feature. | ||
/// The driver will be able to perform optimizations in some cases with this type of allocation. | ||
DedicatedImage { image: vk::Image }, | ||
/// This allocation will be managed by the GPU allocator. | ||
/// It is possible that the allocation will reside in an allocation block shared with other resources. | ||
GpuAllocatorManaged, | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MarijnS95 What do you think about this for the user exposed interface?
We can now also correctly pass the buffer and image when required for dedicated allocations. I got rid of the BlockType
as that was essentially serving the same purpose, just with less configurability and under the hood.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interface looks good, though I'd have reworded some of the comments:
#[derive(Copy, Clone, Debug, Eq, PartialEq)] | |
pub enum AllocationScheme { | |
/// This allocation will be for a buffer, and it will be driver managed using vulkans DedicatedAllocation feature. | |
/// The driver will be able to perform optimizations in some cases with this type of allocation. | |
DedicatedBuffer { buffer: vk::Buffer }, | |
/// This allocation will be for a image, and it will be driver managed using vulkans DedicatedAllocation feature. | |
/// The driver will be able to perform optimizations in some cases with this type of allocation. | |
DedicatedImage { image: vk::Image }, | |
/// This allocation will be managed by the GPU allocator. | |
/// It is possible that the allocation will reside in an allocation block shared with other resources. | |
GpuAllocatorManaged, | |
} | |
#[derive(Copy, Clone, Debug, Eq, PartialEq)] | |
pub enum AllocationScheme { | |
/// Perform a dedicated, driver-managed allocation for the given buffer, allowing | |
/// it to perform optimizations on this type of allocation. | |
DedicatedBuffer { buffer: vk::Buffer }, | |
/// Perform a dedicated, driver-managed allocation for the given image, allowing | |
/// it to perform optimizations on this type of allocation. | |
DedicatedImage { image: vk::Image }, | |
/// The memory for this resource will be allocated and managed by gpu-allocator. | |
/// It is possible that the allocation will reside in [`vk::Memory`] shared with other resources. | |
GpuAllocatorManaged, | |
} | |
@@ -743,6 +794,131 @@ impl Allocator { | |||
} | |||
} | |||
} | |||
|
|||
/// Create a resource according to the provided parameters. | |||
/// Created resources should be freed at the end of their lifetime by calling [`Self::free_resource()`]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need a Drop
destructor to call this or print a warning when it was not called?
// Committed resources are implicitly dropped when their refcount reaches 0. | ||
// We only have to change the allocation and size tracking. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well you're explicitly dropping resource
with ManuallyDrop
right above... It's just that there's no allocation
to clean up here.
buffer_device_address: bool, | ||
allocation_scheme: &AllocationScheme, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a cheap Copy
type, just pass-by-value. The user will likely ad-hoc create it anyway.
DedicatedBuffer { buffer: vk::Buffer }, | ||
/// This allocation will be for a image, and it will be driver managed using vulkans DedicatedAllocation feature. | ||
/// The driver will be able to perform optimizations in some cases with this type of allocation. | ||
DedicatedImage { image: vk::Image }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also feel free to just use a tuple-variant here, the name of the variant conveys the same name as the only named field here.
Box::new(allocator::FreeListAllocator::new(size)) | ||
}; | ||
let sub_allocator: Box<dyn allocator::SubAllocator> = | ||
if !matches!(allocation_scheme, AllocationScheme::GpuAllocatorManaged) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just use ==
:)
Changes
This PR adds the option to create dedicated allocations in the Vulkan allocator and CommittedResources in the Dx12 allocator. These types of allocations are managed by the driver, which allows it to do special optimizations (🧙♂️ magic).
Vulkan
In the Vulkan allocator, you must now pass an extra bool
dedicated_allocation
into theallocate
function. Vulkan 1.1 is required for this to be available, though there is an extension for Vulkan 1.0 available (which I didn't integrate, but I could do that if we want to support it).The visualizer now displays whether a memory block is backed by a dedicated allocation or not.
D3D12
In DirectX, dedicated allocations are hidden behind the
CreateCommittedResource()
call. It is not possible to access these allocations, so I've added acreate_resource
function to the dx12 allocator which will return aResource
object. You can decide whether you want this to be aPlaced
orCommitted
resource, and the rest is handled under the hood for you. When freeing a resource, you have to call thefree_resource
function on the allocator.I have added a special section that displays the total amount of committed resources and their total size per memory type to the visualizer.
Testing
I have tested these changes in the dx12 and vulkan backends of the Breda framework. Performance on vulkan and dx12 increased by about 10-fold in our ray-tracing shaders when marking render targets as dedicated resources.