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])); }
// 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 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); }
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)); } }