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

Dedicated frame buffers. #125

Merged
merged 32 commits into from
Feb 19, 2024
Merged

Dedicated frame buffers. #125

merged 32 commits into from
Feb 19, 2024

Conversation

crud89
Copy link
Owner

@crud89 crud89 commented Feb 19, 2024

Describe the pull request

This PR decouples frame buffers from render passes, which allows to have multiple frame buffers (for example of different resolutions and/or sampling rates) that pass through the same render pass during a single frame, ultimately making it easier to implement features like render textures or viewports with differing properties. It is an extension of the concepts introduced in PR #124.

Frame buffers have now a slightly different semantic compared to their low-level counterparts (most importantly Vulkan). A frame buffer in the engine now is merely more than is a set of images that can be mapped to render targets. A frame buffer itself can store images of different resolutions and samples and only if a render pass uses the images for rendering, their restrictions are enforced. At this point, the render target sampling rate and format must match the image sampling rate and format. Additionally all images that are used as render targets in one render pass must have equal sampling rates.

Frame buffer images are mapped to render targets. This can be done in different ways. Conceptually a frame buffer image is addressed by an index, whilst a render target can now be identified via an identifier. A mapping must be explicitly set up when creating the render pass. To simplify this process, render target identifiers can be deduced from their name's hash. Similarly, a frame buffer image can be mapped using its name's hash. If a render target uses the same name as a frame buffer image, it is sufficient to pass the render target to IFrameBuffer::mapRenderTarget to establish a mapping. Render targets from different render passes can use the same name (or identifier) to map to the same image this way (alternatively, they can use different names, but have manual mappings defined).

When a render pass begins, the mappings are resolved for the render targets and they are implicitly transitioned into compatible render target states. Similarly, if a render pass ends, the render targets are transitioned back into compatbile shader resource states. Note that by default render targets are expected to be in read-only shader resource states outside of render passes. If a resource should be written to (for example from a compute shader), it needs manual barriers to ensure the layouts transition from and back into shader resource state. The compute sample demonstrates how to do this.

Whenever a render pipeline gets used on a render pass, the input attachments it is using are resolved and bound through the render pass in a similar fashion to how render targets are resolved described above. This means that an input attachment must resolve to a resource from the same frame buffer. Mapping render targets to different frame buffers or sharing images between multiple frame buffers is not supported. In other words: a frame buffer stores all target images for a single frame that is rendered.

The Vulkan backend now uses the dynamic rendering to model render passes, which has two major advantages: first, it allows to specify sampling rates at pipeline level. This makes it possible to have multiple pipelines at different sampling rates that use the same render pass instead of having to create a new one for different sampling rates. The natural limitation being the frame buffer requirements mentioned above. The second avantage is that it is now possible to use the same shader code base for render pass inputs between the DirectX 12 and Vulkan backends. Subpass attachments and dependencies are no longer supported.

Finally, the render pass example has been extended significantly. It now uses three render passes to demonstrate how to share frame buffer images between them. Previously one had to fetch contents from an earlier render pass to write them into it's own local resource, which not only increased memory consumption (every render pass had it's own local frame buffer images), but also is more expensive in some situations, for example when using a depth buffer from an earlier pass to do an early depth test. In the example, the first render pass draws to a color and depth texture. A second render pass reads the color buffer and copies the result into a new one (purely for demonstration purposes). The last render pass binds the second color buffer as well as the depth buffer and draws more geometry with proper depth testing enabled, but without writing it's own depth values.

Note that the changes in this PR require changes to the code base, as frame buffers now must be managed by the application. To aid with this, they can be put into the device state, though. All examples have been updated to demonstrate how to use the new frame buffers.

- Move render pass dependency to rendering base library and simplify it (finally remove render pass dependency source).
- Move secondary command buffers to render pass.
- Allow adding frame buffer images directly from render targets.
- Implement frame buffer resize and release events.
- Implement render pass and pipeline frame buffer caches.
- Adjust builder interfaces to above changes.
@crud89 crud89 added DX12 ❎ The issue involves the DX12 backend. Build 🛠 Issues that involve the build process. labels Feb 19, 2024
@crud89 crud89 added this to the Alpha #04 milestone Feb 19, 2024
@crud89 crud89 self-assigned this Feb 19, 2024
@crud89 crud89 marked this pull request as ready for review February 19, 2024 10:56
@crud89 crud89 merged commit 864a2dc into main Feb 19, 2024
1 check passed
@crud89 crud89 deleted the decouple-framebuffers branch February 19, 2024 11:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Build 🛠 Issues that involve the build process. DX12 ❎ The issue involves the DX12 backend.
Projects
Status: v0.4.1
Development

Successfully merging this pull request may close these issues.

1 participant