@@ -115,20 +115,18 @@ VertexOutput vertMain(uint vid : SV_VertexID) {
115115}
116116----
117117
118- The `vertMain` function is invoked for every vertex. The built-in
119- `SV_VertexID`
118+ The `vertMain` function is invoked for every vertex. The built-in `SV_VertexID`
120119annotated variable in the parameters contains the index of the current vertex.
121120This is usually an index into the vertex buffer, but in our case, it will be
122121an index into a hardcoded array of vertex data. The position of each vertex
123122is accessed from the constant array in the shader and combined with dummy
124123`z` and `w` components to produce a position in clip coordinates. The
125- built-in annotation `SV_Position` functions as
126- the output. Within the VertexOutput struct.
124+ built-in annotation `SV_Position` marks the output in the VertexOutput struct.
127125Something worth mentioning if you're familiar with other shading languages
128126like GLSL or HLSL, there are no instructions for bindings. This is a feature
129- of Slang. Slang is designed to automatically infer the bindings by the
130- order of declaration. The struct for positions is a static to inform the
131- compiler that we don't need any bindings in our shader.
127+ of Slang. Slang is designed to automatically infer the bindings by the
128+ order of declaration. The struct for positions is a static to inform the
129+ compiler that we don't need any bindings in our shader.
132130Studious observers will notice that we're calling our main function
133131vertMain instead of main, this is because Slang and SPIR-V both support
134132having multiple entry points in one file. This is important when you're
@@ -425,22 +423,22 @@ will later be explicit about its size.
425423== Creating shader modules
426424
427425Before we can pass the code to the pipeline, we have to wrap it in a
428- `VkShaderModule ` object. Let's create a helper function `createShaderModule` to
426+ `vk::raii::ShaderModule ` object. Let's create a helper function `createShaderModule` to
429427do that.
430428
431429[,c++]
432430----
433- [[nodiscard]] vk::raii::ShaderModule createShaderModule(const std::vector<char>& code) const {
434-
431+ [[nodiscard]] vk::raii::ShaderModule createShaderModule(const std::vector<char>& code) const
432+ {
435433}
436434----
437435
438436The function will take a buffer with the bytecode as parameter and create a
439- `VkShaderModule ` from it.
437+ `vk::raii::ShaderModule ` from it.
440438
441439Creating a shader module is straightforward, we only need to specify a pointer to the
442440buffer with the bytecode and the length of it. This information is specified in
443- a `VkShaderModuleCreateInfo ` structure. The one catch is that the size of the
441+ a `vk::ShaderModuleCreateInfo ` structure. The one catch is that the size of the
444442bytecode is specified in bytes, but the bytecode pointer is a `uint32_t` pointer
445443rather than a `char` pointer. Therefore, we will need to cast the pointer with
446444`reinterpret_cast` as shown below. When you perform a cast like this, you also
@@ -453,18 +451,17 @@ already ensures that the data satisfies the worst case alignment requirements.
453451vk::ShaderModuleCreateInfo createInfo{ .codeSize = code.size() * sizeof(char), .pCode = reinterpret_cast<const uint32_t*>(code.data()) };
454452----
455453
456- The `VkShaderModule ` can then be created with a call to `vkCreateShaderModule` :
454+ The `vk::raii::ShaderModule ` can then be created by its constructor :
457455
458456[,c++]
459457----
460458vk::raii::ShaderModule shaderModule{ device, createInfo };
461459----
462460
463461The parameters are the same as those in previous object creation functions: the
464- logical device, pointer to create info structure, optional pointer to custom
465- allocators and handle output variable. The buffer with the code can be freed
466- immediately after creating the shader module. Remember to return the created
467- shader module:
462+ logical device and a reference to the create info structure. The buffer with the
463+ code can be freed immediately after creating the shader module. Remember to return
464+ the created shader module:
468465
469466[,c++]
470467----
@@ -484,7 +481,7 @@ void createGraphicsPipeline() {
484481== Shader stage creation
485482
486483To actually use the shaders, we'll need to assign them to a specific
487- pipeline stage through `VkPipelineShaderStageCreateInfo ` structures as part
484+ pipeline stage through `vk::PipelineShaderStageCreateInfo ` structures as part
488485of the actual pipeline creation process.
489486
490487We'll start by filling in the structure for the vertex shader, again in the
@@ -495,21 +492,21 @@ We'll start by filling in the structure for the vertex shader, again in the
495492vk::PipelineShaderStageCreateInfo vertShaderStageInfo{ .stage = vk::ShaderStageFlagBits::eVertex, .module = shaderModule, .pName = "vertMain" };
496493----
497494
498- The first two parameters are the flags and the stage that we're operating
499- in. The next two parameters specify the shader module containing the code, and
500- the function to invoke, known as the _entrypoint_.
495+ The first parameter is the stage that we're operating in. The next two parameters
496+ specify the shader module containing the code, and the function to invoke, known
497+ as the _entrypoint_.
501498That means that it's possible to combine multiple fragment shaders into a
502- single shader module and use different entry points to differentiate between
503- their behaviors.
499+ single shader module and use different entry points to differentiate between their
500+ behaviors.
504501
505502There is one more (optional) member, `pSpecializationInfo`, which we won't
506- be using here, but is worth discussing. It allows you to specify values for
507- shader constants. You can use a single shader module where its behavior can
508- be configured in pipeline creation by specifying different values for the
509- constants used in it.
503+ be using here, but is worth discussing. It allows you to specify values for
504+ shader constants. You can use a single shader module where its behavior can
505+ be configured in pipeline creation by specifying different values for the
506+ constants used in it.
510507This is more efficient than configuring the shader using variables at render
511- time, because the compiler can do optimizations like eliminating `if`
512- statements that depend on these values.
508+ time, because the compiler can do optimizations like eliminating `if`
509+ statements that depend on these values.
513510If you don't have any constants like that, then you can set the member to
514511`nullptr`, which our struct initialization does automatically.
515512
0 commit comments