-
-
Notifications
You must be signed in to change notification settings - Fork 401
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
VMASharp API Review #595
base: feature/vmasharp
Are you sure you want to change the base?
VMASharp API Review #595
Conversation
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.
Generally speaking, it would help if the main structs/classes had a description of what the intended purpose of the class is.
public sealed class VulkanMemoryAllocator : IDisposable | ||
{ | ||
public Device Device { get; } | ||
public VulkanMemoryAllocator(in VulkanMemoryAllocatorCreateInfo createInfo); |
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.
Definition of VulkanMemoryAllocatorCreateInfo is missing. Is this intentional (AllocationCreateInfo is listed)?
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 could honestly be replaced with { get; init; }
properties with a few required constructor arguments. I wrote this before those were a thing.
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.
Depends on whether we want to support NS20 with this library or not - init
doesn't work there.
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.
Weren't you planning on being .NET 6 only?
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.
That's 3.0. VMASharp isn't triaged against any release at the moment. It could reasonably be a new feature in 2.X sustaining so the question would be do we want to support this package everywhere Silk.NET.Vulkan is supported today?
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.
Depends on whether we want to support NS20 with this library or not -
init
doesn't work there.
I think for clarity for users, we should support NS20, and in 3.0 look into rewriting parts to use the newer features of .NET 6(+)
public MapMemoryException(Result res); | ||
public MapMemoryException(string message, Result res); | ||
} | ||
public enum MemoryUsage |
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.
So i guess this is a combination of BufferUsageFlags, SharingMode and MemoryPropertyFlags ?
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.
These are presets for MemoryPropertyFlags, essentially.
long SumFreeSize { get; } | ||
long UnusedRangeSizeMax { get; } | ||
bool IsEmpty { get; } | ||
void Validate(); |
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.
i guess since it is void this throws if it is invalid ?
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.
Yes, that is the design choice, but its only called in Debug Builds
bool IsEmpty { get; } | ||
void Validate(); | ||
void CalcAllocationStatInfo(out StatInfo outInfo); | ||
void AddPoolStats(ref PoolStats stats); |
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.
What does this method do to the stats ?
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.
Something like this.
} | ||
public struct AllocationRequest | ||
{ | ||
public const long LostAllocationCost = 1048576; |
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.
What is this magic number for ? Is it a limit or a threshold ?
public int MinBlockCount; | ||
public int MaxBlockCount; | ||
public int FrameInUseCount; | ||
public Func<long, IBlockMetadata>? AllocationAlgorithmCreate; |
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.
What does this function do ?
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.
Allows the user to specify what algorithm they want to use for allocating out of each memory block in the pool.
MinFragmentation = WorstFit, // 0x00000002 | ||
} | ||
[Flags] | ||
public enum AllocatorCreateFlags |
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.
I guess this flag is used in the VulkanMemoryAllocatorCreateInfo ?
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.
Yup
{ | ||
ExternallySyncronized = 1, | ||
ExtMemoryBudget = 8, | ||
AMDDeviceCoherentMemory = 16, // 0x00000010 |
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.
Whats so special for AMD ?
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.
That's just what the Vulkan extension is named. AMD (and some other vendors) expose a way to check whether the driver thinks it'd be better for performance if a buffer/image would get a dedicated allocation, instead of bing sub-allocated
public object Item; | ||
public object CustomData; | ||
public AllocationRequestType Type; | ||
public readonly long CalcCost(); |
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.
I guess the cost will be used internally in the allocator itself to decide something internal ?
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.
Yes
int frameInUseCount = 0, | ||
Func<long, IBlockMetadata>? allocationAlgorithemCreate = null); | ||
} | ||
public struct AllocationRequest |
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.
What is the purpose of the AllocationRequest compared to a normal allocation, better asked why would i care for the request and not just use an allocation via AllocateMemory?
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.
VMA has this weird internal multi-stage allocation mechanism to support a few key features. This stores state for that.
Ok, so, much of the internal logic is semi-documented in VMA, the native library I ported this from. No, I didn't bother to document a lot of this stuff, at the time it was a passion project. I may have done a lot more work on this if I were actively using Vulkan, but alas, my time had other places it needed to be spent. I'm saying this for your benefit and for public record. Edit: I'll do active feedback on your review tomorrow, as I'm spent today. |
@sunkin351 |
Fear not, my fellow developer. I didn't take any of this personally, though I did write that reply while under heavy fatigue, I hope you can forgive me. My only desire is to help turn this into a usable tool that every developer can enjoy. Also, am I reading some of this right in that there are data structure definitions missing? |
I haven't included anything internal, should just be the public (and hopefully protected) APIs in this document. As well as defragmentation which is being excluded altogether for the time being. |
Assigning to Kai as he's the Vulkan area owner. |
VulkanMemoryAllocatorCreateInfo struct would be nice to have in the document so we can discuss which stuff is actually needed to create one. |
well i tried to create some kind of basic overview diagram to highlight the public relations of the classes (plantuml source in the spoiler at the end). plantuml source@startuml interface IBlockMetadata class AllocationBudget << (S, gold) >> class AllocationContext << (S, gold) >> class AllocationRequest << (S, gold) >> class PoolStats<< (S, gold) >> class StatInfo<< (S, gold) >> class VulkanMemoryAllocator class VulkanMemoryPool enum SuballocationType {} AllocationRequest <-- AllocationRequestType AllocationCreateInfo <-- MemoryUsage AllocationContext <-- AllocationStrategyFlags Allocation --> Memory : occupies a chunk VulkanMemoryAllocator <-- AllocationCreateInfo : for Allocations IBlockMetadata --> StatInfo : calculates BlockAllocation --> Allocation hide empty members |
The |
Ok i some time to look through the source and the interface is basically the extension point of this library via the AllocationPoolCreateInfo struct where you could specify custom pool allocation strategy. So we can't reduce the surface without sacrificing this feature (IBlockMetadata, allocation request/context would then be internal). Otherwise i think the api is ok. When it gets in before the big 3.0 it can be battle tested and if there are some api changes that would be beneficial but breaking, they could be postponed to 3.0. |
It looks like there isn't a lot of movement on this, and 2.X isn't really where the Silk.NET team themselves are focusing at this time. We (I) still want this in mainline Silk.NET, though, and we own the code now (#599) so we can always revisit this later down the line! For now @sunkin351 did you want the original VMASharp to join the Silk.NET community program? Hopefully this will make the community more willing to use VMASharp in the interim period. |
I'm closing this as I won't be coming back to this, and with all maintainers being dedicated to 3.0 I'm not sure if anyone else would either. I've protected the branch, so it should stay put should anyone else want to pick this up. |
Re-opening since there's active work on 2.x again, and a plan for more often API review meetings and more coffee & code streams, once #1253 is in, ill PR to rebase this branch |
Assigning @Beyley for API review given we don't really have any Vulkaneers around atm. |
Theres quite a few cases of |
Bear in mind, this was written in a time before nint and nuint were introduced and likewise has not been updated to reflect the newest standards. |
The original design of this API revolved around the ability to free "lost" allocations should they not be accessed in X (user defined) frames. If we don't wanna support that, we might be able to simplify the Edit: I'm probably forgetting some of the other things the convoluted design allowed... |
Oh wee Oh wee Ifeel it. lol.. |
This will serve as the place where we'll review the VMASharp API.
The public API has been summarised in a single file (in markdown format so we can add words/discussions/conclusions/action items if we want to), which will be the file for reviewing.
Internal APIs have been excluded.