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)); }
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); }
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); }
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}"); } }
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); } }
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); }
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)); }
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])); }
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(); }
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(); } } } }
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); }
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); }
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); }
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); }
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); }
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)); }
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)); }
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)); }
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)); }
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);
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)) { } } } }
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 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(); } } }
internal static unsafe extern void vkGetBufferMemoryRequirements(Device device, Buffer buffer, MemoryRequirements* memoryRequirements);
internal static unsafe extern void vkGetImageMemoryRequirements(Device device, Image image, MemoryRequirements* memoryRequirements);
public unsafe void GetBufferMemoryRequirements(Buffer buffer, out MemoryRequirements memoryRequirements) { fixed (MemoryRequirements* __memoryRequirements__ = &memoryRequirements) { vkGetBufferMemoryRequirements(this, buffer, __memoryRequirements__); } }
public unsafe void GetImageMemoryRequirements(Image image, out MemoryRequirements memoryRequirements) { fixed (MemoryRequirements* __memoryRequirements__ = &memoryRequirements) { vkGetImageMemoryRequirements(this, image, __memoryRequirements__); } }