From dc02dccc6253ebec5d031debceee583f71109bb5 Mon Sep 17 00:00:00 2001 From: Petr Kraus Date: Thu, 13 Jul 2023 22:29:37 +0200 Subject: [PATCH 01/31] Fix depth buffer reuse sync (#345) --- code/27_depth_buffering.cpp | 4 ++-- code/28_model_loading.cpp | 4 ++-- code/29_mipmapping.cpp | 4 ++-- code/30_multisampling.cpp | 4 ++-- en/07_Depth_buffering.md | 3 ++- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/code/27_depth_buffering.cpp b/code/27_depth_buffering.cpp index 96015dd4..5e0452c2 100644 --- a/code/27_depth_buffering.cpp +++ b/code/27_depth_buffering.cpp @@ -561,8 +561,8 @@ class HelloTriangleApplication { VkSubpassDependency dependency{}; dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependency.srcAccessMask = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; diff --git a/code/28_model_loading.cpp b/code/28_model_loading.cpp index 6f1b7b44..319e4f7f 100644 --- a/code/28_model_loading.cpp +++ b/code/28_model_loading.cpp @@ -568,8 +568,8 @@ class HelloTriangleApplication { VkSubpassDependency dependency{}; dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependency.srcAccessMask = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; diff --git a/code/29_mipmapping.cpp b/code/29_mipmapping.cpp index c12692b4..f1cdf23c 100644 --- a/code/29_mipmapping.cpp +++ b/code/29_mipmapping.cpp @@ -569,8 +569,8 @@ class HelloTriangleApplication { VkSubpassDependency dependency{}; dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependency.srcAccessMask = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; diff --git a/code/30_multisampling.cpp b/code/30_multisampling.cpp index d430108d..8bf9cd59 100644 --- a/code/30_multisampling.cpp +++ b/code/30_multisampling.cpp @@ -596,8 +596,8 @@ class HelloTriangleApplication { VkSubpassDependency dependency{}; dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependency.srcAccessMask = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; diff --git a/en/07_Depth_buffering.md b/en/07_Depth_buffering.md index 0aed8eab..92040cb3 100644 --- a/en/07_Depth_buffering.md +++ b/en/07_Depth_buffering.md @@ -425,7 +425,8 @@ Next, update the `VkSubpassDependency` struct to refer to both attachments. ```c++ -dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; +dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; +dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; ``` From e16c14242429b54ed02dc0136ac011716f7cc570 Mon Sep 17 00:00:00 2001 From: Gleb Ezhov Date: Sun, 16 Jul 2023 21:13:16 +0400 Subject: [PATCH 02/31] Added missing dot (#348) --- en/05_Uniform_buffers/00_Descriptor_layout_and_buffer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/05_Uniform_buffers/00_Descriptor_layout_and_buffer.md b/en/05_Uniform_buffers/00_Descriptor_layout_and_buffer.md index b2c18ebb..b274cb38 100644 --- a/en/05_Uniform_buffers/00_Descriptor_layout_and_buffer.md +++ b/en/05_Uniform_buffers/00_Descriptor_layout_and_buffer.md @@ -233,7 +233,7 @@ We should have multiple buffers, because multiple frames may be in flight at the time and we don't want to update the buffer in preparation of the next frame while a previous one is still reading from it! Thus, we need to have as many uniform buffers as we have frames in flight, and write to a uniform buffer that is not currently -being read by the GPU +being read by the GPU. To that end, add new class members for `uniformBuffers`, and `uniformBuffersMemory`: From 681c588e3b4f4372ba26bef28f479d812a699c98 Mon Sep 17 00:00:00 2001 From: Jay Xu <69374701+krfantasy@users.noreply.github.com> Date: Tue, 25 Jul 2023 02:43:47 +0800 Subject: [PATCH 03/31] Fix multisampled color attachment sync (#349) (#350) * Fix multisampled color attachment sync (#349) * Update 10_Multisampling.md fix typo --- code/30_multisampling.cpp | 2 +- en/10_Multisampling.md | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/code/30_multisampling.cpp b/code/30_multisampling.cpp index 8bf9cd59..61b7a421 100644 --- a/code/30_multisampling.cpp +++ b/code/30_multisampling.cpp @@ -597,7 +597,7 @@ class HelloTriangleApplication { dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.dstSubpass = 0; dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; diff --git a/en/10_Multisampling.md b/en/10_Multisampling.md index e85dba91..70b27b51 100644 --- a/en/10_Multisampling.md +++ b/en/10_Multisampling.md @@ -196,6 +196,14 @@ Set the `pResolveAttachments` subpass struct member to point to the newly create ... ``` +Since we're reusing the multisampled color image, it's necessary to update the `srcAccessMask` of the `VkSubpassDependency`. This update ensures that any write operations to the color attachment are completed before subsequent ones begin, thus preventing write-after-write hazards that can lead to unstable rendering results: + +```c++ + ... + dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + ... +``` + Now update render pass info struct with the new color attachment: ```c++ From bba1ee6e63cc738fd9b26a7b43b59c448c36ecad Mon Sep 17 00:00:00 2001 From: Reese Gallagher Date: Wed, 2 Aug 2023 17:22:31 -0400 Subject: [PATCH 04/31] Update development environment tutorial for Linux to indicate possible libraries which may need to be installed (#353) --- en/02_Development_environment.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/en/02_Development_environment.md b/en/02_Development_environment.md index 4f1da483..8eac260f 100644 --- a/en/02_Development_environment.md +++ b/en/02_Development_environment.md @@ -219,6 +219,11 @@ include the Vulkan runtime and that your graphics card is supported. See the [introduction chapter](!en/Introduction) for links to drivers from the major vendors. +### X Window System and XFree86-VidModeExtension +It is possible that these libraries are not on the system, if not, you can install them using the following commands: +* `sudo apt install libxxf86vm-dev` or `dnf install libXxf86vm-devel`: Provides an interface to the XFree86-VidModeExtension. +* `sudo apt install libxi-dev` or `dnf install libXi-devel`: Provides an X Window System client interface to the XINPUT extension. + ### GLFW As mentioned before, Vulkan by itself is a platform agnostic API and does not From 1dbd594b5c2d6f0c3fb9fbf1d78e7fd2b53ad710 Mon Sep 17 00:00:00 2001 From: Chuigda WhiteGive Date: Thu, 3 Aug 2023 05:24:31 +0800 Subject: [PATCH 05/31] Add another good Rust tutorial (#352) * Add another good Rust tutorial * Update 00_Introduction.md --- en/00_Introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/00_Introduction.md b/en/00_Introduction.md index b6c55caa..5bc90df6 100644 --- a/en/00_Introduction.md +++ b/en/00_Introduction.md @@ -48,7 +48,7 @@ for a great introduction of computer graphics concepts. Some other great compute You can use C instead of C++ if you want, but you will have to use a different linear algebra library and you will be on your own in terms of code structuring. We will use C++ features like classes and RAII to organize logic and resource -lifetimes. There is also an [alternative version](https://github.com/bwasty/vulkan-tutorial-rs) of this tutorial available for Rust developers. +lifetimes. There are also two alternative versions of this tutorial available for Rust developers: [Vulkano based](https://github.com/bwasty/vulkan-tutorial-rs), [Vulkanalia based](https://kylemayes.github.io/vulkanalia). To make it easier to follow along for developers using other programming languages, and to get some experience with the base API we'll be using the original C API to work with Vulkan. If you are using C++, however, you may prefer using the newer [Vulkan-Hpp](https://github.com/KhronosGroup/Vulkan-Hpp) bindings that abstract some of the dirty work and help prevent certain classes of errors. From 898f655f925ca57a8b4757e3b4e82b106fe9073c Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Wed, 9 Aug 2023 21:35:09 +0200 Subject: [PATCH 06/31] Use `VK_LOD_CLAMP_NONE` constant to set mipmap max LOD level in sampler (#354) This allows for using different texture sizes without having to know the mipmap count in advance. All conformant Vulkan implementations should be able to handle this constant, which is equal to `1000.0f`. --- code/29_mipmapping.cpp | 2 +- code/30_multisampling.cpp | 2 +- en/09_Generating_Mipmaps.md | 4 ++-- "fr/09_G\303\251n\303\251rer_des_mipmaps.md" | 5 ++--- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/code/29_mipmapping.cpp b/code/29_mipmapping.cpp index f1cdf23c..ae0cadf5 100644 --- a/code/29_mipmapping.cpp +++ b/code/29_mipmapping.cpp @@ -952,7 +952,7 @@ class HelloTriangleApplication { samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = static_cast(mipLevels); + samplerInfo.maxLod = VK_LOD_CLAMP_NONE; samplerInfo.mipLodBias = 0.0f; if (vkCreateSampler(device, &samplerInfo, nullptr, &textureSampler) != VK_SUCCESS) { diff --git a/code/30_multisampling.cpp b/code/30_multisampling.cpp index 61b7a421..638c2219 100644 --- a/code/30_multisampling.cpp +++ b/code/30_multisampling.cpp @@ -1002,7 +1002,7 @@ class HelloTriangleApplication { samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = static_cast(mipLevels); + samplerInfo.maxLod = VK_LOD_CLAMP_NONE; samplerInfo.mipLodBias = 0.0f; if (vkCreateSampler(device, &samplerInfo, nullptr, &textureSampler) != VK_SUCCESS) { diff --git a/en/09_Generating_Mipmaps.md b/en/09_Generating_Mipmaps.md index 377ffa53..e4033136 100644 --- a/en/09_Generating_Mipmaps.md +++ b/en/09_Generating_Mipmaps.md @@ -317,13 +317,13 @@ void createTextureSampler() { ... samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; samplerInfo.minLod = 0.0f; // Optional - samplerInfo.maxLod = static_cast(mipLevels); + samplerInfo.maxLod = VK_LOD_CLAMP_NONE; samplerInfo.mipLodBias = 0.0f; // Optional ... } ``` -To allow the full range of mip levels to be used, we set `minLod` to 0.0f, and `maxLod` to the number of mip levels. We have no reason to change the `lod` value , so we set `mipLodBias` to 0.0f. +To allow the full range of mip levels to be used, we set `minLod` to 0.0f, and `maxLod` to `VK_LOD_CLAMP_NONE`. This constant is equal to `1000.0f`, which means that all available mipmap levels in the texture will be sampled. We have no reason to change the `lod` value, so we set `mipLodBias` to 0.0f. Now run your program and you should see the following: diff --git "a/fr/09_G\303\251n\303\251rer_des_mipmaps.md" "b/fr/09_G\303\251n\303\251rer_des_mipmaps.md" index 33ffaa25..7d328479 100644 --- "a/fr/09_G\303\251n\303\251rer_des_mipmaps.md" +++ "b/fr/09_G\303\251n\303\251rer_des_mipmaps.md" @@ -375,14 +375,13 @@ void createTextureSampler() { ... samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = static_cast(mipLevels); + samplerInfo.maxLod = VK_LOD_CLAMP_NONE; samplerInfo.mipLodBias = 0.0f; // Optionnel ... } ``` -Pour utiliser la totalité des niveaux de mipmaps, nous mettons `minLod` à `0.0f` et `maxLod` au nombre de niveaux de -mipmaps. Nous n'avons aucune raison d'altérer `lod` avec `mipLodBias`, alors nous pouvons le mettre à `0.0f`. +Pour utiliser la totalité des niveaux de mipmaps, nous mettons `minLod` à `0.0f` et `maxLod` à `VK_LOD_CLAMP_NONE`. Cette constante est égale à `1000.0f`, ce qui veut dire que la totalité des niveaux de mipmaps disponible dans la texture sera échantillonée. Nous n'avons aucune raison d'altérer `lod` avec `mipLodBias`, alors nous pouvons le mettre à `0.0f`. Lancez votre programme et vous devriez voir ceci : From 71b71e484127919a947d954d05c6954a30ed994f Mon Sep 17 00:00:00 2001 From: Chuigda WhiteGive Date: Tue, 26 Sep 2023 03:31:00 +0800 Subject: [PATCH 07/31] replace "descriptor layout" with "descriptor set layout" (#358) --- ...criptor_layout.cpp => 22_descriptor_set_layout.cpp} | 6 +++--- code/CMakeLists.txt | 2 +- ...uffer.md => 00_Descriptor_set_layout_and_buffer.md} | 10 +++++----- en/05_Uniform_buffers/01_Descriptor_pool_and_sets.md | 6 +++--- en/06_Texture_mapping/02_Combined_image_sampler.md | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) rename code/{22_descriptor_layout.cpp => 22_descriptor_set_layout.cpp} (99%) rename en/05_Uniform_buffers/{00_Descriptor_layout_and_buffer.md => 00_Descriptor_set_layout_and_buffer.md} (98%) diff --git a/code/22_descriptor_layout.cpp b/code/22_descriptor_set_layout.cpp similarity index 99% rename from code/22_descriptor_layout.cpp rename to code/22_descriptor_set_layout.cpp index 123c2269..3d54aa6a 100644 --- a/code/22_descriptor_layout.cpp +++ b/code/22_descriptor_set_layout.cpp @@ -232,7 +232,7 @@ class HelloTriangleApplication { vkDestroyPipeline(device, graphicsPipeline, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyRenderPass(device, renderPass, nullptr); - + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { vkDestroyBuffer(device, uniformBuffers[i], nullptr); vkFreeMemory(device, uniformBuffersMemory[i], nullptr); @@ -593,7 +593,7 @@ class HelloTriangleApplication { viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; viewportState.viewportCount = 1; viewportState.scissorCount = 1; - + VkPipelineRasterizationStateCreateInfo rasterizer{}; rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; rasterizer.depthClampEnable = VK_FALSE; @@ -751,7 +751,7 @@ class HelloTriangleApplication { for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffers[i], uniformBuffersMemory[i]); - + vkMapMemory(device, uniformBuffersMemory[i], 0, bufferSize, 0, &uniformBuffersMapped[i]); } } diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index e8c67b02..63da81c0 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -128,7 +128,7 @@ add_chapter (21_index_buffer SHADER 18_shader_vertexbuffer LIBS glm::glm) -add_chapter (22_descriptor_layout +add_chapter (22_descriptor_set_layout SHADER 22_shader_ubo LIBS glm::glm) diff --git a/en/05_Uniform_buffers/00_Descriptor_layout_and_buffer.md b/en/05_Uniform_buffers/00_Descriptor_set_layout_and_buffer.md similarity index 98% rename from en/05_Uniform_buffers/00_Descriptor_layout_and_buffer.md rename to en/05_Uniform_buffers/00_Descriptor_set_layout_and_buffer.md index b274cb38..2bdcc2dc 100644 --- a/en/05_Uniform_buffers/00_Descriptor_layout_and_buffer.md +++ b/en/05_Uniform_buffers/00_Descriptor_set_layout_and_buffer.md @@ -13,11 +13,11 @@ images. We're going to set up a buffer that contains the transformation matrices and have the vertex shader access them through a descriptor. Usage of descriptors consists of three parts: -* Specify a descriptor layout during pipeline creation +* Specify a descriptor set layout during pipeline creation * Allocate a descriptor set from a descriptor pool * Bind the descriptor set during rendering -The *descriptor layout* specifies the types of resources that are going to be +The *descriptor set layout* specifies the types of resources that are going to be accessed by the pipeline, just like a render pass specifies the types of attachments that will be accessed. A *descriptor set* specifies the actual buffer or image resources that will be bound to the descriptors, just like a @@ -86,7 +86,7 @@ void main() { Note that the order of the `uniform`, `in` and `out` declarations doesn't matter. The `binding` directive is similar to the `location` directive for -attributes. We're going to reference this binding in the descriptor layout. The +attributes. We're going to reference this binding in the descriptor set layout. The line with `gl_Position` is changed to use the transformations to compute the final position in clip coordinates. Unlike the 2D triangles, the last component of the clip coordinates may not be `1`, which will result in a division when @@ -208,7 +208,7 @@ layouts here, because a single one already includes all of the bindings. We'll get back to that in the next chapter, where we'll look into descriptor pools and descriptor sets. -The descriptor layout should stick around while we may create new graphics +The descriptor set layout should stick around while we may create new graphics pipelines i.e. until the program ends: ```c++ @@ -411,6 +411,6 @@ In the next chapter we'll look at descriptor sets, which will actually bind the `VkBuffer`s to the uniform buffer descriptors so that the shader can access this transformation data. -[C++ code](/code/22_descriptor_layout.cpp) / +[C++ code](/code/22_descriptor_set_layout.cpp) / [Vertex shader](/code/22_shader_ubo.vert) / [Fragment shader](/code/22_shader_ubo.frag) diff --git a/en/05_Uniform_buffers/01_Descriptor_pool_and_sets.md b/en/05_Uniform_buffers/01_Descriptor_pool_and_sets.md index 5e373f68..b204db24 100644 --- a/en/05_Uniform_buffers/01_Descriptor_pool_and_sets.md +++ b/en/05_Uniform_buffers/01_Descriptor_pool_and_sets.md @@ -1,6 +1,6 @@ ## Introduction -The descriptor layout from the previous chapter describes the type of +The descriptor set layout from the previous chapter describes the type of descriptors that can be bound. In this chapter we're going to create a descriptor set for each `VkBuffer` resource to bind it to the uniform buffer descriptor. @@ -95,7 +95,7 @@ void createDescriptorSets() { A descriptor set allocation is described with a `VkDescriptorSetAllocateInfo` struct. You need to specify the descriptor pool to allocate from, the number of -descriptor sets to allocate, and the descriptor layout to base them on: +descriptor sets to allocate, and the descriptor set layout to base them on: ```c++ std::vector layouts(MAX_FRAMES_IN_FLIGHT, descriptorSetLayout); @@ -374,7 +374,7 @@ Don't forget to recompile your shader after removing the `foo` field. ## Multiple descriptor sets As some of the structures and function calls hinted at, it is actually possible -to bind multiple descriptor sets simultaneously. You need to specify a descriptor layout for +to bind multiple descriptor sets simultaneously. You need to specify a descriptor set layout for each descriptor set when creating the pipeline layout. Shaders can then reference specific descriptor sets like this: diff --git a/en/06_Texture_mapping/02_Combined_image_sampler.md b/en/06_Texture_mapping/02_Combined_image_sampler.md index b86853d6..9c8721db 100644 --- a/en/06_Texture_mapping/02_Combined_image_sampler.md +++ b/en/06_Texture_mapping/02_Combined_image_sampler.md @@ -6,7 +6,7 @@ image sampler*. This descriptor makes it possible for shaders to access an image resource through a sampler object like the one we created in the previous chapter. -We'll start by modifying the descriptor layout, descriptor pool and descriptor +We'll start by modifying the descriptor set layout, descriptor pool and descriptor set to include such a combined image sampler descriptor. After that, we're going to add texture coordinates to `Vertex` and modify the fragment shader to read colors from the texture instead of just interpolating the vertex colors. From fe86b765ddc6fe47c5c3a0162d047883b066674c Mon Sep 17 00:00:00 2001 From: Hyungki Kim Date: Tue, 17 Oct 2023 03:25:58 +0900 Subject: [PATCH 08/31] Update 01_Shader_modules.md (#360) --- .../02_Graphics_pipeline_basics/01_Shader_modules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/03_Drawing_a_triangle/02_Graphics_pipeline_basics/01_Shader_modules.md b/en/03_Drawing_a_triangle/02_Graphics_pipeline_basics/01_Shader_modules.md index 20aee6b5..ef12e836 100644 --- a/en/03_Drawing_a_triangle/02_Graphics_pipeline_basics/01_Shader_modules.md +++ b/en/03_Drawing_a_triangle/02_Graphics_pipeline_basics/01_Shader_modules.md @@ -45,7 +45,7 @@ two SPIR-V binaries and load them into the program. ## Vertex shader The vertex shader processes each incoming vertex. It takes its attributes, like -world position, color, normal and texture coordinates as input. The output is +model space position, color, normal and texture coordinates as input. The output is the final position in clip coordinates and the attributes that need to be passed on to the fragment shader, like color and texture coordinates. These values will then be interpolated over the fragments by the rasterizer to produce a smooth From 2742b9f1a7369db054e0da0abedce31945c80483 Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Mon, 30 Oct 2023 21:43:40 +0100 Subject: [PATCH 09/31] Add compute shader compilation to cmake (#362) * Add compute shader to build targets (if present) Fixes #351 Fixes #361 * Add compute shader to build targets (if present) Fixes #351 Fixes #361 * Add compute shader to build targets (if present) Fixes #351 Fixes #361 --- code/CMakeLists.txt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 63da81c0..4c409f92 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -28,8 +28,15 @@ function (add_shaders_target TARGET) OUTPUT ${SHADERS_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory ${SHADERS_DIR} ) + set (SHADERS ${SHADERS_DIR}/frag.spv ${SHADERS_DIR}/vert.spv) + # Some chapters may have compute shaders in addition to vertex and fragment shaders, + # so we conditionally check this and add them to the target + string(FIND "${SHADER_SOURCES}" "${CHAPTER_SHADER}.comp" COMPUTE_SHADER_INDEX) + if (${COMPUTE_SHADER_INDEX} GREATER -1) + set (SHADERS ${SHADERS} ${SHADERS_DIR}/comp.spv) + endif() add_custom_command ( - OUTPUT ${SHADERS_DIR}/frag.spv ${SHADERS_DIR}/vert.spv + OUTPUT ${SHADERS} COMMAND glslang::validator ARGS --target-env vulkan1.0 ${SHADER_SOURCES} --quiet WORKING_DIRECTORY ${SHADERS_DIR} @@ -37,7 +44,7 @@ function (add_shaders_target TARGET) COMMENT "Compiling Shaders" VERBATIM ) - add_custom_target (${TARGET} DEPENDS ${SHADERS_DIR}/frag.spv ${SHADERS_DIR}/vert.spv) + add_custom_target (${TARGET} DEPENDS ${SHADERS}) endfunction () function (add_chapter CHAPTER_NAME) @@ -52,7 +59,7 @@ function (add_chapter CHAPTER_NAME) if (DEFINED CHAPTER_SHADER) set (CHAPTER_SHADER_TARGET ${CHAPTER_NAME}_shader) - file (GLOB SHADER_SOURCES ${CHAPTER_SHADER}.frag ${CHAPTER_SHADER}.vert) + file (GLOB SHADER_SOURCES ${CHAPTER_SHADER}.frag ${CHAPTER_SHADER}.vert ${CHAPTER_SHADER}.comp) add_shaders_target (${CHAPTER_SHADER_TARGET} CHAPTER_NAME ${CHAPTER_NAME} SOURCES ${SHADER_SOURCES}) add_dependencies (${CHAPTER_NAME} ${CHAPTER_SHADER_TARGET}) endif () From 2f3ac600c1ec8104d63707d3733b78e50c671630 Mon Sep 17 00:00:00 2001 From: Ryan Linnit Date: Tue, 14 Nov 2023 18:22:52 +0000 Subject: [PATCH 10/31] Use range-based loops in markdown (#365) --- .../04_Swap_chain_recreation.md | 8 ++++---- .../04_Recr\303\251ation_de_la_swap_chain.md" | 19 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/en/03_Drawing_a_triangle/04_Swap_chain_recreation.md b/en/03_Drawing_a_triangle/04_Swap_chain_recreation.md index 5da07458..9c598528 100644 --- a/en/03_Drawing_a_triangle/04_Swap_chain_recreation.md +++ b/en/03_Drawing_a_triangle/04_Swap_chain_recreation.md @@ -56,12 +56,12 @@ chain refresh from `cleanup` to `cleanupSwapChain`: ```c++ void cleanupSwapChain() { - for (size_t i = 0; i < swapChainFramebuffers.size(); i++) { - vkDestroyFramebuffer(device, swapChainFramebuffers[i], nullptr); + for (auto framebuffer : swapChainFramebuffers) { + vkDestroyFramebuffer(device, framebuffer, nullptr); } - for (size_t i = 0; i < swapChainImageViews.size(); i++) { - vkDestroyImageView(device, swapChainImageViews[i], nullptr); + for (auto imageView : swapChainImageViews) { + vkDestroyImageView(device, imageView, nullptr); } vkDestroySwapchainKHR(device, swapChain, nullptr); diff --git "a/fr/03_Dessiner_un_triangle/04_Recr\303\251ation_de_la_swap_chain.md" "b/fr/03_Dessiner_un_triangle/04_Recr\303\251ation_de_la_swap_chain.md" index 4f979076..175ae235 100644 --- "a/fr/03_Dessiner_un_triangle/04_Recr\303\251ation_de_la_swap_chain.md" +++ "b/fr/03_Dessiner_un_triangle/04_Recr\303\251ation_de_la_swap_chain.md" @@ -58,18 +58,12 @@ Nous allons déplacer le code de suppression depuis `cleanup` jusqu'à `cleanupS ```c++ void cleanupSwapChain() { - for (size_t i = 0; i < swapChainFramebuffers.size(); i++) { - vkDestroyFramebuffer(device, swapChainFramebuffers[i], nullptr); + for (auto framebuffer : swapChainFramebuffers) { + vkDestroyFramebuffer(device, framebuffer, nullptr); } - vkFreeCommandBuffers(device, commandPool, static_cast(commandBuffers.size()), commandBuffers.data()); - - vkDestroyPipeline(device, graphicsPipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyRenderPass(device, renderPass, nullptr); - - for (size_t i = 0; i < swapChainImageViews.size(); i++) { - vkDestroyImageView(device, swapChainImageViews[i], nullptr); + for (auto imageView : swapChainImageViews) { + vkDestroyImageView(device, imageView, nullptr); } vkDestroySwapchainKHR(device, swapChain, nullptr); @@ -82,6 +76,11 @@ Nous pouvons ensuite appeler cette nouvelle fonction depuis `cleanup` pour évit void cleanup() { cleanupSwapChain(); + vkDestroyPipeline(device, graphicsPipeline, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + + vkDestroyRenderPass(device, renderPass, nullptr); + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr); vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr); From 51f440d436f0354294e349f1bc11323e9689a0b5 Mon Sep 17 00:00:00 2001 From: BRH <62248962+0BAB1@users.noreply.github.com> Date: Mon, 4 Dec 2023 20:47:38 +0100 Subject: [PATCH 11/31] Fix typo (#370) Forgot an "a". --- fr/03_Dessiner_un_triangle/00_Mise_en_place/01_Instance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fr/03_Dessiner_un_triangle/00_Mise_en_place/01_Instance.md b/fr/03_Dessiner_un_triangle/00_Mise_en_place/01_Instance.md index 496e840a..851c5aee 100644 --- a/fr/03_Dessiner_un_triangle/00_Mise_en_place/01_Instance.md +++ b/fr/03_Dessiner_un_triangle/00_Mise_en_place/01_Instance.md @@ -20,7 +20,7 @@ VkInstance instance; Pour créer l'instance, nous allons d'abord remplir une première structure avec des informations sur notre application. Ces données sont optionnelles, mais elles peuvent fournir des informations utiles au driver pour optimiser ou -dignostiquer les erreurs lors de l'exécution, par exemple en reconnaissant le nom d'un moteur graphique. Cette structure +diagnostiquer les erreurs lors de l'exécution, par exemple en reconnaissant le nom d'un moteur graphique. Cette structure s'appelle `VkApplicationInfo` : ```c++ From eb5e70e580fefa5cd57b61fa0bc1d2307ad7809d Mon Sep 17 00:00:00 2001 From: Alexander Overvoorde Date: Mon, 11 Dec 2023 20:11:37 +0100 Subject: [PATCH 12/31] Add a link to a Chinese translation of the tutorial --- config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.json b/config.json index 35920b42..bc711b52 100644 --- a/config.json +++ b/config.json @@ -26,7 +26,8 @@ "Rust code": "https://github.com/bwasty/vulkan-tutorial-rs", "Java code": "https://github.com/Naitsirc98/Vulkan-Tutorial-Java", "Go code": "https://github.com/vkngwrapper/vulkan-tutorial", - "Visual Studio 2019 samples": "https://github.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles" + "Visual Studio 2019 samples": "https://github.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles", + "Chinese translation": "https://github.com/fangcun010/VulkanTutorialCN" } }, "ignore": { From f4a98c0c5ace18f66065401ed938aa12d0769761 Mon Sep 17 00:00:00 2001 From: Jing Luo <60296981+delgh1@users.noreply.github.com> Date: Fri, 5 Jan 2024 04:08:39 +0900 Subject: [PATCH 13/31] Add license files and a license section in introduction (#372) * 00_Introduction.md: add a license section Add a "license" section to clarify the copyright status of the website/ebook. * Add LICENSE.CC-BY-SA-40 * Add LICENSE.CC0 --- LICENSE.CC-BY-SA-40 | 427 ++++++++++++++++++++++++++++++++++++++++++ LICENSE.CC0 | 121 ++++++++++++ en/00_Introduction.md | 17 ++ 3 files changed, 565 insertions(+) create mode 100644 LICENSE.CC-BY-SA-40 create mode 100644 LICENSE.CC0 diff --git a/LICENSE.CC-BY-SA-40 b/LICENSE.CC-BY-SA-40 new file mode 100644 index 00000000..7028425e --- /dev/null +++ b/LICENSE.CC-BY-SA-40 @@ -0,0 +1,427 @@ +Attribution-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-ShareAlike 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-ShareAlike 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + l. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + m. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + including for purposes of Section 3(b); and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the "Licensor". The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/LICENSE.CC0 b/LICENSE.CC0 new file mode 100644 index 00000000..0e259d42 --- /dev/null +++ b/LICENSE.CC0 @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/en/00_Introduction.md b/en/00_Introduction.md index 5bc90df6..e56799e9 100644 --- a/en/00_Introduction.md +++ b/en/00_Introduction.md @@ -125,3 +125,20 @@ still stuck after that, then feel free to ask for help in the comment section of the closest related chapter. Ready to dive into the future of high performance graphics APIs? [Let's go!](!en/Overview) + +## License + +Copyright (C) 2015-2023, Alexander Overvoorde + +The contents are licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/), +unless stated otherwise. By contributing, you agree to license +your contributions to the public under that same license. + +The code listings in the `code` directory in the source repository are licensed +under [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/). +By contributing to that directory, you agree to license your contributions to +the public under that same public domain-like license. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. From fe5f29e23f5e976ed99a8dea9bc092d9c0beb0b3 Mon Sep 17 00:00:00 2001 From: Hyungki Kim Date: Thu, 7 Mar 2024 04:31:38 +0900 Subject: [PATCH 14/31] fix misleading description (#376) --- en/06_Texture_mapping/02_Combined_image_sampler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/06_Texture_mapping/02_Combined_image_sampler.md b/en/06_Texture_mapping/02_Combined_image_sampler.md index 9c8721db..787ea367 100644 --- a/en/06_Texture_mapping/02_Combined_image_sampler.md +++ b/en/06_Texture_mapping/02_Combined_image_sampler.md @@ -129,7 +129,7 @@ are now ready to be used by the shaders! ## Texture coordinates There is one important ingredient for texture mapping that is still missing, and -that's the actual coordinates for each vertex. The coordinates determine how the +that's the actual texture coordinates for each vertex. The texture coordinates determine how the image is actually mapped to the geometry. ```c++ From b2ea3a7337f64aaa44eb0ee152662d6a1f66f6a4 Mon Sep 17 00:00:00 2001 From: Jacob Anderson Date: Thu, 9 May 2024 04:35:18 -0700 Subject: [PATCH 15/31] Patch 1 (#380) * fix casing of a create info struct field * fix French too --- en/03_Drawing_a_triangle/01_Presentation/01_Swap_chain.md | 2 +- .../01_Pr\303\251sentation/01_Swap_chain.md" | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/en/03_Drawing_a_triangle/01_Presentation/01_Swap_chain.md b/en/03_Drawing_a_triangle/01_Presentation/01_Swap_chain.md index ef1ceabd..f593b5a6 100644 --- a/en/03_Drawing_a_triangle/01_Presentation/01_Swap_chain.md +++ b/en/03_Drawing_a_triangle/01_Presentation/01_Swap_chain.md @@ -515,7 +515,7 @@ you'll get the best performance by enabling clipping. createInfo.oldSwapchain = VK_NULL_HANDLE; ``` -That leaves one last field, `oldSwapChain`. With Vulkan it's possible that your swap chain becomes invalid or unoptimized while your application is +That leaves one last field, `oldSwapchain`. With Vulkan it's possible that your swap chain becomes invalid or unoptimized while your application is running, for example because the window was resized. In that case the swap chain actually needs to be recreated from scratch and a reference to the old one must be specified in this field. This is a complex topic that we'll learn more about diff --git "a/fr/03_Dessiner_un_triangle/01_Pr\303\251sentation/01_Swap_chain.md" "b/fr/03_Dessiner_un_triangle/01_Pr\303\251sentation/01_Swap_chain.md" index d12f1c76..539efe5b 100644 --- "a/fr/03_Dessiner_un_triangle/01_Pr\303\251sentation/01_Swap_chain.md" +++ "b/fr/03_Dessiner_un_triangle/01_Pr\303\251sentation/01_Swap_chain.md" @@ -458,7 +458,7 @@ informations, vous obtiendrez de meilleures performances en activant ce mode. createInfo.oldSwapchain = VK_NULL_HANDLE; ``` -Il nous reste un dernier champ, `oldSwapChain`. Il est possible avec Vulkan que la swap chain devienne +Il nous reste un dernier champ, `oldSwapchain`. Il est possible avec Vulkan que la swap chain devienne invalide ou mal adaptée pendant que votre application tourne, par exemple parce que la fenêtre a été redimensionnée. Dans ce cas la swap chain doit être intégralement recréée et une référence à l'ancienne swap chain doit être fournie. C'est un sujet compliqué que nous aborderons [dans un chapitre futur](!fr/Dessiner_un_triangle/Recréation_de_la_swap_chain). From c54c38236c7b026940c58c91ca28d7e6e182fbac Mon Sep 17 00:00:00 2001 From: Anonymous Coward <84487930+driftveil@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:03:00 +1000 Subject: [PATCH 16/31] Update 02_Development_environment.md (#383) Arch Linux doesn't have separate `glfw-wayland` and `glfw-x11` packages now. --- en/02_Development_environment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/02_Development_environment.md b/en/02_Development_environment.md index 8eac260f..83f14844 100644 --- a/en/02_Development_environment.md +++ b/en/02_Development_environment.md @@ -246,7 +246,7 @@ sudo dnf install glfw-devel ``` or ```bash -sudo pacman -S glfw-wayland # glfw-x11 for X11 users +sudo pacman -S glfw ``` ### GLM From efed1afa1616b3426c7b42b4df192ae0a466d7e0 Mon Sep 17 00:00:00 2001 From: Zach Madsen Date: Sun, 30 Jun 2024 10:03:35 -0700 Subject: [PATCH 17/31] Remove an extra word (#385) --- .../02_Graphics_pipeline_basics/02_Fixed_functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/03_Drawing_a_triangle/02_Graphics_pipeline_basics/02_Fixed_functions.md b/en/03_Drawing_a_triangle/02_Graphics_pipeline_basics/02_Fixed_functions.md index a80f72ae..5b4bfdec 100644 --- a/en/03_Drawing_a_triangle/02_Graphics_pipeline_basics/02_Fixed_functions.md +++ b/en/03_Drawing_a_triangle/02_Graphics_pipeline_basics/02_Fixed_functions.md @@ -175,7 +175,7 @@ viewportState.scissorCount = 1; viewportState.pScissors = &scissor; ``` -Independent of how you set them, it's is possible to use multiple viewports and scissor rectangles on some graphics cards, so the structure members reference an array of them. Using multiple requires enabling a GPU feature (see logical device creation). +Independent of how you set them, it's possible to use multiple viewports and scissor rectangles on some graphics cards, so the structure members reference an array of them. Using multiple requires enabling a GPU feature (see logical device creation). ## Rasterizer From 3bf8f964e083013efdc5a4b098867cb4d52b18aa Mon Sep 17 00:00:00 2001 From: Alexander Overvoorde Date: Sun, 30 Jun 2024 19:16:38 +0200 Subject: [PATCH 18/31] Update Debian package name for validation layers --- en/02_Development_environment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/02_Development_environment.md b/en/02_Development_environment.md index 83f14844..6ce016ca 100644 --- a/en/02_Development_environment.md +++ b/en/02_Development_environment.md @@ -204,7 +204,7 @@ The most important components you'll need for developing Vulkan applications on * `sudo apt install vulkan-tools` or `sudo dnf install vulkan-tools`: Command-line utilities, most importantly `vulkaninfo` and `vkcube`. Run these to confirm your machine supports Vulkan. * `sudo apt install libvulkan-dev` or `sudo dnf install vulkan-loader-devel` : Installs Vulkan loader. The loader looks up the functions in the driver at runtime, similarly to GLEW for OpenGL - if you're familiar with that. -* `sudo apt install vulkan-validationlayers-dev spirv-tools` or `sudo dnf install mesa-vulkan-devel vulkan-validation-layers-devel`: Installs the standard validation layers and required SPIR-V tools. These are crucial when debugging Vulkan applications, and we'll discuss them in the upcoming chapter. +* `sudo apt install vulkan-validationlayers spirv-tools` or `sudo dnf install mesa-vulkan-devel vulkan-validation-layers-devel`: Installs the standard validation layers and required SPIR-V tools. These are crucial when debugging Vulkan applications, and we'll discuss them in the upcoming chapter. On Arch Linux, you can run `sudo pacman -S vulkan-devel` to install all the required tools above. From b42b308210b41d4b2b3d41a8c34031ddfe757406 Mon Sep 17 00:00:00 2001 From: triacontakai <31161627+triacontakai@users.noreply.github.com> Date: Fri, 8 Nov 2024 03:16:28 -0500 Subject: [PATCH 19/31] Fix Xxf68vm typo (#393) --- en/02_Development_environment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/02_Development_environment.md b/en/02_Development_environment.md index 6ce016ca..e5990f38 100644 --- a/en/02_Development_environment.md +++ b/en/02_Development_environment.md @@ -353,7 +353,7 @@ LDFLAGS = -lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi The flag `-lglfw` is for GLFW, `-lvulkan` links with the Vulkan function loader and the remaining flags are low-level system libraries that GLFW needs. The remaining flags are dependencies of GLFW itself: the threading and window management. -It is possible that the `Xxf68vm` and `Xi` libraries are not yet installed on your system. You can find them in the following packages: +It is possible that the `Xxf86vm` and `Xi` libraries are not yet installed on your system. You can find them in the following packages: ```bash sudo apt install libxxf86vm-dev libxi-dev From 7d8dbddb499fdca7f47c58c6dc8f227355538cb8 Mon Sep 17 00:00:00 2001 From: Alexander Overvoorde Date: Wed, 22 Jan 2025 22:37:39 +0100 Subject: [PATCH 20/31] Fix broken link (fixes #395) --- en/06_Texture_mapping/02_Combined_image_sampler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/06_Texture_mapping/02_Combined_image_sampler.md b/en/06_Texture_mapping/02_Combined_image_sampler.md index 787ea367..0f1e5496 100644 --- a/en/06_Texture_mapping/02_Combined_image_sampler.md +++ b/en/06_Texture_mapping/02_Combined_image_sampler.md @@ -74,7 +74,7 @@ type (`VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER`, etc.) as specified by the corresponding `descriptorCount` members for the creation of the descriptor pool. However, it remains best practise to do so, and in the future, `VK_LAYER_KHRONOS_validation` will warn about this type of problem if you enable -[Best Practice Validation](https://vulkan.lunarg.com/doc/view/1.2.189.0/linux/best_practices.html). +[Best Practice Validation](https://vulkan.lunarg.com/doc/view/1.4.304.0/linux/best_practices.html). The final step is to bind the actual image and sampler resources to the descriptors in the descriptor set. Go to the `createDescriptorSets` function. From f4122e51041fabe58bf8d4181fe4aaacacea4d29 Mon Sep 17 00:00:00 2001 From: Vincent Giraud Date: Wed, 26 Feb 2025 22:55:00 +0100 Subject: [PATCH 21/31] Replace mesa-vulkan-devel with mesa-vulkan-drivers in Fedora (#398) --- en/02_Development_environment.md | 2 +- "fr/02_Environnement_de_d\303\251veloppement.md" | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/en/02_Development_environment.md b/en/02_Development_environment.md index e5990f38..2d8b2535 100644 --- a/en/02_Development_environment.md +++ b/en/02_Development_environment.md @@ -204,7 +204,7 @@ The most important components you'll need for developing Vulkan applications on * `sudo apt install vulkan-tools` or `sudo dnf install vulkan-tools`: Command-line utilities, most importantly `vulkaninfo` and `vkcube`. Run these to confirm your machine supports Vulkan. * `sudo apt install libvulkan-dev` or `sudo dnf install vulkan-loader-devel` : Installs Vulkan loader. The loader looks up the functions in the driver at runtime, similarly to GLEW for OpenGL - if you're familiar with that. -* `sudo apt install vulkan-validationlayers spirv-tools` or `sudo dnf install mesa-vulkan-devel vulkan-validation-layers-devel`: Installs the standard validation layers and required SPIR-V tools. These are crucial when debugging Vulkan applications, and we'll discuss them in the upcoming chapter. +* `sudo apt install vulkan-validationlayers spirv-tools` or `sudo dnf install mesa-vulkan-drivers vulkan-validation-layers-devel`: Installs the standard validation layers and required SPIR-V tools. These are crucial when debugging Vulkan applications, and we'll discuss them in the upcoming chapter. On Arch Linux, you can run `sudo pacman -S vulkan-devel` to install all the required tools above. diff --git "a/fr/02_Environnement_de_d\303\251veloppement.md" "b/fr/02_Environnement_de_d\303\251veloppement.md" index 80796d81..1041fdbe 100644 --- "a/fr/02_Environnement_de_d\303\251veloppement.md" +++ "b/fr/02_Environnement_de_d\303\251veloppement.md" @@ -186,7 +186,7 @@ packages. Il vous faut un compilateur qui supporte C++17 (GCC 7+ ou Clang 5+). V Les composants les plus importants pour le développement d'applications Vulkan sous Linux sont le loader Vulkan, les validation layers et quelques utilitaires pour tester que votre machine est bien en état de faire fonctionner une application Vulkan: * `sudo apt install vulkan-tools` ou `sudo dnf install vulkan-tools`: Les utilitaires en ligne de commande, plus précisément `vulkaninfo` et `vkcube`. Lancez ceux-ci pour vérifier le bon fonctionnement de votre machine pour Vulkan. * `sudo apt install libvulkan-dev` ou `sudo dnf install vulkan-headers vulkan-loader-devel`: Installe le loader Vulkan. Il sert à aller chercher les fonctions auprès du driver de votre GPU au runtime, de la même façon que GLEW le fait pour OpenGL - si vous êtes familier avec ceci. -* `sudo apt install vulkan-validationlayers-dev` ou `sudo dnf install mesa-vulkan-devel vulkan-validation-layers-devel`: Installe les layers de validation standards. Ceux-ci sont cruciaux pour débugger vos applications Vulkan, et nous en reparlerons dans un prochain chapitre. +* `sudo apt install vulkan-validationlayers-dev` ou `sudo dnf install mesa-vulkan-drivers vulkan-validation-layers-devel`: Installe les layers de validation standards. Ceux-ci sont cruciaux pour débugger vos applications Vulkan, et nous en reparlerons dans un prochain chapitre. Si l'installation est un succès, vous devriez être prêt pour la partie Vulkan. N'oubliez pas de lancer `vkcube` et assurez-vous de voir la fenêtre suivante: From 404a54800d598f8c6e18031ae73f59249b427aeb Mon Sep 17 00:00:00 2001 From: qiyuewuyi2333 <130756071+qiyuewuyi2333@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:27:26 +0800 Subject: [PATCH 22/31] Fix: a miss language typo (#400) --- en/03_Drawing_a_triangle/04_Swap_chain_recreation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/03_Drawing_a_triangle/04_Swap_chain_recreation.md b/en/03_Drawing_a_triangle/04_Swap_chain_recreation.md index 9c598528..ce58528b 100644 --- a/en/03_Drawing_a_triangle/04_Swap_chain_recreation.md +++ b/en/03_Drawing_a_triangle/04_Swap_chain_recreation.md @@ -49,7 +49,7 @@ void recreateSwapChain() { } ``` -Note that we don't recreate the renderpass here for simplicity. In theory it can be possible for the swap chain image format to change during an applications' lifetime, e.g. when moving a window from an standard range to an high dynamic range monitor. This may require the application to recreate the renderpass to make sure the change between dynamic ranges is properly reflected. +Note that we don't recreate the renderpass here for simplicity. In theory it can be possible for the swap chain image format to change during an applications' lifetime, e.g. when moving a window from a standard range to a high dynamic range monitor. This may require the application to recreate the renderpass to make sure the change between dynamic ranges is properly reflected. We'll move the cleanup code of all objects that are recreated as part of a swap chain refresh from `cleanup` to `cleanupSwapChain`: From d61a0f1e7c737baea17181e2904066ff04cacb1c Mon Sep 17 00:00:00 2001 From: Alexander Overvoorde Date: Fri, 2 May 2025 13:33:57 +0200 Subject: [PATCH 23/31] Update Vulkan guide link (fixes #405) --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index bc711b52..edb3a0b3 100644 --- a/config.json +++ b/config.json @@ -21,7 +21,7 @@ "Support the website": "https://www.paypal.me/AOvervoorde", "Vulkan Specification": "https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/", "LunarG Vulkan SDK": "https://lunarg.com/vulkan-sdk/", - "Vulkan Guide": "https://github.com/KhronosGroup/Vulkan-Guide", + "Vulkan Guide": "https://docs.vulkan.org/guide/latest/", "Vulkan Hardware Database": "https://vulkan.gpuinfo.org/", "Rust code": "https://github.com/bwasty/vulkan-tutorial-rs", "Java code": "https://github.com/Naitsirc98/Vulkan-Tutorial-Java", From 02e283d54835aa0c4aed2cdc361baf10335137a6 Mon Sep 17 00:00:00 2001 From: Daxturus <36318410+Daxturus@users.noreply.github.com> Date: Sun, 11 May 2025 10:26:42 +0000 Subject: [PATCH 24/31] Remove invalid "warn" argument passed to tinyobj::loadObject(...) (#406) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update 28_model_loading.cpp Removed "warn" argument passed to tinyobj::LoadObj(...). * Update 29_mipmapping.cpp Removed "warn" argument passed to tinyobj::LoadObj(...). * Update 30_multisampling.cpp Removed "warn" argument passed to tinyobj::LoadObj(...). * Update 08_Loading_models.md Removed "warn" argument passed to tinyobj::LoadObj(...) from e-book. * Update 08_Charger_des_modèles.md Removed "warn" argument passed to tinyobj::LoadObj(...). --- code/28_model_loading.cpp | 6 +++--- code/29_mipmapping.cpp | 6 +++--- code/30_multisampling.cpp | 6 +++--- en/08_Loading_models.md | 6 +++--- "fr/08_Charger_des_mod\303\250les.md" | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/code/28_model_loading.cpp b/code/28_model_loading.cpp index 319e4f7f..0097a311 100644 --- a/code/28_model_loading.cpp +++ b/code/28_model_loading.cpp @@ -995,10 +995,10 @@ class HelloTriangleApplication { tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; - std::string warn, err; + std::string err; - if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, MODEL_PATH.c_str())) { - throw std::runtime_error(warn + err); + if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, MODEL_PATH.c_str())) { + throw std::runtime_error(err); } std::unordered_map uniqueVertices{}; diff --git a/code/29_mipmapping.cpp b/code/29_mipmapping.cpp index ae0cadf5..874a8d82 100644 --- a/code/29_mipmapping.cpp +++ b/code/29_mipmapping.cpp @@ -1089,10 +1089,10 @@ class HelloTriangleApplication { tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; - std::string warn, err; + std::string err; - if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, MODEL_PATH.c_str())) { - throw std::runtime_error(warn + err); + if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, MODEL_PATH.c_str())) { + throw std::runtime_error(err); } std::unordered_map uniqueVertices{}; diff --git a/code/30_multisampling.cpp b/code/30_multisampling.cpp index 638c2219..ab6cbc3f 100644 --- a/code/30_multisampling.cpp +++ b/code/30_multisampling.cpp @@ -1139,10 +1139,10 @@ class HelloTriangleApplication { tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; - std::string warn, err; + std::string err; - if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, MODEL_PATH.c_str())) { - throw std::runtime_error(warn + err); + if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, MODEL_PATH.c_str())) { + throw std::runtime_error(err); } std::unordered_map uniqueVertices{}; diff --git a/en/08_Loading_models.md b/en/08_Loading_models.md index 620e31bf..f3ae89c0 100644 --- a/en/08_Loading_models.md +++ b/en/08_Loading_models.md @@ -138,10 +138,10 @@ void loadModel() { tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; - std::string warn, err; + std::string err; - if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, MODEL_PATH.c_str())) { - throw std::runtime_error(warn + err); + if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, MODEL_PATH.c_str())) { + throw std::runtime_error(err); } } ``` diff --git "a/fr/08_Charger_des_mod\303\250les.md" "b/fr/08_Charger_des_mod\303\250les.md" index 13a9b35e..04cdfda1 100644 --- "a/fr/08_Charger_des_mod\303\250les.md" +++ "b/fr/08_Charger_des_mod\303\250les.md" @@ -120,10 +120,10 @@ void loadModel() { tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; - std::string warn, err; + std::string err; - if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, MODEL_PATH.c_str())) { - throw std::runtime_error(warn + err); + if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, MODEL_PATH.c_str())) { + throw std::runtime_error(err); } } ``` From 527216eb95af095b807a6edd1ddedc8327381f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Llu=C3=ADs=20Alemany=20Puig?= Date: Sat, 30 Aug 2025 15:04:00 +0200 Subject: [PATCH 25/31] Optionally specify margin size #396 (#411) Whoever wants to shrink the margins, they can now do so via the new optional command line arguments --geometry:left --geometry:right --geometry:top --geometry:bottom which are default options in pandoc (see pandoc's documentation [here](https://pandoc.org/demo/example33/6.2-variables.html)). Their default value is ''. These options are not passed to pandoc when their value is ''. The argument parser added can be extended easily with other pandoc's argument options. If the new options' default value is '' then they will not be passed to pandoc. --- build_ebook.py | 24 +++++++++++++++++++----- make_parser.py | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 make_parser.py diff --git a/build_ebook.py b/build_ebook.py index 39e9a969..112483dc 100755 --- a/build_ebook.py +++ b/build_ebook.py @@ -11,6 +11,9 @@ from subprocess import CalledProcessError from re import Match import shutil +import argparse +import sys +from make_parser import make_parser logging.basicConfig( format="%(asctime)s %(levelname)-8s %(message)s", @@ -148,7 +151,7 @@ def compile_full_markdown( return markdown_file -def build_pdf(markdown_file: Path, pdf_file: Path) -> Path: +def build_pdf(markdown_file: Path, pdf_file: Path, args: argparse.Namespace) -> Path: """Build combined Markdown file into a PDF.""" try: @@ -157,12 +160,21 @@ def build_pdf(markdown_file: Path, pdf_file: Path) -> Path: raise RuntimeError(f"failed to build {pdf_file}: xelatex not installed") try: + keys_values = [(arg, getattr(args, arg)) for arg in vars(args)] + opts = [f"{key}={val}" for key, val in keys_values if val != ""] + pandoc_args = [x for i in opts for x in ("-V", i)] + subprocess.check_output( [ "pandoc", markdown_file.as_posix(), "-V", - "documentclass=report", + "documentclass=report" + ] + + + pandoc_args + + + [ "-t", "latex", "-s", @@ -202,8 +214,10 @@ def build_epub(markdown_file: Path, epub_file: Path) -> Path: return epub_file - def main() -> None: + parser = make_parser() + args = parser.parse_args(sys.argv[1:]) + """Build ebooks.""" with TemporaryDirectory() as raw_out_dir: out_dir = Path(raw_out_dir) @@ -223,11 +237,11 @@ def main() -> None: ) logging.info(f"{lang}: building pdf...") - pdf_file = build_pdf(markdown_file, out_dir / f"{lang}.pdf") + pdf_file = build_pdf(markdown_file, out_dir / f"{lang}.pdf", args) logging.info(f"{lang}: building epub...") epub_file = build_epub(markdown_file, out_dir / f"{lang}.epub") - + shutil.copy(pdf_file, f"ebook/vulkan_tutorial_{lang}.pdf") shutil.copy(epub_file, f"ebook/vulkan_tutorial_{lang}.epub") diff --git a/make_parser.py b/make_parser.py new file mode 100644 index 00000000..12e10a2f --- /dev/null +++ b/make_parser.py @@ -0,0 +1,37 @@ +import argparse + +def make_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser( + description="Build the pdf and epub files of the Vulkan Tutorial." + ) + + parser.add_argument( + "--geometry:left", + type=str, + required=False, + default="", + help="Specify left margin space as a string. Example: 2cm.", + ) + parser.add_argument( + "--geometry:right", + type=str, + required=False, + default="", + help="Specify right margin space as a string. Example: 2cm.", + ) + parser.add_argument( + "--geometry:top", + type=str, + required=False, + default="", + help="Specify top margin space as a string. Example: 2cm.", + ) + parser.add_argument( + "--geometry:bottom", + type=str, + required=False, + default="", + help="Specify bottom margin space as a string. Example: 2cm.", + ) + + return parser From c7ec526bd3c3e20854409b21962d656a60aedc2b Mon Sep 17 00:00:00 2001 From: Alexander Overvoorde Date: Sun, 21 Sep 2025 17:06:20 +0000 Subject: [PATCH 26/31] Update default PDF margins (fixes #396) --- .gitignore | 219 +++++++++++++++++++++++++++++++++++++++++++++++- .python-version | 1 + make_parser.py | 8 +- pyproject.toml | 7 ++ uv.lock | 8 ++ 5 files changed, 238 insertions(+), 5 deletions(-) create mode 100644 .python-version create mode 100644 pyproject.toml create mode 100644 uv.lock diff --git a/.gitignore b/.gitignore index ae5f6c81..410b95ad 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,221 @@ ads.txt build_ebook.log temp_ebook.md ebook/*.pdf -ebook/*.epub \ No newline at end of file +ebook/*.epub + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[codz] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py.cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +# Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +# poetry.lock +# poetry.toml + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python. +# https://pdm-project.org/en/latest/usage/project/#working-with-version-control +# pdm.lock +# pdm.toml +.pdm-python +.pdm-build/ + +# pixi +# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control. +# pixi.lock +# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one +# in the .venv directory. It is recommended not to include this directory in version control. +.pixi + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# Redis +*.rdb +*.aof +*.pid + +# RabbitMQ +mnesia/ +rabbitmq/ +rabbitmq-data/ + +# ActiveMQ +activemq-data/ + +# SageMath parsed files +*.sage.py + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +# .idea/ + +# Abstra +# Abstra is an AI-powered process automation framework. +# Ignore directories containing user credentials, local state, and settings. +# Learn more at https://abstra.io/docs +.abstra/ + +# Visual Studio Code +# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore +# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore +# and can be added to the global gitignore or merged into this file. However, if you prefer, +# you could uncomment the following to ignore the entire vscode folder +# .vscode/ + +# Ruff stuff: +.ruff_cache/ + +# PyPI configuration file +.pypirc + +# Marimo +marimo/_static/ +marimo/_lsp/ +__marimo__/ + +# Streamlit +.streamlit/secrets.toml diff --git a/.python-version b/.python-version new file mode 100644 index 00000000..24ee5b1b --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/make_parser.py b/make_parser.py index 12e10a2f..8d0c5b5b 100644 --- a/make_parser.py +++ b/make_parser.py @@ -9,28 +9,28 @@ def make_parser() -> argparse.ArgumentParser: "--geometry:left", type=str, required=False, - default="", + default="2.5cm", help="Specify left margin space as a string. Example: 2cm.", ) parser.add_argument( "--geometry:right", type=str, required=False, - default="", + default="2.5cm", help="Specify right margin space as a string. Example: 2cm.", ) parser.add_argument( "--geometry:top", type=str, required=False, - default="", + default="2.5cm", help="Specify top margin space as a string. Example: 2cm.", ) parser.add_argument( "--geometry:bottom", type=str, required=False, - default="", + default="2.5cm", help="Specify bottom margin space as a string. Example: 2cm.", ) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..7749678c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,7 @@ +[project] +name = "vulkantutorial" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = "~=3.13.0" +dependencies = [] diff --git a/uv.lock b/uv.lock new file mode 100644 index 00000000..84d6b942 --- /dev/null +++ b/uv.lock @@ -0,0 +1,8 @@ +version = 1 +revision = 3 +requires-python = "==3.13.*" + +[[package]] +name = "vulkantutorial" +version = "0.1.0" +source = { virtual = "." } From 3e78cbe874396341af8554768df03f3db34566db Mon Sep 17 00:00:00 2001 From: ladysadie <144490006+ladysadie@users.noreply.github.com> Date: Sun, 21 Sep 2025 10:11:09 -0700 Subject: [PATCH 27/31] Add a code block for the GLFW window pointer. (#413) Almost all of the code listed in this chapter uses a c++ code block. The block for the 'GLFWWindow* window' was missing. --- en/03_Drawing_a_triangle/00_Setup/00_Base_code.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/en/03_Drawing_a_triangle/00_Setup/00_Base_code.md b/en/03_Drawing_a_triangle/00_Setup/00_Base_code.md index df26c6ac..e5b0e0b3 100644 --- a/en/03_Drawing_a_triangle/00_Setup/00_Base_code.md +++ b/en/03_Drawing_a_triangle/00_Setup/00_Base_code.md @@ -145,8 +145,14 @@ disable it for now with another window hint call: glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); ``` -All that's left now is creating the actual window. Add a `GLFWwindow* window;` -private class member to store a reference to it and initialize the window with: +All that's left now is creating the actual window. Add a private class member to store a reference to it: + +```c++ +private: +GLFWwindow* window; +``` + +Initialize the window with ```c++ window = glfwCreateWindow(800, 600, "Vulkan", nullptr, nullptr); From 06165e5245fd0a22f7fa7deebeb2da1577cc04bd Mon Sep 17 00:00:00 2001 From: ladysadie <144490006+ladysadie@users.noreply.github.com> Date: Sun, 21 Sep 2025 10:11:34 -0700 Subject: [PATCH 28/31] Fix typo in the html generation instructions. (#412) * Fix typo in the html generation instructions. * Add a code block for the GLFW window pointer. Almost all of the code listed in this chapter uses a c++ code block. The block for the 'GLFWWindow* window' was missing. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fcbb3775..b14b7f26 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ necessary. Now with the above done, we can generate the static files. Asuming the daux.io and VulkanTutorial directories are next to each other, go into the `daux.io` directory and run a command similar to: -`php generate -s ../VulkanTutorial -d ../VulkanTutorial/out`. +`daux generate -s ../VulkanTutorial -d ../VulkanTutorial/out`. `-s` tells it where to find the documentation, while `-d` tells it where to put the generated files. From ab3b8400cf163894c8e3174d22af90597dbe8deb Mon Sep 17 00:00:00 2001 From: Alexander Overvoorde Date: Sun, 25 Jan 2026 17:19:27 +0000 Subject: [PATCH 29/31] Add notice about age of the tutorial (fixes #416) --- en/00_Introduction.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/en/00_Introduction.md b/en/00_Introduction.md index e56799e9..f2741b0a 100644 --- a/en/00_Introduction.md +++ b/en/00_Introduction.md @@ -1,3 +1,12 @@ +>## Read before following this tutorial +> +>This tutorial was written shortly after Vulkan was initially released, back in +>2016. A lot has changed since then and this tutorial no longer reflects the best +>way to use Vulkan today. +> +>Instead of reading this website, I recommend to follow the guide or one of the +>tutorials linked here: https://vulkan.org/learn + ## About This tutorial will teach you the basics of using the [Vulkan](https://www.khronos.org/vulkan/) From 8951d937b95331f70b82f03f68194318ef2d4532 Mon Sep 17 00:00:00 2001 From: Alexander Overvoorde Date: Sun, 25 Jan 2026 17:29:14 +0000 Subject: [PATCH 30/31] Fix link --- en/00_Introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/00_Introduction.md b/en/00_Introduction.md index f2741b0a..bbcb39ac 100644 --- a/en/00_Introduction.md +++ b/en/00_Introduction.md @@ -5,7 +5,7 @@ >way to use Vulkan today. > >Instead of reading this website, I recommend to follow the guide or one of the ->tutorials linked here: https://vulkan.org/learn +>tutorials linked here: [https://vulkan.org/learn] ## About From 945583820d5e6286879d08bb87cb245c56d880a6 Mon Sep 17 00:00:00 2001 From: Alexander Overvoorde Date: Sun, 25 Jan 2026 17:29:46 +0000 Subject: [PATCH 31/31] Fix link even more --- en/00_Introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/00_Introduction.md b/en/00_Introduction.md index bbcb39ac..1d14c781 100644 --- a/en/00_Introduction.md +++ b/en/00_Introduction.md @@ -5,7 +5,7 @@ >way to use Vulkan today. > >Instead of reading this website, I recommend to follow the guide or one of the ->tutorials linked here: [https://vulkan.org/learn] +>tutorials linked here: [https://vulkan.org/learn](https://vulkan.org/learn) ## About