Skip to content
Open

RWMC #218

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 49 additions & 30 deletions 31_HLSLPathTracer/app_resources/hlsl/pathtracer.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <nbl/builtin/hlsl/colorspace/encodeCIEXYZ.hlsl>
#include <nbl/builtin/hlsl/math/functions.hlsl>
#include <nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl>
#include <nbl/builtin/hlsl/vector_utils/vector_traits.hlsl>
#include <nbl/builtin/hlsl/concepts.hlsl>

#include "rand_gen.hlsl"
#include "ray_gen.hlsl"
Expand Down Expand Up @@ -40,10 +42,33 @@ struct PathTracerCreationParams
BxDFCreation dielectricParams;
};

template<class RandGen, class RayGen, class Intersector, class MaterialSystem, /* class PathGuider, */ class NextEventEstimator>
template<typename OutputTypeVec NBL_PRIMARY_REQUIRES(concepts::FloatingPointVector<OutputTypeVec>)
struct DefaultAccumulator
{
using output_storage_type = OutputTypeVec;
using this_t = DefaultAccumulator<OutputTypeVec>;
output_storage_type accumulation;

static this_t create()
{
this_t retval;
retval.accumulation = promote<OutputTypeVec, float32_t>(0.0f);

return retval;
}

void addSample(uint32_t sampleCount, float32_t3 sample)
{
using ScalarType = typename vector_traits<OutputTypeVec>::scalar_type;
ScalarType rcpSampleSize = 1.0 / (sampleCount);
accumulation += (sample - accumulation) * rcpSampleSize;
}
};

template<class RandGen, class RayGen, class Intersector, class MaterialSystem, /* class PathGuider, */ class NextEventEstimator, class Accumulator>
struct Unidirectional
{
using this_t = Unidirectional<RandGen, RayGen, Intersector, MaterialSystem, NextEventEstimator>;
using this_t = Unidirectional<RandGen, RayGen, Intersector, MaterialSystem, NextEventEstimator, Accumulator>;
using randgen_type = RandGen;
using raygen_type = RayGen;
using intersector_type = Intersector;
Expand All @@ -53,6 +78,7 @@ struct Unidirectional
using scalar_type = typename MaterialSystem::scalar_type;
using vector3_type = vector<scalar_type, 3>;
using measure_type = typename MaterialSystem::measure_type;
using output_storage_type = typename Accumulator::output_storage_type; // ?
using sample_type = typename NextEventEstimator::sample_type;
using ray_dir_info_type = typename sample_type::ray_dir_info_type;
using ray_type = typename RayGen::ray_type;
Expand Down Expand Up @@ -266,40 +292,33 @@ struct Unidirectional
}

// Li
measure_type getMeasure(uint32_t numSamples, uint32_t depth, NBL_CONST_REF_ARG(scene_type) scene)
void sampleMeasure(uint32_t sampleIndex, uint32_t maxDepth, NBL_CONST_REF_ARG(scene_type) scene, NBL_REF_ARG(Accumulator) accumulator)
{
measure_type Li = (measure_type)0.0;
scalar_type meanLumaSq = 0.0;
for (uint32_t i = 0; i < numSamples; i++)
//scalar_type meanLumaSq = 0.0;
vector3_type uvw = rand3d(0u, sampleIndex, randGen.rng()); // TODO: take from scramblebuf?
ray_type ray = rayGen.generate(uvw);

// bounces
bool hit = true;
bool rayAlive = true;
for (int d = 1; (d <= maxDepth) && hit && rayAlive; d += 2)
{
vector3_type uvw = rand3d(0u, i, randGen.rng()); // TODO: take from scramblebuf?
ray_type ray = rayGen.generate(uvw);

// bounces
bool hit = true;
bool rayAlive = true;
for (int d = 1; (d <= depth) && hit && rayAlive; d += 2)
{
ray.intersectionT = numeric_limits<scalar_type>::max;
ray.objectID = intersector_type::traceRay(ray, scene);
ray.intersectionT = numeric_limits<scalar_type>::max;
ray.objectID = intersector_type::traceRay(ray, scene);

hit = ray.objectID.id != -1;
if (hit)
rayAlive = closestHitProgram(1, i, ray, scene);
}
if (!hit)
missProgram(ray);

measure_type accumulation = ray.payload.accumulation;
scalar_type rcpSampleSize = 1.0 / (i + 1);
Li += (accumulation - Li) * rcpSampleSize;
hit = ray.objectID.id != -1;
if (hit)
rayAlive = closestHitProgram(1, sampleIndex, ray, scene);
}
if (!hit)
missProgram(ray);

// TODO: visualize high variance
const uint32_t sampleCount = sampleIndex + 1;
accumulator.addSample(sampleCount, ray.payload.accumulation);

// TODO: russian roulette early exit?
}
// TODO: visualize high variance

return Li;
// TODO: russian roulette early exit?
}

NBL_CONSTEXPR_STATIC_INLINE uint32_t MAX_DEPTH_LOG2 = 4u;
Expand Down
4 changes: 2 additions & 2 deletions 31_HLSLPathTracer/app_resources/hlsl/present.frag.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ using namespace nbl::hlsl;
using namespace ext::FullScreenTriangle;

// binding 0 set 0
[[vk::combinedImageSampler]] [[vk::binding(0, 0)]] Texture2D texture;
[[vk::combinedImageSampler]] [[vk::binding(0, 0)]] Texture2DArray texture;
[[vk::combinedImageSampler]] [[vk::binding(0, 0)]] SamplerState samplerState;

[[vk::location(0)]] float32_t4 main(SVertexAttributes vxAttr) : SV_Target0
{
return float32_t4(texture.Sample(samplerState, vxAttr.uv).rgb, 1.0f);
return float32_t4(texture.Sample(samplerState, float3(vxAttr.uv, 0)).rgb, 1.0f);
}
90 changes: 73 additions & 17 deletions 31_HLSLPathTracer/app_resources/hlsl/render.comp.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,31 @@
#define LIGHT_COUNT 1
#define BXDF_COUNT 7

#include "render_common.hlsl"
#include <render_common.hlsl>
#include <rwmc_global_settings_common.hlsl>

#ifdef RWMC_ENABLED
#include <nbl/builtin/hlsl/rwmc/CascadeAccumulator.hlsl>
#include <render_rwmc_common.hlsl>
#endif

#ifdef RWMC_ENABLED
[[vk::push_constant]] RenderRWMCPushConstants pc;
#else
[[vk::push_constant]] RenderPushConstants pc;
#endif

[[vk::combinedImageSampler]] [[vk::binding(0, 2)]] Texture2D<float3> envMap; // unused
[[vk::combinedImageSampler]] [[vk::binding(0, 2)]] SamplerState envSampler;

[[vk::binding(1, 2)]] Buffer<uint3> sampleSequence;

[[vk::combinedImageSampler]] [[vk::binding(2, 2)]] Texture2D<uint2> scramblebuf; // unused
[[vk::combinedImageSampler]] [[vk::binding(2, 2)]] SamplerState scrambleSampler;

[[vk::image_format("rgba16f")]] [[vk::binding(0)]] RWTexture2DArray<float32_t4> outImage;
[[vk::image_format("rgba16f")]] [[vk::binding(1)]] RWTexture2DArray<float32_t4> cascade;

#include "pathtracer.hlsl"

using namespace nbl;
Expand All @@ -59,15 +83,15 @@ NBL_CONSTEXPR ext::PTPolygonMethod POLYGON_METHOD = ext::PPM_SOLID_ANGLE;

int32_t2 getCoordinates()
{
uint32_t width, height;
outImage.GetDimensions(width, height);
uint32_t width, height, imageArraySize;
outImage.GetDimensions(width, height, imageArraySize);
return int32_t2(glsl::gl_GlobalInvocationID().x % width, glsl::gl_GlobalInvocationID().x / width);
}

float32_t2 getTexCoords()
{
uint32_t width, height;
outImage.GetDimensions(width, height);
uint32_t width, height, imageArraySize;
outImage.GetDimensions(width, height, imageArraySize);
int32_t2 iCoords = getCoordinates();
return float32_t2(float(iCoords.x) / width, 1.0 - float(iCoords.y) / height);
}
Expand Down Expand Up @@ -96,7 +120,14 @@ using raygen_type = ext::RayGen::Basic<ray_type>;
using intersector_type = ext::Intersector::Comprehensive<ray_type, light_type, bxdfnode_type>;
using material_system_type = ext::MaterialSystem::System<diffuse_bxdf_type, conductor_bxdf_type, dielectric_bxdf_type>;
using nee_type = ext::NextEventEstimator::Estimator<scene_type, ray_type, sample_t, aniso_interaction, ext::IntersectMode::IM_PROCEDURAL, LIGHT_TYPE, POLYGON_METHOD>;
using pathtracer_type = ext::PathTracer::Unidirectional<randgen_type, raygen_type, intersector_type, material_system_type, nee_type>;

#ifdef RWMC_ENABLED
using accumulator_type = rwmc::CascadeAccumulator<float32_t3, CascadeCount>;
#else
using accumulator_type = ext::PathTracer::DefaultAccumulator<float32_t3>;
#endif

using pathtracer_type = ext::PathTracer::Unidirectional<randgen_type, raygen_type, intersector_type, material_system_type, nee_type, accumulator_type>;

static const ext::Shape<ext::PST_SPHERE> spheres[SPHERE_COUNT] = {
ext::Shape<ext::PST_SPHERE>::create(float3(0.0, -100.5, -1.0), 100.0, 0u, light_type::INVALID_ID),
Expand Down Expand Up @@ -129,7 +160,7 @@ static const ext::Shape<ext::PST_RECTANGLE> rectangles[1];
#endif

static const light_type lights[LIGHT_COUNT] = {
light_type::create(spectral_t(30.0,25.0,15.0),
light_type::create(LightEminence,
#ifdef SPHERE_LIGHT
8u,
#else
Expand All @@ -154,11 +185,22 @@ static const ext::Scene<light_type, bxdfnode_type> scene = ext::Scene<light_type
lights, LIGHT_COUNT, bxdfs, BXDF_COUNT
);

[numthreads(WorkgroupSize, 1, 1)]
RenderPushConstants retireveRenderPushConstants()
{
#ifdef RWMC_ENABLED
return pc.renderPushConstants;
#else
return pc;
#endif
}

[numthreads(RenderWorkgroupSize, 1, 1)]
void main(uint32_t3 threadID : SV_DispatchThreadID)
{
uint32_t width, height;
outImage.GetDimensions(width, height);
const RenderPushConstants renderPushConstants = retireveRenderPushConstants();

uint32_t width, height, imageArraySize;
outImage.GetDimensions(width, height, imageArraySize);
#ifdef PERSISTENT_WORKGROUPS
uint32_t virtualThreadIndex;
[loop]
Expand All @@ -180,10 +222,10 @@ void main(uint32_t3 threadID : SV_DispatchThreadID)
#endif
}

if (((pc.depth - 1) >> MAX_DEPTH_LOG2) > 0 || ((pc.sampleCount - 1) >> MAX_SAMPLES_LOG2) > 0)
if (((renderPushConstants.depth - 1) >> MAX_DEPTH_LOG2) > 0 || ((renderPushConstants.sampleCount - 1) >> MAX_SAMPLES_LOG2) > 0)
{
float32_t4 pixelCol = float32_t4(1.0,0.0,0.0,1.0);
outImage[coords] = pixelCol;
outImage[uint3(coords.x, coords.y, 0)] = pixelCol;
#ifdef PERSISTENT_WORKGROUPS
continue;
#else
Expand All @@ -203,23 +245,37 @@ void main(uint32_t3 threadID : SV_DispatchThreadID)

float4 NDC = float4(texCoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
{
float4 tmp = mul(pc.invMVP, NDC);
float4 tmp = mul(renderPushConstants.invMVP, NDC);
ptCreateParams.camPos = tmp.xyz / tmp.w;
NDC.z = 1.0;
}

ptCreateParams.NDC = NDC;
ptCreateParams.invMVP = pc.invMVP;
ptCreateParams.invMVP = renderPushConstants.invMVP;

ptCreateParams.diffuseParams = bxdfs[0].params;
ptCreateParams.conductorParams = bxdfs[3].params;
ptCreateParams.dielectricParams = bxdfs[6].params;

pathtracer_type pathtracer = pathtracer_type::create(ptCreateParams);

float32_t3 color = pathtracer.getMeasure(pc.sampleCount, pc.depth, scene);
float32_t4 pixCol = float32_t4(color, 1.0);
outImage[coords] = pixCol;
#ifdef RWMC_ENABLED
accumulator_type accumulator = accumulator_type::create(pc.splattingParameters);
#else
accumulator_type accumulator = accumulator_type::create();
#endif
// path tracing loop
for(int i = 0; i < renderPushConstants.sampleCount; ++i)
pathtracer.sampleMeasure(i, renderPushConstants.depth, scene, accumulator);

#ifdef RWMC_ENABLED
for (uint32_t i = 0; i < CascadeCount; ++i)
cascade[uint3(coords.x, coords.y, i)] = float32_t4(accumulator.accumulation.data[i], 1.0f);
#else
outImage[uint3(coords.x, coords.y, 0)] = float32_t4(accumulator.accumulation, 1.0);
#endif



#ifdef PERSISTENT_WORKGROUPS
}
Expand Down
24 changes: 12 additions & 12 deletions 31_HLSLPathTracer/app_resources/hlsl/render_common.hlsl
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
#ifndef _NBL_HLSL_PATHTRACER_RENDER_COMMON_INCLUDED_
#define _NBL_HLSL_PATHTRACER_RENDER_COMMON_INCLUDED_
#include "nbl/builtin/hlsl/cpp_compat.hlsl"

struct SPushConstants
#ifndef __HLSL_VERSION
#include "matrix4SIMD.h"
#endif

struct RenderPushConstants
{
#ifdef __HLSL_VERSION
float32_t4x4 invMVP;
#else
nbl::hlsl::float32_t4x4 invMVP;
#endif
int sampleCount;
int depth;
};

[[vk::push_constant]] SPushConstants pc;

[[vk::combinedImageSampler]][[vk::binding(0, 2)]] Texture2D<float3> envMap; // unused
[[vk::combinedImageSampler]][[vk::binding(0, 2)]] SamplerState envSampler;

[[vk::binding(1, 2)]] Buffer<uint3> sampleSequence;

[[vk::combinedImageSampler]][[vk::binding(2, 2)]] Texture2D<uint2> scramblebuf; // unused
[[vk::combinedImageSampler]][[vk::binding(2, 2)]] SamplerState scrambleSampler;

[[vk::image_format("rgba16f")]][[vk::binding(0, 0)]] RWTexture2D<float32_t4> outImage;
NBL_CONSTEXPR nbl::hlsl::float32_t3 LightEminence = nbl::hlsl::float32_t3(30.0f, 25.0f, 15.0f);
NBL_CONSTEXPR uint32_t RenderWorkgroupSize = 512u;

#endif
17 changes: 17 additions & 0 deletions 31_HLSLPathTracer/app_resources/hlsl/render_rwmc_common.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef _NBL_HLSL_PATHTRACER_RENDER_RWMC_COMMON_INCLUDED_
#define _NBL_HLSL_PATHTRACER_RENDER_RWMC_COMMON_INCLUDED_
#include "nbl/builtin/hlsl/cpp_compat.hlsl"
#include "nbl/builtin/hlsl/rwmc/SplattingParameters.hlsl"
#include "render_common.hlsl"

#ifndef __HLSL_VERSION
#include "matrix4SIMD.h"
#endif

struct RenderRWMCPushConstants
{
RenderPushConstants renderPushConstants;
nbl::hlsl::rwmc::SplattingParameters splattingParameters;
};

#endif
33 changes: 33 additions & 0 deletions 31_HLSLPathTracer/app_resources/hlsl/resolve.comp.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <nbl/builtin/hlsl/rwmc/resolve.hlsl>
#include "resolve_common.hlsl"
#include "rwmc_global_settings_common.hlsl"
#ifdef PERSISTENT_WORKGROUPS
#include "nbl/builtin/hlsl/math/morton.hlsl"
#endif

[[vk::push_constant]] ResolvePushConstants pc;
[[vk::image_format("rgba16f")]] [[vk::binding(0)]] RWTexture2DArray<float32_t4> outImage;
[[vk::image_format("rgba16f")]] [[vk::binding(1)]] RWTexture2DArray<float32_t4> cascade;

using namespace nbl;
using namespace hlsl;

int32_t2 getImageExtents()
{
uint32_t width, height, imageArraySize;
outImage.GetDimensions(width, height, imageArraySize);
return int32_t2(width, height);
}

[numthreads(ResolveWorkgroupSizeX, ResolveWorkgroupSizeY, 1)]
void main(uint32_t3 threadID : SV_DispatchThreadID)
{
const int32_t2 coords = int32_t2(threadID.x, threadID.y);
const int32_t2 imageExtents = getImageExtents();
if (coords.x >= imageExtents.x || coords.y >= imageExtents.y)
return;

float32_t3 color = rwmc::reweight(pc.resolveParameters, cascade, coords);

outImage[uint3(coords.x, coords.y, 0)] = float32_t4(color, 1.0f);
}
15 changes: 15 additions & 0 deletions 31_HLSLPathTracer/app_resources/hlsl/resolve_common.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef _NBL_HLSL_PATHTRACER_RESOLVE_COMMON_INCLUDED_
#define _NBL_HLSL_PATHTRACER_RESOLVE_COMMON_INCLUDED_
#include "nbl/builtin/hlsl/cpp_compat.hlsl"
#include "nbl/builtin/hlsl/rwmc/ResolveParameters.hlsl"

struct ResolvePushConstants
{
uint32_t sampleCount;
nbl::hlsl::rwmc::ResolveParameters resolveParameters;
};

NBL_CONSTEXPR uint32_t ResolveWorkgroupSizeX = 32u;
NBL_CONSTEXPR uint32_t ResolveWorkgroupSizeY = 16u;

#endif
Loading