SaschaWillems / Vulkan

C++ examples for the Vulkan graphics API
MIT License
10.39k stars 2.04k forks source link

Problems with descriptorbuffer example on AMD GPU #1118

Closed SRSaunders closed 6 months ago

SRSaunders commented 7 months ago

When running on Windows 10 with an AMD 6600XT GPU, I am having problems with the descriptorbuffer example. The VK_EXT_descriptor_buffer extension and buffer device address features are available on the GPU, but the example crashes on swap chain creation with an out-of-host memory error. However, I think this is a red herring - I suspect the issue is elsewhere.

As a test, I commented out the following line in buildCommandBuffers():

    // Image (set 2)
    uint32_t bufferIndexImage = 1;
    bufferOffset = j * combinedImageDescriptor.layoutSize;
--> //vkCmdSetDescriptorBufferOffsetsEXT(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 2, 1, &bufferIndexImage, &bufferOffset);
    model.draw(drawCmdBuffers[i]);

This allows the example to run showing two rotating cubes, but there are visible "blue noise" artifacts overlaid on the texture-less cube face surfaces. It looks almost like old-time analog TV reception snow projected onto the rotating cube faces. I am not sure what is going on here, but I suspect there may be a memory sync or mapping coherence issue, or perhaps incorrect indexing into device or host memory.

Is this something you have seen in your testing? Have you verified if this works on other AMD devices?

UPDATE: I just realized this is very similar to #1091, but on Windows 10. I can also confirm that reverting e006185 fixes the issue. Interestingly, commenting out the same line above on the old code results in the same blue noise effect. So that observation is clearly irrelevant, and the real issue must have something to do with bad indexing and/or offsets into the combined image descriptors in that line of code.

SRSaunders commented 6 months ago

I think I found the issue - a typo on line 236. The offset calculation should refer tocombinedImageDescriptor not uniformDescriptor:

    // Put image descriptors into the corresponding resource buffer
    char* imageDescriptorBufPtr = (char*)combinedImageDescriptor.buffer.mapped;
    descriptorInfo.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    for (uint32_t i = 0; i < static_cast<uint32_t>(cubes.size()); i++) {
        descriptorInfo.data.pCombinedImageSampler = &cubes[i].texture.descriptor;
-->     vkGetDescriptorEXT(device, &descriptorInfo, descriptorBufferProperties.combinedImageSamplerDescriptorSize, imageDescriptorBufPtr + i * uniformDescriptor.layoutSize + uniformDescriptor.layoutOffset);
    }
                                                                                                                                                       ^^^^^^^^^^^^^^^^^              ^^^^^^^^^^^^^^^^^

Making this change results in a working example for me. Hopefully should solve this and #1091.

SaschaWillems commented 6 months ago

Thank you very much for bringing this up. I'll fix this as soon as time permits.

SRSaunders commented 6 months ago

I decided to add the fix to my open PR #1117. I hope you don't mind.