////
 * Copyright (c) 2024, Huawei Technologies Co., Ltd.
 *
 * 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.
////
= Hello Triangle with Vulkan 1.3 Features

ifdef::site-gen-antora[]
TIP: The source for this sample can be found in the https://github.com/KhronosGroup/Vulkan-Samples/tree/main/samples/api/hello_triangle_1_3[Khronos Vulkan samples github repository].
endif::[]


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:

- **Dynamic Rendering**
- **Synchronization2**
- **Extended Dynamic State**
- **Vertex Buffers**

## Overview

The sample renders a colored triangle to the screen using Vulkan 1.3. It showcases how to:

- Initialize Vulkan with Vulkan 1.3 features enabled.
- Use dynamic rendering to simplify the rendering pipeline.
- Employ the Synchronization2 API for improved synchronization.
- Utilize extended dynamic states to reduce pipeline complexity.
- Manage vertex data using vertex buffers instead of hard-coded vertices.

## Key Features

### 1. Dynamic Rendering

**What is Dynamic Rendering?**

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.

**How It's Used in the Sample:**

- **No Render Passes or Framebuffers:** The sample does not create `VkRenderPass` or `VkFramebuffer` objects.
- **`vkCmdBeginRendering()` and `vkCmdEndRendering()`:** These functions are used to begin and end rendering operations dynamically.
- **Pipeline Creation:** Uses `VkPipelineRenderingCreateInfo` during pipeline creation to specify rendering details.

**Benefits:**

- Simplifies code by reducing boilerplate associated with render passes and framebuffers.
- Increases flexibility by allowing rendering to different attachments without recreating render passes.

### 2. Synchronization2

**What is Synchronization2?**

Synchronization2 is an improved synchronization API introduced in Vulkan 1.3. It provides more granular control over synchronization primitives and simplifies the synchronization process.

**How It's Used in the Sample:**

- **`vkCmdPipelineBarrier2()`:** Replaces the older `vkCmdPipelineBarrier()` for more detailed synchronization.
- **`VkDependencyInfo` and `VkImageMemoryBarrier2`:** Used to specify precise memory dependencies and image layout transitions.

**Example Usage:**

```cpp
VkImageMemoryBarrier2 image_barrier = {
    .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
    // ... other members ...
};

VkDependencyInfo dependency_info = {
    .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
    .imageMemoryBarrierCount = 1,
    .pImageMemoryBarriers = &image_barrier,
};

vkCmdPipelineBarrier2(cmd, &dependency_info);
```

**Benefits:**

- Provides more expressive and flexible synchronization.
- Reduces the potential for synchronization errors.
- Simplifies the specification of pipeline stages and access masks.

### 3. Extended Dynamic State

**What is Extended Dynamic State?**

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.

**How It's Used in the Sample:**

- **Dynamic States Enabled:** The sample enables dynamic states like `VK_DYNAMIC_STATE_CULL_MODE`, `VK_DYNAMIC_STATE_FRONT_FACE`, and `VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY`.
- **Dynamic State Commands:** Uses `vkCmdSetCullMode()`, `vkCmdSetFrontFace()`, and `vkCmdSetPrimitiveTopology()` to set these states dynamically.

**Example Usage:**

```cpp
vkCmdSetCullMode(cmd, VK_CULL_MODE_NONE);
vkCmdSetFrontFace(cmd, VK_FRONT_FACE_CLOCKWISE);
vkCmdSetPrimitiveTopology(cmd, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
```

**Benefits:**

- Reduces the need to create multiple pipelines for different state configurations.
- Enhances flexibility by allowing state changes without pipeline recreation.

### 4. Vertex Buffers

**What Changed?**

Unlike the original sample, which used hard-coded vertices in the shader, this sample uses a vertex buffer to store vertex data.

**How It's Used in the Sample:**

- **Vertex Structure Defined:**

```cpp
  struct Vertex {
      glm::vec2 position;
      glm::vec3 color;
  };
```

- **Vertex Data Stored in a Buffer:**

```cpp
  std::vector<Vertex> vertices = {
      {{0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}}, // Red Vertex
      // ... other vertices ...
  };
```

- **Buffer Creation and Memory Allocation:**

```cpp
  VkBufferCreateInfo buffer_info = { /* ... */ };
  vkCreateBuffer(device, &buffer_info, nullptr, &vertex_buffer);

  VkMemoryAllocateInfo alloc_info = { /* ... */ };
  vkAllocateMemory(device, &alloc_info, nullptr, &vertex_buffer_memory);
```

- **Binding the Vertex Buffer:**

```cpp
  vkCmdBindVertexBuffers(cmd, 0, 1, &vertex_buffer, &offset);
```

**Benefits:**

- **Flexibility:** Easier to modify vertex data without changing shaders.
- **Performance:** Potentially better performance due to efficient memory usage.
- **Scalability:** Simplifies rendering more complex geometries.

## How the Sample Works

1. **Initialization:**

   - **Instance Creation:** Initializes a Vulkan instance with Vulkan 1.3 API version and required extensions.
   - **Device Selection:** Chooses a physical device that supports Vulkan 1.3 and required features.
   - **Logical Device Creation:** Creates a logical device with enabled Vulkan 1.3 features like dynamic rendering, synchronization2, and extended dynamic state.
   - **Surface and Swapchain Creation:** Sets up the window surface and initializes the swapchain for presenting images.

2. **Vertex Buffer Setup:**

   - **Vertex Data Definition:** Defines vertices with positions and colors.
   - **Buffer Creation:** Creates a buffer to store vertex data.
   - **Memory Allocation:** Allocates memory for the buffer and maps the vertex data into it.

3. **Pipeline Setup:**

   - **Shader Modules:** Loads and compiles vertex and fragment shaders.
   - **Pipeline Layout:** Creates a pipeline layout (empty in this case as no descriptors are used).
   - **Dynamic States Specification:** Specifies which states will be dynamic.
   - **Graphics Pipeline Creation:** Creates the graphics pipeline with dynamic rendering info and dynamic states enabled.

4. **Rendering Loop:**

   - **Acquire Swapchain Image:** Gets the next available image from the swapchain.
   - **Command Buffer Recording:**

     - **Begin Rendering:** Uses `vkCmdBeginRendering()` with dynamic rendering info.
     - **Set Dynamic States:** Sets viewport, scissor, cull mode, front face, and primitive topology dynamically.
     - **Bind Pipeline and Vertex Buffer:** Binds the graphics pipeline and the vertex buffer.
     - **Draw Call:** Issues a draw call to render the triangle.
     - **End Rendering:** Uses `vkCmdEndRendering()` to finish rendering.
     - **Image Layout Transition:** Transitions the swapchain image layout for presentation using `vkCmdPipelineBarrier2()`.

   - **Queue Submission:** Submits the command buffer to the graphics queue.
   - **Present Image:** Presents the rendered image to the screen.

5. **Cleanup:**

   - **Resource Destruction:** Cleans up Vulkan resources like pipelines, buffers, and swapchain images upon application exit.

## Dependencies and Requirements

- **Vulkan SDK 1.3 or Later:** Ensure you have the Vulkan SDK that supports Vulkan 1.3.
- **Hardware Support:** A GPU that supports Vulkan 1.3 features, including dynamic rendering, synchronization2, and extended dynamic state.
- **GLM Library:** Used for vector and matrix operations.
- **Shader Compiler:** GLSL shaders are compiled at runtime using a GLSL compiler.