From 95232aedf4f9bde3c5648e3c9ae806858682db7b Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 16 Nov 2021 00:57:06 +0100 Subject: [PATCH] Add progress dots for CPU tracer and streamline how they look --- src/lightmap/cpuraytracer.cpp | 28 +++++++- src/lightmap/gpuraytracer.cpp | 126 +++++++++++++++++++++++----------- src/lightmap/gpuraytracer.h | 3 +- 3 files changed, 115 insertions(+), 42 deletions(-) diff --git a/src/lightmap/cpuraytracer.cpp b/src/lightmap/cpuraytracer.cpp index 02289f1..93b243e 100644 --- a/src/lightmap/cpuraytracer.cpp +++ b/src/lightmap/cpuraytracer.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include extern bool VKDebug; extern int NumThreads; @@ -491,19 +493,43 @@ void CPURaytracer::RunJob(int count, std::function callback) numThreads = std::min(numThreads, count); + std::condition_variable condvar; + std::mutex m; + int threadsleft = 0; + + { + std::unique_lock lock(m); + threadsleft = numThreads; + } + std::vector threads; for (int threadIndex = 0; threadIndex < numThreads; threadIndex++) { - threads.push_back(std::thread([=]() { + threads.push_back(std::thread([&]() { for (int i = threadIndex; i < count; i += numThreads) { callback(i); } + std::unique_lock lock(m); + threadsleft--; + lock.unlock(); + condvar.notify_all(); + })); } + { + std::unique_lock lock(m); + while (threadsleft != 0) + { + condvar.wait_for(lock, std::chrono::milliseconds(500), [&]() { return threadsleft == 0; }); + printf("."); + } + printf("\n"); + } + for (int i = 0; i < numThreads; i++) threads[i].join(); } diff --git a/src/lightmap/gpuraytracer.cpp b/src/lightmap/gpuraytracer.cpp index 6869347..277228a 100644 --- a/src/lightmap/gpuraytracer.cpp +++ b/src/lightmap/gpuraytracer.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "glsl_rgen_bounce.h" #include "glsl_rgen_light.h" #include "glsl_rchit_bounce.h" @@ -86,58 +88,60 @@ void GPURaytracer::Raytrace(LevelMesh* level) printf("Ray tracing with %d bounce(s)\n", mesh->map->LightBounce); - size_t maxTasks = (size_t)rayTraceImageSize * rayTraceImageSize; - for (size_t startTask = 0; startTask < tasks.size(); startTask += maxTasks) - { - size_t numTasks = std::min(tasks.size() - startTask, maxTasks); - UploadTasks(tasks.data() + startTask, numTasks); - - BeginTracing(); - - Uniforms uniforms = {}; - uniforms.SampleDistance = (float)mesh->samples; - uniforms.LightCount = mesh->map->ThingLights.Size(); - uniforms.SunDir = mesh->map->GetSunDirection(); - uniforms.SunColor = mesh->map->GetSunColor(); - uniforms.SunIntensity = 1.0f; - - uniforms.PassType = 0; - uniforms.SampleIndex = 0; - uniforms.SampleCount = bounceSampleCount; - RunTrace(uniforms, rgenBounceRegion); - - uniforms.SampleCount = coverageSampleCount; - RunTrace(uniforms, rgenLightRegion); - - for (uint32_t i = 0; i < (uint32_t)bounceSampleCount; i++) + RunWithProgressDots([&]() { + size_t maxTasks = (size_t)rayTraceImageSize * rayTraceImageSize; + for (size_t startTask = 0; startTask < tasks.size(); startTask += maxTasks) { - uniforms.PassType = 1; - uniforms.SampleIndex = i; + size_t numTasks = std::min(tasks.size() - startTask, maxTasks); + UploadTasks(tasks.data() + startTask, numTasks); + + BeginTracing(); + + Uniforms uniforms = {}; + uniforms.SampleDistance = (float)mesh->samples; + uniforms.LightCount = mesh->map->ThingLights.Size(); + uniforms.SunDir = mesh->map->GetSunDirection(); + uniforms.SunColor = mesh->map->GetSunColor(); + uniforms.SunIntensity = 1.0f; + + uniforms.PassType = 0; + uniforms.SampleIndex = 0; uniforms.SampleCount = bounceSampleCount; - uniforms.HemisphereVec = HemisphereVectors[uniforms.SampleIndex]; RunTrace(uniforms, rgenBounceRegion); - for (int bounce = 0; bounce < mesh->map->LightBounce; bounce++) - { - uniforms.SampleCount = coverageSampleCount; - RunTrace(uniforms, rgenLightRegion); + uniforms.SampleCount = coverageSampleCount; + RunTrace(uniforms, rgenLightRegion); - uniforms.PassType = 2; - uniforms.SampleIndex = (i + bounce) % uniforms.SampleCount; + for (uint32_t i = 0; i < (uint32_t)bounceSampleCount; i++) + { + uniforms.PassType = 1; + uniforms.SampleIndex = i; uniforms.SampleCount = bounceSampleCount; uniforms.HemisphereVec = HemisphereVectors[uniforms.SampleIndex]; RunTrace(uniforms, rgenBounceRegion); - } - } - EndTracing(); - DownloadTasks(tasks.data() + startTask, numTasks); - } + for (int bounce = 0; bounce < mesh->map->LightBounce; bounce++) + { + uniforms.SampleCount = coverageSampleCount; + RunTrace(uniforms, rgenLightRegion); + + uniforms.PassType = 2; + uniforms.SampleIndex = (i + bounce) % uniforms.SampleCount; + uniforms.SampleCount = bounceSampleCount; + uniforms.HemisphereVec = HemisphereVectors[uniforms.SampleIndex]; + RunTrace(uniforms, rgenBounceRegion); + } + } + + EndTracing(); + DownloadTasks(tasks.data() + startTask, numTasks); + } + }); if (device->renderdoc) device->renderdoc->EndFrameCapture(0, 0); - printf("\nRaytrace complete\n"); + printf("Raytrace complete\n"); } void GPURaytracer::CreateVulkanObjects() @@ -264,7 +268,6 @@ void GPURaytracer::EndTracing() cmdbuffer->end(); SubmitCommands(); - printf("."); cmdbuffer = cmdpool->createBuffer(); cmdbuffer->begin(); @@ -929,3 +932,46 @@ float GPURaytracer::RadicalInverse_VdC(uint32_t bits) bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); return float(bits) * 2.3283064365386963e-10f; // / 0x100000000 } + +void GPURaytracer::RunWithProgressDots(std::function callback) +{ + std::exception_ptr e; + std::condition_variable condvar; + std::mutex m; + bool stop; + + { + std::unique_lock lock(m); + stop = false; + } + + std::thread t([&]() { + try + { + callback(); + } + catch (...) + { + e = std::current_exception(); + } + std::unique_lock lock(m); + stop = true; + lock.unlock(); + condvar.notify_all(); + }); + + { + std::unique_lock lock(m); + while (!stop) + { + condvar.wait_for(lock, std::chrono::milliseconds(500), [&]() { return stop; }); + printf("."); + } + printf("\n"); + } + + t.join(); + + if (e) + std::rethrow_exception(e); +} diff --git a/src/lightmap/gpuraytracer.h b/src/lightmap/gpuraytracer.h index c680837..7d58c38 100644 --- a/src/lightmap/gpuraytracer.h +++ b/src/lightmap/gpuraytracer.h @@ -81,6 +81,8 @@ private: static float RadicalInverse_VdC(uint32_t bits); static vec2 Hammersley(uint32_t i, uint32_t N); + static void RunWithProgressDots(std::function callback); + const int coverageSampleCount = 256; const int bounceSampleCount = 2048; int rayTraceImageSize = 1024; @@ -139,5 +141,4 @@ private: std::unique_ptr cmdpool; std::unique_ptr cmdbuffer; - };