diff --git a/README.md b/README.md index 74bc572d..1877b305 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This personal project follows my own attempts at CPU ray tracing following Peter ## Gallery - + ## Performance @@ -78,6 +78,7 @@ If in doubt, please check the GitHub Actions [continuous integration configurati * [D3D12 Raytracing Samples](https://github.com/Microsoft/DirectX-Graphics-Samples/tree/master/Samples/Desktop/D3D12Raytracing) * [George Ouzounoudis's vk_exp](https://github.com/georgeouzou/vk_exp) * [NVIDIA Vulkan Forums](https://devtalk.nvidia.com/default/board/166/vulkan) +* [Profiling DXR shaders with Timer Instrumentation](https://www.reddit.com/r/vulkan/comments/hhyeyj/profiling_dxr_shaders_with_timer_instrumentation/) ### VK_KHR_ray_tracing Port diff --git a/assets/shaders/Heatmap.glsl b/assets/shaders/Heatmap.glsl new file mode 100644 index 00000000..ae90f8da --- /dev/null +++ b/assets/shaders/Heatmap.glsl @@ -0,0 +1,33 @@ + +// Profiling DXR Shaders with Timer Instrumentation +// https://developer.nvidia.com/blog/profiling-dxr-shaders-with-timer-instrumentation/ +vec3 heatmap(float t) +{ + const vec3 c[10] = { + vec3(0.0f / 255.0f, 2.0f / 255.0f, 91.0f / 255.0f), + vec3(0.0f / 255.0f, 108.0f / 255.0f, 251.0f / 255.0f), + vec3(0.0f / 255.0f, 221.0f / 255.0f, 221.0f / 255.0f), + vec3(51.0f / 255.0f, 221.0f / 255.0f, 0.0f / 255.0f), + vec3(255.0f / 255.0f, 252.0f / 255.0f, 0.0f / 255.0f), + vec3(255.0f / 255.0f, 180.0f / 255.0f, 0.0f / 255.0f), + vec3(255.0f / 255.0f, 104.0f / 255.0f, 0.0f / 255.0f), + vec3(226.0f / 255.0f, 22.0f / 255.0f, 0.0f / 255.0f), + vec3(191.0f / 255.0f, 0.0f / 255.0f, 83.0f / 255.0f), + vec3(145.0f / 255.0f, 0.0f / 255.0f, 65.0f / 255.0f) + }; + + const float s = t * 10.0f; + + const int cur = int(s) <= 9 ? int(s) : 9; + const int prv = cur >= 1 ? cur - 1 : 0; + const int nxt = cur < 9 ? cur + 1 : 9; + + const float blur = 0.8f; + + const float wc = smoothstep(float(cur) - blur, float(cur) + blur, s) * (1.0f - smoothstep(float(cur + 1) - blur, float(cur + 1) + blur, s)); + const float wp = 1.0f - smoothstep(float(cur) - blur, float(cur) + blur, s); + const float wn = smoothstep(float(cur + 1) - blur, float(cur + 1) + blur, s); + + const vec3 r = wc * c[cur] + wp * c[prv] + wn * c[nxt]; + return vec3(clamp(r.x, 0.0f, 1.0f), clamp(r.y, 0.0f, 1.0f), clamp(r.z, 0.0f, 1.0f)); +} \ No newline at end of file diff --git a/assets/shaders/RayTracing.rgen b/assets/shaders/RayTracing.rgen index ee24b51c..4036f6fe 100644 --- a/assets/shaders/RayTracing.rgen +++ b/assets/shaders/RayTracing.rgen @@ -1,6 +1,10 @@ #version 460 +#extension GL_ARB_gpu_shader_int64 : require +#extension GL_ARB_shader_clock : require #extension GL_GOOGLE_include_directive : require #extension GL_EXT_ray_tracing : require + +#include "Heatmap.glsl" #include "Random.glsl" #include "RayPayload.glsl" #include "UniformBufferObject.glsl" @@ -12,8 +16,11 @@ layout(binding = 3) readonly uniform UniformBufferObjectStruct { UniformBufferOb layout(location = 0) rayPayloadEXT RayPayload Ray; + void main() { + const uint64_t clock = Camera.ShowHeatmap ? clockARB() : 0; + // Initialise separate random seeds for the pixel and the rays. // - pixel: we want the same random seed for each pixel to get a homogeneous anti-aliasing. // - ray: we want a noisy random seed, different for each pixel. @@ -79,10 +86,16 @@ void main() pixelColor = accumulatedColor / Camera.TotalNumberOfSamples; - if (Camera.GammaCorrection) + // Apply raytracing-in-one-weekend gamma correction. + pixelColor = sqrt(pixelColor); + + if (Camera.ShowHeatmap) { - // Apply raytracing-in-one-weekend gamma correction. - pixelColor = sqrt(pixelColor); + const uint64_t deltaTime = clockARB() - clock; + const float heatmapScale = 1000000.0f * Camera.HeatmapScale * Camera.HeatmapScale; + const float deltaTimeScaled = clamp(float(deltaTime) / heatmapScale, 0.0f, 1.0f); + + pixelColor = heatmap(deltaTimeScaled); } imageStore(AccumulationImage, ivec2(gl_LaunchIDEXT.xy), vec4(accumulatedColor, 0)); diff --git a/assets/shaders/UniformBufferObject.glsl b/assets/shaders/UniformBufferObject.glsl index 6fe97b85..0ecefb55 100644 --- a/assets/shaders/UniformBufferObject.glsl +++ b/assets/shaders/UniformBufferObject.glsl @@ -7,10 +7,11 @@ struct UniformBufferObject mat4 ProjectionInverse; float Aperture; float FocusDistance; + float HeatmapScale; uint TotalNumberOfSamples; uint NumberOfSamples; uint NumberOfBounces; uint RandomSeed; - bool GammaCorrection; bool HasSky; + bool ShowHeatmap; }; diff --git a/gallery/Heatmap.png b/gallery/Heatmap.png new file mode 100644 index 00000000..86797e43 Binary files /dev/null and b/gallery/Heatmap.png differ diff --git a/gallery/LucyHeatmap.png b/gallery/LucyHeatmap.png new file mode 100644 index 00000000..6b7c9515 Binary files /dev/null and b/gallery/LucyHeatmap.png differ diff --git a/src/Assets/UniformBuffer.hpp b/src/Assets/UniformBuffer.hpp index 5dfadf0b..abf42db0 100644 --- a/src/Assets/UniformBuffer.hpp +++ b/src/Assets/UniformBuffer.hpp @@ -22,12 +22,13 @@ namespace Assets glm::mat4 ProjectionInverse; float Aperture; float FocusDistance; + float HeatmapScale; uint32_t TotalNumberOfSamples; uint32_t NumberOfSamples; uint32_t NumberOfBounces; uint32_t RandomSeed; - uint32_t GammaCorrection; // bool uint32_t HasSky; // bool + uint32_t ShowHeatmap; // bool }; class UniformBuffer diff --git a/src/ModelViewController.cpp b/src/ModelViewController.cpp index 50acdc95..8b5b3e1a 100644 --- a/src/ModelViewController.cpp +++ b/src/ModelViewController.cpp @@ -13,6 +13,9 @@ void ModelViewController::Reset(const glm::mat4& modelView) modelRotX_ = 0; modelRotY_ = 0; + mouseLeftPressed_ = false; + mouseRightPressed_ = false; + UpdateVectors(); } diff --git a/src/RayTracer.cpp b/src/RayTracer.cpp index 9f60d637..59f771f5 100644 --- a/src/RayTracer.cpp +++ b/src/RayTracer.cpp @@ -51,8 +51,9 @@ Assets::UniformBufferObject RayTracer::GetUniformBufferObject(const VkExtent2D e ubo.NumberOfSamples = numberOfSamples_; ubo.NumberOfBounces = userSettings_.NumberOfBounces; ubo.RandomSeed = 1; - ubo.GammaCorrection = userSettings_.GammaCorrection; ubo.HasSky = init.HasSky; + ubo.ShowHeatmap = userSettings_.ShowHeatmap; + ubo.HeatmapScale = userSettings_.HeatmapScale; return ubo; } @@ -63,9 +64,17 @@ void RayTracer::SetPhysicalDevice( VkPhysicalDeviceFeatures& deviceFeatures, void* nextDeviceFeatures) { + // Required extensions. + requiredExtensions.insert(requiredExtensions.end(), + { + // VK_KHR_SHADER_CLOCK is required for heatmap + VK_KHR_SHADER_CLOCK_EXTENSION_NAME + }); + // Opt-in into mandatory device features. deviceFeatures.fillModeNonSolid = true; deviceFeatures.samplerAnisotropy = true; + deviceFeatures.shaderInt64 = true; Application::SetPhysicalDevice(physicalDevice, requiredExtensions, deviceFeatures, nextDeviceFeatures); } @@ -187,6 +196,7 @@ void RayTracer::OnKey(int key, int scancode, int action, int mods) case GLFW_KEY_F1: userSettings_.ShowSettings = !userSettings_.ShowSettings; break; case GLFW_KEY_F2: userSettings_.ShowOverlay = !userSettings_.ShowOverlay; break; case GLFW_KEY_R: userSettings_.IsRayTraced = !userSettings_.IsRayTraced; break; + case GLFW_KEY_H: userSettings_.ShowHeatmap = !userSettings_.ShowHeatmap; break; case GLFW_KEY_P: isWireFrame_ = !isWireFrame_; break; default: break; } @@ -261,7 +271,6 @@ void RayTracer::LoadScene(const uint32_t sceneIndex) userSettings_.FieldOfView = cameraInitialSate_.FieldOfView; userSettings_.Aperture = cameraInitialSate_.Aperture; userSettings_.FocusDistance = cameraInitialSate_.FocusDistance; - userSettings_.GammaCorrection = cameraInitialSate_.GammaCorrection; modelViewController_.Reset(cameraInitialSate_.ModelView); diff --git a/src/UserInterface.cpp b/src/UserInterface.cpp index 07742b71..1c7d4b33 100644 --- a/src/UserInterface.cpp +++ b/src/UserInterface.cpp @@ -181,21 +181,15 @@ void UserInterface::DrawSettings() ImGui::Text("Help"); ImGui::Separator(); - ImGui::BulletText("Press F1 to toggle Settings."); - ImGui::BulletText("Press F2 to toggle Statistics."); - ImGui::BulletText("Press R to toggle ray tracing."); - ImGui::NewLine(); - - ImGui::Text("Controls"); - ImGui::Separator(); + ImGui::BulletText("F1: toggle Settings."); + ImGui::BulletText("F2: toggle Statistics."); ImGui::BulletText( - "Press %c%c%c%c/SHIFT/CTRL to move camera.", + "%c%c%c%c/SHIFT/CTRL: move camera.", std::toupper(window.GetKeyName(GLFW_KEY_W, 0)[0]), std::toupper(window.GetKeyName(GLFW_KEY_A, 0)[0]), std::toupper(window.GetKeyName(GLFW_KEY_S, 0)[0]), std::toupper(window.GetKeyName(GLFW_KEY_D, 0)[0])); - ImGui::BulletText("Click left mouse to rotate camera."); - ImGui::BulletText("Click right mouse to rotate scene."); + ImGui::BulletText("L/R Mouse: rotate camera/scene."); ImGui::NewLine(); ImGui::Text("Scene"); @@ -203,7 +197,6 @@ void UserInterface::DrawSettings() ImGui::PushItemWidth(-1); ImGui::Combo("", &Settings().SceneIndex, scenes.data(), static_cast(scenes.size())); ImGui::PopItemWidth(); - ImGui::Checkbox("Show statistics overlay", &Settings().ShowOverlay); ImGui::NewLine(); ImGui::Text("Ray Tracing"); @@ -221,7 +214,12 @@ void UserInterface::DrawSettings() ImGui::SliderFloat("FoV", &Settings().FieldOfView, UserSettings::FieldOfViewMinValue, UserSettings::FieldOfViewMaxValue, "%.0f"); ImGui::SliderFloat("Aperture", &Settings().Aperture, 0.0f, 1.0f, "%.2f"); ImGui::SliderFloat("Focus", &Settings().FocusDistance, 0.1f, 20.0f, "%.1f"); - ImGui::Checkbox("Apply gamma correction", &Settings().GammaCorrection); + ImGui::NewLine(); + + ImGui::Text("Profiler"); + ImGui::Separator(); + ImGui::Checkbox("Show heatmap", &Settings().ShowHeatmap); + ImGui::SliderFloat("Scaling", &Settings().HeatmapScale, 0.01f, 10.0f, "%.2f", 2); ImGui::NewLine(); } ImGui::End(); diff --git a/src/UserSettings.hpp b/src/UserSettings.hpp index dd2fac0f..3339a9b0 100644 --- a/src/UserSettings.hpp +++ b/src/UserSettings.hpp @@ -23,7 +23,10 @@ struct UserSettings final float FieldOfView; float Aperture; float FocusDistance; - bool GammaCorrection; + + // Profiler + bool ShowHeatmap; + float HeatmapScale; // UI bool ShowSettings; diff --git a/src/main.cpp b/src/main.cpp index fc3d5498..de811b25 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -108,6 +108,9 @@ namespace userSettings.ShowSettings = !options.Benchmark; userSettings.ShowOverlay = true; + userSettings.ShowHeatmap = false; + userSettings.HeatmapScale = 1.5f; + return userSettings; }