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.rs file 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.

2021-04-10T13:32:38,317578437-04:00 2021-04-10T13:30:22,210279536-04:00 vulkan_samples.txt capture.txt

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 40 (9 by maintainers)

Most upvoted comments

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: image And here is how it gets Rendered with vulkano (latest version, ofc.) image

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.