Skip to content

Commit c87b0d2

Browse files
authored
Merge branch 'SaschaWillems:master' into master
2 parents ea911a6 + 1b308da commit c87b0d2

File tree

4 files changed

+41
-36
lines changed

4 files changed

+41
-36
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ Note that some examples require specific device features, and if you are on a mu
8383

8484
## Shaders
8585

86-
Vulkan consumes shaders in an intermediate representation called SPIR-V. This makes it possible to use different shader languages by compiling them to that bytecode format. The primary shader language used here is [GLSL](shaders/glsl), most samples also come with [slang](shaders/slang/) and [HLSL](shaders/hlsl) shader sources, making it easy to compare the differences between those shading languages.
86+
Vulkan consumes shaders in an intermediate representation called SPIR-V. This makes it possible to use different shader languages by compiling them to that bytecode format. The primary shader language used here is [GLSL](shaders/glsl), most samples also come with [slang](shaders/slang/) and [HLSL](shaders/hlsl) shader sources, making it easy to compare the differences between those shading languages. The [Rust GPU](https://rust-gpu.github.io/) project maintains [Rust](https://www.rust-lang.org/) shader sources in a [separate repo](https://github.com/Rust-GPU/VulkanShaderExamples/tree/master/shaders/rust).
8787

8888
## A note on synchronization
8989

examples/triangle/triangle.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,8 @@ class VulkanExample : public VulkanExampleBase
110110
std::array<VkCommandBuffer, MAX_CONCURRENT_FRAMES> commandBuffers{};
111111
std::array<VkFence, MAX_CONCURRENT_FRAMES> waitFences{};
112112

113-
// To select the correct sync and command objects, we need to keep track of the current frame and (swapchain) image index
113+
// To select the correct sync and command objects, we need to keep track of the current frame
114114
uint32_t currentFrame{ 0 };
115-
uint32_t currentSemaphore{ 0 };
116115

117116
VulkanExample() : VulkanExampleBase()
118117
{
@@ -189,16 +188,19 @@ class VulkanExample : public VulkanExampleBase
189188
// Fence used to ensure that command buffer has completed exection before using it again
190189
VK_CHECK_RESULT(vkCreateFence(device, &fenceCI, nullptr, &waitFences[i]));
191190
}
192-
// Semaphores are per swapchain image
193-
presentCompleteSemaphores.resize(swapChain.images.size());
191+
// Semaphores are used for correct command ordering within a queue
192+
// Used to ensure that image presentation is complete before starting to submit again
193+
presentCompleteSemaphores.resize(MAX_CONCURRENT_FRAMES);
194+
for (auto& semaphore : presentCompleteSemaphores) {
195+
VkSemaphoreCreateInfo semaphoreCI{ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
196+
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &semaphore));
197+
}
198+
// Render completion
199+
// Semaphore used to ensure that all commands submitted have been finished before submitting the image to the queue
194200
renderCompleteSemaphores.resize(swapChain.images.size());
195-
for (size_t i = 0; i < swapChain.images.size(); i++) {
196-
// Semaphores are used for correct command ordering within a queue
201+
for (auto& semaphore : renderCompleteSemaphores) {
197202
VkSemaphoreCreateInfo semaphoreCI{ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
198-
// Semaphore used to ensure that image presentation is complete before starting to submit again
199-
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &presentCompleteSemaphores[i]));
200-
// Semaphore used to ensure that all commands submitted have been finished before submitting the image to the queue
201-
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &renderCompleteSemaphores[i]));
203+
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &semaphore));
202204
}
203205
}
204206

@@ -915,7 +917,7 @@ class VulkanExample : public VulkanExampleBase
915917
// Get the next swap chain image from the implementation
916918
// Note that the implementation is free to return the images in any order, so we must use the acquire function and can't just cycle through the images/imageIndex on our own
917919
uint32_t imageIndex;
918-
VkResult result = vkAcquireNextImageKHR(device, swapChain.swapChain, UINT64_MAX, presentCompleteSemaphores[currentSemaphore], VK_NULL_HANDLE, &imageIndex);
920+
VkResult result = vkAcquireNextImageKHR(device, swapChain.swapChain, UINT64_MAX, presentCompleteSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
919921
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
920922
windowResize();
921923
return;
@@ -1011,10 +1013,10 @@ class VulkanExample : public VulkanExampleBase
10111013
submitInfo.commandBufferCount = 1; // We submit a single command buffer
10121014

10131015
// Semaphore to wait upon before the submitted command buffer starts executing
1014-
submitInfo.pWaitSemaphores = &presentCompleteSemaphores[currentSemaphore];
1016+
submitInfo.pWaitSemaphores = &presentCompleteSemaphores[currentFrame];
10151017
submitInfo.waitSemaphoreCount = 1;
10161018
// Semaphore to be signaled when command buffers have completed
1017-
submitInfo.pSignalSemaphores = &renderCompleteSemaphores[currentSemaphore];
1019+
submitInfo.pSignalSemaphores = &renderCompleteSemaphores[imageIndex];
10181020
submitInfo.signalSemaphoreCount = 1;
10191021

10201022
// Submit to the graphics queue passing a wait fence
@@ -1027,7 +1029,7 @@ class VulkanExample : public VulkanExampleBase
10271029
VkPresentInfoKHR presentInfo{};
10281030
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
10291031
presentInfo.waitSemaphoreCount = 1;
1030-
presentInfo.pWaitSemaphores = &renderCompleteSemaphores[currentSemaphore];
1032+
presentInfo.pWaitSemaphores = &renderCompleteSemaphores[imageIndex];
10311033
presentInfo.swapchainCount = 1;
10321034
presentInfo.pSwapchains = &swapChain.swapChain;
10331035
presentInfo.pImageIndices = &imageIndex;
@@ -1042,8 +1044,6 @@ class VulkanExample : public VulkanExampleBase
10421044

10431045
// Select the next frame to render to, based on the max. no. of concurrent frames
10441046
currentFrame = (currentFrame + 1) % MAX_CONCURRENT_FRAMES;
1045-
// Similar for the semaphores, which need to be unique to the swapchain images
1046-
currentSemaphore = (currentSemaphore + 1) % swapChain.imageCount;
10471047
}
10481048
};
10491049

examples/trianglevulkan13/trianglevulkan13.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,8 @@ class VulkanExample : public VulkanExampleBase
9595
VkCommandPool commandPool{ VK_NULL_HANDLE };
9696
std::array<VkCommandBuffer, MAX_CONCURRENT_FRAMES> commandBuffers{};
9797

98-
// To select the correct sync and command objects, we need to keep track of the current frame and (swapchain) image index
98+
// To select the correct sync and command objects, we need to keep track of the current frame
9999
uint32_t currentFrame{ 0 };
100-
uint32_t currentSemaphore{ 0 };
101100

102101
VkPhysicalDeviceVulkan13Features enabledFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES };
103102

@@ -182,16 +181,19 @@ class VulkanExample : public VulkanExampleBase
182181
fenceCI.flags = VK_FENCE_CREATE_SIGNALED_BIT;
183182
VK_CHECK_RESULT(vkCreateFence(device, &fenceCI, nullptr, &waitFences[i]));
184183
}
185-
// Semaphores are per swapchain image
186-
presentCompleteSemaphores.resize(swapChain.images.size());
184+
// Semaphores are used for correct command ordering within a queue
185+
// Used to ensure that image presentation is complete before starting to submit again
186+
presentCompleteSemaphores.resize(MAX_CONCURRENT_FRAMES);
187+
for (auto& semaphore : presentCompleteSemaphores) {
188+
VkSemaphoreCreateInfo semaphoreCI{ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
189+
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &semaphore));
190+
}
191+
// Render completion
192+
// Semaphore used to ensure that all commands submitted have been finished before submitting the image to the queue
187193
renderCompleteSemaphores.resize(swapChain.images.size());
188-
for (size_t i = 0; i < swapChain.images.size(); i++) {
189-
// Semaphores are used for correct command ordering within a queue
194+
for (auto& semaphore : renderCompleteSemaphores) {
190195
VkSemaphoreCreateInfo semaphoreCI{ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
191-
// Semaphore used to ensure that image presentation is complete before starting to submit again
192-
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &presentCompleteSemaphores[i]));
193-
// Semaphore used to ensure that all commands submitted have been finished before submitting the image to the queue
194-
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &renderCompleteSemaphores[i]));
196+
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCI, nullptr, &semaphore));
195197
}
196198
}
197199

@@ -701,7 +703,7 @@ class VulkanExample : public VulkanExampleBase
701703
// Get the next swap chain image from the implementation
702704
// Note that the implementation is free to return the images in any order, so we must use the acquire function and can't just cycle through the images/imageIndex on our own
703705
uint32_t imageIndex{ 0 };
704-
VkResult result = vkAcquireNextImageKHR(device, swapChain.swapChain, UINT64_MAX, presentCompleteSemaphores[currentSemaphore], VK_NULL_HANDLE, &imageIndex);
706+
VkResult result = vkAcquireNextImageKHR(device, swapChain.swapChain, UINT64_MAX, presentCompleteSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
705707
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
706708
windowResize();
707709
return;
@@ -788,10 +790,10 @@ class VulkanExample : public VulkanExampleBase
788790
submitInfo.commandBufferCount = 1; // We submit a single command buffer
789791

790792
// Semaphore to wait upon before the submitted command buffer starts executing
791-
submitInfo.pWaitSemaphores = &presentCompleteSemaphores[currentSemaphore];
793+
submitInfo.pWaitSemaphores = &presentCompleteSemaphores[currentFrame];
792794
submitInfo.waitSemaphoreCount = 1;
793795
// Semaphore to be signaled when command buffers have completed
794-
submitInfo.pSignalSemaphores = &renderCompleteSemaphores[currentSemaphore];
796+
submitInfo.pSignalSemaphores = &renderCompleteSemaphores[imageIndex];
795797
submitInfo.signalSemaphoreCount = 1;
796798

797799
// Submit to the graphics queue passing a wait fence
@@ -802,7 +804,7 @@ class VulkanExample : public VulkanExampleBase
802804
// This ensures that the image is not presented to the windowing system until all commands have been submitted
803805
VkPresentInfoKHR presentInfo{ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
804806
presentInfo.waitSemaphoreCount = 1;
805-
presentInfo.pWaitSemaphores = &renderCompleteSemaphores[currentSemaphore];
807+
presentInfo.pWaitSemaphores = &renderCompleteSemaphores[imageIndex];
806808
presentInfo.swapchainCount = 1;
807809
presentInfo.pSwapchains = &swapChain.swapChain;
808810
presentInfo.pImageIndices = &imageIndex;
@@ -815,8 +817,6 @@ class VulkanExample : public VulkanExampleBase
815817

816818
// Select the next frame to render to, based on the max. no. of concurrent frames
817819
currentFrame = (currentFrame + 1) % MAX_CONCURRENT_FRAMES;
818-
// Similar for the semaphores, which need to be unique to the swapchain images
819-
currentSemaphore = (currentSemaphore + 1) % swapChain.imageCount;
820820
}
821821

822822
// Override these as otherwise the base class would generate frame buffers and render passes

examples/validate_all.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,21 @@
33

44
# Runs all samples in benchmark mode and stores all validation messages into a single text file
55

6-
# Note: Need to be copied to where the binary files have been compiled
6+
# Note: Needs to be copied to where the binary files have been compiled (e.g. build/windows/bin/debug)
77

88
import glob
99
import subprocess
1010
import os
11+
import platform
1112

1213
if os.path.exists("validation_output.txt"):
1314
os.remove("validation_output.txt")
14-
for sample in glob.glob("*.exe"):
15-
# Skip headless samples, as they require manual keypress
15+
if platform.system() == 'Linux' or platform.system() == 'Darwin':
16+
binaries = "./*"
17+
else:
18+
binaries = "*.exe"
19+
for sample in glob.glob(binaries):
20+
# Skip headless samples, as they require a manual keypress
1621
if "headless" in sample:
1722
continue
1823
subprocess.call("%s -v -vl -b -bfs %s" % (sample, 50), shell=True)

0 commit comments

Comments
 (0)