public override void GetBufferMemoryRequirements(VkBuffer buffer, out VkMemoryRequirements pMemoryRequirements) { pMemoryRequirements = new VkMemoryRequirements(); pMemoryRequirements.memoryTypeBits = 1; pMemoryRequirements.size = ((SoftwareBuffer)buffer).createInfo.size; pMemoryRequirements.alignment = 4; }
internal void GetImageMemoryRequirements(out VkMemoryRequirements pMemoryRequirements) { int pixelSize = 4; pMemoryRequirements.alignment = 4; pMemoryRequirements.memoryTypeBits = int.MaxValue; pMemoryRequirements.size = m_imageExtent.width * m_imageExtent.height * m_imageExtent.depth * pixelSize; }
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 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; }
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); }
void loadTexture(string fileName, VkFormat format, bool forceLinearTiling) { KtxFile tex2D; using (var fs = File.OpenRead(fileName)) { tex2D = KtxFile.Load(fs, false); } VkFormatProperties formatProperties; texture.width = tex2D.Header.PixelWidth; texture.height = tex2D.Header.PixelHeight; texture.mipLevels = tex2D.Header.NumberOfMipmapLevels; // Get Device properites for the requested texture format vkGetPhysicalDeviceFormatProperties(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.) uint useStaging = 1; // Only use linear tiling if forced if (forceLinearTiling) { // Don't use linear if format is not supported for (linear) shader sampling useStaging = ((formatProperties.linearTilingFeatures & VkFormatFeatureFlags.SampledImage) != VkFormatFeatureFlags.SampledImage) ? 1u : 0u; } VkMemoryAllocateInfo memAllocInfo = Initializers.memoryAllocateInfo(); VkMemoryRequirements memReqs = new VkMemoryRequirements(); if (useStaging == 1) { // Create a host-visible staging buffer that contains the raw image data VkBuffer stagingBuffer; VkDeviceMemory stagingMemory; VkBufferCreateInfo bufferCreateInfo = Initializers.bufferCreateInfo(); bufferCreateInfo.size = tex2D.GetTotalSize(); // This buffer is used as a transfer source for the buffer copy bufferCreateInfo.usage = VkBufferUsageFlags.TransferSrc; bufferCreateInfo.sharingMode = VkSharingMode.Exclusive; Util.CheckResult(vkCreateBuffer(device, &bufferCreateInfo, null, &stagingBuffer)); // Get memory requirements for the staging buffer (alignment, memory type bits) vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs); memAllocInfo.allocationSize = memReqs.size; // Get memory type index for a host visible buffer memAllocInfo.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent); Util.CheckResult(vkAllocateMemory(device, &memAllocInfo, null, &stagingMemory)); Util.CheckResult(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0)); // Copy texture data into staging buffer byte *data; Util.CheckResult(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data)); byte[] allData = tex2D.GetAllTextureData(); fixed(byte *tex2DDataPtr = &allData[0]) { Unsafe.CopyBlock(data, tex2DDataPtr, (uint)allData.Length); } vkUnmapMemory(device, stagingMemory); // Setup buffer copy regions for each mip level NativeList <VkBufferImageCopy> bufferCopyRegions = new NativeList <VkBufferImageCopy>(); uint offset = 0; for (uint i = 0; i < texture.mipLevels; i++) { VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy(); bufferCopyRegion.imageSubresource.aspectMask = VkImageAspectFlags.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 = Initializers.imageCreateInfo(); imageCreateInfo.imageType = VkImageType.Image2D; imageCreateInfo.format = format; imageCreateInfo.mipLevels = texture.mipLevels; imageCreateInfo.arrayLayers = 1; imageCreateInfo.samples = VkSampleCountFlags.Count1; imageCreateInfo.tiling = VkImageTiling.Optimal; imageCreateInfo.sharingMode = VkSharingMode.Exclusive; // Set initial layout of the image to undefined imageCreateInfo.initialLayout = VkImageLayout.Undefined; imageCreateInfo.extent = new VkExtent3D { width = texture.width, height = texture.height, depth = 1 }; imageCreateInfo.usage = VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled; Util.CheckResult(vkCreateImage(device, &imageCreateInfo, null, out texture.image)); vkGetImageMemoryRequirements(device, texture.image, &memReqs); memAllocInfo.allocationSize = memReqs.size; memAllocInfo.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal); Util.CheckResult(vkAllocateMemory(device, &memAllocInfo, null, out texture.DeviceMemory)); Util.CheckResult(vkBindImageMemory(device, texture.image, texture.DeviceMemory, 0)); VkCommandBuffer copyCmd = base.createCommandBuffer(VkCommandBufferLevel.Primary, true); // Image barrier for optimal image // The sub resource range describes the regions of the image we will be transition VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange(); // Image only contains color data subresourceRange.aspectMask = VkImageAspectFlags.Color; // Start at first mip level subresourceRange.baseMipLevel = 0; // We will transition on all mip levels subresourceRange.levelCount = texture.mipLevels; // The 2D texture only has one layer subresourceRange.layerCount = 1; // Optimal image will be used as destination for the copy, so we must transfer from our // initial undefined image layout to the transfer destination layout setImageLayout( copyCmd, texture.image, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, subresourceRange); // Copy mip levels from staging buffer vkCmdCopyBufferToImage( copyCmd, stagingBuffer, texture.image, VkImageLayout.TransferDstOptimal, bufferCopyRegions.Count, bufferCopyRegions.Data); // Change texture image layout to shader read after all mip levels have been copied texture.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; setImageLayout( copyCmd, texture.image, VkImageAspectFlags.Color, VkImageLayout.TransferDstOptimal, texture.imageLayout, subresourceRange); flushCommandBuffer(copyCmd, queue, true); // Clean up staging resources vkFreeMemory(device, stagingMemory, null); vkDestroyBuffer(device, 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.) * * VkImage mappableImage; * VkDeviceMemory mappableMemory; * * // Load mip map level 0 to linear tiling image * VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo(); * imageCreateInfo.imageType = VkImageType._2d; * imageCreateInfo.format = format; * imageCreateInfo.mipLevels = 1; * imageCreateInfo.arrayLayers = 1; * imageCreateInfo.samples = VkSampleCountFlags._1; * imageCreateInfo.tiling = VkImageTiling.Linear; * imageCreateInfo.usage = VkImageUsageFlags.Sampled; * imageCreateInfo.sharingMode = VkSharingMode.Exclusive; * imageCreateInfo.initialLayout = VkImageLayout.Preinitialized; * imageCreateInfo.extent = new VkExtent3D { width = texture.width, height = texture.height, depth = 1 }; * Util.CheckResult(vkCreateImage(Device, &imageCreateInfo, null, &mappableImage)); * * // Get memory requirements for this image * // like size and alignment * vkGetImageMemoryRequirements(Device, 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 = VulkanDevice.GetMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent); * * // Allocate host memory * Util.CheckResult(vkAllocateMemory(Device, &memAllocInfo, null, &mappableMemory)); * * // Bind allocated image for use * Util.CheckResult(vkBindImageMemory(Device, mappableImage, mappableMemory, 0)); * * // Get sub resource layout * // Mip map count, array layer, etc. * VkImageSubresource subRes = new VkImageSubresource(); * subRes.aspectMask = VkImageAspectFlags.Color; * * VkSubresourceLayout subResLayout; * void* data; * * // Get sub resources layout * // Includes row pitch, size offsets, etc. * vkGetImageSubresourceLayout(Device, mappableImage, &subRes, &subResLayout); * * // Map image memory * Util.CheckResult(vkMapMemory(Device, mappableMemory, 0, memReqs.size, 0, &data)); * * // Copy image data into memory * memcpy(data, tex2D[subRes.mipLevel].data(), tex2D[subRes.mipLevel].size()); * * vkUnmapMemory(Device, mappableMemory); * * // Linear tiled images don't need to be staged * // and can be directly used as textures * texture.image = mappableImage; * texture.DeviceMemory = mappableMemory; * texture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; * * VkCommandBuffer copyCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); * * // Setup image memory barrier transfer image to shader read layout * * // The sub resource range describes the regions of the image we will be transition * VkImageSubresourceRange subresourceRange = { }; * // Image only contains color data * subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; * // Start at first mip level * subresourceRange.baseMipLevel = 0; * // Only one mip level, most implementations won't support more for linear tiled images * subresourceRange.levelCount = 1; * // The 2D texture only has one layer * subresourceRange.layerCount = 1; * * setImageLayout( * copyCmd, * texture.image, * VK_IMAGE_ASPECT_COLOR_BIT, * VK_IMAGE_LAYOUT_PREINITIALIZED, * texture.imageLayout, * subresourceRange); * * VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true); */ } // Create sampler // In Vulkan textures are accessed by samplers // This separates all the sampling information from the // texture data // This means you could have multiple sampler objects // for the same texture with different settings // Similar to the samplers available with OpenGL 3.3 VkSamplerCreateInfo sampler = Initializers.samplerCreateInfo(); sampler.magFilter = VkFilter.Linear; sampler.minFilter = VkFilter.Linear; sampler.mipmapMode = VkSamplerMipmapMode.Linear; sampler.addressModeU = VkSamplerAddressMode.Repeat; sampler.addressModeV = VkSamplerAddressMode.Repeat; sampler.addressModeW = VkSamplerAddressMode.Repeat; sampler.mipLodBias = 0.0f; sampler.compareOp = VkCompareOp.Never; sampler.minLod = 0.0f; // Set max level-of-detail to mip level count of the texture sampler.maxLod = (useStaging == 1) ? (float)texture.mipLevels : 0.0f; // Enable anisotropic filtering // This feature is optional, so we must check if it's supported on the Device if (vulkanDevice.features.samplerAnisotropy == 1) { // Use max. level of anisotropy for this example sampler.maxAnisotropy = vulkanDevice.properties.limits.maxSamplerAnisotropy; sampler.anisotropyEnable = True; } else { // The Device does not support anisotropic filtering sampler.maxAnisotropy = 1.0f; sampler.anisotropyEnable = False; } sampler.borderColor = VkBorderColor.FloatOpaqueWhite; Util.CheckResult(vkCreateSampler(device, ref sampler, null, out texture.sampler)); // 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 view = Initializers.imageViewCreateInfo(); view.viewType = VkImageViewType.Image2D; view.format = format; view.components = new VkComponentMapping { r = VkComponentSwizzle.R, g = VkComponentSwizzle.G, b = VkComponentSwizzle.B, a = VkComponentSwizzle.A }; // The subresource range describes the set of mip levels (and array layers) that can be accessed through this image view // It's possible to create multiple image views for a single image referring to different (and/or overlapping) ranges of the image view.subresourceRange.aspectMask = VkImageAspectFlags.Color; view.subresourceRange.baseMipLevel = 0; view.subresourceRange.baseArrayLayer = 0; view.subresourceRange.layerCount = 1; // Linear tiling usually won't support mip maps // Only set mip map count if optimal tiling is used view.subresourceRange.levelCount = (useStaging == 1) ? texture.mipLevels : 1; // The view will be based on the texture's image view.image = texture.image; Util.CheckResult(vkCreateImageView(device, &view, null, out texture.view)); }
public VkBuffer(VkGraphicsDevice gd, uint sizeInBytes, BufferUsage usage, string callerMember = null) { _gd = gd; SizeInBytes = sizeInBytes; Usage = usage; VkBufferUsageFlags vkUsage = VkBufferUsageFlags.TransferSrc | VkBufferUsageFlags.TransferDst; if ((usage & BufferUsage.VertexBuffer) == BufferUsage.VertexBuffer) { vkUsage |= VkBufferUsageFlags.VertexBuffer; } if ((usage & BufferUsage.IndexBuffer) == BufferUsage.IndexBuffer) { vkUsage |= VkBufferUsageFlags.IndexBuffer; } if ((usage & BufferUsage.UniformBuffer) == BufferUsage.UniformBuffer) { vkUsage |= VkBufferUsageFlags.UniformBuffer; } if ((usage & BufferUsage.StructuredBufferReadWrite) == BufferUsage.StructuredBufferReadWrite || (usage & BufferUsage.StructuredBufferReadOnly) == BufferUsage.StructuredBufferReadOnly) { vkUsage |= VkBufferUsageFlags.StorageBuffer; } if ((usage & BufferUsage.IndirectBuffer) == BufferUsage.IndirectBuffer) { vkUsage |= VkBufferUsageFlags.IndirectBuffer; } VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New(); bufferCI.size = sizeInBytes; bufferCI.usage = vkUsage; VkResult result = vkCreateBuffer(gd.Device, ref bufferCI, null, out _deviceBuffer); CheckResult(result); bool prefersDedicatedAllocation; if (_gd.GetBufferMemoryRequirements2 != null) { VkBufferMemoryRequirementsInfo2KHR memReqInfo2 = VkBufferMemoryRequirementsInfo2KHR.New(); memReqInfo2.buffer = _deviceBuffer; VkMemoryRequirements2KHR memReqs2 = VkMemoryRequirements2KHR.New(); VkMemoryDedicatedRequirementsKHR dedicatedReqs = VkMemoryDedicatedRequirementsKHR.New(); memReqs2.pNext = &dedicatedReqs; _gd.GetBufferMemoryRequirements2(_gd.Device, &memReqInfo2, &memReqs2); _bufferMemoryRequirements = memReqs2.memoryRequirements; prefersDedicatedAllocation = dedicatedReqs.prefersDedicatedAllocation || dedicatedReqs.requiresDedicatedAllocation; } else { vkGetBufferMemoryRequirements(gd.Device, _deviceBuffer, out _bufferMemoryRequirements); prefersDedicatedAllocation = false; } bool hostVisible = (usage & BufferUsage.Dynamic) == BufferUsage.Dynamic || (usage & BufferUsage.Staging) == BufferUsage.Staging; VkMemoryPropertyFlags memoryPropertyFlags = hostVisible ? VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent : VkMemoryPropertyFlags.DeviceLocal; VkMemoryBlock memoryToken = gd.MemoryManager.Allocate( gd.PhysicalDeviceMemProperties, _bufferMemoryRequirements.memoryTypeBits, memoryPropertyFlags, hostVisible, _bufferMemoryRequirements.size, _bufferMemoryRequirements.alignment, prefersDedicatedAllocation, VkImage.Null, _deviceBuffer); _memory = memoryToken; result = vkBindBufferMemory(gd.Device, _deviceBuffer, _memory.DeviceMemory, _memory.Offset); CheckResult(result); RefCount = new ResourceRefCount(DisposeCore); }
public override void GetImageMemoryRequirements(VkImage image, out VkMemoryRequirements pMemoryRequirements) { throw new NotImplementedException(); }
public override void GetBufferMemoryRequirements(VkBuffer buffer, out VkMemoryRequirements pMemoryRequirements) { throw new NotImplementedException(); }
public VulkanMemorySlice Allocate(VkMemoryRequirements requirements, bool hostVisible) => Allocate(requirements.size, requirements.alignment, requirements.memoryTypeBits, hostVisible);
private void CopyDataSingleStagingBuffer(IntPtr pixelsFront, IntPtr pixelsBack, IntPtr pixelsLeft, IntPtr pixelsRight, IntPtr pixelsTop, IntPtr pixelsBottom, VkMemoryRequirements memReqs) { VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New(); bufferCI.size = memReqs.size; bufferCI.usage = VkBufferUsageFlags.TransferSrc; vkCreateBuffer(_device, ref bufferCI, null, out VkBuffer stagingBuffer); vkGetBufferMemoryRequirements(_device, stagingBuffer, out VkMemoryRequirements stagingMemReqs); VkMemoryBlock stagingMemory = _memoryManager.Allocate( FindMemoryType( _physicalDevice, stagingMemReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent), stagingMemReqs.size, stagingMemReqs.alignment); VkResult result = vkBindBufferMemory(_device, stagingBuffer, stagingMemory.DeviceMemory, 0); CheckResult(result); StackList <IntPtr, Size6IntPtr> faces = new StackList <IntPtr, Size6IntPtr>(); faces.Add(pixelsRight); faces.Add(pixelsLeft); faces.Add(pixelsTop); faces.Add(pixelsBottom); faces.Add(pixelsBack); faces.Add(pixelsFront); for (uint i = 0; i < 6; i++) { VkImageSubresource subresource; subresource.aspectMask = VkImageAspectFlags.Color; subresource.arrayLayer = i; subresource.mipLevel = 0; vkGetImageSubresourceLayout(_device, _image, ref subresource, out VkSubresourceLayout faceLayout); void *mappedPtr; result = vkMapMemory(_device, stagingMemory.DeviceMemory, faceLayout.offset, faceLayout.size, 0, &mappedPtr); CheckResult(result); Buffer.MemoryCopy((void *)faces[i], mappedPtr, faceLayout.size, faceLayout.size); vkUnmapMemory(_device, stagingMemory.DeviceMemory); } StackList <VkBufferImageCopy, Size512Bytes> copyRegions = new StackList <VkBufferImageCopy, Size512Bytes>(); for (uint i = 0; i < 6; i++) { VkImageSubresource subres; subres.aspectMask = VkImageAspectFlags.Color; subres.mipLevel = 0; subres.arrayLayer = i; vkGetImageSubresourceLayout(_device, _image, ref subres, out VkSubresourceLayout layout); VkBufferImageCopy copyRegion; copyRegion.bufferOffset = layout.offset; copyRegion.bufferImageHeight = 0; copyRegion.bufferRowLength = 0; copyRegion.imageExtent.width = (uint)Width; copyRegion.imageExtent.height = (uint)Height; copyRegion.imageExtent.depth = 1; copyRegion.imageOffset.x = 0; copyRegion.imageOffset.y = 0; copyRegion.imageOffset.z = 0; copyRegion.imageSubresource.baseArrayLayer = i; copyRegion.imageSubresource.aspectMask = VkImageAspectFlags.Color; copyRegion.imageSubresource.layerCount = 1; copyRegion.imageSubresource.mipLevel = 0; copyRegions.Add(copyRegion); } VkFenceCreateInfo fenceCI = VkFenceCreateInfo.New(); result = vkCreateFence(_device, ref fenceCI, null, out VkFence copyFence); CheckResult(result); TransitionImageLayout(_image, (uint)MipLevels, 0, 6, _imageLayout, VkImageLayout.TransferDstOptimal); VkCommandBuffer copyCmd = _rc.BeginOneTimeCommands(); vkCmdCopyBufferToImage(copyCmd, stagingBuffer, _image, VkImageLayout.TransferDstOptimal, copyRegions.Count, (IntPtr)copyRegions.Data); _rc.EndOneTimeCommands(copyCmd, copyFence); result = vkWaitForFences(_device, 1, ref copyFence, true, ulong.MaxValue); CheckResult(result); vkDestroyBuffer(_device, stagingBuffer, null); _memoryManager.Free(stagingMemory); }
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 void GetImageMemoryRequirements(Image image, out VkMemoryRequirements pMemoryRequirements) { vkGetImageMemoryRequirements(device, image, out pMemoryRequirements); }
public static void GetBufferMemoryRequirements(VkBuffer buffer, out VkMemoryRequirements pMemoryRequirements) { vkGetBufferMemoryRequirements(device, buffer, out pMemoryRequirements); }
public override void GetImageMemoryRequirements(VkImage image, out VkMemoryRequirements pMemoryRequirements) { ((SoftwareImage)image).GetImageMemoryRequirements(out pMemoryRequirements); }
public static extern void GetBufferMemoryRequirements( VkDevice device, VkBuffer buffer, out VkMemoryRequirements pMemoryRequirements );
public static extern void GetImageMemoryRequirements( VkDevice device, VkImage image, out VkMemoryRequirements pMemoryRequirements );
public abstract void GetBufferMemoryRequirements(VkBuffer buffer, out VkMemoryRequirements pMemoryRequirements);
public static bool TryAllocateMemoryForBuffer(ulong size, VkDevice device, VkPhysicalDevice pDevice, ref VkMemoryRequirements memoryRequirements, ref VkMemoryPropertyFlags memoryProperties, out ulong offset, out VkDeviceMemory mem) { if (size > Buffer.LargestBufferSize) { Buffer.LargestBufferSize = size; } if (size >= Buffer.LargePooledBufferSize) { offset = 0; mem = VkDeviceMemory.Null; Buffer.PoolMissesDueToSize++; return(false); } else if (size >= Buffer.SmallPooledBufferSize) { if (BigMemoryPool == VkDeviceMemory.Null) { AllocatePool(out BigMemoryPool, ref device, ref pDevice, ref memoryProperties, ref memoryRequirements, Buffer.LargePooledBufferCount * Buffer.LargePooledBufferSize); for (ulong i = 0; i < Buffer.LargePooledBufferCount; i++) { FreeBig.Enqueue(i * Buffer.LargePooledBufferSize); } } if (FreeBig.TryDequeue(out offset)) { Buffer.CurrentFreeBigPool = FreeBig.Count; mem = BigMemoryPool; return(true); } } else { if (SmallMemoryPool == VkDeviceMemory.Null) { AllocatePool(out SmallMemoryPool, ref device, ref pDevice, ref memoryProperties, ref memoryRequirements, Buffer.SmallPooledBufferCount * Buffer.SmallPooledBufferSize); for (ulong i = 0; i < Buffer.SmallPooledBufferCount; i++) { FreeSmall.Enqueue(i * Buffer.SmallPooledBufferSize); } } if (FreeSmall.TryDequeue(out offset)) { Buffer.CurrentFreeSmallPool = FreeSmall.Count; mem = SmallMemoryPool; return(true); } } offset = 0; mem = VkDeviceMemory.Null; Buffer.PoolMissesDueToExaustion++; return(false); }
public abstract void GetImageMemoryRequirements(VkImage image, out VkMemoryRequirements pMemoryRequirements);
//VkMemoryPropertyFlagBits.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT private uint GetMemoryTypeIndex(VkPhysicalDeviceMemoryProperties memoryProperties, VkMemoryRequirements memoryReq, VkMemoryPropertyFlagBits flags) { uint result = 0; bool heapIndexSet = false; VkMemoryType *memoryTypes = (VkMemoryType *)memoryProperties.memoryTypes; for (uint i = 0; i < memoryProperties.memoryTypeCount; i++) { if (((memoryReq.memoryTypeBits >> (int)i) & 1) == 1 && (memoryTypes[i].propertyFlags & flags) == flags) { result = i; heapIndexSet = true; break; } } if (!heapIndexSet) { result = memoryTypes[0].heapIndex; } return(result); }
public unsafe Buffer( Device device, uint size, VkBufferUsageFlags bufferUsageFlags, VkMemoryPropertyFlags memoryProperty ) { if (size == 0) { throw new Exception("cannot create buffer with size of zero bytes"); } //make sure buffer supports transfer data to and from buffer if ((bufferUsageFlags & VkBufferUsageFlags.TransferSrc) == 0) { bufferUsageFlags |= VkBufferUsageFlags.TransferSrc; } if ((bufferUsageFlags & VkBufferUsageFlags.TransferDst) == 0) { bufferUsageFlags |= VkBufferUsageFlags.TransferDst; } //store parameter information _size = size; _device = device; _bufferUsage = bufferUsageFlags; _memoryProperty = memoryProperty; var queueFamilyIndices = new NativeList <uint>(); foreach (var queueFamily in device.QueueFamilies) { queueFamilyIndices.Add(queueFamily.Index); } //buffer create info var bufferCreateInfo = new VkBufferCreateInfo { sType = VkStructureType.BufferCreateInfo, size = size, usage = bufferUsageFlags, sharingMode = VkSharingMode.Concurrent, queueFamilyIndexCount = queueFamilyIndices.Count, pQueueFamilyIndices = (uint *)queueFamilyIndices.Data.ToPointer() }; //setup buffer handler VkBuffer buffer; if (VulkanNative.vkCreateBuffer( device.Handle, &bufferCreateInfo, null, &buffer ) != VkResult.Success) { throw new Exception("failed to create vulkan buffer handle"); } _handle = buffer; //memory allocation info _memoryRequirements = GetMemoryRequirements(device.Handle, buffer); var memoryAllocateInfo = new VkMemoryAllocateInfo { sType = VkStructureType.MemoryAllocateInfo, allocationSize = _memoryRequirements.size, memoryTypeIndex = device.FindMemoryType( _memoryRequirements.memoryTypeBits, _memoryProperty ) }; //setup device memory VkDeviceMemory deviceMemory; if (VulkanNative.vkAllocateMemory( device.Handle, &memoryAllocateInfo, null, &deviceMemory ) != VkResult.Success) { throw new Exception("failed to allocat device memory"); } _memoryHandle = deviceMemory; //bind buffer handle with device memory if (VulkanNative.vkBindBufferMemory( device.Handle, buffer, deviceMemory, 0 ) != VkResult.Success) { throw new Exception("failed to bind buffer handler to device memory"); } }