Skip to content

Commit be999a7

Browse files
committed
Multi thread example
1 parent 14081bc commit be999a7

File tree

510 files changed

+565531
-449
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

510 files changed

+565531
-449
lines changed

bookcontents/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,7 @@ The book is structured in the following chapters:
2222
- [Chapter 17](chapter-17/chapter-17.md): Animations.
2323
- [Chapter 18](chapter-18/chapter-18.md): Buffer Device Address (BDA).
2424
- [Chapter 18](chapter-19/chapter-19.md): Indirect drawing.
25+
- [Chapter 18](chapter-19/chapter-20.md): Multi-thread.
26+
- [Chapter 18](chapter-19/chapter-21.md): Ray tracing.
2527
- [Appendix 01](appendix-01/appendix-01.md): This chapter provides some insights on how to troubleshoot a loss of device error.
2628
- [Appendix 02](appendix-02/appendix-02.md): This chapter provides a simple 3D game to put everything together

bookcontents/chapter-07/chapter-07.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ public class ScnRender {
919919
.imageView(depthAttachments[i].getImageView().getVkImageView())
920920
.imageLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
921921
.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR)
922-
.storeOp(VK_ATTACHMENT_STORE_OP_STORE)
922+
.storeOp(VK_ATTACHMENT_STORE_OP_DONT_CARE)
923923
.clearValue(clearValue);
924924
result[i] = attachments;
925925
}
@@ -929,7 +929,9 @@ public class ScnRender {
929929
}
930930
```
931931

932-
The code is quite similar as the one used for color attachments, but the layout is different: `VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL` to state that is for depth values.
932+
The code is quite similar as the one used for color attachments, but the layout is different: `VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL` to state that is for depth values. In this case the store operation can be
933+
`VK_ATTACHMENT_STORE_OP_DONT_CARE` instead of `VK_ATTACHMENT_STORE_OP_STORE` because we do not need to store the results, we just
934+
need a depth attachment to perform depth tests. We do not need to access those results later on.
933935

934936
The `createPipeline` needs to be updated to set the push constants range:
935937

bookcontents/chapter-11/chapter-11.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public class ScnRender {
140140
```
141141

142142
In addition to just having a single `VkRenderingAttachmentInfo.Buffer`, the `imageLayout` is now `VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL` instead of being
143-
`VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR` since the image is not related yo the swp chain now. The methods `createDepthAttachment` and `createDepthAttachmentInfo` are
143+
`VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR` since the image is not related yo the swap chain now. The methods `createDepthAttachment` and `createDepthAttachmentInfo` are
144144
like this:
145145

146146
```java
@@ -159,7 +159,7 @@ public class ScnRender {
159159
.imageView(depthAttachment.getImageView().getVkImageView())
160160
.imageLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
161161
.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR)
162-
.storeOp(VK_ATTACHMENT_STORE_OP_STORE)
162+
.storeOp(VK_ATTACHMENT_STORE_OP_DONT_CARE)
163163
.clearValue(clearValue);
164164
}
165165
...

bookcontents/chapter-14/chapter-14.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ public class ScnRender {
183183
.imageView(mrtAttachments.getDepthAttachment().getImageView().getVkImageView())
184184
.imageLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
185185
.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR)
186-
.storeOp(VK_ATTACHMENT_STORE_OP_STORE)
186+
.storeOp(VK_ATTACHMENT_STORE_OP_DONT_CARE)
187187
.clearValue(clearValue);
188188
}
189189

@@ -272,12 +272,6 @@ public class ScnRender {
272272
VK_ACCESS_NONE, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
273273
VK_IMAGE_ASPECT_COLOR_BIT);
274274
}
275-
VkUtils.imageBarrier(stack, cmdHandle, mrtAttachments.getDepthAttachment().getImage().getVkImage(),
276-
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
277-
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
278-
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
279-
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
280-
VK_IMAGE_ASPECT_DEPTH_BIT);
281275
...
282276
int width = mrtAttachments.getWidth();
283277
int height = mrtAttachments.getHeight();

bookcontents/chapter-16/chapter-16.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -478,10 +478,7 @@ public class ShadowRender {
478478
}
479479
```
480480

481-
We create the depth attachment in the `createDepthAttachment` information. In this case it will be a single image but with as many layers as cascade shadows will be. We
482-
will see how this modifies the creation of attachments. The size of the depth image will not be dependant on the screen size, it weill be a configurable value.
483-
The rest of the methods to crate attachment information, render information and shader and pipeline are quite similar.
484-
In this case, we are using three shader modules for vertex, geometry and fragment shading.
481+
We create the depth attachment in the `createDepthAttachment` information. In this case it will be a single image but with as many layers as cascade shadows will be. We will see how this modifies the creation of attachments. The size of the depth image will not be dependant on the screen size, it weill be a configurable value. The rest of the methods to crate attachment information, render information and shader and pipeline are quite similar. In this case, we are using three shader modules for vertex, geometry and fragment shading. In this case, we need to store depth attachment, this is why we use the `VK_ATTACHMENT_STORE_OP_STORE`, because we will sample it while applying lights
485482

486483
The `ShadowRender` class defines also a `cleanup` method to free the resources and some getters to retrieve the depth attachment and the cascade shadows.
487484

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
# Chapter 20 - Ray tracing
1+
# Chapter 20 - Multi-thread
22
TBD
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Chapter 20 - Ray Tracing
2+
TBD

bookcontents/pandoc/settings.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ input-files:
2222
- ./chapter-18/chapter-18.md
2323
- ./chapter-19/chapter-19.md
2424
- ./chapter-20/chapter-20.md
25+
- ./chapter-21/chapter-21.md
2526
- ./appendix-01/appendix-01.md
2627
- ./appendix-02/appendix-02.md
2728
epub-cover-image: pandoc/cover.png
@@ -50,6 +51,7 @@ resource-path:
5051
- chapter-18
5152
- chapter-19
5253
- chapter-20
54+
- chapter-21
5355
- appendix-01
5456
- appendix-02
5557
toc: true

bookcontents/vulkanbook.epub

518 Bytes
Binary file not shown.

booksamples/appendix-01/src/main/java/org/vulkanb/eng/Engine.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
package org.vulkanb.eng;
22

33
import org.vulkanb.eng.graph.Render;
4+
import org.vulkanb.eng.graph.vk.VkUtils;
45
import org.vulkanb.eng.scene.Scene;
56
import org.vulkanb.eng.sound.SoundManager;
67
import org.vulkanb.eng.wnd.Window;
78

9+
import java.util.concurrent.*;
10+
811
public class Engine {
912

13+
private static final int WORKER_COUNT = 2;
1014
private final EngCtx engCtx;
15+
private final ExecutorService executor;
1116
private final IGameLogic gameLogic;
17+
private final Phaser phaser = new Phaser(1);
1218
private final Render render;
19+
private final Callable<Void> renderTask;
20+
private int currentRenderFrame;
21+
private int currentUpdateFrame;
1322

1423
public Engine(String windowTitle, IGameLogic appLogic) {
1524
this.gameLogic = appLogic;
@@ -18,9 +27,18 @@ public Engine(String windowTitle, IGameLogic appLogic) {
1827
render = new Render(engCtx);
1928
InitData initData = gameLogic.init(engCtx);
2029
render.init(engCtx, initData);
30+
executor = Executors.newFixedThreadPool(WORKER_COUNT);
31+
renderTask = () -> {
32+
render.render(engCtx, currentUpdateFrame);
33+
phaser.arriveAndDeregister();
34+
return null;
35+
};
36+
currentUpdateFrame = 1;
37+
currentRenderFrame = 0;
2138
}
2239

2340
private void cleanup() {
41+
executor.shutdownNow();
2442
gameLogic.cleanup();
2543
render.cleanup();
2644
engCtx.cleanup();
@@ -34,10 +52,16 @@ public void run() {
3452

3553
long updateTime = initialTime;
3654
Window window = engCtx.window();
55+
boolean firstExec = true;
3756
while (!window.shouldClose()) {
3857
long now = System.currentTimeMillis();
3958
deltaUpdate += (now - initialTime) / timeU;
4059

60+
if (!firstExec) {
61+
phaser.register();
62+
executor.submit(renderTask);
63+
}
64+
4165
window.pollEvents();
4266
gameLogic.input(engCtx, now - initialTime);
4367
window.resetInput();
@@ -48,10 +72,17 @@ public void run() {
4872
updateTime = now;
4973
deltaUpdate--;
5074
}
75+
render.updateGlobalBuffers(engCtx, currentUpdateFrame);
76+
77+
if (!firstExec) {
78+
phaser.arriveAndAwaitAdvance();
79+
}
5180

52-
render.render(engCtx);
81+
currentUpdateFrame = (currentUpdateFrame + 1) % VkUtils.MAX_IN_FLIGHT;
82+
currentRenderFrame = (currentRenderFrame + 1) % VkUtils.MAX_IN_FLIGHT;
5383

5484
initialTime = now;
85+
firstExec = false;
5586
}
5687

5788
cleanup();

0 commit comments

Comments
 (0)