internal static unsafe void AllocatePool(out VkDeviceMemory NativeMemory, ref VkDevice device, ref VkPhysicalDevice pDevice, ref VkMemoryPropertyFlags memoryProperties, ref VkMemoryRequirements memoryRequirements, ulong size) { var allocateInfo = new VkMemoryAllocateInfo { sType = VkStructureType.MemoryAllocateInfo, allocationSize = size, }; Vortice.Vulkan.Vulkan.vkGetPhysicalDeviceMemoryProperties(pDevice, out var 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 = *(&physicalDeviceMemoryProperties.memoryTypes_0 + i); if ((memoryType.propertyFlags & memoryProperties) == memoryProperties) { allocateInfo.memoryTypeIndex = i; break; } } typeBits >>= 1; } NativeMemory = new VkDeviceMemory(); Vortice.Vulkan.Vulkan.vkAllocateMemory(device, &allocateInfo, null, out NativeMemory); }
public static VkMemoryAllocateInfo memoryAllocateInfo() { VkMemoryAllocateInfo memAllocInfo = new VkMemoryAllocateInfo(); memAllocInfo.sType = VkStructureType.MemoryAllocateInfo; return(memAllocInfo); }
public ChunkAllocator(VkDevice device, uint memoryTypeIndex, bool persistentMapped) { _device = device; _memoryTypeIndex = memoryTypeIndex; _persistentMapped = persistentMapped; _totalMemorySize = persistentMapped ? PersistentMappedChunkSize : UnmappedChunkSize; VkMemoryAllocateInfo memoryAI = VkMemoryAllocateInfo.New(); memoryAI.allocationSize = _totalMemorySize; memoryAI.memoryTypeIndex = _memoryTypeIndex; VkResult result = vkAllocateMemory(_device, ref memoryAI, null, out _memory); CheckResult(result); void *mappedPtr = null; if (persistentMapped) { result = vkMapMemory(_device, _memory, 0, _totalMemorySize, 0, &mappedPtr); CheckResult(result); } VkMemoryBlock initialBlock = new VkMemoryBlock(_memory, 0, _totalMemorySize, _memoryTypeIndex, mappedPtr); _freeBlocks.Add(initialBlock); }
public void Allocate(uint memoryTypeIndex) { if (imageMemoryBind.memory != VkDeviceMemory.Null) { return; } imageMemoryBind = new VkSparseImageMemoryBind(); var allocInfo = new VkMemoryAllocateInfo(); allocInfo.sType = VkStructureType.MemoryAllocateInfo; allocInfo.allocationSize = size; allocInfo.memoryTypeIndex = memoryTypeIndex; imageMemoryBind.memory = Device.AllocateMemory(ref allocInfo); // Sparse image memory binding imageMemoryBind.subresource = new VkImageSubresource { aspectMask = VkImageAspectFlags.Color, mipLevel = mipLevel, arrayLayer = layer, }; imageMemoryBind.extent = extent; imageMemoryBind.offset = offset; }
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); } }
void CreateImage(int width, int height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, out VkImage image, out VkDeviceMemory memory) { var info = new VkImageCreateInfo(); info.imageType = VkImageType._2D; info.extent.width = width; info.extent.height = height; info.extent.depth = 1; info.mipLevels = 1; info.arrayLayers = 1; info.format = format; info.tiling = tiling; info.initialLayout = VkImageLayout.Undefined; info.usage = usage; info.sharingMode = VkSharingMode.Exclusive; info.samples = VkSampleCountFlags._1_Bit; image = new VkImage(device, info); var req = image.Requirements; var allocInfo = new VkMemoryAllocateInfo(); allocInfo.allocationSize = req.size; allocInfo.memoryTypeIndex = FindMemoryType(req.memoryTypeBits, properties); memory = new VkDeviceMemory(device, allocInfo); image.Bind(memory, 0); }
protected void allocateMemory() { VkMemoryAllocateInfo memInfo = VkMemoryAllocateInfo.New(); memInfo.allocationSize = memReqs.size; memInfo.memoryTypeIndex = Dev.GetMemoryTypeIndex(memReqs.memoryTypeBits, MemoryFlags); Utils.CheckResult(vkAllocateMemory(Dev.VkDev, ref memInfo, IntPtr.Zero, out vkMemory)); }
internal unsafe void AllocateOneTimeUploadBuffer(int size, out UploadBuffer uploadBuffer) { var bufferCreateInfo = new VkBufferCreateInfo { sType = VkStructureType.BufferCreateInfo, size = (ulong)size, flags = VkBufferCreateFlags.None, usage = VkBufferUsageFlags.TransferSrc, }; uploadBuffer = new UploadBuffer { size = size }; vkCreateBuffer(NativeDevice, &bufferCreateInfo, null, out uploadBuffer.buffer); // figure out the memory type if (properType == uint.MaxValue) { VkMemoryPropertyFlags memoryProperties = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent; vkGetBufferMemoryRequirements(nativeDevice, uploadBuffer.buffer, out var memoryRequirements); vkGetPhysicalDeviceMemoryProperties(NativePhysicalDevice, out var 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 = *(&physicalDeviceMemoryProperties.memoryTypes_0 + i); if ((memoryType.propertyFlags & memoryProperties) == memoryProperties) { properType = i; break; } } typeBits >>= 1; } } var allocateInfo = new VkMemoryAllocateInfo { sType = VkStructureType.MemoryAllocateInfo, allocationSize = (ulong)size, memoryTypeIndex = properType }; fixed(VkDeviceMemory *nativeUploadBufferMemoryPtr = &uploadBuffer.memory) vkAllocateMemory(NativeDevice, &allocateInfo, null, nativeUploadBufferMemoryPtr); vkBindBufferMemory(NativeDevice, uploadBuffer.buffer, uploadBuffer.memory, 0); fixed(IntPtr *nativeUploadBufferStartPtr = &uploadBuffer.address) vkMapMemory(NativeDevice, uploadBuffer.memory, 0, (ulong)size, VkMemoryMapFlags.None, (void **)nativeUploadBufferStartPtr); }
public override VkResult AllocateMemory(VkMemoryAllocateInfo pAllocateInfo, out VkDeviceMemory pMemory) { VkPreconditions.CheckRange(pAllocateInfo.allocationSize, 1, int.MaxValue, nameof(pAllocateInfo.allocationSize)); VkPreconditions.CheckRange(pAllocateInfo.memoryTypeIndex != 0, nameof(pAllocateInfo.memoryTypeIndex)); var ret = new SoftwareDeviceMemory(this, pAllocateInfo); m_DeviceMemory.Add(ret); pMemory = ret; return(VkResult.VK_SUCCESS); }
protected unsafe void AllocateMemory(VkMemoryPropertyFlags memoryProperties, VkMemoryRequirements memoryRequirements) { if (NativeMemory != VkDeviceMemory.Null) { return; } if (memoryRequirements.size == 0) { return; } var allocateInfo = new VkMemoryAllocateInfo { sType = VkStructureType.MemoryAllocateInfo, allocationSize = memoryRequirements.size, }; VkPhysicalDeviceMemoryProperties localProps; if (!gotProps) { gotProps = true; vkGetPhysicalDeviceMemoryProperties(GraphicsDevice.NativePhysicalDevice, out physicalDeviceMemoryProperties); } localProps = physicalDeviceMemoryProperties; var typeBits = memoryRequirements.memoryTypeBits; for (uint i = 0; i < localProps.memoryTypeCount; i++) { if ((typeBits & 1) == 1) { // Type is available, does it match user properties? var memoryType = *(&localProps.memoryTypes_0 + i); if ((memoryType.propertyFlags & memoryProperties) == memoryProperties) { allocateInfo.memoryTypeIndex = i; break; } } typeBits >>= 1; } var result = vkAllocateMemory(GraphicsDevice.NativeDevice, &allocateInfo, null, out NativeMemory); if (result != VkResult.Success) { string err = "Couldn't allocate memory: " + result + ", NativeMemory: " + NativeMemory + ", type: " + allocateInfo.memoryTypeIndex + ", size: " + memoryRequirements.size; Xenko.Core.ErrorFileLogger.WriteLogToFile(err); throw new Exception(err); } }
public VkMemoryBlock Allocate( VkPhysicalDeviceMemoryProperties memProperties, uint memoryTypeBits, VkMemoryPropertyFlags flags, bool persistentMapped, ulong size, ulong alignment) { lock (_lock) { uint memoryTypeIndex = FindMemoryType(memProperties, memoryTypeBits, flags); ulong minDedicatedAllocationSize = persistentMapped ? MinDedicatedAllocationSizeDynamic : MinDedicatedAllocationSizeNonDynamic; if (size >= minDedicatedAllocationSize) { VkMemoryAllocateInfo allocateInfo = VkMemoryAllocateInfo.New(); allocateInfo.allocationSize = size; allocateInfo.memoryTypeIndex = memoryTypeIndex; VkResult allocationResult = vkAllocateMemory(_device, ref allocateInfo, null, out VkDeviceMemory memory); if (allocationResult != VkResult.Success) { throw new VeldridException("Unable to allocate sufficient Vulkan memory."); } void *mappedPtr = null; if (persistentMapped) { VkResult mapResult = vkMapMemory(_device, memory, 0, size, 0, &mappedPtr); if (mapResult != VkResult.Success) { throw new VeldridException("Unable to map newly-allocated Vulkan memory."); } } return(new VkMemoryBlock(memory, 0, size, memoryTypeBits, null, true)); } else { ChunkAllocatorSet allocator = GetAllocator(memoryTypeIndex, persistentMapped); bool result = allocator.Allocate(size, alignment, out VkMemoryBlock ret); if (!result) { throw new VeldridException("Unable to allocate sufficient Vulkan memory."); } return(ret); } } }
void CreateDeviceMemory(ulong allocationSize, uint memoryTypeIndex) { var info = new VkMemoryAllocateInfo(); info.sType = VkStructureType.MemoryAllocateInfo; info.allocationSize = allocationSize; info.memoryTypeIndex = memoryTypeIndex; Device.Commands.allocateMemory(Device.Native, ref info, Device.Instance.AllocationCallbacks, out deviceMemory); Size = allocationSize; MemoryTypeIndex = memoryTypeIndex; }
/** * Create a buffer on the device * * @param usageFlags Usage flag bitmask for the buffer (i.e. index, vertex, uniform buffer) * @param memoryPropertyFlags Memory properties for this buffer (i.e. device local, host visible, coherent) * @param buffer Pointer to a vk::Vulkan buffer object * @param size Size of the buffer in byes * @param data Pointer to the data that should be copied to the buffer after creation (optional, if not set, no data is copied over) * * @return Success if buffer handle and memory have been created and (optionally passed) data has been copied */ public VkResult createBuffer(VkBufferUsageFlagBits usageFlags, VkMemoryPropertyFlagBits memoryPropertyFlags, vksBuffer buffer, ulong size, void *data = null) { buffer.device = _logicalDevice; // Create the buffer handle VkBufferCreateInfo bufferCreateInfo = new VkBufferCreateInfo(); bufferCreateInfo.sType = BufferCreateInfo; bufferCreateInfo.usage = usageFlags; bufferCreateInfo.size = size; { VkBuffer vkBuffer; vkCreateBuffer(_logicalDevice, &bufferCreateInfo, null, &vkBuffer); buffer.buffer = vkBuffer; } // Create the memory backing up the buffer handle VkMemoryRequirements memReqs; VkMemoryAllocateInfo memAlloc = new VkMemoryAllocateInfo(); memAlloc.sType = MemoryAllocateInfo; vkGetBufferMemoryRequirements(_logicalDevice, buffer.buffer, &memReqs); memAlloc.allocationSize = memReqs.size; // Find a memory type index that fits the properties of the buffer memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags); { VkDeviceMemory memory; vkAllocateMemory(_logicalDevice, &memAlloc, null, &memory); buffer.memory = memory; } buffer.alignment = memReqs.alignment; buffer.size = memAlloc.allocationSize; buffer.usageFlags = usageFlags; buffer.memoryPropertyFlags = memoryPropertyFlags; // If a pointer to the buffer data has been passed, map the buffer and copy over the data if (data != null) { buffer.map(); Unsafe.CopyBlock(buffer.mapped, data, (uint)size); buffer.unmap(); } // Initialize a default descriptor that covers the whole buffer size buffer.setupDescriptor(); // Attach the memory to the buffer object return(buffer.bind()); }
private VkDeviceMemory CreateVulkanDeviceMemory() { _state.ThrowIfDisposedOrDisposing(); VkDeviceMemory vulkanDeviceMemory; var memoryAllocateInfo = new VkMemoryAllocateInfo { sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, allocationSize = Size, memoryTypeIndex = GetMemoryTypeIndex(VulkanGraphicsDevice.VulkanGraphicsAdapter.VulkanPhysicalDevice, CpuAccess), }; ThrowExternalExceptionIfNotSuccess(nameof(vkAllocateMemory), vkAllocateMemory(VulkanGraphicsDevice.VulkanDevice, &memoryAllocateInfo, pAllocator: null, (ulong *)&vulkanDeviceMemory)); return(vulkanDeviceMemory);
public ChunkAllocator(VkDevice device, uint memoryTypeIndex) { _device = device; _memoryTypeIndex = memoryTypeIndex; VkMemoryAllocateInfo memoryAI = VkMemoryAllocateInfo.New(); memoryAI.allocationSize = _totalMemorySize; memoryAI.memoryTypeIndex = _memoryTypeIndex; VkResult result = vkAllocateMemory(_device, ref memoryAI, null, out _memory); CheckResult(result); VkMemoryBlock initialBlock = new VkMemoryBlock(_memory, 0, _totalMemorySize, _memoryTypeIndex); _freeBlocks.Add(initialBlock); }
public static VulkanBuffer DynamicUniform <T>(VulkanContext ctx, int count) where T : struct { long size = Unsafe.SizeOf <T>() * count; VkBufferCreateInfo createInfo = new VkBufferCreateInfo { sType = VkStructureType.BufferCreateInfo, pNext = null, size = (ulong)size, usage = VkBufferUsageFlags.UniformBuffer }; VkBuffer buffer; VkResult result = vkCreateBuffer(ctx.Device, &createInfo, null, out buffer); result.CheckResult(); VkMemoryRequirements memoryRequirements; vkGetBufferMemoryRequirements(ctx.Device, buffer, out memoryRequirements); vkGetPhysicalDeviceMemoryProperties(ctx.PhysicalDevice, out VkPhysicalDeviceMemoryProperties memoryProperties); uint memoryTypeIndex = BufferHelper.GetMemoryTypeIndex(memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent, memoryProperties); // 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. VkMemoryAllocateInfo memAllocInfo = new VkMemoryAllocateInfo() { sType = VkStructureType.MemoryAllocateInfo, pNext = null, allocationSize = memoryRequirements.size, memoryTypeIndex = memoryTypeIndex }; VkDeviceMemory memory; result = vkAllocateMemory(ctx.Device, &memAllocInfo, null, &memory); result.CheckResult(); result = vkBindBufferMemory(ctx.Device, buffer, memory, 0); result.CheckResult(); return(new VulkanBuffer(ctx.Device, ctx.GraphicsCommandPool, buffer, memory, count)); }
private void Setup() { disposed = false; VkImageCreateInfo image = VkImageCreateInfo.New(); image.imageType = VkImageType.Image2D; image.format = device.DepthFormat; image.extent = new VkExtent3D() { width = swapchain.width, height = swapchain.height, depth = 1 }; image.mipLevels = 1; image.arrayLayers = 1; image.samples = VkSampleCountFlags.Count1; image.tiling = VkImageTiling.Optimal; image.usage = (VkImageUsageFlags.DepthStencilAttachment | VkImageUsageFlags.TransferSrc); image.flags = 0; VkMemoryAllocateInfo mem_alloc = VkMemoryAllocateInfo.New(); mem_alloc.allocationSize = 0; mem_alloc.memoryTypeIndex = 0; VkImageViewCreateInfo depthStencilView = VkImageViewCreateInfo.New(); depthStencilView.viewType = VkImageViewType.Image2D; depthStencilView.format = device.DepthFormat; depthStencilView.flags = 0; depthStencilView.subresourceRange = new VkImageSubresourceRange(); depthStencilView.subresourceRange.aspectMask = (VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil); depthStencilView.subresourceRange.baseMipLevel = 0; depthStencilView.subresourceRange.levelCount = 1; depthStencilView.subresourceRange.baseArrayLayer = 0; depthStencilView.subresourceRange.layerCount = 1; Util.CheckResult(vkCreateImage(device.device, &image, null, out vkImage)); vkGetImageMemoryRequirements(device.device, vkImage, out VkMemoryRequirements memReqs); mem_alloc.allocationSize = memReqs.size; mem_alloc.memoryTypeIndex = device.vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal); Util.CheckResult(vkAllocateMemory(device.device, &mem_alloc, null, out vkMem)); Util.CheckResult(vkBindImageMemory(device.device, vkImage, vkMem, 0)); depthStencilView.image = vkImage; Util.CheckResult(vkCreateImageView(device.device, ref depthStencilView, null, out vkView)); }
/** * Create a buffer on the device * * @param usageFlags Usage flag bitmask for the buffer (i.e. index, vertex, uniform buffer) * @param memoryPropertyFlags Memory properties for this buffer (i.e. device local, host visible, coherent) * @param size Size of the buffer in byes * @param buffer Pointer to the buffer handle acquired by the function * @param memory Pointer to the memory handle acquired by the function * @param data Pointer to the data that should be copied to the buffer after creation (optional, if not set, no data is copied over) * * @return Success if buffer handle and memory have been created and (optionally passed) data has been copied */ public VkResult createBuffer(VkBufferUsageFlagBits usageFlags, VkMemoryPropertyFlagBits memoryPropertyFlags, ulong size, VkBuffer *buffer, VkDeviceMemory *memory, void *data = null) { // Create the buffer handle VkBufferCreateInfo bufferCreateInfo = new VkBufferCreateInfo(); bufferCreateInfo.sType = BufferCreateInfo; bufferCreateInfo.usage = usageFlags; bufferCreateInfo.size = size; bufferCreateInfo.sharingMode = VkSharingMode.Exclusive; vkCreateBuffer(LogicalDevice, &bufferCreateInfo, null, buffer); // Create the memory backing up the buffer handle VkMemoryRequirements memReqs; VkMemoryAllocateInfo memAlloc = new VkMemoryAllocateInfo(); memAlloc.sType = MemoryAllocateInfo; vkGetBufferMemoryRequirements(LogicalDevice, *buffer, &memReqs); memAlloc.allocationSize = memReqs.size; // Find a memory type index that fits the properties of the buffer memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags); vkAllocateMemory(LogicalDevice, &memAlloc, null, memory); // If a pointer to the buffer data has been passed, map the buffer and copy over the data if (data != null) { IntPtr mapped; vkMapMemory(LogicalDevice, *memory, 0, size, 0, &mapped); Unsafe.CopyBlock(mapped, data, (uint)size); // If host coherency hasn't been requested, do a manual flush to make writes visible if ((memoryPropertyFlags & VkMemoryPropertyFlagBits.HostCoherent) == 0) { VkMappedMemoryRange mappedRange = new VkMappedMemoryRange(); mappedRange.memory = *memory; mappedRange.offset = 0; mappedRange.size = size; vkFlushMappedMemoryRanges(LogicalDevice, 1, &mappedRange); } vkUnmapMemory(LogicalDevice, *memory); } // Attach the memory to the buffer object vkBindBufferMemory(LogicalDevice, *buffer, *memory, 0); return(VkResult.Success); }
void CreateBuffer(long size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, out VkBuffer buffer, out VkDeviceMemory memory) { var info = new VkBufferCreateInfo(); info.size = size; info.usage = usage; info.sharingMode = VkSharingMode.Exclusive; buffer = new VkBuffer(device, info); var allocInfo = new VkMemoryAllocateInfo(); allocInfo.allocationSize = buffer.Requirements.size; allocInfo.memoryTypeIndex = FindMemoryType(buffer.Requirements.memoryTypeBits, properties); memory = new VkDeviceMemory(device, allocInfo); buffer.Bind(memory, 0); }
protected virtual void SetupDepthStencil() { VkImageCreateInfo image = VkImageCreateInfo.New(); image.imageType = VkImageType._2d; image.format = DepthFormat; image.extent = new VkExtent3D() { width = Width, height = Height, depth = 1 }; image.mipLevels = 1; image.arrayLayers = 1; image.samples = VkSampleCountFlags._1; image.tiling = VkImageTiling.Optimal; image.usage = (VkImageUsageFlags.DepthStencilAttachment | VkImageUsageFlags.TransferSrc); image.flags = 0; VkMemoryAllocateInfo mem_alloc = VkMemoryAllocateInfo.New(); mem_alloc.allocationSize = 0; mem_alloc.memoryTypeIndex = 0; VkImageViewCreateInfo depthStencilView = VkImageViewCreateInfo.New(); depthStencilView.viewType = VkImageViewType._2d; depthStencilView.format = DepthFormat; depthStencilView.flags = 0; depthStencilView.subresourceRange = new VkImageSubresourceRange(); depthStencilView.subresourceRange.aspectMask = (VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil); depthStencilView.subresourceRange.baseMipLevel = 0; depthStencilView.subresourceRange.levelCount = 1; depthStencilView.subresourceRange.baseArrayLayer = 0; depthStencilView.subresourceRange.layerCount = 1; Util.CheckResult(vkCreateImage(Device, &image, null, out DepthStencil.Image)); vkGetImageMemoryRequirements(Device, DepthStencil.Image, out VkMemoryRequirements memReqs); mem_alloc.allocationSize = memReqs.size; mem_alloc.memoryTypeIndex = VulkanDevice.GetMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal); Util.CheckResult(vkAllocateMemory(Device, &mem_alloc, null, out DepthStencil.Mem)); Util.CheckResult(vkBindImageMemory(Device, DepthStencil.Image, DepthStencil.Mem, 0)); depthStencilView.image = DepthStencil.Image; Util.CheckResult(vkCreateImageView(Device, ref depthStencilView, null, out DepthStencil.View)); }
private void CreateDepthImage(VkPhysicalDevice physicalDevice, uint width, uint height) { VkImageCreateInfo createInfo = VkImageCreateInfo.New(); createInfo.imageType = VkImageType.Image2D; createInfo.extent.width = width; createInfo.extent.height = height; createInfo.extent.depth = 1; createInfo.mipLevels = 1; createInfo.arrayLayers = 1; createInfo.format = VkFormat.D32Sfloat; createInfo.tiling = VkImageTiling.Optimal; createInfo.initialLayout = VkImageLayout.Undefined; createInfo.usage = VkImageUsageFlags.DepthStencilAttachment; createInfo.sharingMode = VkSharingMode.Exclusive; createInfo.samples = VkSampleCountFlags.Count1; VkImage depthImage; Assert(vkCreateImage(device, &createInfo, null, &depthImage)); VkMemoryRequirements memoryRequirements; vkGetImageMemoryRequirements(device, depthImage, &memoryRequirements); VkPhysicalDeviceMemoryProperties memoryProperties = new VkPhysicalDeviceMemoryProperties(); vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties); VkMemoryAllocateInfo allocateInfo = VkMemoryAllocateInfo.New(); allocateInfo.allocationSize = memoryRequirements.size; allocateInfo.memoryTypeIndex = FDataBuffer <byte> .SelectMemoryType(memoryProperties, memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal); VkDeviceMemory depthImageMemory; Assert(vkAllocateMemory(device, &allocateInfo, null, &depthImageMemory)); vkBindImageMemory(device, depthImage, depthImageMemory, 0); this.depthImage = depthImage; this.depthImageMemory = depthImageMemory; }
private VkDeviceMemory CreateVulkanDeviceMemory() { ThrowIfDisposedOrDisposing(_state, nameof(VulkanGraphicsMemoryBlock)); VkDeviceMemory vulkanDeviceMemory; var collection = Collection; var vulkanDevice = collection.Allocator.Device.VulkanDevice; var memoryAllocateInfo = new VkMemoryAllocateInfo { sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, allocationSize = Size, memoryTypeIndex = collection.VulkanMemoryTypeIndex, }; ThrowExternalExceptionIfNotSuccess(vkAllocateMemory(vulkanDevice, &memoryAllocateInfo, pAllocator: null, (ulong *)&vulkanDeviceMemory), nameof(vkAllocateMemory)); return(vulkanDeviceMemory); }
internal VkResult AllocateDeviceMemory() { VkMemoryAllocateInfo info = VkMemoryAllocateInfo.New(); info.allocationSize = max_size; info.memoryTypeIndex = memoryTypeIndex; VkResult result = vkAllocateMemory(device.device, &info, null, out vkDeviceMemory); if (result != VkResult.Success) { return(result); } if ((memoryPropertyFlags & VkMemoryPropertyFlags.HostVisible) != 0) { Map(); } return(result); }
protected unsafe void AllocateMemory(VkMemoryPropertyFlags memoryProperties, VkMemoryRequirements memoryRequirements) { if (NativeMemory != VkDeviceMemory.Null) { return; } if (memoryRequirements.size == 0) { return; } var allocateInfo = new VkMemoryAllocateInfo { sType = VkStructureType.MemoryAllocateInfo, allocationSize = memoryRequirements.size, }; vkGetPhysicalDeviceMemoryProperties(GraphicsDevice.NativePhysicalDevice, out var 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 = *(&physicalDeviceMemoryProperties.memoryTypes_0 + i); if ((memoryType.propertyFlags & memoryProperties) == memoryProperties) { allocateInfo.memoryTypeIndex = i; break; } } typeBits >>= 1; } fixed(VkDeviceMemory *nativeMemoryPtr = &NativeMemory) vkAllocateMemory(GraphicsDevice.NativeDevice, &allocateInfo, null, nativeMemoryPtr); }
public FDataBuffer(VkDevice device, VkPhysicalDevice physicalDevice, int length, VkBufferUsageFlags usage, VkSharingMode sharingMode) { this.device = device; VkBufferCreateInfo createInfo = VkBufferCreateInfo.New(); size = (ulong)(sizeof(T) * length); createInfo.size = size; createInfo.usage = usage; createInfo.sharingMode = sharingMode; VkBuffer buffer = VkBuffer.Null; Assert(vkCreateBuffer(device, &createInfo, null, &buffer)); this.Buffer = buffer; VkMemoryRequirements memoryRequirements = new VkMemoryRequirements(); vkGetBufferMemoryRequirements(device, this.Buffer, &memoryRequirements); VkPhysicalDeviceMemoryProperties memoryProperties = new VkPhysicalDeviceMemoryProperties(); vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties); VkMemoryAllocateInfo allocateInfo = VkMemoryAllocateInfo.New(); allocateInfo.allocationSize = memoryRequirements.size; allocateInfo.memoryTypeIndex = SelectMemoryType(memoryProperties, memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent); VkDeviceMemory memory = new VkDeviceMemory(); Assert(vkAllocateMemory(device, &allocateInfo, null, &memory)); Memory = memory; Assert(vkBindBufferMemory(device, this.Buffer, memory, 0)); spanLength = length; }
private void createVertexBuffer() { VkBufferCreateInfo bufferInfo = new VkBufferCreateInfo(); bufferInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferInfo.size = Marshal.SizeOf(vertices[0]) * vertices.Length; bufferInfo.usage = VkBufferUsageFlagBits.VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; bufferInfo.sharingMode = VkSharingMode.VK_SHARING_MODE_EXCLUSIVE; VkResult result = Vulkan.vkCreateBuffer(device, bufferInfo, null, out vertexBuffer); if (result != VkResult.VK_SUCCESS) { throw Program.Throw("failed to create vertex buffer!", result); } VkMemoryRequirements memRequirements; Vulkan.vkGetBufferMemoryRequirements(device, vertexBuffer, out memRequirements); VkMemoryAllocateInfo allocInfo = new VkMemoryAllocateInfo(); allocInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.allocationSize = memRequirements.size; allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, VkMemoryPropertyFlagBits.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VkMemoryPropertyFlagBits.VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); result = Vulkan.vkAllocateMemory(device, allocInfo, null, out vertexBufferMemory); if (result != VkResult.VK_SUCCESS) { throw Program.Throw("failed to allocate vertex buffer memory!", result); } Vulkan.vkBindBufferMemory(device, vertexBuffer, vertexBufferMemory, 0); byte[] data; Vulkan.vkMapMemory(device, vertexBufferMemory, 0, bufferInfo.size, 0, out data); MemoryCopyHelper.Copy(vertices, data, 0, bufferInfo.size); Vulkan.vkUnmapMemory(device, vertexBufferMemory); }
private bool TryAllocateNormal(ulong capacity, MemoryType memoryType) { unsafe { var info = new VkMemoryAllocateInfo() { SType = VkStructureType.MemoryAllocateInfo, AllocationSize = capacity, MemoryTypeIndex = memoryType.TypeIndex, PNext = IntPtr.Zero }; Handle = Device.Handle.AllocateMemory(&info, Instance.AllocationCallbacks); } if (Handle == VkDeviceMemory.Null) { return(false); } DedicatedMemoryOwner = null; Capacity = capacity; return(true); }
protected unsafe void AllocateMemory(VkMemoryPropertyFlags memoryProperties) { vkGetBufferMemoryRequirements(nativeDevice, nativeUploadBuffer, out var memoryRequirements); if (memoryRequirements.size == 0) { return; } var allocateInfo = new VkMemoryAllocateInfo { sType = VkStructureType.MemoryAllocateInfo, allocationSize = memoryRequirements.size, }; vkGetPhysicalDeviceMemoryProperties(NativePhysicalDevice, out var 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 = *(&physicalDeviceMemoryProperties.memoryTypes_0 + i); if ((memoryType.propertyFlags & memoryProperties) == memoryProperties) { allocateInfo.memoryTypeIndex = i; break; } } typeBits >>= 1; } vkAllocateMemory(NativeDevice, &allocateInfo, null, out nativeUploadBufferMemory); vkBindBufferMemory(NativeDevice, nativeUploadBuffer, nativeUploadBufferMemory, 0); }
VkBuffer CreateBuffer(VkPhysicalDevice physicalDevice, VkDevice device, object values, VkBufferUsageFlagBits usageFlags, System.Type type) { var array = values as System.Array; var length = (array != null) ? array.Length : 1; var size = System.Runtime.InteropServices.Marshal.SizeOf(type) * length; VkBuffer buffer; { UInt32 index = 0; var info = new VkBufferCreateInfo { sType = VkStructureType.BufferCreateInfo }; info.size = (UInt64)size; info.usage = usageFlags; info.sharingMode = VkSharingMode.Exclusive; info.queueFamilyIndices = index; //VkBuffer buffer = device.CreateBuffer(ref info); vkAPI.vkCreateBuffer(device, &info, null, &buffer).Check(); info.Free(); } VkDeviceMemory deviceMemory; // = device.AllocateMemory(ref allocInfo); VkMemoryRequirements memoryReq; //VkMemoryRequirements memoryReq = device.GetBufferMemoryRequirements(buffer); vkAPI.vkGetBufferMemoryRequirements(device, buffer, &memoryReq); var allocInfo = new VkMemoryAllocateInfo { sType = VkStructureType.MemoryAllocateInfo }; { allocInfo.allocationSize = memoryReq.size; VkPhysicalDeviceMemoryProperties memoryProperties; vkAPI.vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties); allocInfo.memoryTypeIndex = GetMemoryTypeIndex(memoryProperties, memoryReq, VkMemoryPropertyFlagBits.HostVisible | VkMemoryPropertyFlagBits.HostCoherent); vkAPI.vkAllocateMemory(device, &allocInfo, null, &deviceMemory).Check(); } { IntPtr memPtr = IntPtr.Zero; vkAPI.vkMapMemory(device, deviceMemory, 0, (UInt64)size, 0, &memPtr).Check(); if (type == typeof(float)) { System.Runtime.InteropServices.Marshal.Copy(values as float[], 0, memPtr, length); } else if (type == typeof(short)) { System.Runtime.InteropServices.Marshal.Copy(values as short[], 0, memPtr, length); } else if (type == typeof(AreaUniformBuffer)) { System.Runtime.InteropServices.Marshal.StructureToPtr(values, memPtr, false); this.vkBuffer = buffer; this.vkDeviceMemory = deviceMemory; this.uniformSize = memoryReq.size; } vkAPI.vkUnmapMemory(device, deviceMemory); } vkAPI.vkBindBufferMemory(device, buffer, deviceMemory, 0).Check(); return(buffer); }
/** * Load a 2D texture including all mip levels * * @param filename File to load (supports .ktx and .dds) * @param format Vulkan format of the image data stored in the file * @param device Vulkan device to create the texture on * @param copyQueue Queue used for the texture staging copy commands (must support transfer) * @param (Optional) imageUsageFlags Usage flags for the texture's image (defaults to VK_IMAGE_USAGE_SAMPLED_BIT) * @param (Optional) imageLayout Usage layout for the texture (defaults VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) * @param (Optional) forceLinear Force linear tiling (not advised, defaults to false) * */ public void loadFromFile( string filename, VkFormat format, vksVulkanDevice device, VkQueue copyQueue, VkImageUsageFlagBits imageUsageFlags = VkImageUsageFlagBits.Sampled, VkImageLayout imageLayout = VkImageLayout.ShaderReadOnlyOptimal, bool forceLinear = false) { KtxFile tex2D; using (var fs = File.OpenRead(filename)) { tex2D = KtxFile.Load(fs, false); } this.device = device; width = tex2D.Header.PixelWidth; height = tex2D.Header.PixelHeight; if (height == 0) { height = width; } mipLevels = tex2D.Header.NumberOfMipmapLevels; // Get device properites for the requested texture format VkFormatProperties formatProperties; vkGetPhysicalDeviceFormatProperties(device.PhysicalDevice, format, &formatProperties); // Only use linear tiling if requested (and supported by the device) // Support for linear tiling is mostly limited, so prefer to use // optimal tiling instead // On most implementations linear tiling will only support a very // limited amount of formats and features (mip maps, cubemaps, arrays, etc.) bool useStaging = !forceLinear; VkMemoryAllocateInfo memAllocInfo = new VkMemoryAllocateInfo(); memAllocInfo.sType = MemoryAllocateInfo; VkMemoryRequirements memReqs; // Use a separate command buffer for texture loading VkCommandBuffer copyCmd = device.createCommandBuffer(VkCommandBufferLevel.Primary, true); if (useStaging) { // Create a host-visible staging buffer that contains the raw image data VkBuffer stagingBuffer; VkDeviceMemory stagingMemory; VkBufferCreateInfo bufferCreateInfo = new VkBufferCreateInfo(); bufferCreateInfo.sType = BufferCreateInfo; bufferCreateInfo.size = tex2D.GetTotalSize(); // This buffer is used as a transfer source for the buffer copy bufferCreateInfo.usage = VkBufferUsageFlagBits.TransferSrc; bufferCreateInfo.sharingMode = VkSharingMode.Exclusive; vkCreateBuffer(device.LogicalDevice, &bufferCreateInfo, null, &stagingBuffer); // Get memory requirements for the staging buffer (alignment, memory type bits) vkGetBufferMemoryRequirements(device.LogicalDevice, stagingBuffer, &memReqs); memAllocInfo.allocationSize = memReqs.size; // Get memory type index for a host visible buffer memAllocInfo.memoryTypeIndex = device.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlagBits.HostVisible | VkMemoryPropertyFlagBits.HostCoherent); vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, &stagingMemory); vkBindBufferMemory(device.LogicalDevice, stagingBuffer, stagingMemory, 0); // Copy texture data into staging buffer IntPtr data; vkMapMemory(device.LogicalDevice, stagingMemory, 0, memReqs.size, 0, &data); byte[] pixelData = tex2D.GetAllTextureData(); fixed(byte *pixelDataPtr = &pixelData[0]) { Unsafe.CopyBlock(data, pixelDataPtr, (uint)pixelData.Length); } vkUnmapMemory(device.LogicalDevice, stagingMemory); // Setup buffer copy regions for each mip level var bufferCopyRegions = new List <VkBufferImageCopy>(); uint offset = 0; for (uint i = 0; i < mipLevels; i++) { VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy(); bufferCopyRegion.imageSubresource.aspectMask = VkImageAspectFlagBits.Color; bufferCopyRegion.imageSubresource.mipLevel = i; bufferCopyRegion.imageSubresource.baseArrayLayer = 0; bufferCopyRegion.imageSubresource.layerCount = 1; bufferCopyRegion.imageExtent.width = tex2D.Faces[0].Mipmaps[i].Width; bufferCopyRegion.imageExtent.height = tex2D.Faces[0].Mipmaps[i].Height; bufferCopyRegion.imageExtent.depth = 1; bufferCopyRegion.bufferOffset = offset; bufferCopyRegions.Add(bufferCopyRegion); offset += tex2D.Faces[0].Mipmaps[i].SizeInBytes; } // Create optimal tiled target image VkImageCreateInfo imageCreateInfo = new VkImageCreateInfo(); imageCreateInfo.sType = ImageCreateInfo; imageCreateInfo.imageType = VkImageType._2d; imageCreateInfo.format = format; imageCreateInfo.mipLevels = mipLevels; imageCreateInfo.arrayLayers = 1; imageCreateInfo.samples = VkSampleCountFlagBits._1; imageCreateInfo.tiling = VkImageTiling.Optimal; imageCreateInfo.sharingMode = VkSharingMode.Exclusive; imageCreateInfo.initialLayout = VkImageLayout.Undefined; imageCreateInfo.extent = new VkExtent3D { width = width, height = height, depth = 1 }; imageCreateInfo.usage = imageUsageFlags; // Ensure that the TRANSFER_DST bit is set for staging if ((imageCreateInfo.usage & VkImageUsageFlagBits.TransferDst) == 0) { imageCreateInfo.usage |= VkImageUsageFlagBits.TransferDst; } { VkImage vkImage; vkCreateImage(device.LogicalDevice, &imageCreateInfo, null, &vkImage); this.image = vkImage; } vkGetImageMemoryRequirements(device.LogicalDevice, image, &memReqs); memAllocInfo.allocationSize = memReqs.size; memAllocInfo.memoryTypeIndex = device.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlagBits.DeviceLocal); { VkDeviceMemory memory; vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, &memory); this.deviceMemory = memory; } vkBindImageMemory(device.LogicalDevice, image, deviceMemory, 0); VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange(); subresourceRange.aspectMask = VkImageAspectFlagBits.Color; subresourceRange.baseMipLevel = 0; subresourceRange.levelCount = mipLevels; subresourceRange.layerCount = 1; // Image barrier for optimal image (target) // Optimal image will be used as destination for the copy Tools.setImageLayout( copyCmd, image, VkImageAspectFlagBits.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, subresourceRange); // Copy mip levels from staging buffer fixed(VkBufferImageCopy *pointer = bufferCopyRegions.ToArray()) { vkCmdCopyBufferToImage( copyCmd, stagingBuffer, image, VkImageLayout.TransferDstOptimal, (UInt32)bufferCopyRegions.Count, pointer); } // Change texture image layout to shader read after all mip levels have been copied this.imageLayout = imageLayout; Tools.setImageLayout( copyCmd, image, VkImageAspectFlagBits.Color, VkImageLayout.TransferDstOptimal, imageLayout, subresourceRange); device.flushCommandBuffer(copyCmd, copyQueue); // Clean up staging resources vkFreeMemory(device.LogicalDevice, stagingMemory, null); vkDestroyBuffer(device.LogicalDevice, stagingBuffer, null); } else { throw new NotImplementedException(); /* * // Prefer using optimal tiling, as linear tiling * // may support only a small set of features * // depending on implementation (e.g. no mip maps, only one layer, etc.) * * // Check if this support is supported for linear tiling * Debug.Assert((formatProperties.linearTilingFeatures & VkFormatFeatureFlags.SampledImage) != 0); * * VkImage mappableImage; * VkDeviceMemory mappableMemory; * * VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo(); * imageCreateInfo.imageType = VkImageType._2d; * imageCreateInfo.format = format; * imageCreateInfo.extent = new VkExtent3D { width = width, height = height, depth = 1 }; * imageCreateInfo.mipLevels = 1; * imageCreateInfo.arrayLayers = 1; * imageCreateInfo.samples = VkSampleCountFlags._1; * imageCreateInfo.tiling = VkImageTiling.Linear; * imageCreateInfo.usage = imageUsageFlags; * imageCreateInfo.sharingMode = VkSharingMode.Exclusive; * imageCreateInfo.initialLayout = VkImageLayout.Undefined; * * // Load mip map level 0 to linear tiling image * Util.CheckResult(vkCreateImage(device.LogicalDevice, &imageCreateInfo, null, &mappableImage)); * * // Get memory requirements for this image * // like size and alignment * vkGetImageMemoryRequirements(device.LogicalDevice, mappableImage, &memReqs); * // Set memory allocation size to required memory size * memAllocInfo.allocationSize = memReqs.size; * * // Get memory type that can be mapped to host memory * memAllocInfo.memoryTypeIndex = device.GetMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent); * * // Allocate host memory * Util.CheckResult(vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, &mappableMemory)); * * // Bind allocated image for use * Util.CheckResult(vkBindImageMemory(device.LogicalDevice, mappableImage, mappableMemory, 0)); * * // Get sub resource layout * // Mip map count, array layer, etc. * VkImageSubresource subRes = new VkImageSubresource(); * subRes.aspectMask = VkImageAspectFlags.Color; * subRes.mipLevel = 0; * * VkSubresourceLayout subResLayout; * void* data; * * // Get sub resources layout * // Includes row pitch, size offsets, etc. * vkGetImageSubresourceLayout(device.LogicalDevice, mappableImage, &subRes, &subResLayout); * * // Map image memory * Util.CheckResult(vkMapMemory(device.LogicalDevice, mappableMemory, 0, memReqs.size, 0, &data)); * * // Copy image data into memory * memcpy(data, tex2D[subRes.mipLevel].data(), tex2D[subRes.mipLevel].size()); * * vkUnmapMemory(device.LogicalDevice, mappableMemory); * * // Linear tiled images don't need to be staged * // and can be directly used as textures * image = mappableImage; * deviceMemory = mappableMemory; * imageLayout = imageLayout; * * // Setup image memory barrier * vks::tools::setImageLayout(copyCmd, image, VkImageAspectFlags.Color, VkImageLayout.Undefined, imageLayout); * * device.flushCommandBuffer(copyCmd, copyQueue); */ } // Create a defaultsampler VkSamplerCreateInfo samplerCreateInfo = new VkSamplerCreateInfo(); samplerCreateInfo.sType = SamplerCreateInfo; samplerCreateInfo.magFilter = VkFilter.Linear; samplerCreateInfo.minFilter = VkFilter.Linear; samplerCreateInfo.mipmapMode = VkSamplerMipmapMode.Linear; samplerCreateInfo.addressModeU = VkSamplerAddressMode.Repeat; samplerCreateInfo.addressModeV = VkSamplerAddressMode.Repeat; samplerCreateInfo.addressModeW = VkSamplerAddressMode.Repeat; samplerCreateInfo.mipLodBias = 0.0f; samplerCreateInfo.compareOp = VkCompareOp.Never; samplerCreateInfo.minLod = 0.0f; // Max level-of-detail should match mip level count samplerCreateInfo.maxLod = (useStaging) ? (float)mipLevels : 0.0f; // Enable anisotropic filtering samplerCreateInfo.maxAnisotropy = 8; samplerCreateInfo.anisotropyEnable = true; samplerCreateInfo.borderColor = VkBorderColor.FloatOpaqueWhite; { VkSampler vkSampler; vkCreateSampler(device.LogicalDevice, &samplerCreateInfo, null, &vkSampler); this.sampler = vkSampler; } // Create image view // Textures are not directly accessed by the shaders and // are abstracted by image views containing additional // information and sub resource ranges VkImageViewCreateInfo viewCreateInfo = new VkImageViewCreateInfo(); viewCreateInfo.sType = ImageViewCreateInfo; viewCreateInfo.viewType = VkImageViewType._2d; viewCreateInfo.format = format; viewCreateInfo.components = new VkComponentMapping { r = VkComponentSwizzle.R, g = VkComponentSwizzle.G, b = VkComponentSwizzle.B, a = VkComponentSwizzle.A }; viewCreateInfo.subresourceRange = new VkImageSubresourceRange { aspectMask = VkImageAspectFlagBits.Color, baseMipLevel = 0, levelCount = 1, baseArrayLayer = 0, layerCount = 1 }; // Linear tiling usually won't support mip maps // Only set mip map count if optimal tiling is used viewCreateInfo.subresourceRange.levelCount = (useStaging) ? mipLevels : 1; viewCreateInfo.image = image; { VkImageView vkImageView; vkCreateImageView(device.LogicalDevice, &viewCreateInfo, null, &vkImageView); this.view = vkImageView; } // Update descriptor image info member that can be used for setting up descriptor sets updateDescriptor(); }