attackgoat / screen-13

Screen 13 is an easy-to-use Vulkan rendering engine in the spirit of QBasic.
Apache License 2.0
251 stars 13 forks source link

Issues rendering to specific mip level #84

Open DGriffin91 opened 2 weeks ago

DGriffin91 commented 2 weeks ago

It seems that it's not currently possible to render to a specific texture mip level. (as an attachment)

It seems that at least render_area() and begin_render_pass() don't take into account the base_mip_level specified in the ImageViewInfo.

This results in errors like:

VUID-VkRenderPassBeginInfo-framebuffer-03211(ERROR / SPEC): msgNum: 567145121 - Validation Error: [ VUID-VkRenderPassBeginInfo-framebuffer-03211 ] Object 0: handle = 0xd3dd54000000008e, type = VK_OBJECT_TYPE_RENDER_PASS; Object 1: handle = 0xfbbae800000000a2, type = VK_OBJECT_TYPE_FRAMEBUFFER; Object 2: handle = 0xe2478b00000000a1, type = VK_OBJECT_TYPE_IMAGE_VIEW; Object 3: handle = 0xba7514000000002a, type = VK_OBJECT_TYPE_IMAGE; | MessageID = 0x21cdf2a1 | vkCmdBeginRenderPass(): pRenderPassBegin->pNext<VkRenderPassAttachmentBeginInfo>.pAttachments[0] has VkImageView width (1600) at mip level 1 (800) != VkFramebufferAttachmentsCreateInfo::pAttachments[0].width (1600). The Vulkan spec states: If framebuffer was created with a VkFramebufferCreateInfo::flags value that included VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of the pAttachments member of a VkRenderPassAttachmentBeginInfo structure included in the pNext chain must be a VkImageView with a width equal to the width member of the corresponding element of VkFramebufferAttachmentsCreateInfo::pAttachmentImageInfos used to create framebuffer (https://vulkan.lunarg.com/doc/view/1.3.280.0/windows/1.3-extensions/vkspec.html#VUID-VkRenderPassBeginInfo-framebuffer-03211)

I tried manually setting the render area with set_render_area, with this the device was not immediately lost but it still didn't render the mips and had the same errors.

attackgoat commented 2 weeks ago

This is something I have not yet tested, but should work as you describe. I've added a basic example to #86 and will work on getting it to render properly this weekend.

attackgoat commented 2 weeks ago

The new example (mip_map.rs) shows a single mip-mapped image rendered to the swapchain as slices, one for each mip level. The slices on the right become smaller, with the last one only being 3 pixels tall and so it's pretty coarse compared to the first slice.

Screenshot ![image](https://github.com/user-attachments/assets/fa8dc0ce-5942-4489-90cf-d72fd27e35a4)

Unfortunately, to get this to work without validation layers I had to disable render pass merging and break each RenderGraph::begin_pass() call into one pass per level. The issue is that image/buffer access is tracked using a single state for each resource and does not track subresource access at all.

Screen-13 should instead track access to any combination of subresources (image mip levels/layers/aspects, buffer regions) and calculate the correct state changes to bring a resource from the old access to the new. This will have to be a tree or vector of some kind and won't use the existing approach of atomic variables. I don't want to use a mutex, because only one thread should have owned access to modify an image at one time, but doing that might be a very large change to the API.

There were a collection of other issues related to the way this example uses render areas, exposing the fact that scissor access is maybe simplified too much.

DGriffin91 commented 2 weeks ago

Thanks for taking a look at this!! Your explanation regarding the subresource access makes sense and I think is probably related to some of the other issues I've been having.