public ValueBufferCpu(Device device, VkBufferUsageFlag usage, VkBufferCreateFlag flags, bool coherent, params T[] values) : base(device, usage, flags, FindHostMemory(device.PhysicalDevice, coherent, (ulong)Marshal.SizeOf <T>() * (ulong)values.LongLength), values) { Coherent = BackingBuffer.Memory.BackingMemory.MemoryType.HostCoherent; CommitEverything(); }
private List <BufferPool> PoolForUsage(MemoryType type, VkBufferUsageFlag usage, VkBufferCreateFlag create) { var cval = _poolsByType[type.TypeIndex, (int)usage, (int)create]; if (cval != null) { return(cval); } return(_poolsByType[type.TypeIndex, (int)usage, (int)create] = new List <BufferPool>()); }
protected ValueBuffer(Device device, VkBufferUsageFlag usage, VkBufferCreateFlag flags, MemoryType mem, params T[] values) : base(device, mem, (ulong)Marshal.SizeOf <T>() * (ulong)values.LongLength, usage, flags) { _data = values; _itemSize = (ulong)Marshal.SizeOf <T>(); _dirtyMin = 0; _dirtyMax = (uint)_data.Length; ; }
public PooledMemoryBuffer(Device dev, VkBufferUsageFlag usage, VkBufferCreateFlag flags, MemoryRequirements req, ulong size, params uint[] sharedQueueFamilies) : base(dev, usage, flags, size, sharedQueueFamilies) { var pool = Size >= DeviceMemoryPools.BlockSizeForPool(DeviceMemoryPools.Pool.LargeBufferPool) ? DeviceMemoryPools.Pool.LargeBufferPool : DeviceMemoryPools.Pool.SmallBufferPool; var reqs = MemoryRequirements.Union(MemoryRequirements, req); var type = reqs.FindMemoryType(PhysicalDevice); _memory = Device.MemoryPool.Allocate(type, pool, reqs.TypeRequirements.Size); BindMemory(_memory.BackingMemory, _memory.Offset); }
private ulong BlockSizeForUsage(VkBufferUsageFlag flag) { if ((flag & VkBufferUsageFlag.UniformBuffer) != 0) { return(Extensions.LeastCommonMultiple(128, PhysicalDevice.Limits.MinUniformBufferOffsetAlignment)); } if ((flag & VkBufferUsageFlag.VertexBuffer) != 0) { return(1024 * 128); // 4k VertexTextured } if ((flag & VkBufferUsageFlag.IndexBuffer) != 0) { return(1024 * 32); // 8k uint indices } return(1024 * 16); }
/// <summary> /// Allocates a new memory pool. /// </summary> /// <param name="dev">Device to allocate on</param> /// <param name="blockSize">Memory block size</param> /// <param name="blockCount">Number of blocks to allocate</param> /// <param name="usage">buffer usage</param> /// <param name="flags">buffer creation flags</param> /// <param name="memoryType">Memory to use</param> /// <param name="sharedQueueFamilies">Concurrency mode, or exclusive if empty</param> public BufferPool(Device dev, ulong blockSize, ulong blockCount, VkBufferUsageFlag usage, VkBufferCreateFlag flags, MemoryType memoryType, params uint[] sharedQueueFamilies) { Device = dev; var bitAlignment = (uint)System.Math.Ceiling(System.Math.Log(blockSize) / System.Math.Log(2)); blockSize = (1UL << (int)bitAlignment); _pool = new MemoryPool(blockSize * blockCount, bitAlignment); _buffer = new PooledMemoryBuffer(dev, usage, flags, new MemoryRequirements() { TypeRequirements = new VkMemoryRequirements() { MemoryTypeBits = 1u << (int)memoryType.TypeIndex } }, blockSize * blockCount, sharedQueueFamilies); }
/// <summary> /// Creates a new buffer /// </summary> /// <param name="dev">device</param> /// <param name="usage">buffer usage</param> /// <param name="flags">buffer creation flags</param> /// <param name="size">buffer size</param> /// <param name="sharedQueueFamilies">Concurrency mode, or exclusive if empty</param> public Buffer(Device dev, VkBufferUsageFlag usage, VkBufferCreateFlag flags, ulong size, params uint[] sharedQueueFamilies) { Logging.Allocations?.Trace($"Creating {Extensions.FormatFileSize(size)} buffer with usage {usage}"); Device = dev; Size = size; Usage = usage; unsafe { var pin = sharedQueueFamilies.Length > 0 ? GCHandle.Alloc(sharedQueueFamilies, GCHandleType.Pinned) : default(GCHandle); try { var info = new VkBufferCreateInfo() { SType = VkStructureType.BufferCreateInfo, PNext = IntPtr.Zero, Flags = flags, Size = size, Usage = usage, SharingMode = sharedQueueFamilies.Length > 0 ? VkSharingMode.Concurrent : VkSharingMode.Exclusive, QueueFamilyIndexCount = (uint)sharedQueueFamilies.Length, PQueueFamilyIndices = (uint *)(sharedQueueFamilies.Length > 0 ? Marshal.UnsafeAddrOfPinnedArrayElement(sharedQueueFamilies, 0) : IntPtr.Zero).ToPointer() }; Handle = dev.Handle.CreateBuffer(&info, Instance.AllocationCallbacks); } finally { if (sharedQueueFamilies.Length > 0) { pin.Free(); } } } }
[MethodImpl(MethodImplOptions.Synchronized)] // TODO better sync with rwlock public MemoryHandle Allocate(MemoryType type, VkBufferUsageFlag usage, VkBufferCreateFlag create, ulong size) { var pools = PoolForUsage(type, usage, create); foreach (var pool in pools) { if (pool.TryAllocate(size, out var tmp)) { return(new MemoryHandle(pool, tmp)); } } // Create a new pool var blockSize = BlockSizeForUsage(usage); var blockCount = System.Math.Max((ulong)System.Math.Ceiling(size / (double)blockSize) * 4UL, PoolBlockCount); var families = Device.Queues.Select(x => x.FamilyIndex).Distinct().ToArray(); // TODO consider how concurrency works here. Needed? // families.Length > 1 ? families : new uint[0]); var npool = new BufferPool(Device, blockSize, blockCount, usage, create, type, new uint[0]); pools.Add(npool); return(new MemoryHandle(npool, npool.Allocate(size))); }
public ValueBufferGpu(DeferredTransfer flush, VkBufferUsageFlag usage, VkBufferCreateFlag create, T[] values) : base(flush.Device, usage, create, FindDeviceMemory(flush.PhysicalDevice, (ulong)Marshal.SizeOf <T>() * (ulong)values.LongLength), values) { _deferredFlusher = flush; }
public PooledBuffer(Device dev, MemoryType memType, ulong capacity, VkBufferUsageFlag usage, VkBufferCreateFlag create = 0) { Handle = dev.BufferPools.Allocate(memType, usage, create, capacity); }