Skip to content

Commit 8031f39

Browse files
authored
Port to the finalised Vulkan Khronos ray tracing extensions (#21)
* Saving first WiP steps for when SDK is updated to final specs for ray tracing * Upgraded to latest Vulkan SDK (1.2.162) with support for VK_KHR_acceleration_structure and VK_KHR_ray_tracing_pipeline. Hopefully fixed all of the Vulkan calls and validation errors. Fixed ImGui::SliderFloat logarithmic call (API break). * Fix Windows CI. * Fix Linux build (missing header include). Fix Windows CI (update msbuild setup). * Fix Linux build (missing header include). Fix Windows CI (update msbuild setup).
1 parent 083bbd4 commit 8031f39

30 files changed

Lines changed: 333 additions & 411 deletions

.github/workflows/linux.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77

88
runs-on: ubuntu-20.04
99
env:
10-
SDK_VERSION: 1.2.154
10+
SDK_VERSION: 1.2.162
1111

1212
steps:
1313
- uses: actions/checkout@v2

.github/workflows/windows.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ jobs:
77

88
runs-on: windows-latest
99
env:
10-
SDK_VERSION: 1.2.154.1
10+
SDK_VERSION: 1.2.162.0
1111

1212
steps:
1313
- uses: actions/checkout@v2
1414
- name: Download Vulkan SDK
15-
run: Invoke-WebRequest "https://sdk.lunarg.com/sdk/download/${env:SDK_VERSION}/windows/VulkanSDK-${env:SDK_VERSION}-Installer.exe?Human=true" -OutFile VulkanSDK.exe -v
15+
run: Invoke-WebRequest "https://sdk.lunarg.com/sdk/download/${env:SDK_VERSION}/windows/vulkan_sdk.exe?Human=true" -OutFile vulkan_sdk.exe -v
1616
- name: Install Vulkan SDK
17-
run: .\VulkanSDK.exe /S
17+
run: .\vulkan_sdk.exe /S
1818
shell: cmd
1919
- name: Compile vcpkg dependencies
2020
run: vcpkg_windows.bat
@@ -25,7 +25,7 @@ jobs:
2525
# (originally at https://github.com/warrenbuckley/Setup-MSBuild, later on adopted by Microsoft themselves).
2626
# Comedy bonus: GitHub is now owned by Microsoft.
2727
- name: Setup MSBuild
28-
uses: microsoft/setup-msbuild@v1.0.0
28+
uses: microsoft/setup-msbuild@v1
2929
- name: Compile raytracer
3030
run: |
3131
set VULKAN_SDK=C:\VulkanSDK\%SDK_VERSION%

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ find_package(imgui CONFIG REQUIRED)
4848
find_package(tinyobjloader CONFIG REQUIRED)
4949
find_package(Vulkan REQUIRED)
5050

51+
add_definitions(-DIMGUI_DISABLE_OBSOLETE_FUNCTIONS)
52+
5153
IF (NOT Vulkan_FOUND)
5254
message(FATAL_ERROR "Could not find Vulkan library!")
5355
ELSE()

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<img align="center" src="https://github.com/GPSnoopy/RayTracingInVulkan/blob/master/gallery/LucySettings.jpg">
44

5-
My implementation of [Peter Shirley's Ray Tracing in One Weekend](https://github.com/RayTracing/raytracing.github.io) books using Vulkan and NVIDIA's RTX extension (VK_NV_ray_tracing, now ported to VK_KHR_ray_tracing). This allows most scenes to be rendered at interactive speed on appropriate hardware.
5+
My implementation of [Peter Shirley's Ray Tracing in One Weekend](https://github.com/RayTracing/raytracing.github.io) books using Vulkan and NVIDIA's RTX extension (formerly VK_NV_ray_tracing, now ported to Khronos cross platform extensions). This allows most scenes to be rendered at interactive speed on appropriate hardware.
66

77
The real-time ray tracer can also load full geometry from OBJ files as well as render the procedural spheres from the book. An accumulation buffer is used to increase the sample count when the camera is not moving while keeping the frame rate interactive. I have added a UI built using [Dear ImGui](https://github.com/ocornut/imgui) to allow changing the renderer parameters on the fly. Unlike projects such as [Q2VKPT](http://brechpunkt.de/q2vkpt/), there is no denoising filter. So the image will get noisy when moving the camera.
88

@@ -64,7 +64,7 @@ If in doubt, please check the GitHub Actions [continuous integration configurati
6464

6565
## References
6666

67-
### Initial Implementation
67+
### Initial Implementation (NVIDIA vendor specific extension)
6868

6969
* [Vulkan Tutorial](https://vulkan-tutorial.com/)
7070
* [Introduction to Real-Time Ray Tracing with Vulkan](https://devblogs.nvidia.com/vulkan-raytracing)
@@ -77,8 +77,9 @@ If in doubt, please check the GitHub Actions [continuous integration configurati
7777
* [NVIDIA Vulkan Forums](https://devtalk.nvidia.com/default/board/166/vulkan)
7878
* [Profiling DXR shaders with Timer Instrumentation](https://www.reddit.com/r/vulkan/comments/hhyeyj/profiling_dxr_shaders_with_timer_instrumentation/)
7979

80-
### VK_KHR_ray_tracing Port
80+
### Vulkan Khronos Ray Tracing (cross platform extension)
8181

8282
* [Khronos Vulkan Registry](https://www.khronos.org/registry/vulkan/)
83-
* [NVIDIA Vulkan Ray Tracing Tutorial (VK_KHR_ray_tracing)](https://nvpro-samples.github.io/vk_raytracing_tutorial_KHR)
83+
* [NVIDIA Vulkan Ray Tracing Tutorial (VK_KHR_ray_tracing)](https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR)
8484
* [NVIDIA Converting VK_NV_ray_tracing to VK_KHR_ray_tracing](https://nvpro-samples.github.io/vk_raytracing_tutorial_KHR/NV_to_KHR.md.htm)
85+
* [Vulkan Ray Tracing Final Specification Release](https://www.khronos.org/blog/vulkan-ray-tracing-final-specification-release)

src/Assets/Scene.cpp

Lines changed: 15 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,65 +3,14 @@
33
#include "Sphere.hpp"
44
#include "Texture.hpp"
55
#include "TextureImage.hpp"
6-
#include "Vulkan/Buffer.hpp"
7-
#include "Vulkan/Device.hpp"
8-
#include "Vulkan/CommandPool.hpp"
6+
#include "Vulkan/BufferUtil.hpp"
97
#include "Vulkan/ImageView.hpp"
108
#include "Vulkan/Sampler.hpp"
119
#include "Utilities/Exception.hpp"
12-
#include <cstring>
10+
#include "Vulkan/SingleTimeCommands.hpp"
1311

14-
namespace Assets {
15-
16-
namespace
17-
{
18-
19-
template <class T>
20-
void CopyFromStagingBuffer(Vulkan::CommandPool& commandPool, Vulkan::Buffer& dstBuffer, const std::vector<T>& content)
21-
{
22-
const auto& device = commandPool.Device();
23-
const auto contentSize = sizeof(content[0]) * content.size();
24-
25-
// Create a temporary host-visible staging buffer.
26-
auto stagingBuffer = std::make_unique<Vulkan::Buffer>(device, contentSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
27-
auto stagingBufferMemory = stagingBuffer->AllocateMemory(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
28-
29-
// Copy the host data into the staging buffer.
30-
const auto data = stagingBufferMemory.Map(0, contentSize);
31-
std::memcpy(data, content.data(), contentSize);
32-
stagingBufferMemory.Unmap();
33-
34-
// Copy the staging buffer to the device buffer.
35-
dstBuffer.CopyFrom(commandPool, *stagingBuffer, contentSize);
36-
37-
// Delete the buffer before the memory
38-
stagingBuffer.reset();
39-
}
4012

41-
template <class T>
42-
void CreateDeviceBuffer(
43-
Vulkan::CommandPool& commandPool,
44-
const char* const name,
45-
const VkBufferUsageFlags usage,
46-
const std::vector<T>& content,
47-
std::unique_ptr<Vulkan::Buffer>& buffer,
48-
std::unique_ptr<Vulkan::DeviceMemory>& memory)
49-
{
50-
const auto& device = commandPool.Device();
51-
const auto& debugUtils = device.DebugUtils();
52-
const auto contentSize = sizeof(content[0]) * content.size();
53-
const VkMemoryAllocateFlags allocateFlags = usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT ? VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT : 0;
54-
55-
buffer.reset(new Vulkan::Buffer(device, contentSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage));
56-
memory.reset(new Vulkan::DeviceMemory(buffer->AllocateMemory(allocateFlags, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)));
57-
58-
debugUtils.SetObjectName(buffer->Handle(), (name + std::string(" Buffer")).c_str());
59-
debugUtils.SetObjectName(memory->Handle(), (name + std::string(" Memory")).c_str());
60-
61-
CopyFromStagingBuffer(commandPool, *buffer, content);
62-
}
63-
64-
}
13+
namespace Assets {
6514

6615
Scene::Scene(Vulkan::CommandPool& commandPool, std::vector<Model>&& models, std::vector<Texture>&& textures, bool usedForRayTracing) :
6716
models_(std::move(models)),
@@ -96,7 +45,7 @@ Scene::Scene(Vulkan::CommandPool& commandPool, std::vector<Model>&& models, std:
9645
}
9746

9847
// Add optional procedurals.
99-
const auto sphere = dynamic_cast<const Sphere*>(model.Procedural());
48+
const auto* const sphere = dynamic_cast<const Sphere*>(model.Procedural());
10049
if (sphere != nullptr)
10150
{
10251
const auto aabb = sphere->BoundingBox();
@@ -112,24 +61,25 @@ Scene::Scene(Vulkan::CommandPool& commandPool, std::vector<Model>&& models, std:
11261

11362
const auto flag = usedForRayTracing ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT : 0;
11463

115-
CreateDeviceBuffer(commandPool, "Vertices", VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | flag, vertices, vertexBuffer_, vertexBufferMemory_);
116-
CreateDeviceBuffer(commandPool, "Indices", VK_BUFFER_USAGE_INDEX_BUFFER_BIT | flag, indices, indexBuffer_, indexBufferMemory_);
117-
CreateDeviceBuffer(commandPool, "Materials", flag, materials, materialBuffer_, materialBufferMemory_);
118-
CreateDeviceBuffer(commandPool, "Offsets", flag, offsets, offsetBuffer_, offsetBufferMemory_);
64+
Vulkan::BufferUtil::CreateDeviceBuffer(commandPool, "Vertices", VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | flag, vertices, vertexBuffer_, vertexBufferMemory_);
65+
Vulkan::BufferUtil::CreateDeviceBuffer(commandPool, "Indices", VK_BUFFER_USAGE_INDEX_BUFFER_BIT | flag, indices, indexBuffer_, indexBufferMemory_);
66+
Vulkan::BufferUtil::CreateDeviceBuffer(commandPool, "Materials", flag, materials, materialBuffer_, materialBufferMemory_);
67+
Vulkan::BufferUtil::CreateDeviceBuffer(commandPool, "Offsets", flag, offsets, offsetBuffer_, offsetBufferMemory_);
11968

120-
CreateDeviceBuffer(commandPool, "AABBs", flag, aabbs, aabbBuffer_, aabbBufferMemory_);
121-
CreateDeviceBuffer(commandPool, "Procedurals", flag, procedurals, proceduralBuffer_, proceduralBufferMemory_);
69+
Vulkan::BufferUtil::CreateDeviceBuffer(commandPool, "AABBs", flag, aabbs, aabbBuffer_, aabbBufferMemory_);
70+
Vulkan::BufferUtil::CreateDeviceBuffer(commandPool, "Procedurals", flag, procedurals, proceduralBuffer_, proceduralBufferMemory_);
12271

72+
12373
// Upload all textures
12474
textureImages_.reserve(textures_.size());
12575
textureImageViewHandles_.resize(textures_.size());
12676
textureSamplerHandles_.resize(textures_.size());
127-
77+
12878
for (size_t i = 0; i != textures_.size(); ++i)
12979
{
130-
textureImages_.emplace_back(new TextureImage(commandPool, textures_[i]));
131-
textureImageViewHandles_[i] = textureImages_[i]->ImageView().Handle();
132-
textureSamplerHandles_[i] = textureImages_[i]->Sampler().Handle();
80+
textureImages_.emplace_back(new TextureImage(commandPool, textures_[i]));
81+
textureImageViewHandles_[i] = textureImages_[i]->ImageView().Handle();
82+
textureSamplerHandles_[i] = textureImages_[i]->Sampler().Handle();
13383
}
13484
}
13585

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ set(src_files_vulkan
4141
Vulkan/Application.hpp
4242
Vulkan/Buffer.cpp
4343
Vulkan/Buffer.hpp
44+
Vulkan/BufferUtil.hpp
4445
Vulkan/CommandBuffers.cpp
4546
Vulkan/CommandBuffers.hpp
4647
Vulkan/CommandPool.cpp

src/UserInterface.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ void UserInterface::DrawSettings()
219219
ImGui::Text("Profiler");
220220
ImGui::Separator();
221221
ImGui::Checkbox("Show heatmap", &Settings().ShowHeatmap);
222-
ImGui::SliderFloat("Scaling", &Settings().HeatmapScale, 0.01f, 10.0f, "%.2f", 2);
222+
ImGui::SliderFloat("Scaling", &Settings().HeatmapScale, 0.10f, 10.0f, "%.2f", ImGuiSliderFlags_Logarithmic);
223223
ImGui::NewLine();
224224
}
225225
ImGui::End();

src/Vulkan/Buffer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ VkDeviceAddress Buffer::GetDeviceAddress() const
6060

6161
void Buffer::CopyFrom(CommandPool& commandPool, const Buffer& src, VkDeviceSize size)
6262
{
63-
SingleTimeCommands::Submit(commandPool, [&] (VkCommandBuffer commandBuffer)
63+
SingleTimeCommands::Submit(commandPool, [&](VkCommandBuffer commandBuffer)
6464
{
6565
VkBufferCopy copyRegion = {};
6666
copyRegion.srcOffset = 0; // Optional

src/Vulkan/Buffer.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "Vulkan.hpp"
44
#include "DeviceMemory.hpp"
55

6+
67
namespace Vulkan
78
{
89
class CommandPool;
@@ -32,5 +33,4 @@ namespace Vulkan
3233

3334
VULKAN_HANDLE(VkBuffer, buffer_)
3435
};
35-
3636
}

src/Vulkan/BufferUtil.hpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#pragma once
2+
3+
#include "Buffer.hpp"
4+
#include "CommandPool.hpp"
5+
#include "Device.hpp"
6+
#include "DeviceMemory.hpp"
7+
#include <cstring>
8+
#include <memory>
9+
#include <string>
10+
#include <vector>
11+
12+
13+
namespace Vulkan
14+
{
15+
class BufferUtil final
16+
{
17+
public:
18+
19+
template <class T>
20+
static void CopyFromStagingBuffer(CommandPool& commandPool, Buffer& dstBuffer, const std::vector<T>& content);
21+
22+
template <class T>
23+
static void CreateDeviceBuffer(
24+
CommandPool& commandPool,
25+
const char* name,
26+
VkBufferUsageFlags usage,
27+
const std::vector<T>& content,
28+
std::unique_ptr<Buffer>& buffer,
29+
std::unique_ptr<DeviceMemory>& memory);
30+
};
31+
32+
template <class T>
33+
void BufferUtil::CopyFromStagingBuffer(CommandPool& commandPool, Buffer& dstBuffer, const std::vector<T>& content)
34+
{
35+
const auto& device = commandPool.Device();
36+
const auto contentSize = sizeof(content[0]) * content.size();
37+
38+
// Create a temporary host-visible staging buffer.
39+
auto stagingBuffer = std::make_unique<Buffer>(device, contentSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
40+
auto stagingBufferMemory = stagingBuffer->AllocateMemory(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
41+
42+
// Copy the host data into the staging buffer.
43+
const auto data = stagingBufferMemory.Map(0, contentSize);
44+
std::memcpy(data, content.data(), contentSize);
45+
stagingBufferMemory.Unmap();
46+
47+
// Copy the staging buffer to the device buffer.
48+
dstBuffer.CopyFrom(commandPool, *stagingBuffer, contentSize);
49+
50+
// Delete the buffer before the memory
51+
stagingBuffer.reset();
52+
}
53+
54+
template <class T>
55+
void BufferUtil::CreateDeviceBuffer(
56+
CommandPool& commandPool,
57+
const char* const name,
58+
const VkBufferUsageFlags usage,
59+
const std::vector<T>& content,
60+
std::unique_ptr<Buffer>& buffer,
61+
std::unique_ptr<DeviceMemory>& memory)
62+
{
63+
const auto& device = commandPool.Device();
64+
const auto& debugUtils = device.DebugUtils();
65+
const auto contentSize = sizeof(content[0]) * content.size();
66+
const VkMemoryAllocateFlags allocateFlags = usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
67+
? VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT
68+
: 0;
69+
70+
buffer.reset(new Buffer(device, contentSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage));
71+
memory.reset(new DeviceMemory(buffer->AllocateMemory(allocateFlags, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)));
72+
73+
debugUtils.SetObjectName(buffer->Handle(), (name + std::string(" Buffer")).c_str());
74+
debugUtils.SetObjectName(memory->Handle(), (name + std::string(" Memory")).c_str());
75+
76+
CopyFromStagingBuffer(commandPool, *buffer, content);
77+
}
78+
}

0 commit comments

Comments
 (0)