Skip to content

Commit 58e0fe7

Browse files
committed
Merge branch 'upstream-main' into address-resize-issue-73
# Conflicts: # attachments/17_swap_chain_recreation.cpp # attachments/18_vertex_input.cpp # attachments/19_vertex_buffer.cpp # attachments/20_staging_buffer.cpp # attachments/26_texture_mapping.cpp # attachments/27_depth_buffering.cpp # attachments/30_multisampling.cpp # attachments/31_compute_shader.cpp
2 parents f87c2d3 + 182bb57 commit 58e0fe7

File tree

112 files changed

+16758
-2112
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+16758
-2112
lines changed

.github/workflows/workflow.yml

Lines changed: 382 additions & 70 deletions
Large diffs are not rendered by default.

README.adoc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,19 @@ The Khronos Vulkan^®^ Tutorial is based on the "link:https://vulkan-tutorial.co
88

99
This repository hosts the contents of the link:https://docs.vulkan.org/tutorial/latest[Khronos Vulkan Tutorial]. The tutorial is part of the link:https://github.com/KhronosGroup/Vulkan-Site[Vulkan Documentation Project].
1010

11+
== Differences
12+
13+
Compared to the original tutorial, this version of the tutorial is teaching up-to-date concepts:
14+
15+
* Vulkan 1.4 as a baseline
16+
* Dynamic rendering instead of render passes
17+
* Timeline semaphores
18+
* link:https://shader-slang.org/[Slang] as the primary shading language
19+
* Modern C++ (20) with modules
20+
* link:https://github.com/KhronosGroup/Vulkan-Hpp[Vulkan-Hpp] with link:https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization[RAII]
21+
22+
It also contains Vulkan usage clarifications, improved synchronization and new content.
23+
1124
== Project Structure
1225

1326
The repository is organized into several important directories:

antora/modules/ROOT/nav.adoc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,10 @@
4646
* xref:09_Generating_Mipmaps.adoc[Generating Mipmaps]
4747
* xref:10_Multisampling.adoc[Multisampling]
4848
* xref:11_Compute_Shader.adoc[Compute Shader]
49-
* xref:90_FAQ.adoc[FAQ]
49+
* xref:12_Ecosystem_Utilities_and_Compatibility.adoc[Ecosystem Utilities and GPU Compatibility]
50+
* xref:13_Vulkan_Profiles.adoc[Vulkan Profiles]
51+
* xref:14_Android.adoc[Android]
52+
* xref:15_GLTF_KTX2_Migration.adoc[Migrating to Modern Asset Formats: glTF and KTX2]
53+
* xref:16_Multiple_Objects.adoc[Rendering Multiple Objects]
54+
* xref:17_Multithreading.adoc[Multithreading]
55+
* xref:90_FAQ.adoc[FAQ]

attachments/00_base_code.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#include <memory>
2+
#ifdef __INTELLISENSE__
3+
#include <vulkan/vulkan_raii.hpp>
4+
#else
25
import vulkan_hpp;
6+
#endif
7+
#include <vulkan/vk_platform.h>
38
#include <GLFW/glfw3.h>
49

510
#include <iostream>
@@ -48,9 +53,8 @@ class HelloTriangleApplication {
4853
};
4954

5055
int main() {
51-
HelloTriangleApplication app{};
52-
5356
try {
57+
HelloTriangleApplication app;
5458
app.run();
5559
} catch (const std::exception& e) {
5660
std::cerr << e.what() << std::endl;

attachments/01_instance_creation.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
#include <cstdlib>
55
#include <memory>
66

7+
#ifdef __INTELLISENSE__
8+
#include <vulkan/vulkan_raii.hpp>
9+
#else
710
import vulkan_hpp;
11+
#endif
12+
813
#include <vulkan/vk_platform.h>
914

1015
#define GLFW_INCLUDE_VULKAN // REQUIRED only for GLFW CreateWindowSurface.

attachments/02_validation_layers.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
66
#include <memory>
77
#include <algorithm>
88

9+
#ifdef __INTELLISENSE__
10+
#include <vulkan/vulkan_raii.hpp>
11+
#else
912
import vulkan_hpp;
13+
#endif
14+
1015
#include <vulkan/vk_platform.h>
1116

1217
#define GLFW_INCLUDE_VULKAN // REQUIRED only for GLFW CreateWindowSurface.

attachments/03_physical_device_selection.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
66
#include <memory>
77
#include <algorithm>
88

9+
#ifdef __INTELLISENSE__
10+
#include <vulkan/vulkan_raii.hpp>
11+
#else
912
import vulkan_hpp;
13+
#endif
14+
1015
#include <vulkan/vk_platform.h>
1116

1217
#define GLFW_INCLUDE_VULKAN // REQUIRED only for GLFW CreateWindowSurface.
@@ -166,7 +171,7 @@ class HelloTriangleApplication {
166171

167172
auto features = device.template getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan13Features, vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>();
168173
bool supportsRequiredFeatures = features.template get<vk::PhysicalDeviceVulkan13Features>().dynamicRendering &&
169-
features.template get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>().extendedDynamicState;
174+
features.template get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>().extendedDynamicState;
170175

171176
return supportsVulkan1_3 && supportsGraphics && supportsAllRequiredExtensions && supportsRequiredFeatures;
172177
} );

attachments/04_logical_device.cpp

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <assert.h>
12
#include <iostream>
23
#include <stdexcept>
34
#include <vector>
@@ -6,7 +7,12 @@
67
#include <memory>
78
#include <algorithm>
89

10+
#ifdef __INTELLISENSE__
11+
#include <vulkan/vulkan_raii.hpp>
12+
#else
913
import vulkan_hpp;
14+
#endif
15+
1016
#include <vulkan/vk_platform.h>
1117

1218
#define GLFW_INCLUDE_VULKAN // REQUIRED only for GLFW CreateWindowSurface.
@@ -170,7 +176,7 @@ class HelloTriangleApplication {
170176

171177
auto features = device.template getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan13Features, vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>();
172178
bool supportsRequiredFeatures = features.template get<vk::PhysicalDeviceVulkan13Features>().dynamicRendering &&
173-
features.template get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>().extendedDynamicState;
179+
features.template get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>().extendedDynamicState;
174180

175181
return supportsVulkan1_3 && supportsGraphics && supportsAllRequiredExtensions && supportsRequiredFeatures;
176182
} );
@@ -191,25 +197,27 @@ class HelloTriangleApplication {
191197
// get the first index into queueFamilyProperties which supports graphics
192198
auto graphicsQueueFamilyProperty = std::ranges::find_if( queueFamilyProperties, []( auto const & qfp )
193199
{ return (qfp.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast<vk::QueueFlags>(0); } );
200+
assert(graphicsQueueFamilyProperty != queueFamilyProperties.end() && "No graphics queue family found!");
194201

195202
auto graphicsIndex = static_cast<uint32_t>( std::distance( queueFamilyProperties.begin(), graphicsQueueFamilyProperty ) );
196203

197204
// query for Vulkan 1.3 features
198-
auto features = physicalDevice.getFeatures2();
199-
vk::PhysicalDeviceVulkan13Features vulkan13Features;
200-
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT extendedDynamicStateFeatures;
201-
vulkan13Features.dynamicRendering = vk::True;
202-
extendedDynamicStateFeatures.extendedDynamicState = vk::True;
203-
vulkan13Features.pNext = &extendedDynamicStateFeatures;
204-
features.pNext = &vulkan13Features;
205+
vk::StructureChain<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan13Features, vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT> featureChain = {
206+
{}, // vk::PhysicalDeviceFeatures2
207+
{.dynamicRendering = true }, // vk::PhysicalDeviceVulkan13Features
208+
{.extendedDynamicState = true } // vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT
209+
};
210+
205211
// create a Device
206212
float queuePriority = 0.0f;
207-
vk::DeviceQueueCreateInfo deviceQueueCreateInfo { .queueFamilyIndex = graphicsIndex, .queueCount = 1, .pQueuePriorities = &queuePriority };
208-
vk::DeviceCreateInfo deviceCreateInfo{ .pNext = &features, .queueCreateInfoCount = 1, .pQueueCreateInfos = &deviceQueueCreateInfo };
209-
deviceCreateInfo.enabledExtensionCount = requiredDeviceExtension.size();
210-
deviceCreateInfo.ppEnabledExtensionNames = requiredDeviceExtension.data();
211-
212-
device = vk::raii::Device( physicalDevice, deviceCreateInfo );
213+
vk::DeviceQueueCreateInfo deviceQueueCreateInfo{ .queueFamilyIndex = graphicsIndex, .queueCount = 1, .pQueuePriorities = &queuePriority };
214+
vk::DeviceCreateInfo deviceCreateInfo{ .pNext = &featureChain.get<vk::PhysicalDeviceFeatures2>(),
215+
.queueCreateInfoCount = 1,
216+
.pQueueCreateInfos = &deviceQueueCreateInfo,
217+
.enabledExtensionCount = static_cast<uint32_t>(requiredDeviceExtension.size()),
218+
.ppEnabledExtensionNames = requiredDeviceExtension.data() };
219+
220+
device = vk::raii::Device(physicalDevice, deviceCreateInfo);
213221
graphicsQueue = vk::raii::Queue( device, graphicsIndex, 0 );
214222
}
215223

attachments/05_window_surface.cpp

Lines changed: 40 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
66
#include <memory>
77
#include <algorithm>
88

9+
#ifdef __INTELLISENSE__
10+
#include <vulkan/vulkan_raii.hpp>
11+
#else
912
import vulkan_hpp;
13+
#endif
14+
1015
#include <vulkan/vk_platform.h>
1116

1217
#define GLFW_INCLUDE_VULKAN // REQUIRED only for GLFW CreateWindowSurface.
@@ -35,18 +40,14 @@ class HelloTriangleApplication {
3540
}
3641

3742
private:
38-
GLFWwindow* window = nullptr;
39-
40-
vk::raii::Context context;
41-
vk::raii::Instance instance = nullptr;
43+
GLFWwindow * window = nullptr;
44+
vk::raii::Context context;
45+
vk::raii::Instance instance = nullptr;
4246
vk::raii::DebugUtilsMessengerEXT debugMessenger = nullptr;
43-
vk::raii::SurfaceKHR surface = nullptr;
44-
45-
vk::raii::PhysicalDevice physicalDevice = nullptr;
46-
vk::raii::Device device = nullptr;
47-
48-
vk::raii::Queue graphicsQueue = nullptr;
49-
vk::raii::Queue presentQueue = nullptr;
47+
vk::raii::SurfaceKHR surface = nullptr;
48+
vk::raii::PhysicalDevice physicalDevice = nullptr;
49+
vk::raii::Device device = nullptr;
50+
vk::raii::Queue queue = nullptr;
5051

5152
std::vector<const char*> requiredDeviceExtension = {
5253
vk::KHRSwapchainExtensionName,
@@ -181,7 +182,7 @@ class HelloTriangleApplication {
181182

182183
auto features = device.template getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan13Features, vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>();
183184
bool supportsRequiredFeatures = features.template get<vk::PhysicalDeviceVulkan13Features>().dynamicRendering &&
184-
features.template get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>().extendedDynamicState;
185+
features.template get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>().extendedDynamicState;
185186

186187
return supportsVulkan1_3 && supportsGraphics && supportsAllRequiredExtensions && supportsRequiredFeatures;
187188
} );
@@ -196,71 +197,43 @@ class HelloTriangleApplication {
196197
}
197198

198199
void createLogicalDevice() {
199-
// find the index of the first queue family that supports graphics
200-
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
201-
202-
// get the first index into queueFamilyProperties which supports graphics
203-
auto graphicsQueueFamilyProperty = std::ranges::find_if( queueFamilyProperties, []( auto const & qfp )
204-
{ return (qfp.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast<vk::QueueFlags>(0); } );
205-
206-
auto graphicsIndex = static_cast<uint32_t>( std::distance( queueFamilyProperties.begin(), graphicsQueueFamilyProperty ) );
200+
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
207201

208-
// determine a queueFamilyIndex that supports present
209-
// first check if the graphicsIndex is good enough
210-
auto presentIndex = physicalDevice.getSurfaceSupportKHR( graphicsIndex, *surface )
211-
? graphicsIndex
212-
: ~0;
213-
if ( presentIndex == queueFamilyProperties.size() )
202+
// get the first index into queueFamilyProperties which supports both graphics and present
203+
uint32_t queueIndex = ~0;
204+
for (uint32_t qfpIndex = 0; qfpIndex < queueFamilyProperties.size(); qfpIndex++)
214205
{
215-
// the graphicsIndex doesn't support present -> look for another family index that supports both
216-
// graphics and present
217-
for ( size_t i = 0; i < queueFamilyProperties.size(); i++ )
218-
{
219-
if ( ( queueFamilyProperties[i].queueFlags & vk::QueueFlagBits::eGraphics ) &&
220-
physicalDevice.getSurfaceSupportKHR( static_cast<uint32_t>( i ), *surface ) )
221-
{
222-
graphicsIndex = static_cast<uint32_t>( i );
223-
presentIndex = graphicsIndex;
224-
break;
225-
}
226-
}
227-
if ( presentIndex == queueFamilyProperties.size() )
228-
{
229-
// there's nothing like a single family index that supports both graphics and present -> look for another
230-
// family index that supports present
231-
for ( size_t i = 0; i < queueFamilyProperties.size(); i++ )
232-
{
233-
if ( physicalDevice.getSurfaceSupportKHR( static_cast<uint32_t>( i ), *surface ) )
234-
{
235-
presentIndex = static_cast<uint32_t>( i );
236-
break;
237-
}
238-
}
239-
}
206+
if ((queueFamilyProperties[qfpIndex].queueFlags & vk::QueueFlagBits::eGraphics) &&
207+
physicalDevice.getSurfaceSupportKHR(qfpIndex, *surface))
208+
{
209+
// found a queue family that supports both graphics and present
210+
queueIndex = qfpIndex;
211+
break;
212+
}
240213
}
241-
if ( ( graphicsIndex == queueFamilyProperties.size() ) || ( presentIndex == queueFamilyProperties.size() ) )
214+
if (queueIndex == ~0)
242215
{
243-
throw std::runtime_error( "Could not find a queue for graphics or present -> terminating" );
216+
throw std::runtime_error("Could not find a queue for graphics and present -> terminating");
244217
}
245-
218+
246219
// query for Vulkan 1.3 features
247-
auto features = physicalDevice.getFeatures2();
248-
vk::PhysicalDeviceVulkan13Features vulkan13Features;
249-
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT extendedDynamicStateFeatures;
250-
vulkan13Features.dynamicRendering = vk::True;
251-
extendedDynamicStateFeatures.extendedDynamicState = vk::True;
252-
vulkan13Features.pNext = &extendedDynamicStateFeatures;
253-
features.pNext = &vulkan13Features;
220+
vk::StructureChain<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan13Features, vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT> featureChain = {
221+
{}, // vk::PhysicalDeviceFeatures2
222+
{.dynamicRendering = true }, // vk::PhysicalDeviceVulkan13Features
223+
{.extendedDynamicState = true } // vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT
224+
};
225+
254226
// create a Device
255227
float queuePriority = 0.0f;
256-
vk::DeviceQueueCreateInfo deviceQueueCreateInfo { .queueFamilyIndex = graphicsIndex, .queueCount = 1, .pQueuePriorities = &queuePriority };
257-
vk::DeviceCreateInfo deviceCreateInfo{ .pNext = &features, .queueCreateInfoCount = 1, .pQueueCreateInfos = &deviceQueueCreateInfo };
258-
deviceCreateInfo.enabledExtensionCount = requiredDeviceExtension.size();
259-
deviceCreateInfo.ppEnabledExtensionNames = requiredDeviceExtension.data();
228+
vk::DeviceQueueCreateInfo deviceQueueCreateInfo{ .queueFamilyIndex = queueIndex, .queueCount = 1, .pQueuePriorities = &queuePriority };
229+
vk::DeviceCreateInfo deviceCreateInfo{ .pNext = &featureChain.get<vk::PhysicalDeviceFeatures2>(),
230+
.queueCreateInfoCount = 1,
231+
.pQueueCreateInfos = &deviceQueueCreateInfo,
232+
.enabledExtensionCount = static_cast<uint32_t>(requiredDeviceExtension.size()),
233+
.ppEnabledExtensionNames = requiredDeviceExtension.data() };
260234

261235
device = vk::raii::Device( physicalDevice, deviceCreateInfo );
262-
graphicsQueue = vk::raii::Queue( device, graphicsIndex, 0 );
263-
presentQueue = vk::raii::Queue( device, presentIndex, 0 );
236+
queue = vk::raii::Queue( device, queueIndex, 0 );
264237
}
265238

266239
std::vector<const char*> getRequiredExtensions() {

0 commit comments

Comments
 (0)