Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mip map example #86

Merged
merged 28 commits into from
Feb 15, 2025
Merged

Add mip map example #86

merged 28 commits into from
Feb 15, 2025

Conversation

attackgoat
Copy link
Owner

@attackgoat attackgoat commented Aug 30, 2024

This PR overhauls buffer and image barriers to get close to the optimal state. Where previously buffer and image resources would use a single vk_sync::AccessType to track changes, now all subresources are tracked individually using a pair of high-performance diff algorithms. The new code is unit and fuzz tested.

  • Buffers: Track each memory range accessed
  • Images: Track each array layer and mip level of all aspects (color, depth, stencil)

The changes are almost entirely internal to Screen-13 and only visible by noticing the API changes made to the Buffer::access and Image::access functions.

Previously these functions took a single access and provided a single access to use when creating barriers.

Now these functions also require the sub-resource range being accessed and provide a list of sub-resource ranges and their previous access type.

This should all be transparent to users of Screen-13 unless they're doing interop with raw Vulkan code.

In the future Screen-13 will also track command buffer submissions and completions so that existing resource access can be cleared back to AccessType::Nothing and not require barriers in those cases.

@attackgoat attackgoat linked an issue Aug 30, 2024 that may be closed by this pull request
@DGriffin91
Copy link
Contributor

DGriffin91 commented Nov 6, 2024

It looks like this PR eliminates most of the remaining validation errors in my renderer! There's one relevant case where it might not be using the correct barrier. I have a set of passes like this:

let mut mip = 0;
while width > 1 && height > 1 {
    graph
        .begin_pass("low_z_prepass_pyramid")
        .bind_pipeline([...])
        .read_descriptor_as(0, depth_node, info_mip(dwrite_info, mip))
        .write_descriptor_as(1, depth_node, info_mip(dwrite_info, mip + 1))
        .record_compute(move |compute, _bindings| {
            compute.dispatch(width / 8 + 1, height / 8 + 1, 1);
        });
    width /= 2;
    height /= 2;
    mip += 1;
}

fn info_mip(info: ImageViewInfo, level: u32) -> ImageViewInfo {
    let mut write_info = info;
    write_info.base_mip_level = level;
    write_info.mip_level_count = Some(1);
    write_info
}

And it seems that the read_descriptor_as here transitions the mip to an optimal layout and shader read mask (which seems correct). But then in a subsequent pass I read the whole image (with just read_descriptor) and it tries to transition it a second time from a general layout and shader write to optimal layout and shader read which triggers the validation error:

VUID-VkImageMemoryBarrier-oldLayout-01197(ERROR / SPEC): msgNum: 307231540 - Validation Error: [ VUID-VkImageMemoryBarrier-oldLayout-01197 ] Object 0: handle = 0x2255ff10a30, type = VK_OBJECT_TYPE_COMMAND_BUFFER; Object 1: handle = 0x980b0000000002e, type = VK_OBJECT_TYPE_IMAGE; | MessageID = 0x124ffb34 | vkCmdPipelineBarrier(): pImageMemoryBarriers[0].image (VkImage 0x980b0000000002e[]) cannot transition the layout of aspect=1, level=0, layer=0 from VK_IMAGE_LAYOUT_GENERAL when the previous known layout is VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL. The Vulkan spec states: If srcQueueFamilyIndex and dstQueueFamilyIndex define a queue family ownership transfer or oldLayout and newLayout define an image layout transition, oldLayout must be VK_IMAGE_LAYOUT_UNDEFINED or the current layout of the image subresources affected by the barrier (https://vulkan.lunarg.com/doc/view/1.3.296.0/windows/1.3-extensions/vkspec.html#VUID-VkImageMemoryBarrier-oldLayout-01197)

@DGriffin91
Copy link
Contributor

DGriffin91 commented Nov 7, 2024

I did just notice that with this PR I'm getting undefined img in render doc on some attachments and it just renders black on a GTX1060. Still need to track down the cause or make a minimal reproduction. Just wanted to mention. (I tried a few of the basic examples in this repo and it didn't occur, though there were other vulkan validation errors)

@attackgoat
Copy link
Owner Author

attackgoat commented Feb 10, 2025

I've re-worked how image barriers are handled. Where previously only one single access type was tracked for a whole image, now individual access types are tracked for every aspect, layer, and mip level. This should fix a bunch of the troubles around mip levels and other image subresource accesses.

See ImageAccess and ImageAccessIter internal types for implementation details

There is a new mip_compute.rs example that does something similar to what was pasted in above, except the graph no longer needs to create a new "pass" for each level.

This part:

while width > 1 && height > 1 {
    graph
        .begin_pass("low_z_prepass_pyramid")
        .bind_pipeline([...])
        .read_descriptor_as()

...can be changed to:

let mut pass = graph
    .begin_pass("low_z_prepass_pyramid")
    .bind_pipeline([...]);
while width > 1 && height > 1 {
    pass = pass.read_descriptor_as()

There are still a few bugs in the examples (when synchronization validation is enabled) and some todos:

  • Apply the same subresource range tracking to buffers
  • Fix the examples, add new ones to the documentation

@attackgoat attackgoat marked this pull request as ready for review February 13, 2025 03:04
@attackgoat
Copy link
Owner Author

There are still some remaining issues with validation of swapchain and msaa resolve attachments, but those are not related to this PR or mip level handling and will be resolved in later changes.

Also, there will be greatly improved renderpass dependency handling (performance and correctness) coming soon.

@attackgoat attackgoat merged commit 197306b into master Feb 15, 2025
3 checks passed
@attackgoat attackgoat deleted the 84-mip-levels branch February 15, 2025 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants