init
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
# Copyright (c) 2024-2025, 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.
|
||||
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
get_filename_component(FOLDER_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
|
||||
get_filename_component(PARENT_DIR ${CMAKE_CURRENT_LIST_DIR} PATH)
|
||||
get_filename_component(CATEGORY_NAME ${PARENT_DIR} NAME)
|
||||
|
||||
add_sample(
|
||||
ID ${FOLDER_NAME}
|
||||
CATEGORY ${CATEGORY_NAME}
|
||||
AUTHOR "Huawei Technologies Co., Ltd."
|
||||
NAME "Vulkan 1.3 Hello Triangle"
|
||||
DESCRIPTION "An introduction into Vulkan using Vulkan 1.3"
|
||||
SHADER_FILES_GLSL
|
||||
"hello_triangle_1_3/glsl/triangle.vert"
|
||||
"hello_triangle_1_3/glsl/triangle.frag"
|
||||
SHADER_FILES_HLSL
|
||||
"hello_triangle_1_3/hlsl/triangle.vert.hlsl"
|
||||
"hello_triangle_1_3/hlsl/triangle.frag.hlsl"
|
||||
SHADER_FILES_SLANG
|
||||
"hello_triangle_1_3/slang/triangle.vert.slang"
|
||||
"hello_triangle_1_3/slang/triangle.frag.slang")
|
||||
@@ -0,0 +1,213 @@
|
||||
////
|
||||
* 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.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,177 @@
|
||||
/* Copyright (c) 2024-2025, 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/vk_common.h"
|
||||
#include "core/instance.h"
|
||||
#include "platform/application.h"
|
||||
|
||||
/**
|
||||
* @brief A self-contained (minimal use of framework) sample that illustrates
|
||||
* the rendering of a triangle
|
||||
*/
|
||||
class HelloTriangleV13 : public vkb::Application
|
||||
{
|
||||
// Define the Vertex structure
|
||||
struct Vertex
|
||||
{
|
||||
glm::vec2 position;
|
||||
glm::vec3 color;
|
||||
};
|
||||
|
||||
// Define the vertex data
|
||||
const std::vector<Vertex> vertices = {
|
||||
{{0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}}, // Vertex 1: Red
|
||||
{{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}}, // Vertex 2: Green
|
||||
{{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}} // Vertex 3: Blue
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Swapchain state
|
||||
*/
|
||||
struct SwapchainDimensions
|
||||
{
|
||||
/// Width of the swapchain.
|
||||
uint32_t width = 0;
|
||||
|
||||
/// Height of the swapchain.
|
||||
uint32_t height = 0;
|
||||
|
||||
/// Pixel format of the swapchain.
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Per-frame data
|
||||
*/
|
||||
struct PerFrame
|
||||
{
|
||||
VkFence queue_submit_fence = VK_NULL_HANDLE;
|
||||
VkCommandPool primary_command_pool = VK_NULL_HANDLE;
|
||||
VkCommandBuffer primary_command_buffer = VK_NULL_HANDLE;
|
||||
VkSemaphore swapchain_acquire_semaphore = VK_NULL_HANDLE;
|
||||
VkSemaphore swapchain_release_semaphore = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Vulkan objects and global state
|
||||
*/
|
||||
struct Context
|
||||
{
|
||||
/// The Vulkan instance.
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
|
||||
/// The Vulkan physical device.
|
||||
VkPhysicalDevice gpu = VK_NULL_HANDLE;
|
||||
|
||||
/// The Vulkan device.
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
|
||||
/// The Vulkan device queue.
|
||||
VkQueue queue = VK_NULL_HANDLE;
|
||||
|
||||
/// The swapchain.
|
||||
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
|
||||
|
||||
/// The swapchain dimensions.
|
||||
SwapchainDimensions swapchain_dimensions;
|
||||
|
||||
/// The surface we will render to.
|
||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||
|
||||
/// The queue family index where graphics work will be submitted.
|
||||
int32_t graphics_queue_index = -1;
|
||||
|
||||
/// The image view for each swapchain image.
|
||||
std::vector<VkImageView> swapchain_image_views;
|
||||
|
||||
/// The handles to the images in the swapchain.
|
||||
std::vector<VkImage> swapchain_images;
|
||||
|
||||
/// The graphics pipeline.
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
|
||||
/**
|
||||
* The pipeline layout for resources.
|
||||
* Not used in this sample, but we still need to provide a dummy one.
|
||||
*/
|
||||
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
|
||||
|
||||
/// The debug utility messenger callback.
|
||||
VkDebugUtilsMessengerEXT debug_callback = VK_NULL_HANDLE;
|
||||
|
||||
/// A set of semaphores that can be reused.
|
||||
std::vector<VkSemaphore> recycled_semaphores;
|
||||
|
||||
/// A set of per-frame data.
|
||||
std::vector<PerFrame> per_frame;
|
||||
|
||||
/// The Vulkan buffer object that holds the vertex data for the triangle.
|
||||
VkBuffer vertex_buffer = VK_NULL_HANDLE;
|
||||
|
||||
/// The device memory allocated for the vertex buffer.
|
||||
VkDeviceMemory vertex_buffer_memory = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
public:
|
||||
HelloTriangleV13() = default;
|
||||
|
||||
virtual ~HelloTriangleV13();
|
||||
|
||||
virtual bool prepare(const vkb::ApplicationOptions &options) override;
|
||||
|
||||
virtual void update(float delta_time) override;
|
||||
|
||||
virtual bool resize(const uint32_t width, const uint32_t height) override;
|
||||
|
||||
bool validate_extensions(const std::vector<const char *> &required,
|
||||
const std::vector<VkExtensionProperties> &available);
|
||||
|
||||
void init_instance();
|
||||
|
||||
void init_device();
|
||||
|
||||
void init_vertex_buffer();
|
||||
|
||||
void init_per_frame(PerFrame &per_frame);
|
||||
|
||||
void teardown_per_frame(PerFrame &per_frame);
|
||||
|
||||
void init_swapchain();
|
||||
|
||||
VkShaderModule load_shader_module(const std::string &path, VkShaderStageFlagBits shader_stage);
|
||||
|
||||
void init_pipeline();
|
||||
|
||||
VkResult acquire_next_swapchain_image(uint32_t *image);
|
||||
|
||||
void render_triangle(uint32_t swapchain_index);
|
||||
|
||||
VkResult present_image(uint32_t index);
|
||||
|
||||
void transition_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags2 srcAccessMask, VkAccessFlags2 dstAccessMask, VkPipelineStageFlags2 srcStage, VkPipelineStageFlags2 dstStage);
|
||||
|
||||
uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t type_filter, VkMemoryPropertyFlags properties);
|
||||
|
||||
private:
|
||||
Context context;
|
||||
|
||||
std::unique_ptr<vkb::core::InstanceC> vk_instance;
|
||||
};
|
||||
|
||||
std::unique_ptr<vkb::Application> create_hello_triangle_1_3();
|
||||
Reference in New Issue
Block a user