Beispiel #1
0
        public static Texture2D RenderTarget(Graphics g, int width, int height)
        {
            const Format format = Format.B8G8R8A8UNorm;

            // Create optimal tiled target image.
            Image image = g.Context.Device.CreateImage(new ImageCreateInfo
            {
                ImageType     = ImageType.Image2D,
                Format        = format,
                MipLevels     = 1,
                ArrayLayers   = 1,
                Samples       = SampleCounts.Count1,
                Tiling        = ImageTiling.Optimal,
                SharingMode   = SharingMode.Exclusive,
                InitialLayout = ImageLayout.Undefined,
                Extent        = new Extent3D(width, height, 1),
                Usage         = ImageUsages.Sampled | ImageUsages.TransferDst | ImageUsages.TransferSrc | ImageUsages.ColorAttachment
            });
            MemoryRequirements imageMemReq = image.GetMemoryRequirements();
            int imageHeapIndex             = g.Context.MemoryProperties.MemoryTypes.IndexOf(
                imageMemReq.MemoryTypeBits, MemoryProperties.DeviceLocal);
            DeviceMemory memory = g.Context.Device.AllocateMemory(new MemoryAllocateInfo(imageMemReq.Size, imageHeapIndex));

            image.BindMemory(memory);

            var subresourceRange = new ImageSubresourceRange(ImageAspects.Color, 0, 1, 0, 1);

            // Create image view.
            ImageView view = image.CreateView(new ImageViewCreateInfo(format, subresourceRange));

            var sampler = VKHelper.CreateSampler(g.Context, Filter.Linear, Filter.Linear, SamplerMipmapMode.Linear);

            return(new Texture2D(g.Context, image, memory, view, format, new Vector2I(width, height), true));
        }
Beispiel #2
0
        public void Write <T>(T[] values, long pos = 0) where T : struct
        {
            var size  = Interop.SizeOf <T>();
            var count = values.Length;

            if (WriteUsingStagingBuffer)
            {
                MemoryRequirements stagingReq = StagingBuffer.GetMemoryRequirements();
                var    mapSize   = Math.Min(count * size, stagingReq.Size - pos * size);
                IntPtr vertexPtr = StagingMemory.Map(pos * size, mapSize);
                Interop.Write(vertexPtr, values);
                StagingMemory.Unmap();

                // Copy the data from staging buffers to device local buffers.
                StagingCommandBuffer.Begin(new CommandBufferBeginInfo(CommandBufferUsages.OneTimeSubmit));
                StagingCommandBuffer.CmdCopyBuffer(StagingBuffer, Buffer, new BufferCopy(mapSize, pos * size, pos * size));
                StagingCommandBuffer.End();

                // Submit.
                Context.GraphicsQueue.Submit(new SubmitInfo(commandBuffers: new[] { StagingCommandBuffer }), Fence);
                Fence.Wait();
                Fence.Reset();
                StagingCommandBuffer.Reset();

                return;
            }


            IntPtr ptr = Memory.Map(pos * size, count * size);

            Interop.Write(ptr, values);
            Memory.Unmap();
        }
        protected unsafe void AllocateMemory(MemoryPropertyFlags memoryProperties, MemoryRequirements memoryRequirements)
        {
            if (NativeMemory != DeviceMemory.Null)
                return;

            if (memoryRequirements.Size == 0)
                return;

            var allocateInfo = new MemoryAllocateInfo
            {
                StructureType = StructureType.MemoryAllocateInfo,
                AllocationSize = memoryRequirements.Size,
            };

            PhysicalDeviceMemoryProperties physicalDeviceMemoryProperties;
            GraphicsDevice.NativePhysicalDevice.GetMemoryProperties(out physicalDeviceMemoryProperties);
            var typeBits = memoryRequirements.MemoryTypeBits;
            for (uint i = 0; i < physicalDeviceMemoryProperties.MemoryTypeCount; i++)
            {
                if ((typeBits & 1) == 1)
                {
                    // Type is available, does it match user properties?
                    var memoryType = *((MemoryType*)&physicalDeviceMemoryProperties.MemoryTypes + i);
                    if ((memoryType.PropertyFlags & memoryProperties) == memoryProperties)
                    {
                        allocateInfo.MemoryTypeIndex = i;
                        break;
                    }
                }
                typeBits >>= 1;
            }

            NativeMemory = GraphicsDevice.NativeDevice.AllocateMemory(ref allocateInfo);
        }
Beispiel #4
0
        public void CreateDepth()
        {
            ImageCreateInfo imageInfo = new ImageCreateInfo
            {
                ImageType = ImageType.Image2D,
                Format    = Format.D16Unorm,
                Extent    = new Extent3D
                {
                    Width  = BackBufferWidth,
                    Height = BackBufferHeight,
                    Depth  = 1,
                },
                MipLevels   = 1,
                ArrayLayers = 1,
                Samples     = (uint)SampleCountFlags.Count1,
                Tiling      = ImageTiling.Optimal,
                Usage       = (uint)ImageUsageFlags.DepthStencilAttachment,
                Flags       = 0,
            };

            Image image = Device.CreateImage(imageInfo, null);
            MemoryRequirements memReq = Device.GetImageMemoryRequirements(image);

            uint memTypeIndex;

            if (!TryGetMemoryTypeFromProperties(memReq.MemoryTypeBits, 0, out memTypeIndex))
            {
                throw new Exception("Failed to create back buffer");
            }

            MemoryAllocateInfo allocInfo = new MemoryAllocateInfo
            {
                AllocationSize  = 0,
                MemoryTypeIndex = memTypeIndex,
            };

            DeviceMemory imageMem = Device.AllocateMemory(allocInfo, null);

            Device.BindImageMemory(image, imageMem, 0);

            SetImageLayout(image, ImageAspectFlags.Depth, ImageLayout.Undefined, ImageLayout.DepthStencilAttachmentOptimal, 0);

            ImageViewCreateInfo imageViewInfo = new ImageViewCreateInfo
            {
                Image            = image,
                Format           = imageInfo.Format,
                SubresourceRange = new ImageSubresourceRange
                {
                    AspectMask     = (uint)ImageAspectFlags.Depth,
                    BaseMipLevel   = 0,
                    LevelCount     = 1,
                    BaseArrayLayer = 0,
                    LayerCount     = 1,
                },
                Flags    = 0,
                ViewType = ImageViewType.View2D,
            };

            ImageView imageView = Device.CreateImageView(imageViewInfo, null);
        }
Beispiel #5
0
        public DeviceMemory(Device device, MemoryRequirements requirements)
        {
            Device     = device;
            MemoryType = requirements.FindMemoryType(PhysicalDevice);
            Logging.Allocations?.Trace(
                $"Allocating {Extensions.FormatFileSize(requirements.TypeRequirements.Size)} of {MemoryType.Flags} memory");
            if (MemoryType == null)
            {
                throw new NotSupportedException($"Unable to find memory type for {requirements}");
            }

            if (requirements.DedicatedMemory.RequirementLevel != MemoryRequirementLevel.None)
            {
                if (TryAllocateDedicated(requirements, MemoryType))
                {
                    return;
                }
                if (requirements.DedicatedMemory.RequirementLevel == MemoryRequirementLevel.Required)
                {
                    throw new NotSupportedException($"Unable to allocate dedicated memory for {requirements}");
                }
            }

            if (!TryAllocateNormal(requirements.TypeRequirements.Size, MemoryType))
            {
                throw new NotSupportedException($"Failed to allocate memory for {requirements}");
            }
        }
Beispiel #6
0
 private bool TryAllocateDedicated(MemoryRequirements req, MemoryType memoryType)
 {
     unsafe
     {
         if (!Device.ExtensionEnabled(VkExtension.KhrDedicatedAllocation))
         {
             return(false);
         }
         var dedInfo = new VkMemoryDedicatedAllocateInfoKHR()
         {
             SType = VkStructureType.MemoryDedicatedAllocateInfoKhr,
             PNext = IntPtr.Zero
         };
         if (!req.DedicatedMemory.Value.SetOwnerOn(ref dedInfo))
         {
             return(false);
         }
         var info = new VkMemoryAllocateInfo()
         {
             SType           = VkStructureType.MemoryAllocateInfo,
             AllocationSize  = req.TypeRequirements.Size,
             MemoryTypeIndex = memoryType.TypeIndex,
             PNext           = new IntPtr(&dedInfo)
         };
         Handle = Device.Handle.AllocateMemory(&info, Instance.AllocationCallbacks);
         if (Handle == VkDeviceMemory.Null)
         {
             return(false);
         }
         DedicatedMemoryOwner = req.DedicatedMemory.Value;
         Capacity             = req.TypeRequirements.Size;
         return(true);
     }
 }
Beispiel #7
0
        public void BindMemoryAndCreateView()
        {
            using (Image image = CreateImage())
            {
                PhysicalDeviceMemoryProperties deviceMemProps = PhysicalDevice.GetMemoryProperties();
                MemoryRequirements memReq = image.GetMemoryRequirements();

                using (DeviceMemory memory = Device.AllocateMemory(new MemoryAllocateInfo(
                    memReq.Size, 
                    deviceMemProps.MemoryTypes.IndexOf(memReq.MemoryTypeBits, 0))))
                {
                    image.BindMemory(memory);

                    var createInfo = new ImageViewCreateInfo
                    {
                        Format = Format.B8G8R8A8UNorm,
                        ViewType = ImageViewType.Image2D,
                        SubresourceRange = new ImageSubresourceRange
                        {
                            AspectMask = ImageAspects.Color,
                            LayerCount = 1,
                            LevelCount = 1
                        }
                    };
                    using (image.CreateView(createInfo)) { }
                    using (image.CreateView(createInfo, CustomAllocator)) { }
                }
            }
        }
        public Image(VulkanPhysicalDevice myDevice, ImageCreateInfo pCreateInfo, AllocationCallbacks pAllocator = null)
        {
            this.Device = myDevice;
            Result result;

            unsafe
            {
                fixed(UInt64 *ptrpImage = &this.m)
                {
                    result = Interop.NativeMethods.vkCreateImage(myDevice.LogicalDevice.m, pCreateInfo != null ? pCreateInfo.m : (Interop.ImageCreateInfo *) default(IntPtr), pAllocator != null ? pAllocator.m : null, ptrpImage);
                }

                if (result != Result.Success)
                {
                    throw new ResultException(result);
                }
            }

            MemoryRequirements myRequirements = GetImageMemoryRequirements();

            MemoryAllocateInfo MemInfo = new MemoryAllocateInfo();

            MemInfo.AllocationSize = myRequirements.Size;


            MemInfo.MemoryTypeIndex = myDevice.GetMemoryIndexFromProperty(myRequirements.MemoryTypeBits, MemoryPropertyFlags.DeviceLocal);



            deviceMemory = new DeviceMemory(myDevice.LogicalDevice, MemInfo);
            BindImageMemory(deviceMemory, 0);
        }
        internal Block Allocate(Chunk.Location location, MemoryRequirements requirements)
        {
            //Allocate in the first chunk that supports this requirement
            for (int i = 0; i < chunks.Count; i++)
            {
                if (chunks[i].MemoryLocation == location && chunks[i].IsSupported(requirements))
                {
                    Block?block = chunks[i].TryAllocate(requirements);
                    if (block != null)
                    {
                        return(block.Value);
                    }
                }
            }

            //If non supported the requirements then create a new chunk
            Chunk newChunk = new Chunk(logicalDevice, hostDevice, location, requirements.MemoryTypeBits);

            chunks.Add(newChunk);

            logger?.Log("MemoryPool",
                        $"New chuck allocated, location: {newChunk.MemoryLocation}, type: {newChunk.MemoryTypeIndex}, size: {ByteUtils.ByteToMegabyte(newChunk.TotalSize)} MB");

            //Allocate from the new chunk
            Block?newBlock = newChunk.TryAllocate(requirements);

            if (newBlock == null)
            {
                throw new Exception(
                          $"[{nameof(Pool)}] New chunk could not allocate this requirements, is it insanely big?");
            }
            return(newBlock.Value);
        }
Beispiel #10
0
        internal static Texture2D DepthStencil(Context ctx, int width, int height)
        {
            Image image = ctx.Device.CreateImage(new ImageCreateInfo
            {
                ImageType   = ImageType.Image2D,
                Format      = ctx.DepthStencilFormat,
                Extent      = new Extent3D(width, height, 1),
                MipLevels   = 1,
                ArrayLayers = 1,
                Samples     = SampleCounts.Count1,
                Tiling      = ImageTiling.Optimal,
                Usage       = ImageUsages.DepthStencilAttachment | ImageUsages.TransferSrc
            });
            MemoryRequirements memReq = image.GetMemoryRequirements();
            int heapIndex             = ctx.MemoryProperties.MemoryTypes.IndexOf(
                memReq.MemoryTypeBits, MemoryProperties.DeviceLocal);
            DeviceMemory memory = ctx.Device.AllocateMemory(new MemoryAllocateInfo(memReq.Size, heapIndex));

            image.BindMemory(memory);
            ImageView view = image.CreateView(new ImageViewCreateInfo(ctx.DepthStencilFormat,
                                                                      new ImageSubresourceRange(ImageAspects.Depth | ImageAspects.Stencil, 0, 1, 0, 1)));

            //var sampler = VKHelper.CreateSampler(ctx, Filter.Linear, Filter.Linear, SamplerMipmapMode.Nearest);

            return(new Texture2D(ctx, image, memory, view, ctx.DepthStencilFormat, new Vector2I(width, height), false));
        }
Beispiel #11
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 #12
0
        public void Write <T>(ref T value) where T : struct
        {
            if (WriteUsingStagingBuffer)
            {
                MemoryRequirements stagingReq = StagingBuffer.GetMemoryRequirements();
                IntPtr             vertexPtr  = StagingMemory.Map(0, stagingReq.Size);
                Interop.Write(vertexPtr, ref value);
                StagingMemory.Unmap();

                // Copy the data from staging buffers to device local buffers.
                StagingCommandBuffer.Begin(new CommandBufferBeginInfo(CommandBufferUsages.OneTimeSubmit));
                StagingCommandBuffer.CmdCopyBuffer(StagingBuffer, Buffer, new BufferCopy(Size));
                StagingCommandBuffer.End();

                // Submit.
                Context.GraphicsQueue.Submit(new SubmitInfo(commandBuffers: new[] { StagingCommandBuffer }), Fence);
                Fence.Wait();
                Fence.Reset();
                StagingCommandBuffer.Reset();

                return;
            }
            IntPtr ptr = Memory.Map(0, Interop.SizeOf <T>());

            Interop.Write(ptr, ref value);
            Memory.Unmap();
        }
Beispiel #13
0
        public void CmdDraw()
        {
            var renderPassCreateInfo = new RenderPassCreateInfo(new[] { new SubpassDescription(
                                                                            new[] { new AttachmentReference(0, ImageLayout.ColorAttachmentOptimal) }) },
                                                                new[] { new AttachmentDescription {
                                                                            Format = Format.B8G8R8A8UNorm, Samples = SampleCounts.Count1
                                                                        } });
            var imageCreateInfo = new ImageCreateInfo
            {
                Usage       = ImageUsages.ColorAttachment,
                Format      = Format.B8G8R8A8UNorm,
                Extent      = new Extent3D(2, 2, 1),
                ImageType   = ImageType.Image2D,
                MipLevels   = 1,
                ArrayLayers = 1,
                Samples     = SampleCounts.Count1
            };
            var imageViewCreateInfo = new ImageViewCreateInfo(
                Format.B8G8R8A8UNorm,
                new ImageSubresourceRange(ImageAspects.Color, 0, 1, 0, 1));

            using (ShaderModule vertexShader = Device.CreateShaderModule(new ShaderModuleCreateInfo(ReadAllBytes("Shader.vert.spv"))))
                using (ShaderModule fragmentShader = Device.CreateShaderModule(new ShaderModuleCreateInfo(ReadAllBytes("Shader.frag.spv"))))
                    using (PipelineLayout pipelineLayout = Device.CreatePipelineLayout())
                        using (RenderPass renderPass = Device.CreateRenderPass(renderPassCreateInfo))
                            using (Image image = Device.CreateImage(imageCreateInfo))
                            {
                                MemoryRequirements imageMemReq = image.GetMemoryRequirements();
                                int memTypeIndex = PhysicalDeviceMemoryProperties.MemoryTypes.IndexOf(imageMemReq.MemoryTypeBits, MemoryProperties.DeviceLocal);
                                using (DeviceMemory imageMemory = Device.AllocateMemory(new MemoryAllocateInfo(imageMemReq.Size, memTypeIndex)))
                                {
                                    image.BindMemory(imageMemory);
                                    using (ImageView imageView = image.CreateView(imageViewCreateInfo))
                                        using (Framebuffer framebuffer = renderPass.CreateFramebuffer(new FramebufferCreateInfo(new[] { imageView }, 2, 2)))
                                            using (Pipeline pipeline = Device.CreateGraphicsPipeline(new GraphicsPipelineCreateInfo(
                                                                                                         pipelineLayout,
                                                                                                         renderPass,
                                                                                                         0,
                                                                                                         new[]
                                            {
                                                new PipelineShaderStageCreateInfo(ShaderStages.Vertex, vertexShader, "main"),
                                                new PipelineShaderStageCreateInfo(ShaderStages.Fragment, fragmentShader, "main")
                                            },
                                                                                                         new PipelineInputAssemblyStateCreateInfo(),
                                                                                                         new PipelineVertexInputStateCreateInfo(),
                                                                                                         new PipelineRasterizationStateCreateInfo {
                                                RasterizerDiscardEnable = true, LineWidth = 1.0f
                                            })))
                                            {
                                                CommandBuffer.Begin();
                                                CommandBuffer.CmdBeginRenderPass(new RenderPassBeginInfo(framebuffer, new Rect2D(0, 0, 2, 2)));
                                                CommandBuffer.CmdBindPipeline(PipelineBindPoint.Graphics, pipeline);
                                                CommandBuffer.CmdDraw(3);
                                                CommandBuffer.CmdEndRenderPass();
                                                CommandBuffer.End();
                                            }
                                }
                            }
        }
Beispiel #14
0
        byte[] CopyBufferToArray(DeviceMemory bufferMem, MemoryRequirements memRequirements)
        {
            var map  = device.MapMemory(bufferMem, 0, memRequirements.Size);
            var data = new byte[memRequirements.Size];

            Marshal.Copy(map, data, 0, (int)((ulong)memRequirements.Size));
            device.UnmapMemory(bufferMem);
            return(data);
        }
Beispiel #15
0
        public MemoryAllocation AllocateDeviceMemory(
            PhysicalDevice physicalDevice,
            MemoryRequirements requirements,
            MemoryPropertyFlags flags = 0)
        {
            int memoryTypeIndex = FindSuitableMemoryTypeIndex(_api, physicalDevice, requirements.MemoryTypeBits, flags);

            if (memoryTypeIndex < 0)
            {
                return(default);
        public MemoryRequirements GetImageMemoryRequirements()
        {
            MemoryRequirements pMemoryRequirements;

            unsafe
            {
                pMemoryRequirements = new MemoryRequirements();
                Interop.NativeMethods.vkGetImageMemoryRequirements(Device.LogicalDevice.m, this.m, &pMemoryRequirements);
                return(pMemoryRequirements);
            }
        }
        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);
        }
Beispiel #18
0
        private static MemoryType FindDeviceMemory(PhysicalDevice dev, ulong capacity)
        {
            var req = new MemoryRequirements()
            {
                DeviceLocal      = MemoryRequirementLevel.Required,
                TypeRequirements = new VkMemoryRequirements()
                {
                    Size = capacity
                }
            };

            return(req.FindMemoryType(dev));
        }
        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 #20
0
        public static ImageWithMemory CreateSampledImageWithMemory(
            uint width,
            uint height,
            ImageUsageFlags imageUsageFlags,
            SampleCountFlags samples,
            Format format,
            ImageAspectFlags imageAspectFlags)
        {
            ImageWithMemory imageWithMemory = new ImageWithMemory
            {
                Image = VContext.Instance.device.CreateImage
                        (
                    new ImageCreateInfo()
                {
                    ImageType = ImageType.Image2D,
                    Format    = format,
                    Extent    = new Extent3D()
                    {
                        Width  = width,
                        Height = height,
                        Depth  = 1
                    },
                    MipLevels     = 1,
                    ArrayLayers   = 1,
                    Samples       = samples,
                    Tiling        = ImageTiling.Optimal,
                    Usage         = imageUsageFlags,
                    SharingMode   = SharingMode.Exclusive,
                    InitialLayout = ImageLayout.Undefined
                }
                        )
            };

            MemoryRequirements textureMemoryRequirements = VContext.Instance.device.GetImageMemoryRequirements(imageWithMemory.Image);
            uint memoryTypeIndex = Util.GetMemoryTypeIndex(textureMemoryRequirements.MemoryTypeBits, MemoryPropertyFlags.DeviceLocal);

            imageWithMemory.Memory = VContext.Instance.device.AllocateMemory
                                     (
                new MemoryAllocateInfo()
            {
                AllocationSize  = textureMemoryRequirements.Size,
                MemoryTypeIndex = memoryTypeIndex
            }
                                     );
            VContext.Instance.device.BindImageMemory(imageWithMemory.Image, imageWithMemory.Memory, 0);

            imageWithMemory.ImageView = VContext.Instance.CreateImageView(imageWithMemory.Image, format, imageAspectFlags);

            return(imageWithMemory);
        }
Beispiel #21
0
        private static MemoryType FindHostMemory(PhysicalDevice dev, bool requiresCoherent, ulong capacity)
        {
            var req = new MemoryRequirements()
            {
                HostVisible      = MemoryRequirementLevel.Required,
                HostCoherent     = requiresCoherent ? MemoryRequirementLevel.Required : MemoryRequirementLevel.Preferred,
                TypeRequirements = new VkMemoryRequirements()
                {
                    Size = capacity
                }
            };

            return(req.FindMemoryType(dev));
        }
        public DeferredTransfer(Device dev, Queue transferQueue)
        {
            Device = dev;
            var reqs = new MemoryRequirements
            {
                HostVisible  = MemoryRequirementLevel.Required,
                HostCoherent = MemoryRequirementLevel.Preferred
            };

            _transferType  = reqs.FindMemoryType(dev.PhysicalDevice);
            _transferQueue = transferQueue;
            _cmdBufferPool = new CommandPoolCached(dev, transferQueue.FamilyIndex, 32,
                                                   VkCommandPoolCreateFlag.Transient | VkCommandPoolCreateFlag.ResetCommandBuffer);
        }
        public void Initialize()
        {
            DeviceResource = Device.Logical.CreateBuffer(new BufferCreateInfo(
                                                             DeviceSize,
                                                             BufferUsages.StorageBuffer,
                                                             queueFamilyIndices: new[] { Device.QueueFamilyIndex }));

            MemoryRequirements memReq = DeviceResource.GetMemoryRequirements();

            DeviceAlignedSize = DeviceSize.Align(memReq.Alignment);

            MemoryType[] memoryTypes = Device.PhysicalMemoryProperties.MemoryTypes;
            int          memoryTypeIndex;

            if (Direction == ResourceDirection.CpuToGpu)
            {
                memoryTypeIndex = memoryTypes.IndexOf(memReq.MemoryTypeBits, MemoryProperties.DeviceLocal | MemoryProperties.HostVisible);
                if (memoryTypeIndex == -1)
                {
                    memoryTypeIndex = memoryTypes.IndexOf(memReq.MemoryTypeBits, MemoryProperties.HostVisible);
                }
            }
            else
            {
                memoryTypeIndex = memoryTypes.IndexOf(memReq.MemoryTypeBits,
                                                      MemoryProperties.HostVisible | MemoryProperties.HostCoherent | MemoryProperties.HostCached);
            }

            if (memoryTypeIndex == -1)
            {
                throw new ApplicationException("No suitable memory type found for storage buffer");
            }

            // Some platforms may have a limit on the maximum size of a single allocation.
            // For example, certain systems may fail to create allocations with a size greater than or equal to 4GB.
            // Such a limit is implementation-dependent, and if such a failure occurs then the error
            // VK_ERROR_OUT_OF_DEVICE_MEMORY should be returned.
            try
            {
                DeviceMemory = Device.Logical.AllocateMemory(new MemoryAllocateInfo(memReq.Size, memoryTypeIndex));
            }
            catch (VulkanException ex) when(ex.Result == Result.ErrorOutOfDeviceMemory)
            {
                // TODO: Allocate in chunks instead?
                throw;
            }

            DeviceResource.BindMemory(DeviceMemory);
        }
Beispiel #24
0
        internal static VKBuffer Index(Context ctx, int[] indices)
        {
            long size = indices.Length * sizeof(int);

            // Create staging buffer.
            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       indexPtr      = stagingMemory.Map(0, stagingReq.Size);

            Interop.Write(indexPtr, indices);
            stagingMemory.Unmap();
            stagingBuffer.BindMemory(stagingMemory);

            // Create a device local buffer.
            VulkanCore.Buffer  buffer = ctx.Device.CreateBuffer(new BufferCreateInfo(size, BufferUsages.IndexBuffer | 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 buffer to device local buffer.
            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, indices.Length, size));
        }
Beispiel #25
0
        public static VulkanBuffer Vertex <T>(VulkanContext ctx, T[] vertices) where T : struct
        {
            long size = vertices.Length * Interop.SizeOf <T>();

            // Create a staging buffer that is writable by host.
            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, vertices);
            stagingMemory.Unmap();
            stagingBuffer.BindMemory(stagingMemory);

            // Create a device local buffer where the vertex data will be copied and which will be used for rendering.
            Buffer             buffer = ctx.Device.CreateBuffer(new BufferCreateInfo(size, BufferUsages.VertexBuffer | 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 VulkanBuffer(buffer, memory, vertices.Length));
        }
Beispiel #26
0
        public static VulkanImage DepthStencil(VulkanContext device, int width, int height)
        {
            Format[] validFormats =
            {
                Format.D32SFloatS8UInt,
                Format.D32SFloat,
                Format.D24UNormS8UInt,
                Format.D16UNormS8UInt,
                Format.D16UNorm
            };

            Format?potentialFormat = validFormats.FirstOrDefault(
                validFormat =>
            {
                FormatProperties formatProps = device.PhysicalDevice.GetFormatProperties(validFormat);
                return((formatProps.OptimalTilingFeatures & FormatFeatures.DepthStencilAttachment) > 0);
            });

            if (!potentialFormat.HasValue)
            {
                throw new InvalidOperationException("Required depth stencil format not supported.");
            }

            Format format = potentialFormat.Value;

            Image image = device.Device.CreateImage(new ImageCreateInfo
            {
                ImageType   = ImageType.Image2D,
                Format      = format,
                Extent      = new Extent3D(width, height, 1),
                MipLevels   = 1,
                ArrayLayers = 1,
                Samples     = SampleCounts.Count1,
                Tiling      = ImageTiling.Optimal,
                Usage       = ImageUsages.DepthStencilAttachment | ImageUsages.TransferSrc
            });
            MemoryRequirements memReq = image.GetMemoryRequirements();
            int heapIndex             = device.MemoryProperties.MemoryTypes.IndexOf(
                memReq.MemoryTypeBits, MemoryProperties.DeviceLocal);
            DeviceMemory memory = device.Device.AllocateMemory(new MemoryAllocateInfo(memReq.Size, heapIndex));

            image.BindMemory(memory);
            ImageView view = image.CreateView(new ImageViewCreateInfo(format,
                                                                      new ImageSubresourceRange(ImageAspects.Depth | ImageAspects.Stencil, 0, 1, 0, 1)));

            return(new VulkanImage(image, memory, view, format));
        }
Beispiel #27
0
        public static VulkanBuffer DynamicUniform <T>(VulkanContext ctx, int count) where T : struct
        {
            long size = Interop.SizeOf <T>() * count;

            Buffer             buffer             = ctx.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 = ctx.MemoryProperties.MemoryTypes.IndexOf(
                memoryRequirements.MemoryTypeBits,
                MemoryProperties.HostVisible | MemoryProperties.HostCoherent);
            DeviceMemory memory = ctx.Device.AllocateMemory(new MemoryAllocateInfo(memoryRequirements.Size, memoryTypeIndex));

            buffer.BindMemory(memory);

            return(new VulkanBuffer(buffer, memory, count));
        }
Beispiel #28
0
        public unsafe static DeviceMemory AllocateDeviceMemory(
            Vk vk,
            Device device,
            PhysicalDevice physicalDevice,
            MemoryRequirements requirements,
            out long size,
            MemoryPropertyFlags flags = 0,
            bool isExternal           = false)
        {
            _vk = vk;

            size = 0;

            int memoryTypeIndex = FindSuitableMemoryTypeIndex(physicalDevice, requirements.MemoryTypeBits, flags);

            if (memoryTypeIndex < 0)
            {
                return(default);
Beispiel #29
0
        public void BindMemoryAndCreateBufferView()
        {
            using (Buffer buffer = CreateBuffer())
            {
                PhysicalDeviceMemoryProperties deviceMemProps = PhysicalDevice.GetMemoryProperties();
                MemoryRequirements             memReq         = buffer.GetMemoryRequirements();
                var memoryAllocateInfo = new MemoryAllocateInfo(
                    memReq.Size,
                    deviceMemProps.MemoryTypes.IndexOf(memReq.MemoryTypeBits, 0));

                using (DeviceMemory memory = Device.AllocateMemory(memoryAllocateInfo))
                {
                    buffer.BindMemory(memory);

                    var bufferViewCreateInfo = new BufferViewCreateInfo(Format.R32UInt);
                    using (buffer.CreateView(bufferViewCreateInfo)) { }
                    using (buffer.CreateView(bufferViewCreateInfo, CustomAllocator)) { }
                }
            }
        }
Beispiel #30
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 #31
0
        public void CmdBindVertexAndIndexBuffer()
        {
            const int bufferSize = 256;

            using (Buffer buffer = Device.CreateBuffer(new BufferCreateInfo(bufferSize, BufferUsages.VertexBuffer | BufferUsages.IndexBuffer)))
            {
                MemoryRequirements memReq = buffer.GetMemoryRequirements();
                int memTypeIndex          = PhysicalDeviceMemoryProperties.MemoryTypes.IndexOf(
                    memReq.MemoryTypeBits, MemoryProperties.HostVisible);
                using (DeviceMemory memory = Device.AllocateMemory(new MemoryAllocateInfo(memReq.Size, memTypeIndex)))
                {
                    buffer.BindMemory(memory);

                    CommandBuffer.Begin();
                    CommandBuffer.CmdBindVertexBuffer(buffer);
                    CommandBuffer.CmdBindVertexBuffers(0, 1, new[] { buffer }, new long[] { 0 });
                    CommandBuffer.CmdBindIndexBuffer(buffer);
                    CommandBuffer.End();
                }
            }
        }
Beispiel #32
0
 internal static unsafe extern void vkGetBufferMemoryRequirements(Device device, Buffer buffer, MemoryRequirements* memoryRequirements);
Beispiel #33
0
 internal static unsafe extern void vkGetImageMemoryRequirements(Device device, Image image, MemoryRequirements* memoryRequirements);
Beispiel #34
0
 public unsafe void GetBufferMemoryRequirements(Buffer buffer, out MemoryRequirements memoryRequirements)
 {
     fixed (MemoryRequirements* __memoryRequirements__ = &memoryRequirements)
     {
         vkGetBufferMemoryRequirements(this, buffer, __memoryRequirements__);
     }
 }
Beispiel #35
0
 public unsafe void GetImageMemoryRequirements(Image image, out MemoryRequirements memoryRequirements)
 {
     fixed (MemoryRequirements* __memoryRequirements__ = &memoryRequirements)
     {
         vkGetImageMemoryRequirements(this, image, __memoryRequirements__);
     }
 }