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
        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);
        }
Beispiel #3
0
        // 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);
            }
        }
Beispiel #4
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 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);
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
 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);
        }
Beispiel #10
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 #11
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 #12
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));
            }
        }
Beispiel #13
0
        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);
        }