@@ -74,12 +74,12 @@ An instance is created by describing your application and any API extensions
7474=== Step 2 - Logical device and queue families
7575
7676After selecting the right hardware device to use, you need to create a
77- vk::Device (logical device), where you describe more specifically which
77+ ` vk::Device` (logical device), where you describe more specifically which
7878physical device features you will be using, like multi viewport rendering
7979and 64-bit floats.
8080You also need to specify which queue families you would like to use.
8181Most operations performed with Vulkan, like draw commands and memory
82- operations, are asynchronously executed by submitting them to a vk::Queue.
82+ operations, are asynchronously executed by submitting them to a ` vk::Queue` .
8383Queues are allocated from queue families, where each queue family supports a
8484 specific set of operations in its queues.
8585For 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
100100chapter.
101101
102102We need two more parts to actually render to a window: a window surface
103- (vk::SurfaceKHR) and a swap chain (vk::SwapchainKHR).
103+ (` vk::SurfaceKHR` ) and a swap chain (` vk::SwapchainKHR` ).
104104Note the `KHR` postfix, which means that these objects are part of a Vulkan
105105extension. The Vulkan API itself is completely platform-agnostic, which is
106106why 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.
133133=== Step 4 - Image views and Dynamic Rendering
134134
135135To draw to an image acquired from the swap chain, we would typically wrap
136- it into a vk::ImageView and vk::Framebuffer. An image view references a specific
136+ it into a ` vk::ImageView` and ` vk::Framebuffer` . An image view references a specific
137137part of an image to be used, and a framebuffer references image views that are
138138to be used for color, depth, and stencil targets.
139139Because there could be many different images in the swap chain,
@@ -165,24 +165,24 @@ a single image as a color target and instruct Vulkan to clear it to a solid colo
165165
166166=== Step 6 - Graphics pipeline
167167
168- The graphics pipeline in Vulkan is set up by creating a VkPipeline object.
168+ The graphics pipeline in Vulkan is set up by creating a ` VkPipeline` object.
169169It describes the configurable state of the graphics card, like the viewport
170- size and depth buffer operation and the programmable state using vk::ShaderModule objects.
171- The vk::ShaderModule objects are created from shader byte code.
170+ size and depth buffer operation and the programmable state using ` vk::ShaderModule` objects.
171+ The ` vk::ShaderModule` objects are created from shader byte code.
172172The driver also needs to know which render targets will be used in the
173173pipeline, which we specify by referencing the render pass.
174174
175- One of the most distinctive features of Vulkan compared to existing APIs, is
176- that almost all configuration of the graphics pipeline needs to be set in
177- advance.
175+ One of the most distinctive features of Vulkan compared to existing APIs is
176+ that almost all configuration of the graphics pipeline needs to be set in
177+ advance.
178178That means that if you want to switch to a different shader or slightly
179- change your vertex layout, then you need to entirely recreate the graphics
180- pipeline .
181- That means that you will have to create many vk::Pipeline objects in advance
182- for all the different combinations you need for your rendering operations.
179+ change your vertex layout, then you need to recreate the graphics pipeline
180+ entirely .
181+ You will have to create many ` vk::Pipeline` objects in advance for all of the
182+ different combinations you need for your rendering operations.
183183Only some basic configuration, like viewport size and clear color, can be
184184changed dynamically.
185- All the states also need to be described explicitly; there is no default
185+ All states also need to be described explicitly; there is no default
186186color blend state, for example.
187187
188188The good news is that because you're doing the equivalent of ahead-of-time
@@ -195,22 +195,22 @@ are made very explicit.
195195
196196As mentioned earlier, many of the operations in Vulkan that we want to
197197execute, like drawing operations, need to be submitted to a queue.
198- These operations first need to be recorded into a vk::CommandBuffer before
198+ These operations first need to be recorded into a ` vk::CommandBuffer` before
199199they can be submitted.
200200These command buffers are allocated from a `vk::CommandPool` that is
201201associated with a specific queue family.
202- Traditionally, to draw a simple triangle, we need to record a command buffer with the
202+ To draw a triangle prior to dynamic rendering , we would need to record a command buffer with the
203203following operations:
204204
205205* Begin the render pass
206206* Bind the graphics pipeline
207207* Draw three vertices
208208* End the render pass
209209
210- However, with dynamic rendering, things change .
210+ However, dynamic rendering changes things .
211211Instead of "beginning" and "ending" a render pass,
212212you directly define the rendering attachments when you start
213- rendering with vk::BeginRendering.
213+ rendering with ` vk::BeginRendering` .
214214
215215This simplifies the process by allowing you to specify the necessary attachments on the fly,
216216making it more adaptable to scenarios where the swap chain images are dynamically selected.
@@ -223,42 +223,42 @@ allowing Vulkan to be more flexible in handling rendering scenarios.
223223
224224Now that the drawing commands have been wrapped into a command buffer, the
225225main loop is quite straightforward.
226- We first acquire an image from the swap chain with device.acquireNextImageKHR.
226+ We first acquire an image from the swap chain with ` device.acquireNextImageKHR` .
227227We can then select the appropriate command buffer for that image and execute
228- it with graphicsQueue.submit().
228+ it with ` graphicsQueue.submit()` .
229229Finally, we return the image to the swap chain for presentation to the
230- screen with presentQueue.presentKHR(presentInfo).
230+ screen with ` presentQueue.presentKHR(presentInfo)` .
231231
232232Operations that are submitted to queues are executed asynchronously.
233233Therefore, we have to use synchronization objects like semaphores to ensure a
234- correct order of execution.
234+ correct order of execution.
235235Execution of the draw command buffer must be set up to wait on image
236- acquisition to finish; otherwise it may occur that we start rendering to an
236+ acquisition to finish; otherwise, it may occur that we start rendering to an
237237image that is still being read for presentation on the screen.
238- The presentQueue.presentKHR(presentInfoKHR) call in turn needs to wait for rendering to be
238+ The ` presentQueue.presentKHR(presentInfoKHR)` call in turn needs to wait for rendering to be
239239finished, for which we'll use a second semaphore that is signaled after
240240rendering completes.
241241
242242=== Summary
243243
244244This whirlwind tour should give you a basic understanding of the work ahead
245- of drawing the first triangle.
245+ of drawing the first triangle.
246246A real-world program contains more steps, like allocating vertex buffers,
247247creating uniform buffers and uploading texture images that will be covered
248248in later chapters. However, we'll start simple because Vulkan has enough of
249249a steep learning curve as it is.
250250Note that we'll cheat a bit by initially embedding the vertex coordinates in
251- the vertex shader instead of using a vertex buffer.
251+ the vertex shader instead of using a vertex buffer.
252252That's because managing vertex buffers requires some familiarity with
253253command buffers first.
254254
255255So in short, to draw the first triangle, we need to:
256256
257257* Create an Instance
258- * Select a supported graphics card (PhysicalDevice)
259- * Create a Device and Queue for drawing and presentation
258+ * Select a supported graphics card (` PhysicalDevice` )
259+ * Create a ` Device` and ` Queue` for drawing and presentation
260260* Create a window, window surface and swap chain
261- * Wrap the swap chain images into VkImageView
261+ * Wrap the swap chain images into ` VkImageView`
262262* Set up dynamic rendering
263263* Set up the graphics pipeline
264264* Allocate and record a command buffer with the draw commands for every
@@ -269,11 +269,11 @@ and returning the images to the swap chain
269269It's a lot of steps, but the purpose of each step will be made
270270basic and clear in the upcoming chapters.
271271If you're confused about the relation of a single step compared to the whole
272- program, you should refer back to this chapter.
272+ program, you should refer back to this chapter.
273273
274274== API concepts
275275
276- This chapter will conclude with a short overview of how the Vulkan API is
276+ This chapter concludes with a short overview of how the Vulkan API is
277277structured at a lower level.
278278
279279For example, object creation generally follows this pattern:
@@ -301,24 +301,24 @@ Many structures in Vulkan require you to explicitly specify the type of
301301structure in the `sType` member.
302302The `pNext` member can point to an extension structure and will always be
303303`nullptr` in this tutorial.
304- Functions that create or destroy an object will have a VkAllocationCallbacks
305- parameter that allows you to use a custom allocator for driver memory,
306- which will also be left `nullptr` in this tutorial.
304+ Functions that create or destroy an object will have a ` VkAllocationCallbacks`
305+ parameter that allows you to use a custom allocator for driver memory,
306+ which will also be left `nullptr` in this tutorial.
307307
308- Almost all functions return a vk::Result that is either `vk::result::eSuccess`
308+ Almost all functions return a ` vk::Result` that is either `vk::result::eSuccess`
309309or an error code.
310310The specification describes which error codes each function can return and
311311what they mean.
312312
313313Failure of such calls is reported by C++ exceptions. The exception will
314- respond with more information about the error including the aforementioned
315- vk::Result, this enables us to check multiple commands from one call and keep
316- the command syntax clean.
314+ respond with more information about the error including a `vk::Result`.
315+ This enables us to check multiple commands from one call and keep the
316+ command syntax clean.
317317
318318=== Validation layers
319319
320320As mentioned earlier, Vulkan is designed for high performance and low driver
321- overhead.
321+ overhead.
322322Therefore, it will include very limited error checking and debugging
323323capabilities by default.
324324The driver will often crash instead of returning an error code if you do
@@ -335,7 +335,7 @@ completely disable them when releasing your application for zero overhead.
335335Anyone can write their own validation layers, but the Vulkan SDK by LunarG
336336provides a standard set of validation layers that we'll be using in this tutorial.
337337You also need to register a callback function to receive debug messages from
338- the layers.
338+ the layers.
339339
340340Because Vulkan is so explicit about every operation and the validation
341341layers are so extensive, it can actually be a lot easier to find out why
0 commit comments