diff --git a/CMakeLists.txt b/CMakeLists.txt index f697c0c..35ea9d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,6 +128,7 @@ set(TESTS_SOURCE_FILES bvh.cpp gltf.cpp intersection.cpp + math.cpp pt_format.cpp stream.cpp vector_set.cpp) diff --git a/src/common/math.hpp b/src/common/math.hpp new file mode 100644 index 0000000..531de5e --- /dev/null +++ b/src/common/math.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace nlrs +{ +inline float fract(const float x) +{ + if (x >= 0.0f) + { + return x - std::floor(x); + } + else + { + return x - std::ceil(x); + } +} +} // namespace nlrs diff --git a/src/pt/deferred_renderer.cpp b/src/pt/deferred_renderer.cpp index 35a4849..45efbc7 100644 --- a/src/pt/deferred_renderer.cpp +++ b/src/pt/deferred_renderer.cpp @@ -107,7 +107,8 @@ DeferredRenderer::DeferredRenderer( mLightingPass(), mResolvePass(), mGbufferPassDurationsNs(), - mLightingPassDurationsNs() + mLightingPassDurationsNs(), + mFrameCount(0) { { const std::array depthFormats{ @@ -240,6 +241,7 @@ DeferredRenderer::DeferredRenderer(DeferredRenderer&& other) mResolvePass = std::move(other.mResolvePass); mGbufferPassDurationsNs = std::move(other.mGbufferPassDurationsNs); mLightingPassDurationsNs = std::move(other.mLightingPassDurationsNs); + mFrameCount = other.mFrameCount; } } @@ -270,6 +272,7 @@ DeferredRenderer& DeferredRenderer::operator=(DeferredRenderer&& other) mResolvePass = std::move(other.mResolvePass); mGbufferPassDurationsNs = std::move(other.mGbufferPassDurationsNs); mLightingPassDurationsNs = std::move(other.mLightingPassDurationsNs); + mFrameCount = other.mFrameCount; } return *this; } @@ -293,6 +296,10 @@ void DeferredRenderer::render( return wgpuDeviceCreateCommandEncoder(gpuContext.device, &cmdEncoderDesc); }(); + const std::uint32_t frameCount = mFrameCount++; + + // GBuffer pass + wgpuCommandEncoderWriteTimestamp( encoder, mQuerySet, @@ -303,12 +310,15 @@ void DeferredRenderer::render( encoder, mDepthTextureView, mAlbedoTextureView, - mNormalTextureView); + mNormalTextureView, + frameCount); wgpuCommandEncoderWriteTimestamp( encoder, mQuerySet, offsetof(TimestampsLayout, gbufferPassEnd) / TimestampsLayout::MEMBER_SIZE); + // Lighting pass + wgpuCommandEncoderWriteTimestamp( encoder, mQuerySet, @@ -323,13 +333,16 @@ void DeferredRenderer::render( inverseViewProjectionMat, renderDesc.cameraPosition, framebufferSize, - renderDesc.sky); + renderDesc.sky, + frameCount); } wgpuCommandEncoderWriteTimestamp( encoder, mQuerySet, offsetof(TimestampsLayout, lightingPassEnd) / TimestampsLayout::MEMBER_SIZE); + // Resolve pass + wgpuCommandEncoderWriteTimestamp( encoder, mQuerySet, @@ -348,6 +361,8 @@ void DeferredRenderer::render( mQuerySet, offsetof(TimestampsLayout, resolvePassEnd) / TimestampsLayout::MEMBER_SIZE); + // Resolve timestamp queries + wgpuCommandEncoderResolveQuerySet( encoder, mQuerySet, 0, TimestampsLayout::QUERY_COUNT, mQueryBuffer.ptr(), 0); wgpuCommandEncoderCopyBufferToBuffer( @@ -440,7 +455,8 @@ void DeferredRenderer::renderDebug( encoder, mDepthTextureView, mAlbedoTextureView, - mNormalTextureView); + mNormalTextureView, + mFrameCount++); mDebugPass.render(gpuContext, encoder, textureView, framebufferSize, gui); @@ -676,7 +692,7 @@ DeferredRenderer::GbufferPass::GbufferPass( gpuContext.device, "Uniform buffer", {GpuBufferUsage::Uniform, GpuBufferUsage::CopyDst}, - sizeof(glm::mat4)), + sizeof(Uniforms)), mUniformBindGroup(), mSamplerBindGroup(), mPipeline(nullptr) @@ -684,7 +700,7 @@ DeferredRenderer::GbufferPass::GbufferPass( const GpuBindGroupLayout uniformBindGroupLayout{ gpuContext.device, "Uniform bind group layout", - mUniformBuffer.bindGroupLayoutEntry(0, WGPUShaderStage_Vertex, sizeof(glm::mat4))}; + mUniformBuffer.bindGroupLayoutEntry(0, WGPUShaderStage_Vertex, sizeof(Uniforms))}; mUniformBindGroup = GpuBindGroup{ gpuContext.device, @@ -988,14 +1004,11 @@ void DeferredRenderer::GbufferPass::render( const WGPUCommandEncoder cmdEncoder, const WGPUTextureView depthTextureView, const WGPUTextureView albedoTextureView, - const WGPUTextureView normalTextureView) + const WGPUTextureView normalTextureView, + const std::uint32_t /*frameCount*/) { - wgpuQueueWriteBuffer( - gpuContext.queue, - mUniformBuffer.ptr(), - 0, - &viewReverseZProjectionMatrix[0][0], - sizeof(glm::mat4)); + const Uniforms uniforms{viewReverseZProjectionMatrix}; + wgpuQueueWriteBuffer(gpuContext.queue, mUniformBuffer.ptr(), 0, &uniforms, sizeof(Uniforms)); const WGPURenderPassEncoder renderPassEncoder = [cmdEncoder, depthTextureView, @@ -1644,7 +1657,6 @@ DeferredRenderer::LightingPass::LightingPass(LightingPass&& other) noexcept mSampleBindGroup = std::move(other.mSampleBindGroup); mPipeline = other.mPipeline; other.mPipeline = nullptr; - mFrameCount = other.mFrameCount; } } @@ -1670,7 +1682,6 @@ DeferredRenderer::LightingPass& DeferredRenderer::LightingPass::operator=( computePipelineSafeRelease(mPipeline); mPipeline = other.mPipeline; other.mPipeline = nullptr; - mFrameCount = other.mFrameCount; } return *this; } @@ -1681,7 +1692,8 @@ void DeferredRenderer::LightingPass::render( const glm::mat4& inverseViewReverseZProjectionMatrix, const glm::vec3& cameraPosition, const Extent2f& fbsize, - const Sky& sky) + const Sky& sky, + const std::uint32_t frameCount) { if (mCurrentSky != sky) { @@ -1696,7 +1708,7 @@ void DeferredRenderer::LightingPass::render( inverseViewReverseZProjectionMatrix, glm::vec4(cameraPosition, 1.f), glm::vec2(fbsize.x, fbsize.y), - mFrameCount++, + frameCount, 0}; wgpuQueueWriteBuffer( gpuContext.queue, mUniformBuffer.ptr(), 0, &uniforms, sizeof(Uniforms)); diff --git a/src/pt/deferred_renderer.hpp b/src/pt/deferred_renderer.hpp index 94cb87b..8a8be43 100644 --- a/src/pt/deferred_renderer.hpp +++ b/src/pt/deferred_renderer.hpp @@ -106,6 +106,11 @@ class DeferredRenderer GpuBindGroup mSamplerBindGroup{}; WGPURenderPipeline mPipeline = nullptr; + struct Uniforms + { + glm::mat4 viewProjectionMat; + }; + public: GbufferPass() = default; GbufferPass(const GpuContext&, const DeferredRendererDescriptor&); @@ -123,7 +128,8 @@ class DeferredRenderer WGPUCommandEncoder cmdEncoder, WGPUTextureView depthTextureView, WGPUTextureView albedoTextureView, - WGPUTextureView normalTextureView); + WGPUTextureView normalTextureView, + std::uint32_t frameCount); }; struct DebugPass @@ -184,8 +190,6 @@ class DeferredRenderer GpuBindGroup mSampleBindGroup = GpuBindGroup{}; WGPUComputePipeline mPipeline = nullptr; - std::uint32_t mFrameCount = 0; - struct Uniforms { glm::mat4 inverseViewReverseZProjectionMat; @@ -221,7 +225,8 @@ class DeferredRenderer const glm::mat4& inverseViewProjection, const glm::vec3& cameraPosition, const Extent2f& framebufferSize, - const Sky& sky); + const Sky& sky, + std::uint32_t frameCount); void resize( const GpuContext&, WGPUTextureView albedoTextureView, @@ -286,5 +291,6 @@ class DeferredRenderer std::deque mGbufferPassDurationsNs; std::deque mLightingPassDurationsNs; std::deque mResolvePassDurationsNs; + std::uint32_t mFrameCount; }; } // namespace nlrs diff --git a/src/pt/deferred_renderer_gbuffer_pass.wgsl b/src/pt/deferred_renderer_gbuffer_pass.wgsl index 9f33e37..20c50d4 100644 --- a/src/pt/deferred_renderer_gbuffer_pass.wgsl +++ b/src/pt/deferred_renderer_gbuffer_pass.wgsl @@ -1,4 +1,4 @@ -@group(0) @binding(0) var viewProjectionMat: mat4x4f; +@group(0) @binding(0) var viewReverseZProjectionMat: mat4x4f; struct VertexInput { @location(0) position: vec4f, @@ -15,7 +15,7 @@ struct VertexOutput { @vertex fn vsMain(in: VertexInput) -> VertexOutput { var out: VertexOutput; - out.position = viewProjectionMat * in.position; + out.position = viewReverseZProjectionMat * in.position; out.normal = in.normal; out.texCoord = in.texCoord; return out; diff --git a/src/pt/shader_source.hpp b/src/pt/shader_source.hpp index 07f7222..b10e698 100644 --- a/src/pt/shader_source.hpp +++ b/src/pt/shader_source.hpp @@ -623,7 +623,7 @@ fn animatedBlueNoise(coord: vec2u, frameIdx: u32, totalSampleCount: u32) -> vec2 } )"; -const char* const DEFERRED_RENDERER_GBUFFER_PASS_SOURCE = R"(@group(0) @binding(0) var viewProjectionMat: mat4x4f; +const char* const DEFERRED_RENDERER_GBUFFER_PASS_SOURCE = R"(@group(0) @binding(0) var viewReverseZProjectionMat: mat4x4f; struct VertexInput { @location(0) position: vec4f, @@ -640,7 +640,7 @@ struct VertexOutput { @vertex fn vsMain(in: VertexInput) -> VertexOutput { var out: VertexOutput; - out.position = viewProjectionMat * in.position; + out.position = viewReverseZProjectionMat * in.position; out.normal = in.normal; out.texCoord = in.texCoord; return out; diff --git a/src/tests/math.cpp b/src/tests/math.cpp new file mode 100644 index 0000000..ee8c9e4 --- /dev/null +++ b/src/tests/math.cpp @@ -0,0 +1,14 @@ +#include + +#include + +TEST_CASE("Fract", "[math]") +{ + REQUIRE(nlrs::fract(0.0f) == 0.0f); + REQUIRE(nlrs::fract(1.0f) == 0.0f); + REQUIRE(nlrs::fract(1.5f) == 0.5f); + REQUIRE(nlrs::fract(-1.5f) == -0.5f); + REQUIRE(nlrs::fract(-1.0f) == -0.0f); + REQUIRE(nlrs::fract(-0.5f) == -0.5f); + REQUIRE(nlrs::fract(-0.0f) == -0.0f); +}