/** * 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 FromTextureAsset( TextureAsset asset, GraphicsDevice device, VkImageUsageFlags imageUsageFlags = VkImageUsageFlags.Sampled, VkImageLayout imageLayout = VkImageLayout.ShaderReadOnlyOptimal) { VkFormat format = VkFormat.Undefined; KtxFile tex2D = asset.GetTexture(); format = GlFormatToVulkanFormat.vkGetFormatFromOpenGLInternalFormat(tex2D.Header.GlInternalFormat, tex2D.Header.GlFormat, tex2D.Header.GlType); width = tex2D.Header.PixelWidth; height = tex2D.Header.PixelHeight; if (height == 0) { height = width; } mipLevels = tex2D.Header.NumberOfMipmapLevels; this.imageLayout = imageLayout; this.format = format; this.device = device; // Get device properites for the requested texture format VkFormatProperties formatProperties; vkGetPhysicalDeviceFormatProperties(device.physicalDevice, format, out formatProperties); VkMemoryAllocateInfo memAllocInfo = Initializers.memoryAllocateInfo(); VkMemoryRequirements memReqs; // Create optimal tiled target image VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo(); imageCreateInfo.imageType = VkImageType.Image2D; imageCreateInfo.format = format; imageCreateInfo.mipLevels = mipLevels; imageCreateInfo.arrayLayers = 1; imageCreateInfo.samples = VkSampleCountFlags.Count1; 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 & VkImageUsageFlags.TransferDst) == 0) { imageCreateInfo.usage |= VkImageUsageFlags.TransferDst; } Util.CheckResult(vkCreateImage(device.device, &imageCreateInfo, null, out image)); vkGetImageMemoryRequirements(device.device, image, &memReqs); memAllocInfo.allocationSize = memReqs.size; memory = device.memoryAllocator.Allocate(memReqs.size, memReqs.alignment, memReqs.memoryTypeBits, false); Util.CheckResult(vkBindImageMemory(device.device, image, memory.vkDeviceMemory, memory.offset)); //memAllocInfo.memoryTypeIndex = device.vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal); //Util.CheckResult(vkAllocateMemory(device.device, &memAllocInfo, null, out deviceMemory)); //Util.CheckResult(vkBindImageMemory(device.device, image, deviceMemory, 0)); TransferDataKtx(tex2D); CreateSampler(); CreateView(); // Update descriptor image info member that can be used for setting up descriptor sets UpdateDescriptor(); }