Skip to content

Commit 6ced724

Browse files
committed
```
Fix typos and improve clarity in compute shader documentation Corrected grammatical mistakes and improved phrasing for better readability in compute shader documentation. Adjusted links to use `.adoc` extension and reformatted lines for consistency and clarity. No functional changes were made to the content. ```
1 parent 7e5990d commit 6ced724

File tree

1 file changed

+25
-15
lines changed

1 file changed

+25
-15
lines changed

en/11_Compute_Shader.adoc

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ The biggest differences are that you can alias other buffer types to SSBOs and t
9090
Going back to the GPU-based particle system, you might now wonder how to deal with vertices being updated (written) by the compute shader and read (drawn) by the vertex shader, as both usages would seemingly require different buffer types.
9191

9292
But that's not the case.
93-
In Vulkan you can specify multiple usages for buffers and images.
93+
In Vulkan, you can specify multiple usages for buffers and images.
9494
So for the particle vertex buffer to be used as a vertex buffer (in the graphics pass) and as a storage buffer (in the compute pass), you simply create the buffer with those two usage flags:
9595

9696
[,c++]
@@ -105,9 +105,9 @@ shaderStorageBuffers[i] = vk::raii::Buffer(*device, bufferInfo);
105105

106106
The two flags `VK_BUFFER_USAGE_VERTEX_BUFFER_BIT` and `VK_BUFFER_USAGE_STORAGE_BUFFER_BIT` set with `bufferInfo.usage` tell the implementation that we want to use this buffer for two different scenarios: as a vertex buffer in the vertex shader and as a store buffer.
107107
Note that we also added the `VK_BUFFER_USAGE_TRANSFER_DST_BIT` flag in here so we can transfer data from the host to the GPU.
108-
This is crucial as we want the shader storage buffer to stay in GPU memory only (`VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`) we need to to transfer data from the host to this buffer.
108+
This is crucial as we want the shader storage buffer to stay in GPU memory only (`VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`) we need to transfer data from the host to this buffer.
109109

110-
Here is the same code using using the `createBuffer` helper function:
110+
Here is the same code using the `createBuffer` helper function:
111111

112112
[,c++]
113113
----
@@ -138,7 +138,7 @@ RWStructuredBuffer<ParticleSSBO> particlesOut;
138138

139139
In this example we have a typed SSBO with each particle having a position and velocity value (see the `Particle` struct).
140140
The SSBO then contains an unbound number of particles as it is placed into a
141-
StructuredBuffer without upper limit and it's a read only buffer for
141+
StructuredBuffer without upper limit, and it's a read-only buffer for
142142
particlesIn. For particlesOut, we place it into a RWStructedBuffer.
143143
Not having to specify the number of elements in an SSBO is one of the advantages over e.g.
144144
uniform buffers.
@@ -155,7 +155,7 @@ particlesOut[index].particles.position = particlesIn[index].particles.position +
155155
_Note that we won't be doing image manipulation in this chapter.
156156
This paragraph is here to make readers aware that compute shaders can also be used for image manipulation._
157157

158-
A storage image allows you read from and write to an image.
158+
A storage image allows you to read from and write to an image.
159159
Typical use cases are applying image effects to textures, doing post-processing (which in turn is very similar) or generating mip-maps.
160160

161161
This is similar for images:
@@ -199,7 +199,8 @@ outputImage[int2(gl_GlobalInvocationID.xy)] = pixel;
199199

200200
== Compute queue families
201201

202-
In the link:03_Drawing_a_triangle/00_Setup/03_Physical_devices_and_queue_families.md#page_Queue-families[physical device and queue families chapter], we have already learned about queue families and how to select a graphics queue family.
202+
In the link:03_Drawing_a_triangle/00_Setup/03_Physical_devices_and_queue_families.adoc[physical device and queue families chapter],
203+
we have already learned about queue families and how to select a graphics queue family.
203204
Compute uses the queue family properties flag bit `VK_QUEUE_COMPUTE_BIT`.
204205
So if we want to do compute work, we need to get a queue from a queue family that supports compute.
205206

@@ -233,7 +234,7 @@ computeQueue = std::make_unique<vk::raii::Queue>( *device, graphicsAndComputeInd
233234

234235
== The compute shader stage
235236

236-
In the graphics samples we have used different pipeline stages to load shaders and access descriptors.
237+
In the graphics samples, we have used different pipeline stages to load shaders and access descriptors.
237238
Compute shaders are accessed in a similar way by using the `VK_SHADER_STAGE_COMPUTE_BIT` pipeline.
238239
So loading a compute shader is just the same as loading a vertex shader, but with a different shader stage.
239240
We'll talk about this in detail in the next paragraphs.
@@ -266,7 +267,7 @@ std::vector<vk::raii::Buffer> shaderStorageBuffers;
266267
std::vector<vk::raii::DeviceMemory> shaderStorageBuffersMemory;
267268
----
268269

269-
In the `createShaderStorageBuffers` we then clear those vectors to cleanup
270+
In the `createShaderStorageBuffers` we then clear those vectors to clean up
270271
any objects already created in their as is our RAII practice.
271272

272273
[,c++]
@@ -342,7 +343,7 @@ The only difference is that descriptors need to have the `VK_SHADER_STAGE_COMPUT
342343
...
343344
----
344345

345-
Note that you can combine shader stages here, so if you want the descriptor to be accessible from the vertex and compute stage, e.g.
346+
Note that you can combine shader stages here, so if you want the descriptor to be accessible from the vertex and compute stage, e.g.,
346347
for a uniform buffer with parameters shared across them, you set the bits for both stages:
347348

348349
[,c++]
@@ -406,7 +407,7 @@ We need to double the number of `VK_DESCRIPTOR_TYPE_STORAGE_BUFFER` types reques
406407
== Compute pipelines
407408

408409
As compute is not a part of the graphics pipeline, we can't use `vkCreateGraphicsPipelines`.
409-
Instead we need to create a dedicated compute pipeline with `vkCreateComputePipelines` for running our compute commands.
410+
Instead, we need to create a dedicated compute pipeline with `vkCreateComputePipelines` for running our compute commands.
410411
Since a compute pipeline does not touch any of the rasterization state, it has a lot less state than a graphics pipeline:
411412

412413
[,c++]
@@ -587,13 +588,20 @@ Synchronization is an important part of Vulkan, even more so when doing compute
587588
Wrong or lacking synchronization may result in the vertex stage starting to draw (=read) particles while the compute shader hasn't finished updating (=write) them (read-after-write hazard), or the compute shader could start updating particles that are still in use by the vertex part of the pipeline (write-after-read hazard).
588589

589590
So we must make sure that those cases don't happen by properly synchronizing the graphics and the compute load.
590-
There are different ways of doing so, depending on how you submit your compute workload but in our case with two separate submits, we'll be using link:03_Drawing_a_triangle/03_Drawing/02_Rendering_and_presentation.md#page_Semaphores[semaphores] and link:03_Drawing_a_triangle/03_Drawing/02_Rendering_and_presentation.md#page_Fences[fences] to ensure that the vertex shader won't start fetching vertices until the compute shader has finished updating them.
591+
There are different ways of doing so, depending on how you submit your
592+
compute workload, but in our case with two separate submits, we'll be using
593+
link:03_Drawing_a_triangle/03_Drawing/02_Rendering_and_presentation.adoc[semaphores] and
594+
link:03_Drawing_a_triangle/03_Drawing/02_Rendering_and_presentation.adoc[fences] to ensure that the vertex shader won't start fetching
595+
vertices until the compute shader has finished updating them.
591596

592597
This is necessary as even though the two submits are ordered one-after-another, there is no guarantee that they execute on the GPU in this order.
593598
Adding in wait and signal semaphores ensures this execution order.
594599

595600
So we first add a new set of synchronization primitives for the compute work in `createSyncObjects`.
596-
The compute fences, just like the graphics fences, are created in the signaled state because otherwise, the first draw would time out while waiting for the fences to be signaled as detailed link:03_Drawing_a_triangle/03_Drawing/02_Rendering_and_presentation.md#page_Waiting-for-the-previous-frame[here]:
601+
The compute fences, just like the graphics fences, are created in the
602+
signaled state because otherwise, the first draw would time out while waiting
603+
for the fences to be signaled as detailed
604+
link:03_Drawing_a_triangle/03_Drawing/02_Rendering_and_presentation.adoc[here]:
597605

598606
[,c++]
599607
----
@@ -642,8 +650,10 @@ We then use these to synchronize the compute buffer submission with the graphics
642650
graphicsQueue->submit(submitInfo, **inFlightFences[currentFrame]);
643651
----
644652

645-
Similar to the sample in the link:03_Drawing_a_triangle/03_Drawing/02_Rendering_and_presentation.md#page_Semaphores[semaphores chapter], this setup will immediately run the compute shader as we haven't specified any wait semaphores.
646-
Note, that we're using scoping braces above to ensure that the RAII temporary
653+
Similar to the sample in the
654+
link:03_Drawing_a_triangle/03_Drawing/02_Rendering_and_presentation.adoc[semaphore chapter], this setup will immediately run the
655+
compute shader as we haven't specified any wait semaphores.
656+
Note that we're using scoping braces above to ensure that the RAII temporary
647657
variables we use get a chance to clean themselves up between the compute and
648658
the graphics stage.
649659
This is fine, as we are waiting for the compute command buffer of the current frame to finish execution before the compute submission with the `vkWaitForFences` command.
@@ -656,7 +666,7 @@ So we also wait on the `imageAvailableSemaphores` on the current frame at the `V
656666

657667
== Drawing the particle system
658668

659-
Earlier on, we learned that buffers in Vulkan can have multiple use-cases and so we created the shader storage buffer that contains our particles with both the shader storage buffer bit and the vertex buffer bit.
669+
Earlier on, we learned that buffers in Vulkan can have multiple use-cases, and so we created the shader storage buffer that contains our particles with both the shader storage buffer bit and the vertex buffer bit.
660670
This means that we can use the shader storage buffer for drawing just as we used "pure" vertex buffers in the previous chapters.
661671

662672
We first set up the vertex input state to match our particle structure:

0 commit comments

Comments
 (0)