init
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
////
|
||||
Copyright (c) 2021-2023, Holochip
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
////
|
||||
= Dynamic Rendering
|
||||
|
||||
ifdef::site-gen-antora[]
|
||||
TIP: The source for this sample can be found in the https://github.com/KhronosGroup/Vulkan-Samples/tree/main/samples/extensions/dynamic_rendering[Khronos Vulkan samples github repository].
|
||||
endif::[]
|
||||
|
||||
|
||||
== Overview
|
||||
|
||||
This sample demonstrates how to use the `VK_KHR_dynamic_rendering` extension, which eliminates the need to create render passes and improves flexibility while developing render pipelines.
|
||||
|
||||
This extension changes how rendering resources are managed.
|
||||
Rather than using render pass objects, this extension allows the developer to directly reference rendering attachments prior to the start of rendering.
|
||||
|
||||
Below is a comparison of the common Vulkan render pass construction and dynamic rendering.
|
||||
|
||||
|===
|
||||
| Vulkan 1.0 | Dynamic Rendering
|
||||
|
||||
| Rendering begins with `vkCmdBeginRenderPass`
|
||||
| Rendering begins with `vkCmdBeginRenderingKHR`
|
||||
|
||||
| Rendering struct is `VkRenderPassBeginInfo`
|
||||
| Rendering struct is `VkRenderingInfoKHR`
|
||||
|
||||
| Attachments are referenced by `VkFramebuffer`
|
||||
| Attachments are referenced by `VkRenderingAttachmentInfoKHR`
|
||||
|
||||
| `VkFramebuffer` objects are heap-allocated and opaque
|
||||
| `VkRenderingAttachmentInfoKHR` objects are stack-allocated
|
||||
|
||||
| Graphics pipeline creation references a `VkRenderPass`
|
||||
| Graphics pipeline creation references a `VkPipelineRenderingCreateInfoKHR`
|
||||
|
||||
|
|
||||
|
|
||||
|===
|
||||
|
||||
More detail is provided in the sections that follow.
|
||||
|
||||
== Rendering Attachments
|
||||
|
||||
Previously, developers had to create render passes and framebuffers, which would be referenced in `VkRenderPassBeginInfo`.
|
||||
This is illustrated in the non-dynamic version of the command buffer construction sample code:
|
||||
|
||||
[,C++]
|
||||
----
|
||||
VkRenderPassBeginInfo render_pass_begin_info = vkb::initializers::render_pass_begin_info();
|
||||
render_pass_begin_info.renderPass = render_pass;
|
||||
render_pass_begin_info.framebuffer = framebuffers[i];
|
||||
render_pass_begin_info.renderArea.extent.width = width;
|
||||
render_pass_begin_info.renderArea.extent.height = height;
|
||||
render_pass_begin_info.clearValueCount = 3;
|
||||
render_pass_begin_info.pClearValues = clear_values.data();
|
||||
|
||||
vkCmdBeginRenderPass(draw_cmd_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
draw_scene();
|
||||
|
||||
vkCmdEndRenderPass(draw_cmd_buffer);
|
||||
----
|
||||
|
||||
However, with dynamic rendering, the render pass and framebuffer structs are replaced by `VkRenderingAttachmentInfoKHR`, which contains information about color, depth, and stencil attachments, and `VkRenderingInfoKHR`, which references the attachments.
|
||||
These structs are used at the start of rendering with the new command `vkCmdBeginRenderingKHR`, as shown in the dynamic version of the command buffer construction sample code:
|
||||
|
||||
[,C++]
|
||||
----
|
||||
VkRenderingAttachmentInfoKHR color_attachment_info = vkb::initializers::rendering_attachment_info();
|
||||
color_attachment_info.imageView = swapchain_buffers[i].view; // color_attachment.image_view;
|
||||
...
|
||||
|
||||
VkRenderingAttachmentInfoKHR depth_attachment_info = vkb::initializers::rendering_attachment_info();
|
||||
depth_attachment_info.imageView = depth_stencil.view;
|
||||
...
|
||||
|
||||
auto render_area = VkRect2D{VkOffset2D{}, VkExtent2D{width, height}};
|
||||
auto render_info = vkb::initializers::rendering_info(render_area, 1, &color_attachment_info);
|
||||
render_info.layerCount = 1;
|
||||
render_info.pDepthAttachment = &depth_attachment_info;
|
||||
render_info.pStencilAttachment = &depth_attachment_info;
|
||||
|
||||
vkCmdBeginRenderingKHR(draw_cmd_buffer, &render_info);
|
||||
draw_scene();
|
||||
vkCmdEndRenderingKHR(draw_cmd_buffer);
|
||||
----
|
||||
|
||||
== Pipelines
|
||||
|
||||
Dynamic rendering changes how graphics pipelines are created.
|
||||
Whereas before, the `VkGraphicsPipelineCreateInfo` struct was required to reference a non-null pointer to a `VkRenderPass` object, the dynamic rendering information is instead contained in a `VkPipelineRenderingCreateInfoKHR` struct referenced by `pNext` of the graphics pipeline create info:
|
||||
|
||||
[,C++]
|
||||
----
|
||||
// Provide information for dynamic rendering
|
||||
VkPipelineRenderingCreateInfoKHR pipeline_create{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR};
|
||||
pipeline_create.pNext = VK_NULL_HANDLE;
|
||||
pipeline_create.colorAttachmentCount = 1;
|
||||
pipeline_create.pColorAttachmentFormats = &color_rendering_format;
|
||||
pipeline_create.depthAttachmentFormat = depth_format;
|
||||
pipeline_create.stencilAttachmentFormat = depth_format;
|
||||
|
||||
// Use the pNext to point to the rendering create struct
|
||||
VkGraphicsPipelineCreateInfo graphics_create{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO};
|
||||
graphics_create.pNext = &pipeline_create; // reference the new dynamic structure
|
||||
graphics_create.renderPass = VK_NULL_HANDLE; // previously required non-null
|
||||
----
|
||||
|
||||
During graphics pipeline construction, the `VkPipelineRenderingCreateInfoKHR` structure does not contain pointers to the actual attachment images (as the pointers aren't required until `VkRenderingAttachmentInfoKHR`);
|
||||
instead, only the number and format of the attachments are required.
|
||||
|
||||
== Enabling the Extension
|
||||
|
||||
The dynamic rendering api is provided in Vulkan 1.2.197 and the appropriate headers / SDK is required.
|
||||
|
||||
In addition, since dynamic rendering is provided as an extension and may have varying levels of support, the developer must query availability for each device used.
|
||||
|
||||
The device extension is provided by `VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME`, and additional features are provided by the `VkPhysicalDeviceDynamicRenderingFeaturesKHR` struct:
|
||||
|
||||
[,C++]
|
||||
----
|
||||
typedef struct VkPhysicalDeviceDynamicRenderingFeaturesKHR {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
VkBool32 dynamicRendering;
|
||||
} VkPhysicalDeviceDynamicRenderingFeaturesKHR;
|
||||
----
|
||||
|
||||
In addition to enabling the extension, developers may need to dynamically query the function pointers for `vkCmdBeginRenderingKHR` and `vkCmdEndRenderingKHR` if the preprocessor macro `VK_NO_PROTOTYPES` is enabled.
|
||||
This can be achieved through `vkGetInstanceProcAddr`:
|
||||
|
||||
[,C++]
|
||||
----
|
||||
VkInstance instance = get_device().get_gpu().get_instance().get_handle();
|
||||
assert(!!instance);
|
||||
vkCmdBeginRenderingKHR = (PFN_vkCmdBeginRenderingKHR) vkGetInstanceProcAddr(instance, "vkCmdBeginRenderingKHR");
|
||||
vkCmdEndRenderingKHR = (PFN_vkCmdEndRenderingKHR) vkGetInstanceProcAddr(instance, "vkCmdEndRenderingKHR");
|
||||
if (!vkCmdBeginRenderingKHR || !vkCmdEndRenderingKHR)
|
||||
{
|
||||
throw std::runtime_error("Unable to dynamically load vkCmdBeginRenderingKHR and vkCmdEndRenderingKHR");
|
||||
}
|
||||
----
|
||||
Reference in New Issue
Block a user