public static VKBuffer InstanceInfo <T>(Graphics g, int count) where T : struct { long size = count * Interop.SizeOf <T>(); // Create a staging buffer that is writable by host. var stagingBuffer = g.Context.Device.CreateBuffer(new BufferCreateInfo(size, BufferUsages.TransferSrc)); MemoryRequirements stagingReq = stagingBuffer.GetMemoryRequirements(); int stagingMemoryTypeIndex = g.Context.MemoryProperties.MemoryTypes.IndexOf( stagingReq.MemoryTypeBits, MemoryProperties.HostVisible | MemoryProperties.HostCoherent); DeviceMemory stagingMemory = g.Context.Device.AllocateMemory(new MemoryAllocateInfo(stagingReq.Size, stagingMemoryTypeIndex)); stagingBuffer.BindMemory(stagingMemory); // Create a device local buffer where the vertex data will be copied and which will be used for rendering. VulkanCore.Buffer buffer = g.Context.Device.CreateBuffer(new BufferCreateInfo(size, BufferUsages.VertexBuffer | BufferUsages.TransferDst)); MemoryRequirements req = buffer.GetMemoryRequirements(); int memoryTypeIndex = g.Context.MemoryProperties.MemoryTypes.IndexOf( req.MemoryTypeBits, MemoryProperties.DeviceLocal); DeviceMemory memory = g.Context.Device.AllocateMemory(new MemoryAllocateInfo(req.Size, memoryTypeIndex)); buffer.BindMemory(memory); return(new VKBuffer(g.Context, buffer, memory, g.Context.Device.CreateFence(), count, size, true, stagingBuffer, stagingMemory, g.Context.GraphicsCommandPool.AllocateBuffers(new CommandBufferAllocateInfo(CommandBufferLevel.Primary, 1))[0])); }
internal HostBuffer( Device logicalDevice, Pool memoryPool, BufferUsages usages, long size) { if (logicalDevice == null) { throw new ArgumentNullException(nameof(logicalDevice)); } if (memoryPool == null) { throw new ArgumentNullException(nameof(memoryPool)); } this.size = size; //Create the buffer buffer = logicalDevice.CreateBuffer(new BufferCreateInfo( size: size, usages: usages, flags: BufferCreateFlags.None, sharingMode: SharingMode.Exclusive )); //Allocate memory for this buffer memory = memoryPool.AllocateAndBind(buffer, Chunk.Location.Host); }
// Starts a transfer of raw data from the host to a device buffer public unsafe static void PushBuffer(byte *src, uint length, Vk.Buffer dst, uint dstOffset) { // Calculate transfer information uint blockCount = (uint)Mathf.Ceiling(length / (float)DEFAULT_BUFFER_SIZE); // Iterate over the transfer blocks for (uint bidx = 0; bidx < blockCount; ++bidx) { // Calculate offsets and block sizes uint blockOff = bidx * DEFAULT_BUFFER_SIZE; byte *currSrc = src + blockOff; uint currDstOffset = dstOffset + blockOff; uint currLength = Math.Min(length - blockOff, DEFAULT_BUFFER_SIZE); // Wait on the previous transfer s_pushFence.Wait(); s_pushFence.Reset(); // Map the staging buffer, and copy the memory IntPtr mapped = s_pushMemory.Map(0, currLength); System.Buffer.MemoryCopy(currSrc, mapped.ToPointer(), currLength, currLength); s_pushMemory.Unmap(); // Start recording s_pushCommands.Begin(ONE_TIME_SUBMIT_INFO); // Add the transfer command Vk.BufferCopy bc = new Vk.BufferCopy(currLength, 0, currDstOffset); s_pushCommands.CmdCopyBuffer(s_pushBuffer, dst, bc); // End recording, and submit s_pushCommands.End(); s_queue.Submit(s_pushSubmitInfo, fence: s_pushFence); } }
// Size in bytes, and the usages private protected Buffer(uint size, BufferType type, Vk.BufferUsages usages) { Device = SpectrumApp.Instance.GraphicsDevice; Size = size; Type = type; // Create the buffer var bci = new Vk.BufferCreateInfo( size, Vk.BufferUsages.TransferDst | Vk.BufferUsages.TransferSrc | usages, flags: Vk.BufferCreateFlags.None, sharingMode: Vk.SharingMode.Exclusive ); VkBuffer = Device.VkDevice.CreateBuffer(bci); // Create the backing memory var memReq = VkBuffer.GetMemoryRequirements(); var memIdx = Device.FindMemoryTypeIndex(memReq.MemoryTypeBits, Vk.MemoryProperties.DeviceLocal); if (memIdx == -1) { throw new InvalidOperationException("Cannot find a memory type that supports buffers (this means bad or out-of-date hardware)"); } var mai = new Vk.MemoryAllocateInfo(memReq.Size, memIdx); VkMemory = Device.VkDevice.AllocateMemory(mai); VkBuffer.BindMemory(VkMemory); }
internal DeviceBuffer( Device logicalDevice, Pool memoryPool, BufferUsages usages, long size) { if (logicalDevice == null) { throw new ArgumentNullException(nameof(logicalDevice)); } if (memoryPool == null) { throw new ArgumentNullException(nameof(memoryPool)); } this.size = size; //Create the buffer buffer = logicalDevice.CreateBuffer(new BufferCreateInfo( size: size, //Adding 'TransferDst' otherwise we can never copy data to it usages: usages | BufferUsages.TransferDst, flags: BufferCreateFlags.None, sharingMode: SharingMode.Exclusive )); //Bind memory from our pool to this buffer memory = memoryPool.AllocateAndBind(buffer, Chunk.Location.Device); }
internal Block AllocateAndBind(VulkanCore.Buffer buffer, Chunk.Location location) { ThrowIfDisposed(); var memRequirements = buffer.GetMemoryRequirements(); Block block = Allocate(location, memRequirements); buffer.BindMemory(block.Container.Memory, block.Offset); return(block); }
public void CreateBuffer(int sizeInBytes, string name, BufferUsages usage, SharingMode sm, int [] famIndexes = null) { BufferCreateInfo bci = new BufferCreateInfo(sizeInBytes, usage, BufferCreateFlags.None, sm, famIndexes); Buffer buf = mLogical.CreateBuffer(bci); mBuffers.Add(name, buf); }
private VKBuffer(Context ctx, VulkanCore.Buffer buffer, DeviceMemory memory, Fence fence, int count, long size, bool writeUsingStagingBuffer = false, VulkanCore.Buffer stagingBuffer = null, DeviceMemory stagingMemory = null, CommandBuffer stagingCommandBuffer = null) { Context = ctx; Buffer = buffer; Memory = memory; Count = count; Size = size; WriteUsingStagingBuffer = writeUsingStagingBuffer; StagingBuffer = stagingBuffer; StagingMemory = stagingMemory; StagingCommandBuffer = stagingCommandBuffer; Fence = fence; }
void CreateBuffer() { /* * We will now create a buffer. We will render the mandelbrot set into this buffer * in a computer shade later. */ BufferCreateInfo bufferCreateInfo = new BufferCreateInfo() { Size = bufferSize, // buffer size in bytes. Usage = BufferUsages.StorageBuffer, // VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; // buffer is used as a storage buffer. SharingMode = SharingMode.Exclusive // VK_SHARING_MODE_EXCLUSIVE; // buffer is exclusive to a single queue family at a time. }; buffer = device.CreateBuffer(bufferCreateInfo); /* * But the buffer doesn't allocate memory for itself, so we must do that manually. */ /* * First, we find the memory requirements for the buffer. */ MemoryRequirements memoryRequirements = buffer.GetMemoryRequirements(); /* * Now use obtained memory requirements info to allocate the memory for the buffer. */ MemoryAllocateInfo allocateInfo = new MemoryAllocateInfo() { AllocationSize = memoryRequirements.Size, // specify required memory. /* * There are several types of memory that can be allocated, and we must choose a memory type that: * 1) Satisfies the memory requirements(memoryRequirements.memoryTypeBits). * 2) Satifies our own usage requirements. We want to be able to read the buffer memory from the GPU to the CPU * with vkMapMemory, so we set VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT. * Also, by setting VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, memory written by the device(GPU) will be easily * visible to the host(CPU), without having to call any extra flushing commands. So mainly for convenience, we set * this flag. */ MemoryTypeIndex = FindMemoryType( memoryRequirements.MemoryTypeBits, MemoryProperties.HostCoherent | MemoryProperties.HostVisible)// VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); }; bufferMemory = device.AllocateMemory(allocateInfo); // allocate memory on device. // Now associate that allocated memory with the buffer. With that, the buffer is backed by actual memory. buffer.BindMemory(bufferMemory); }
internal static VKBuffer Storage <T>(Context ctx, T[] data) where T : struct { long size = data.Length * Interop.SizeOf <T>(); // Create a staging buffer that is writable by host. VulkanCore.Buffer stagingBuffer = ctx.Device.CreateBuffer(new BufferCreateInfo(size, BufferUsages.TransferSrc)); MemoryRequirements stagingReq = stagingBuffer.GetMemoryRequirements(); int stagingMemoryTypeIndex = ctx.MemoryProperties.MemoryTypes.IndexOf( stagingReq.MemoryTypeBits, MemoryProperties.HostVisible | MemoryProperties.HostCoherent); DeviceMemory stagingMemory = ctx.Device.AllocateMemory(new MemoryAllocateInfo(stagingReq.Size, stagingMemoryTypeIndex)); IntPtr vertexPtr = stagingMemory.Map(0, stagingReq.Size); Interop.Write(vertexPtr, data); stagingMemory.Unmap(); stagingBuffer.BindMemory(stagingMemory); // Create a device local buffer where the data will be copied. VulkanCore.Buffer buffer = ctx.Device.CreateBuffer(new BufferCreateInfo(size, BufferUsages.VertexBuffer | BufferUsages.StorageBuffer | BufferUsages.TransferDst)); MemoryRequirements req = buffer.GetMemoryRequirements(); int memoryTypeIndex = ctx.MemoryProperties.MemoryTypes.IndexOf( req.MemoryTypeBits, MemoryProperties.DeviceLocal); DeviceMemory memory = ctx.Device.AllocateMemory(new MemoryAllocateInfo(req.Size, memoryTypeIndex)); buffer.BindMemory(memory); // Copy the data from staging buffers to device local buffers. CommandBuffer cmdBuffer = ctx.GraphicsCommandPool.AllocateBuffers(new CommandBufferAllocateInfo(CommandBufferLevel.Primary, 1))[0]; cmdBuffer.Begin(new CommandBufferBeginInfo(CommandBufferUsages.OneTimeSubmit)); cmdBuffer.CmdCopyBuffer(stagingBuffer, buffer, new BufferCopy(size)); cmdBuffer.End(); // Submit. Fence fence = ctx.Device.CreateFence(); ctx.GraphicsQueue.Submit(new SubmitInfo(commandBuffers: new[] { cmdBuffer }), fence); fence.Wait(); // Cleanup. fence.Dispose(); cmdBuffer.Dispose(); stagingBuffer.Dispose(); stagingMemory.Dispose(); return(new VKBuffer(ctx, buffer, memory, null, data.Length, size)); }
public void BindMemoryToBuffer(string memName, string bufName) { if (!mDeviceMems.ContainsKey(memName)) { Misc.SafeInvoke(eErrorSpam, "No memory chunk " + memName + "..."); return; } if (!mBuffers.ContainsKey(memName)) { Misc.SafeInvoke(eErrorSpam, "No buffer " + bufName + "..."); return; } Buffer buf = mBuffers[bufName]; DeviceMemory dm = mDeviceMems[bufName]; buf.BindMemory(dm); }
public static VKBuffer UniformBuffer <T>(Graphics g, int count, UniformUsageHint usage = UniformUsageHint.ModifiedRarely) where T : struct { long size = count * Interop.SizeOf <T>(); if (usage == UniformUsageHint.ModifiedRarely) { // Create a staging buffer that is writable by host. var stagingBuffer = g.Context.Device.CreateBuffer(new BufferCreateInfo(size, BufferUsages.TransferSrc)); MemoryRequirements stagingReq = stagingBuffer.GetMemoryRequirements(); int stagingMemoryTypeIndex = g.Context.MemoryProperties.MemoryTypes.IndexOf( stagingReq.MemoryTypeBits, MemoryProperties.HostVisible | MemoryProperties.HostCoherent); DeviceMemory stagingMemory = g.Context.Device.AllocateMemory(new MemoryAllocateInfo(stagingReq.Size, stagingMemoryTypeIndex)); stagingBuffer.BindMemory(stagingMemory); // Create a device local buffer where the vertex data will be copied and which will be used for rendering. VulkanCore.Buffer buffer = g.Context.Device.CreateBuffer(new BufferCreateInfo(size, BufferUsages.UniformBuffer | BufferUsages.TransferDst)); MemoryRequirements req = buffer.GetMemoryRequirements(); int memoryTypeIndex = g.Context.MemoryProperties.MemoryTypes.IndexOf( req.MemoryTypeBits, MemoryProperties.DeviceLocal); DeviceMemory memory = g.Context.Device.AllocateMemory(new MemoryAllocateInfo(req.Size, memoryTypeIndex)); buffer.BindMemory(memory); return(new VKBuffer(g.Context, buffer, memory, g.Context.Device.CreateFence(), count, size, true, stagingBuffer, stagingMemory, g.Context.GraphicsCommandPool.AllocateBuffers(new CommandBufferAllocateInfo(CommandBufferLevel.Primary, 1))[0])); } else { VulkanCore.Buffer buffer = g.Context.Device.CreateBuffer(new BufferCreateInfo(size, BufferUsages.UniformBuffer)); MemoryRequirements memoryRequirements = buffer.GetMemoryRequirements(); // We require host visible memory so we can map it and write to it directly. // We require host coherent memory so that writes are visible to the GPU right after unmapping it. int memoryTypeIndex = g.Context.MemoryProperties.MemoryTypes.IndexOf( memoryRequirements.MemoryTypeBits, MemoryProperties.HostVisible | MemoryProperties.HostCoherent); DeviceMemory memory = g.Context.Device.AllocateMemory(new MemoryAllocateInfo(memoryRequirements.Size, memoryTypeIndex)); buffer.BindMemory(memory); return(new VKBuffer(g.Context, buffer, memory, null, count, size)); } }
public void CreateBufferMemory <T>(string bufName, MemoryProperties props) { if (mDeviceMems.ContainsKey(bufName)) { Misc.SafeInvoke(eErrorSpam, "Buffer " + bufName + " already has a chunk of mem allocated..."); return; } Buffer buf = mBuffers[bufName]; DeviceMemory dm; MemoryRequirements mr = buf.GetMemoryRequirements(); MemoryAllocateInfo mai = new MemoryAllocateInfo(); mai.AllocationSize = mr.Size; mai.MemoryTypeIndex = FindMemoryType(mr.MemoryTypeBits, props); dm = mLogical.AllocateMemory(mai); mDeviceMems.Add(bufName, dm); }