From 7faa086a19647dd915c86fd734e562b5b0256076 Mon Sep 17 00:00:00 2001 From: Johann Muszynski Date: Tue, 2 Apr 2024 20:29:30 +0300 Subject: [PATCH] wip commit 2 --- src/pt/deferred_renderer.cpp | 72 +++++++++++++++++++++++++++++++++++- src/pt/deferred_renderer.hpp | 39 ++++++++++++------- src/pt/main.cpp | 38 ++++++++++++++----- 3 files changed, 124 insertions(+), 25 deletions(-) diff --git a/src/pt/deferred_renderer.cpp b/src/pt/deferred_renderer.cpp index 1b9883c..c5ad45b 100644 --- a/src/pt/deferred_renderer.cpp +++ b/src/pt/deferred_renderer.cpp @@ -8,6 +8,7 @@ #include #include +#include namespace nlrs { @@ -94,7 +95,9 @@ DeferredRenderer::DeferredRenderer( sizeof(TimestampsLayout)), mGbufferPass(gpuContext, rendererDesc), mDebugPass(), - mLightingPass() + mLightingPass(), + mGbufferPassDurationsNs(), + mLightingPassDurationsNs() { { const std::array depthFormats{ @@ -208,7 +211,7 @@ void DeferredRenderer::render(const GpuContext& gpuContext, const RenderDescript do { wgpuDeviceTick(gpuContext.device); - } while (wgpuBufferGetMapState(mTimestampBuffer.ptr()) != WGPUBufferMapState_Unmapped); + } while (wgpuBufferGetMapState(mTimestampsBuffer.ptr()) != WGPUBufferMapState_Unmapped); const WGPUCommandEncoder encoder = [&gpuContext]() { const WGPUCommandEncoderDescriptor cmdEncoderDesc{ @@ -265,6 +268,51 @@ void DeferredRenderer::render(const GpuContext& gpuContext, const RenderDescript return wgpuCommandEncoderFinish(encoder, &cmdBufferDesc); }(); wgpuQueueSubmit(gpuContext.queue, 1, &cmdBuffer); + + wgpuBufferMapAsync( + mTimestampsBuffer.ptr(), + WGPUMapMode_Read, + 0, + sizeof(TimestampsLayout), + [](const WGPUBufferMapAsyncStatus status, void* const userdata) -> void { + if (status == WGPUBufferMapAsyncStatus_Success) + { + NLRS_ASSERT(userdata != nullptr); + DeferredRenderer& renderer = *static_cast(userdata); + GpuBuffer& timestampBuffer = renderer.mTimestampsBuffer; + const void* const bufferData = wgpuBufferGetConstMappedRange( + timestampBuffer.ptr(), 0, sizeof(TimestampsLayout)); + NLRS_ASSERT(bufferData != nullptr); + + const TimestampsLayout& timestamps = + *static_cast(bufferData); + + auto& gbufferDurations = renderer.mGbufferPassDurationsNs; + const auto gbufferDuration = + timestamps.gbufferPassEnd - timestamps.gbufferPassStart; + gbufferDurations.push_back(gbufferDuration); + if (gbufferDurations.size() > 30) + { + gbufferDurations.pop_front(); + } + + auto& lightingDurations = renderer.mLightingPassDurationsNs; + const auto lightingDuration = + timestamps.lightingPassEnd - timestamps.lightingPassStart; + lightingDurations.push_back(lightingDuration); + if (lightingDurations.size() > 30) + { + lightingDurations.pop_front(); + } + + wgpuBufferUnmap(timestampBuffer.ptr()); + } + else + { + std::fprintf(stderr, "Failed to map timestamps buffer\n"); + } + }, + this); } void DeferredRenderer::renderDebug( @@ -1405,4 +1453,24 @@ void DeferredRenderer::LightingPass::render( wgpuRenderPassEncoderDraw(renderPass, 6, 1, 0, 0); wgpuRenderPassEncoderEnd(renderPass); } + +DeferredRenderer::PerfStats DeferredRenderer::getPerfStats() const +{ + NLRS_ASSERT(mGbufferPassDurationsNs.size() == mLightingPassDurationsNs.size()); + + if (mGbufferPassDurationsNs.empty()) + { + return {}; + } + + return { + 0.000001f * + static_cast(std::accumulate( + mGbufferPassDurationsNs.begin(), mGbufferPassDurationsNs.end(), 0ll)) / + mGbufferPassDurationsNs.size(), + 0.000001f * + static_cast(std::accumulate( + mLightingPassDurationsNs.begin(), mLightingPassDurationsNs.end(), 0ll)) / + mLightingPassDurationsNs.size()}; +} } // namespace nlrs diff --git a/src/pt/deferred_renderer.hpp b/src/pt/deferred_renderer.hpp index 0614d0b..63a4802 100644 --- a/src/pt/deferred_renderer.hpp +++ b/src/pt/deferred_renderer.hpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -45,6 +46,12 @@ struct RenderDescriptor class DeferredRenderer { public: + struct PerfStats + { + float averageGbufferPassDurationsMs = 0.0f; + float averageLightingPassDurationsMs = 0.0f; + }; + DeferredRenderer(const GpuContext&, const DeferredRendererDescriptor&); ~DeferredRenderer(); @@ -58,6 +65,8 @@ class DeferredRenderer void renderDebug(const GpuContext&, const glm::mat4&, const Extent2f&, WGPUTextureView); void resize(const GpuContext&, const Extent2u&); + PerfStats getPerfStats() const; + private: struct IndexBuffer { @@ -182,19 +191,21 @@ class DeferredRenderer float exposure); }; - WGPUTexture mDepthTexture; - WGPUTextureView mDepthTextureView; - WGPUTexture mAlbedoTexture; - WGPUTextureView mAlbedoTextureView; - WGPUTexture mNormalTexture; - WGPUTextureView mNormalTextureView; - GpuBindGroupLayout mGbufferBindGroupLayout; - GpuBindGroup mGbufferBindGroup; - WGPUQuerySet mQuerySet; - GpuBuffer mQueryBuffer; - GpuBuffer mTimestampsBuffer; - GbufferPass mGbufferPass; - DebugPass mDebugPass; - LightingPass mLightingPass; + WGPUTexture mDepthTexture; + WGPUTextureView mDepthTextureView; + WGPUTexture mAlbedoTexture; + WGPUTextureView mAlbedoTextureView; + WGPUTexture mNormalTexture; + WGPUTextureView mNormalTextureView; + GpuBindGroupLayout mGbufferBindGroupLayout; + GpuBindGroup mGbufferBindGroup; + WGPUQuerySet mQuerySet; + GpuBuffer mQueryBuffer; + GpuBuffer mTimestampsBuffer; + GbufferPass mGbufferPass; + DebugPass mDebugPass; + LightingPass mLightingPass; + std::deque mGbufferPassDurationsNs; + std::deque mLightingPassDurationsNs; }; } // namespace nlrs diff --git a/src/pt/main.cpp b/src/pt/main.cpp index 835ed3c..ad7c0be 100644 --- a/src/pt/main.cpp +++ b/src/pt/main.cpp @@ -264,7 +264,8 @@ try auto onNewFrame = [&gui]() -> void { gui.beginFrame(); }; - auto onUpdate = [&appState, &renderer](GLFWwindow* windowPtr, float deltaTime) -> void { + auto onUpdate = + [&appState, &renderer, &deferredRenderer](GLFWwindow* windowPtr, float deltaTime) -> void { { // Skip input if ImGui captured input if (!ImGui::GetIO().WantCaptureMouse) @@ -320,14 +321,33 @@ try ImGui::RadioButton("debug", &appState.ui.rendererType, RendererType_Debug); ImGui::Separator(); - ImGui::Text("Renderer stats"); + ImGui::Text("Perf stats"); { - const float renderAverageMs = renderer.averageRenderpassDurationMs(); - const float progressPercentage = renderer.renderProgressPercentage(); - ImGui::Text( - "render pass: %.2f ms (%.1f FPS)", renderAverageMs, 1000.0f / renderAverageMs); - ImGui::Text("render progress: %.2f %%", progressPercentage); + switch (appState.ui.rendererType) + { + case RendererType_PathTracer: + { + const float renderAverageMs = renderer.averageRenderpassDurationMs(); + const float progressPercentage = renderer.renderProgressPercentage(); + ImGui::Text( + "render pass: %.2f ms (%.1f FPS)", + renderAverageMs, + 1000.0f / renderAverageMs); + ImGui::Text("render progress: %.2f %%", progressPercentage); + break; + } + case RendererType_Deferred: + { + const auto perfStats = deferredRenderer.getPerfStats(); + ImGui::Text("gbuffer pass: %.2f ms", perfStats.averageGbufferPassDurationsMs); + ImGui::Text("lighting pass: %.2f ms", perfStats.averageLightingPassDurationsMs); + break; + } + default: + ImGui::Text("no perf stats available"); + } } + ImGui::Separator(); ImGui::Text("Parameters"); @@ -455,8 +475,8 @@ try auto onResize = [&gpuContext, &deferredRenderer, &textureBlitter]( const nlrs::FramebufferSize newSize) -> void { - // TODO: this function is not really needed since I get the current framebuffer size on each - // render anyway. + // TODO: this function is not really needed since I get the current framebuffer size on + // each render anyway. const auto sz = nlrs::Extent2u(newSize); deferredRenderer.resize(gpuContext, sz); textureBlitter.resize(gpuContext, sz);