|
| 1 | +//// |
| 2 | + * Copyright (c) 2025, The Khronos Group |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + * |
| 6 | + * Licensed under the Apache License, Version 2.0 the "License"; |
| 7 | + * you may not use this file except in compliance with the License. |
| 8 | + * You may obtain a copy of the License at |
| 9 | + * |
| 10 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | + * |
| 12 | + * Unless required by applicable law or agreed to in writing, software |
| 13 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | + * See the License for the specific language governing permissions and |
| 16 | + * limitations under the License. |
| 17 | +//// |
| 18 | += Hello Triangle with Vulkan 1.3 Features using Vulkan-Hpp |
| 19 | +
|
| 20 | +ifdef::site-gen-antora[] |
| 21 | +TIP: The source for this sample can be found in the https://github.com/KhronosGroup/Vulkan-Samples/tree/main/samples/api/hpp_hello_triangle_1_3[Khronos Vulkan samples github repository]. |
| 22 | +endif::[] |
| 23 | +
|
| 24 | +NOTE: A transcoded version of the API sample https://github.com/KhronosGroup/Vulkan-Samples/tree/main/samples/api/hello_triangle_1_3[Hello Triangle 1.3] that illustrates the usage of the C{pp} bindings of Vulkan provided by Vulkan-Hpp. |
| 25 | +
|
| 26 | +This sample demonstrates how to render a simple triangle using Vulkan 1.3 core features. It modernizes the traditional "Hello Triangle" Vulkan sample by incorporating: |
| 27 | +
|
| 28 | +- **Dynamic Rendering** |
| 29 | +- **Synchronization2** |
| 30 | +- **Extended Dynamic State** |
| 31 | +- **Vertex Buffers** |
| 32 | +
|
| 33 | +## Overview |
| 34 | +
|
| 35 | +The sample renders a colored triangle to the screen using Vulkan 1.3. It showcases how to: |
| 36 | +
|
| 37 | +- Initialize Vulkan with Vulkan 1.3 features enabled. |
| 38 | +- Use dynamic rendering to simplify the rendering pipeline. |
| 39 | +- Employ the Synchronization2 API for improved synchronization. |
| 40 | +- Utilize extended dynamic states to reduce pipeline complexity. |
| 41 | +- Manage vertex data using vertex buffers instead of hard-coded vertices. |
| 42 | +
|
| 43 | +## Key Features |
| 44 | +
|
| 45 | +### 1. Dynamic Rendering |
| 46 | +
|
| 47 | +**What is Dynamic Rendering?** |
| 48 | +
|
| 49 | +Dynamic Rendering is a feature introduced in Vulkan 1.3 that allows rendering without pre-defined render passes and framebuffers. It simplifies the rendering process by enabling you to specify rendering states directly during command buffer recording. |
| 50 | +
|
| 51 | +**How It's Used in the Sample:** |
| 52 | +
|
| 53 | +- **No Render Passes or Framebuffers:** The sample does not create `vk::RenderPass` or `vk::Framebuffer` objects. |
| 54 | +- **`vk::CommandBuffer::beginRendering()` and `vk::CommandBuffer::endRendering()`:** These functions are used to begin and end rendering operations dynamically. |
| 55 | +- **Pipeline Creation:** Uses `vk::PipelineRenderingCreateInfo` during pipeline creation to specify rendering details. |
| 56 | +
|
| 57 | +**Benefits:** |
| 58 | +
|
| 59 | +- Simplifies code by reducing boilerplate associated with render passes and framebuffers. |
| 60 | +- Increases flexibility by allowing rendering to different attachments without recreating render passes. |
| 61 | +
|
| 62 | +### 2. Synchronization2 |
| 63 | +
|
| 64 | +**What is Synchronization2?** |
| 65 | +
|
| 66 | +Synchronization2 is an improved synchronization API introduced in Vulkan 1.3. It provides more granular control over synchronization primitives and simplifies the synchronization process. |
| 67 | +
|
| 68 | +**How It's Used in the Sample:** |
| 69 | +
|
| 70 | +- **`vk::CommandBuffer::pipelineBarrier2()`:** Replaces the older `vk::CommandBuffer::pipelineBarrier()` for more detailed synchronization. |
| 71 | +- **`vk::DependencyInfo` and `vk::ImageMemoryBarrier2`:** Used to specify precise memory dependencies and image layout transitions. |
| 72 | +
|
| 73 | +**Example Usage:** |
| 74 | +
|
| 75 | +```cpp |
| 76 | +vk::ImageMemoryBarrier2 image_barrier = { |
| 77 | + // ... members ... |
| 78 | +}; |
| 79 | +
|
| 80 | +vk::DependencyInfo dependency_info = { |
| 81 | + .imageMemoryBarrierCount = 1, |
| 82 | + .pImageMemoryBarriers = &image_barrier, |
| 83 | +}; |
| 84 | +
|
| 85 | +cmd.pipelineBarrier2(dependency_info); |
| 86 | +``` |
| 87 | +
|
| 88 | +**Benefits:** |
| 89 | +
|
| 90 | +- Provides more expressive and flexible synchronization. |
| 91 | +- Reduces the potential for synchronization errors. |
| 92 | +- Simplifies the specification of pipeline stages and access masks. |
| 93 | +
|
| 94 | +### 3. Extended Dynamic State |
| 95 | +
|
| 96 | +**What is Extended Dynamic State?** |
| 97 | +
|
| 98 | +Extended Dynamic State allows more pipeline states to be set dynamically at command buffer recording time rather than during pipeline creation. This reduces the number of pipeline objects needed. |
| 99 | +
|
| 100 | +**How It's Used in the Sample:** |
| 101 | +
|
| 102 | +- **Dynamic States Enabled:** The sample enables dynamic states like `vk::DynamicState::eCullMode`, `vk::DynamicState::eFrontFace`, and `vk::DynamicState::ePrimitiveTopology`. |
| 103 | +- **Dynamic State Commands:** Uses `vk::CommandBuffer::setCullMode()`, `vk::CommandBuffer::setFrontFace()`, and `vk::CommandBuffer::setPrimitiveTopology()` to set these states dynamically. |
| 104 | +
|
| 105 | +**Example Usage:** |
| 106 | +
|
| 107 | +```cpp |
| 108 | +cmd.setCullMode(vk::DynamicState::eCullMode); |
| 109 | +cmd.setFrontFace(vk::FrontFace::eClockwise); |
| 110 | +cmd.setPrimitiveTopology(vk::PrimitiveTopology::eTriangleList); |
| 111 | +``` |
| 112 | +
|
| 113 | +**Benefits:** |
| 114 | +
|
| 115 | +- Reduces the need to create multiple pipelines for different state configurations. |
| 116 | +- Enhances flexibility by allowing state changes without pipeline recreation. |
| 117 | +
|
| 118 | +### 4. Vertex Buffers |
| 119 | +
|
| 120 | +**What Changed?** |
| 121 | +
|
| 122 | +Unlike the original sample, which used hard-coded vertices in the shader, this sample uses a vertex buffer to store vertex data. |
| 123 | +
|
| 124 | +**How It's Used in the Sample:** |
| 125 | +
|
| 126 | +- **Vertex Structure Defined:** |
| 127 | +
|
| 128 | +```cpp |
| 129 | + struct Vertex { |
| 130 | + glm::vec2 position; |
| 131 | + glm::vec3 color; |
| 132 | + }; |
| 133 | +``` |
| 134 | +
|
| 135 | +- **Vertex Data Stored in a Buffer:** |
| 136 | +
|
| 137 | +```cpp |
| 138 | + std::vector<Vertex> vertices = { |
| 139 | + {{0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}}, // Red Vertex |
| 140 | + // ... other vertices ... |
| 141 | + }; |
| 142 | +``` |
| 143 | +
|
| 144 | +- **Buffer Creation and Memory Allocation:** |
| 145 | +
|
| 146 | +```cpp |
| 147 | + vk::BufferCreateInfo buffer_info = { /* ... */ }; |
| 148 | + vertex_buffer = device.createBuffer(buffer_info); |
| 149 | +
|
| 150 | + vk::MemoryAllocateInfo alloc_info = { /* ... */ }; |
| 151 | + vertex_buffer_memory = device.allocateMemory(alloc_info); |
| 152 | +``` |
| 153 | +
|
| 154 | +- **Binding the Vertex Buffer:** |
| 155 | +
|
| 156 | +```cpp |
| 157 | + cmd.bindVertexBuffers(0, vertex_buffer, offset); |
| 158 | +``` |
| 159 | +
|
| 160 | +**Benefits:** |
| 161 | +
|
| 162 | +- **Flexibility:** Easier to modify vertex data without changing shaders. |
| 163 | +- **Performance:** Potentially better performance due to efficient memory usage. |
| 164 | +- **Scalability:** Simplifies rendering more complex geometries. |
| 165 | +
|
| 166 | +## How the Sample Works |
| 167 | +
|
| 168 | +1. **Initialization:** |
| 169 | +
|
| 170 | + - **Instance Creation:** Initializes a Vulkan instance with Vulkan 1.3 API version and required extensions. |
| 171 | + - **Device Selection:** Chooses a physical device that supports Vulkan 1.3 and required features. |
| 172 | + - **Logical Device Creation:** Creates a logical device with enabled Vulkan 1.3 features like dynamic rendering, synchronization2, and extended dynamic state. |
| 173 | + - **Surface and Swapchain Creation:** Sets up the window surface and initializes the swapchain for presenting images. |
| 174 | +
|
| 175 | +2. **Vertex Buffer Setup:** |
| 176 | +
|
| 177 | + - **Vertex Data Definition:** Defines vertices with positions and colors. |
| 178 | + - **Buffer Creation:** Creates a buffer to store vertex data. |
| 179 | + - **Memory Allocation:** Allocates memory for the buffer and maps the vertex data into it. |
| 180 | +
|
| 181 | +3. **Pipeline Setup:** |
| 182 | +
|
| 183 | + - **Shader Modules:** Loads and compiles vertex and fragment shaders. |
| 184 | + - **Pipeline Layout:** Creates a pipeline layout (empty in this case as no descriptors are used). |
| 185 | + - **Dynamic States Specification:** Specifies which states will be dynamic. |
| 186 | + - **Graphics Pipeline Creation:** Creates the graphics pipeline with dynamic rendering info and dynamic states enabled. |
| 187 | +
|
| 188 | +4. **Rendering Loop:** |
| 189 | +
|
| 190 | + - **Acquire Swapchain Image:** Gets the next available image from the swapchain. |
| 191 | + - **Command Buffer Recording:** |
| 192 | +
|
| 193 | + - **Begin Rendering:** Uses `vk::CommandBuffer::beginRendering()` with dynamic rendering info. |
| 194 | + - **Set Dynamic States:** Sets viewport, scissor, cull mode, front face, and primitive topology dynamically. |
| 195 | + - **Bind Pipeline and Vertex Buffer:** Binds the graphics pipeline and the vertex buffer. |
| 196 | + - **Draw Call:** Issues a draw call to render the triangle. |
| 197 | + - **End Rendering:** Uses `vk::CommandBuffer::endRendering()` to finish rendering. |
| 198 | + - **Image Layout Transition:** Transitions the swapchain image layout for presentation using `vk::CommandBuffer::pipelineBarrier2()`. |
| 199 | +
|
| 200 | + - **Queue Submission:** Submits the command buffer to the graphics queue. |
| 201 | + - **Present Image:** Presents the rendered image to the screen. |
| 202 | +
|
| 203 | +5. **Cleanup:** |
| 204 | +
|
| 205 | + - **Resource Destruction:** Cleans up Vulkan resources like pipelines, buffers, and swapchain images upon application exit. |
| 206 | +
|
| 207 | +## Dependencies and Requirements |
| 208 | +
|
| 209 | +- **Vulkan SDK 1.3 or Later:** Ensure you have the Vulkan SDK that supports Vulkan 1.3. |
| 210 | +- **Hardware Support:** A GPU that supports Vulkan 1.3 features, including dynamic rendering, synchronization2, and extended dynamic state. |
| 211 | +- **GLM Library:** Used for vector and matrix operations. |
| 212 | +- **Shader Compiler:** GLSL shaders are compiled at runtime using a GLSL compiler. |
0 commit comments