vulkano: Image Loading Fails on Intel Xe Graphics
- Version of vulkano: v0.22.0
- OS: ArchLinux - Linux version 5.11.11-arch1-1 (linux@archlinux) (gcc (GCC) 10.2.0, GNU ld (GNU Binutils) 2.36.1)
- GPU (the selected PhysicalDevice): Intel® Xe Graphics (TGL GT2) (type: IntegratedGpu)
- GPU Driver: vulkan-intel package, 21.0.1-1
- Upload of a reasonably minimal complete
main.rsfile that demonstrates the issue: See the image example in this repo
Issue
Trying to load images goes poorly when trying to do so on an Intel Xe Graphics card. The image becomes almost completely garbled, though it does still load some image portions. See the attached images - one shows the example Rust logo failing to load properly, the other shows a piece of code I put together that loads an image of my dog. It’s easier to tell with the dog image, but it looks like portions of the image are being loaded, but something about the image structure is wrong. Only strong edges seem to be preserved, which to me hints at some kind of alternate sub-sample friendly memory layout.
I’m reasonably sure this isn’t a graphics driver issue, as the Vulkan texture loading examples in C++ work fine.
If I switch to using a StorageImage and read the data back out to a buffer, the buffer contains data different from what I originally used to create the image. Instead, it appears to match up with the pixels as displayed.
I think this is also tangentially reported in #1468 - in that issue, the reporter mentions their integrated graphics card produces “confetti”, but things work fine when using a dedicated card. That sounds like the same issue I’m having here.
My best guess so far is that the image memory barriers used to transition between layouts aren’t set up right. Somehow we’re copying data to the image when its layout is not correct for that operation, or it is getting treated as though its layout is different than what is actually in memory. I’ve done some probing into the Vulkan API calls, looking for differences between how Vulkano and the C++ example works, and that’s about all I’ve come up with so far… well, that and the memory allocations & mapping seem to be handled slightly differently. The copy operations and buffer initialization seem to be basically the same.
The command buffer API calls from Vulkano are:
Thread 0, Frame 0, Time 17382 us:
vkBeginCommandBuffer(commandBuffer, pBeginInfo) returns VkResult VK_SUCCESS (0):
commandBuffer: VkCommandBuffer = 0x563c2d05cd80
pBeginInfo: const VkCommandBufferBeginInfo* = 0x7ffc251f8168:
sType: VkStructureType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO (42)
pNext: const void* = NULL
flags: VkCommandBufferUsageFlags = 0
pInheritanceInfo: const VkCommandBufferInheritanceInfo* = UNUSED
Thread 0, Frame 0, Time 17430 us:
vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers) returns void:
commandBuffer: VkCommandBuffer = 0x563c2d05cd80
srcStageMask: VkPipelineStageFlags = 8192 (VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT)
dstStageMask: VkPipelineStageFlags = 4096 (VK_PIPELINE_STAGE_TRANSFER_BIT)
dependencyFlags: VkDependencyFlags = 1 (VK_DEPENDENCY_BY_REGION_BIT)
memoryBarrierCount: uint32_t = 0
pMemoryBarriers: const VkMemoryBarrier* = 0x7ffc251fd4a8
bufferMemoryBarrierCount: uint32_t = 0
pBufferMemoryBarriers: const VkBufferMemoryBarrier* = 0x7ffc251fd4e8
imageMemoryBarrierCount: uint32_t = 1
pImageMemoryBarriers: const VkImageMemoryBarrier* = 0x7ffc251fd6b8
pImageMemoryBarriers[0]: const VkImageMemoryBarrier = 0x7ffc251fd6b8:
sType: VkStructureType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER (45)
pNext: const void* = NULL
srcAccessMask: VkAccessFlags = 0 (VK_ACCESS_NONE_KHR)
dstAccessMask: VkAccessFlags = 4096 (VK_ACCESS_TRANSFER_WRITE_BIT)
oldLayout: VkImageLayout = VK_IMAGE_LAYOUT_UNDEFINED (0)
newLayout: VkImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (7)
srcQueueFamilyIndex: uint32_t = 4294967295
dstQueueFamilyIndex: uint32_t = 4294967295
image: VkImage = 0x563c2d06fbb0
subresourceRange: VkImageSubresourceRange = 0x7ffc251fd6e8:
aspectMask: VkImageAspectFlags = 1 (VK_IMAGE_ASPECT_COLOR_BIT)
baseMipLevel: uint32_t = 0
levelCount: uint32_t = 1
baseArrayLayer: uint32_t = 0
layerCount: uint32_t = 1
Thread 0, Frame 0, Time 17720 us:
vkCmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions) returns void:
commandBuffer: VkCommandBuffer = 0x563c2d05cd80
srcBuffer: VkBuffer = 0x563c2d057030
dstImage: VkImage = 0x563c2d06fbb0
dstImageLayout: VkImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (7)
regionCount: uint32_t = 1
pRegions: const VkBufferImageCopy* = 0x7ffc251fc178
pRegions[0]: const VkBufferImageCopy = 0x7ffc251fc178:
bufferOffset: VkDeviceSize = 0
bufferRowLength: uint32_t = 0
bufferImageHeight: uint32_t = 0
imageSubresource: VkImageSubresourceLayers = 0x7ffc251fc188:
aspectMask: VkImageAspectFlags = 1 (VK_IMAGE_ASPECT_COLOR_BIT)
mipLevel: uint32_t = 0
baseArrayLayer: uint32_t = 0
layerCount: uint32_t = 1
imageOffset: VkOffset3D = 0x7ffc251fc198:
x: int32_t = 0
y: int32_t = 0
z: int32_t = 0
imageExtent: VkExtent3D = 0x7ffc251fc1a4:
width: uint32_t = 93
height: uint32_t = 93
depth: uint32_t = 1
Thread 0, Frame 0, Time 18375 us:
vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers) returns void:
commandBuffer: VkCommandBuffer = 0x563c2d05cd80
srcStageMask: VkPipelineStageFlags = 4096 (VK_PIPELINE_STAGE_TRANSFER_BIT)
dstStageMask: VkPipelineStageFlags = 1 (VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT)
dependencyFlags: VkDependencyFlags = 1 (VK_DEPENDENCY_BY_REGION_BIT)
memoryBarrierCount: uint32_t = 0
pMemoryBarriers: const VkMemoryBarrier* = 0x7ffc251fc748
bufferMemoryBarrierCount: uint32_t = 0
pBufferMemoryBarriers: const VkBufferMemoryBarrier* = 0x7ffc251fc788
imageMemoryBarrierCount: uint32_t = 1
pImageMemoryBarriers: const VkImageMemoryBarrier* = 0x7ffc251fc958
pImageMemoryBarriers[0]: const VkImageMemoryBarrier = 0x7ffc251fc958:
sType: VkStructureType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER (45)
pNext: const void* = NULL
srcAccessMask: VkAccessFlags = 4096 (VK_ACCESS_TRANSFER_WRITE_BIT)
dstAccessMask: VkAccessFlags = 0 (VK_ACCESS_NONE_KHR)
oldLayout: VkImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (7)
newLayout: VkImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL (5)
srcQueueFamilyIndex: uint32_t = 4294967295
dstQueueFamilyIndex: uint32_t = 4294967295
image: VkImage = 0x563c2d06fbb0
subresourceRange: VkImageSubresourceRange = 0x7ffc251fc988:
aspectMask: VkImageAspectFlags = 1 (VK_IMAGE_ASPECT_COLOR_BIT)
baseMipLevel: uint32_t = 0
levelCount: uint32_t = 1
baseArrayLayer: uint32_t = 0
layerCount: uint32_t = 1
Thread 0, Frame 0, Time 18417 us:
vkEndCommandBuffer(commandBuffer) returns VkResult VK_SUCCESS (0):
commandBuffer: VkCommandBuffer = 0x563c2d05cd80
Compare and contrast with the API calls from the C++ example:
Thread 0, Frame 0, Time 23076 us:
vkBeginCommandBuffer(commandBuffer, pBeginInfo) returns VkResult VK_SUCCESS (0):
commandBuffer: VkCommandBuffer = 0x55a6ab3b7280
pBeginInfo: const VkCommandBufferBeginInfo* = 0x7ffcd4cd7000:
sType: VkStructureType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO (42)
pNext: const void* = NULL
flags: VkCommandBufferUsageFlags = 1 (VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT)
pInheritanceInfo: const VkCommandBufferInheritanceInfo* = UNUSED
Thread 0, Frame 0, Time 23101 us:
vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers) returns void:
commandBuffer: VkCommandBuffer = 0x55a6ab3b7280
srcStageMask: VkPipelineStageFlags = 16384 (VK_PIPELINE_STAGE_HOST_BIT)
dstStageMask: VkPipelineStageFlags = 4096 (VK_PIPELINE_STAGE_TRANSFER_BIT)
dependencyFlags: VkDependencyFlags = 0
memoryBarrierCount: uint32_t = 0
pMemoryBarriers: const VkMemoryBarrier* = NULL
bufferMemoryBarrierCount: uint32_t = 0
pBufferMemoryBarriers: const VkBufferMemoryBarrier* = NULL
imageMemoryBarrierCount: uint32_t = 1
pImageMemoryBarriers: const VkImageMemoryBarrier* = 0x7ffcd4cd7020
pImageMemoryBarriers[0]: const VkImageMemoryBarrier = 0x7ffcd4cd7020:
sType: VkStructureType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER (45)
pNext: const void* = NULL
srcAccessMask: VkAccessFlags = 0 (VK_ACCESS_NONE_KHR)
dstAccessMask: VkAccessFlags = 4096 (VK_ACCESS_TRANSFER_WRITE_BIT)
oldLayout: VkImageLayout = VK_IMAGE_LAYOUT_UNDEFINED (0)
newLayout: VkImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (7)
srcQueueFamilyIndex: uint32_t = 0
dstQueueFamilyIndex: uint32_t = 0
image: VkImage = 0x55a6ab3297d0
subresourceRange: VkImageSubresourceRange = 0x7ffcd4cd7050:
aspectMask: VkImageAspectFlags = 1 (VK_IMAGE_ASPECT_COLOR_BIT)
baseMipLevel: uint32_t = 0
levelCount: uint32_t = 1
baseArrayLayer: uint32_t = 0
layerCount: uint32_t = 1
Thread 0, Frame 0, Time 23515 us:
vkCmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions) returns void:
commandBuffer: VkCommandBuffer = 0x55a6ab3b7280
srcBuffer: VkBuffer = 0x55a6ab325a50
dstImage: VkImage = 0x55a6ab3297d0
dstImageLayout: VkImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (7)
regionCount: uint32_t = 1
pRegions: const VkBufferImageCopy* = 0x55a6ab4661c0
pRegions[0]: const VkBufferImageCopy = 0x55a6ab4661c0:
bufferOffset: VkDeviceSize = 0
bufferRowLength: uint32_t = 0
bufferImageHeight: uint32_t = 0
imageSubresource: VkImageSubresourceLayers = 0x55a6ab4661d0:
aspectMask: VkImageAspectFlags = 1 (VK_IMAGE_ASPECT_COLOR_BIT)
mipLevel: uint32_t = 0
baseArrayLayer: uint32_t = 0
layerCount: uint32_t = 1
imageOffset: VkOffset3D = 0x55a6ab4661e0:
x: int32_t = 0
y: int32_t = 0
z: int32_t = 0
imageExtent: VkExtent3D = 0x55a6ab4661ec:
width: uint32_t = 512
height: uint32_t = 256
depth: uint32_t = 1
Thread 0, Frame 0, Time 24231 us:
vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers) returns void:
commandBuffer: VkCommandBuffer = 0x55a6ab3b7280
srcStageMask: VkPipelineStageFlags = 4096 (VK_PIPELINE_STAGE_TRANSFER_BIT)
dstStageMask: VkPipelineStageFlags = 128 (VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
dependencyFlags: VkDependencyFlags = 0
memoryBarrierCount: uint32_t = 0
pMemoryBarriers: const VkMemoryBarrier* = NULL
bufferMemoryBarrierCount: uint32_t = 0
pBufferMemoryBarriers: const VkBufferMemoryBarrier* = NULL
imageMemoryBarrierCount: uint32_t = 1
pImageMemoryBarriers: const VkImageMemoryBarrier* = 0x7ffcd4cd7020
pImageMemoryBarriers[0]: const VkImageMemoryBarrier = 0x7ffcd4cd7020:
sType: VkStructureType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER (45)
pNext: const void* = NULL
srcAccessMask: VkAccessFlags = 0 (VK_ACCESS_NONE_KHR)
dstAccessMask: VkAccessFlags = 32 (VK_ACCESS_SHADER_READ_BIT)
oldLayout: VkImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (7)
newLayout: VkImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL (5)
srcQueueFamilyIndex: uint32_t = 0
dstQueueFamilyIndex: uint32_t = 0
image: VkImage = 0x55a6ab3297d0
subresourceRange: VkImageSubresourceRange = 0x7ffcd4cd7050:
aspectMask: VkImageAspectFlags = 1 (VK_IMAGE_ASPECT_COLOR_BIT)
baseMipLevel: uint32_t = 0
levelCount: uint32_t = 1
baseArrayLayer: uint32_t = 0
layerCount: uint32_t = 1
Thread 0, Frame 0, Time 24244 us:
vkEndCommandBuffer(commandBuffer) returns VkResult VK_SUCCESS (0):
commandBuffer: VkCommandBuffer = 0x55a6ab3b7280
The full API call dumps are also attached.
I’ll keep trying to tweak things, but I don’t really know anything about pipeline barriers, so I’m mostly making wild guesses as to how this can be fixed.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 40 (9 by maintainers)
Ok, so its been more than 4 months now - here is an Update:
So first, something seems to be changed from the drivers side or vulkano’s side (I will try to find out and tell you then). The Rust logo on the example Image gets rendered correctly. Unfortunately, images with colors still don’t seem to work. Here is an example Image:
And here is how it gets Rendered with vulkano (latest version, ofc.)

As you can see, its getting rendered a lot darker. I am pretty sure that this is a Problem related to Vulkano and not any libary you are using. I tried other file formats, other image loaders, all are showing the same results.