diff --git a/en/00_Introduction.adoc b/en/00_Introduction.adoc index 539414d8..ac4b3bf8 100644 --- a/en/00_Introduction.adoc +++ b/en/00_Introduction.adoc @@ -106,11 +106,11 @@ Some other great computer graphics resources are: * https://github.com/RayTracing/raytracing.github.io[Ray tracing in one weekend] * https://www.pbr-book.org/[Physically Based Rendering book] -You can use C instead of C{pp} 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{pp} features like classes and RAII to organize logic and - resource lifetimes. +This tutorial exclusively uses C{pp} and the Vulkan-Hpp bindings; it does not +provide a parallel C track. We use C{pp} features like classes and RAII to +organize logic and resource lifetimes, so if you use the raw C Vulkan API +instead, the code shown here will not translate directly and you will be on +your own in terms of code structuring. To make it easier to learn to work with Vulkan, we'll be using the newer https://github.com/KhronosGroup/Vulkan-Hpp[Vulkan-Hpp] bindings that diff --git a/en/01_Overview.adoc b/en/01_Overview.adoc index bf0b8d34..a23fc8e4 100644 --- a/en/01_Overview.adoc +++ b/en/01_Overview.adoc @@ -63,10 +63,10 @@ This is just to give you a big picture to relate all the individual components t === Step 1 - Instance and physical device selection -A Vulkan application starts by setting up the Vulkan API through a `vk::Instance`. +A Vulkan application starts by setting up the Vulkan API through a `vk::raii::Instance`. An instance is created by describing your application and any API extensions you will be using. After creating the instance, you can query for Vulkan - supported hardware and select one or more ``vk::PhysicalDevice``s to use for + supported hardware and select one or more ``vk::raii::PhysicalDevice``s to use for operations. You can query for properties like VRAM size and device capabilities to select desired devices, for example, to prefer using dedicated graphics cards. @@ -74,12 +74,12 @@ An instance is created by describing your application and any API extensions === Step 2 - Logical device and queue families After selecting the right hardware device to use, you need to create a -`vk::Device` (logical device), where you describe more specifically which +`vk::raii::Device` (logical device), where you describe more specifically which physical device features you will be using, like multi viewport rendering and 64-bit floats. You also need to specify which queue families you would like to use. Most operations performed with Vulkan, like draw commands and memory -operations, are asynchronously executed by submitting them to a `vk::Queue`. +operations, are asynchronously executed by submitting them to a `vk::raii::Queue`. Queues are allocated from queue families, where each queue family supports a specific set of operations in its queues. For example, there could be separate queue families for graphics, compute @@ -100,7 +100,7 @@ We will be using GLFW in this tutorial, but more about that in the next chapter. We need two more parts to actually render to a window: a window surface - (`vk::SurfaceKHR`) and a swap chain (`vk::SwapchainKHR`). + (`vk::raii::SurfaceKHR`) and a swap chain (`vk::raii::SwapchainKHR`). Note the `KHR` postfix, which means that these objects are part of a Vulkan extension. The Vulkan API itself is completely platform-agnostic, which is why we need to use the standardized WSI (Window System Interface) extension @@ -133,7 +133,7 @@ could be used to implement your own window manager, for example. === Step 4 - Swap chain image views To draw to an image acquired from the swap chain, we would typically wrap -it into a `vk::ImageView`. An image view references a specific +it into a `vk::raii::ImageView`. An image view references a specific part of an image to be used for e.g. color writes. Because there could be different images in the swap chain, we would preemptively create an image view for each @@ -144,18 +144,18 @@ of them and select the right one at draw time. In earlier versions of Vulkan, a render pass defined how rendering operations should occur with framebuffers, specifying the types of images used (e.g., color, depth) and how their contents should be treated (e.g., cleared, loaded, or stored). -A `vk::RenderPass` would define subpasses and attachment usage, and a `vk::Framebuffer` +A `vk::raii::RenderPass` would define subpasses and attachment usage, and a `vk::raii::Framebuffer` would bind specific image views to these attachments. However, with dynamic rendering (introduced in Vulkan 1.3), -you no longer need to create a `vk::Framebuffer` at all. +you no longer need to create a `vk::raii::Framebuffer` at all. Dynamic rendering eliminates the need for predefined render passes and framebuffers, allowing you to specify rendering attachments directly during command recording. This makes the API much simpler, as we can define the rendering targets on the fly without worrying about the overhead of managing framebuffers. -With dynamic rendering, you no longer need to predefine `vk::RenderPass` or `vk::Framebuffer`. -Instead, you specify the rendering attachments at the start of command recording, using `vk::beginRendering` +With dynamic rendering, you no longer need to predefine `vk::raii::RenderPass` or `vk::raii::Framebuffer`. +Instead, you specify the rendering attachments at the start of command recording, using `vk::raii::CommandBuffer::beginRendering` and structs like `vk::RenderingInfo` to provide all necessary attachment information dynamically. In our initial triangle rendering application, @@ -164,10 +164,10 @@ a single image as a color target and instruct Vulkan to clear it to a solid colo === Step 6 - Graphics pipeline -The graphics pipeline in Vulkan is set up by creating a `VkPipeline` object. +The graphics pipeline in Vulkan is set up by creating a `vk::raii::Pipeline` object. It describes the configurable state of the graphics card, like the viewport -size and depth buffer operation and the programmable state using `vk::ShaderModule` objects. -The `vk::ShaderModule` objects are created from shader byte code. +size and depth buffer operation and the programmable state using `vk::raii::ShaderModule` objects. +The `vk::raii::ShaderModule` objects are created from shader byte code. The driver also needs to know which render targets will be used in the pipeline, which we specify by referencing the render pass. @@ -194,9 +194,9 @@ are made very explicit. As mentioned earlier, many of the operations in Vulkan that we want to execute, like drawing operations, need to be submitted to a queue. -These operations first need to be recorded into a `vk::CommandBuffer` before +These operations first need to be recorded into a `vk::raii::CommandBuffer` before they can be submitted. -These command buffers are allocated from a `vk::CommandPool` that is +These command buffers are allocated from a `vk::raii::CommandPool` that is associated with a specific queue family. To draw a triangle prior to dynamic rendering, we would need to record a command buffer with the following operations: @@ -257,7 +257,7 @@ So in short, to draw the first triangle, we need to: * Select a supported graphics card (`PhysicalDevice`) * Create a `Device` and `Queue` for drawing and presentation * Create a window, window surface and swap chain -* Wrap the swap chain images into `VkImageView` +* Wrap the swap chain images into `vk::raii::ImageView` * Set up dynamic rendering * Set up the graphics pipeline * Allocate and record a command buffer with the draw commands for every @@ -300,7 +300,7 @@ Many structures in Vulkan require you to explicitly specify the type of structure in the `sType` member. The `pNext` member can point to an extension structure and will always be `nullptr` in this tutorial. -Functions that create or destroy an object will have a `VkAllocationCallbacks` +Functions that create or destroy an object will have a `vk::AllocationCallbacks` parameter that allows you to use a custom allocator for driver memory, which will also be left `nullptr` in this tutorial. diff --git a/en/05_Uniform_buffers/01_Descriptor_pool_and_sets.adoc b/en/05_Uniform_buffers/01_Descriptor_pool_and_sets.adoc index f5fdb9ab..1aba2cba 100644 --- a/en/05_Uniform_buffers/01_Descriptor_pool_and_sets.adoc +++ b/en/05_Uniform_buffers/01_Descriptor_pool_and_sets.adoc @@ -48,7 +48,7 @@ vk::DescriptorPoolCreateInfo poolInfo{ .flags = vk::DescriptorPoolCreateFlagBits Aside from the maximum number of individual descriptors that are available, we also need to specify the maximum number of descriptor sets that may be allocated. The structure has an optional flag similar to command pools that determines if individual descriptor sets can be freed or not. -As the `vk::raii::DescriptorSets` destroy the underlying `VkDescriptorSet` on destruction we need to set it to `vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet` to allow that. +As the `vk::raii::DescriptorSets` destroy the underlying `vk::DescriptorSet` on destruction we need to set it to `vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet` to allow that. [,c++] ---- diff --git a/en/06_Texture_mapping/01_Image_view_and_sampler.adoc b/en/06_Texture_mapping/01_Image_view_and_sampler.adoc index 26795ef7..94e80ecd 100644 --- a/en/06_Texture_mapping/01_Image_view_and_sampler.adoc +++ b/en/06_Texture_mapping/01_Image_view_and_sampler.adoc @@ -10,7 +10,7 @@ The first resource is one that we've already seen before while working with the We've seen before, with the swap chain images and the framebuffer, that images are accessed through image views rather than directly. We will also need to create such an image view for the texture image. -Add a class member to hold a `VkImageView` for the texture image and create a new function `createTextureImageView` where we'll create it: +Add a class member to hold a `vk::raii::ImageView` for the texture image and create a new function `createTextureImageView` where we'll create it: [,c++] ---- diff --git a/en/06_Texture_mapping/02_Combined_image_sampler.adoc b/en/06_Texture_mapping/02_Combined_image_sampler.adoc index f020df1c..f3dba50e 100644 --- a/en/06_Texture_mapping/02_Combined_image_sampler.adoc +++ b/en/06_Texture_mapping/02_Combined_image_sampler.adoc @@ -15,7 +15,7 @@ After that, we're going to add texture coordinates to `Vertex`, replacing the co == Updating the descriptors -Browse to the `createDescriptorSetLayout` function and add a `VkDescriptorSetLayoutBinding` for a combined image sampler descriptor. +Browse to the `createDescriptorSetLayout` function and add a `vk::DescriptorSetLayoutBinding` for a combined image sampler descriptor. We'll simply put it in the binding after the uniform buffer: [,c++] diff --git a/en/11_Compute_Shader.adoc b/en/11_Compute_Shader.adoc index 84ca031e..a621fa18 100644 --- a/en/11_Compute_Shader.adoc +++ b/en/11_Compute_Shader.adoc @@ -449,7 +449,7 @@ work on a one-dimensional array, like we do in this chapter, you only have to sp As an example: If we dispatch a work group count of [64, 1, 1] with a compute shader local size of [32, 32, 1], our compute shader will be invoked 64 x 32 x 32 = 65,536 times. -Note that the maximum count for work groups and local sizes differs from implementation to implementation, so you should always check the compute related `maxComputeWorkGroupCount`, `maxComputeWorkGroupInvocations` and `maxComputeWorkGroupSize` limits in `VkPhysicalDeviceLimits`. +Note that the maximum count for work groups and local sizes differs from implementation to implementation, so you should always check the compute related `maxComputeWorkGroupCount`, `maxComputeWorkGroupInvocations` and `maxComputeWorkGroupSize` limits in `vk::PhysicalDeviceLimits`. == Compute shaders diff --git a/en/courses/18_Ray_tracing/01_Dynamic_rendering.adoc b/en/courses/18_Ray_tracing/01_Dynamic_rendering.adoc index f2465697..14fa2112 100644 --- a/en/courses/18_Ray_tracing/01_Dynamic_rendering.adoc +++ b/en/courses/18_Ray_tracing/01_Dynamic_rendering.adoc @@ -2,7 +2,7 @@ *Objective*: Ensure the base project uses *dynamic rendering* and understand how to verify it using RenderDoc. -In dynamic rendering, we no longer create a VkRenderPass or VkFrameBuffer; instead we begin rendering with `vkCmdBeginRenderingKHR`, specifying attachments on-the-fly. This makes our code more flexible (no need to predeclare subpasses) and is now the "modern" way to render in Vulkan. +In dynamic rendering, we no longer create a `vk::raii::RenderPass` or `vk::raii::Framebuffer`; instead we begin rendering with `commandBuffer.beginRendering()`, specifying attachments on-the-fly. This makes our code more flexible (no need to predeclare subpasses) and is now the "modern" way to render in Vulkan. == Task 1: Check the setup for dynamic rendering diff --git a/en/courses/18_Ray_tracing/02_Acceleration_structures.adoc b/en/courses/18_Ray_tracing/02_Acceleration_structures.adoc index 67a16e72..009e5b44 100644 --- a/en/courses/18_Ray_tracing/02_Acceleration_structures.adoc +++ b/en/courses/18_Ray_tracing/02_Acceleration_structures.adoc @@ -69,14 +69,14 @@ vk::AccelerationStructureBuildSizesInfoKHR blasBuildSizes = ); ---- -This helper function uses `vkGetAccelerationStructureBuildSizesKHR()` and returns the memory sizes needed for the BLAS. We need to allocate: +This helper function uses `device.getAccelerationStructureBuildSizesKHR()` and returns the memory sizes needed for the BLAS. We need to allocate: . A buffer for the BLAS itself. . Another buffer for the scratch space used during the build process. We can then create these buffers and store them in persistent arrays as they will be needed later. -We also need to create the BLAS handle itself, which is done with `vk::AccelerationStructureCreateInfoKHR` and this device function helper that uses `vkCreateAccelerationStructureKHR()`. The handle is stored in a vector for later use (remember that we need one for each submesh): +We also need to create the BLAS handle itself, which is done with `vk::AccelerationStructureCreateInfoKHR` and this device function helper that uses `device.createAccelerationStructureKHR()`. The handle is stored in a vector for later use (remember that we need one for each submesh): [,c{pp}] ---- @@ -98,7 +98,7 @@ The following diagram summarizes all the structures and buffers we have created image::../../../images/38_TASK02_blas_structures.png[] -To put it all together, we need to submit a command buffer to build the BLAS on the GPU. This is done with `vkCmdBuildAccelerationStructuresKHR()`, which takes the build info and a range. The range adds flexibility to build multiple geometries in one go, but here we only have one geometry per BLAS so it is kept simple: +To put it all together, we need to submit a command buffer to build the BLAS on the GPU. This is done with the command buffer's `buildAccelerationStructuresKHR()` method, which takes the build info and a range. The range adds flexibility to build multiple geometries in one go, but here we only have one geometry per BLAS so it is kept simple: [,c{pp}] ---- @@ -148,7 +148,7 @@ vk::AccelerationStructureInstanceKHR instance{ instances.push_back(instance); ---- -Note how we needed to get the device address of the BLAS using `vkGetAccelerationStructureDeviceAddressKHR()`. We also set the transform matrix as the identity matrix for now, we will revisit this later in the lab. +Note how we needed to get the device address of the BLAS using `device.getAccelerationStructureAddressKHR()`. We also set the transform matrix as the identity matrix for now, we will revisit this later in the lab. Now that all instances are stored in a vector, we need to prepare the instance data for the TLAS. This involves creating a buffer that holds the instance data. @@ -201,7 +201,7 @@ vk::AccelerationStructureBuildSizesInfoKHR tlasBuildSizes = And again we create the necessary buffers. -To create the TLAS handle, we use `vkCreateAccelerationStructureKHR()` as before: +To create the TLAS handle, we use `device.createAccelerationStructureKHR()` as before: [,c{pp}] ---- @@ -274,7 +274,7 @@ vk::WriteDescriptorSet asWrite{ }; ---- -And later on call `vkUpdateDescriptorSets()` with the TLAS included in the list: +And later on call `device.updateDescriptorSets()` with the TLAS included in the list: [,c{pp}] ----