Beispiel #1
0
        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]));
        }
Beispiel #2
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);
        }
Beispiel #5
0
        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));
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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));
            }
        }