提交 225ea05a 编写于 作者: M Matt Pharr

Update from book source.

No functionality changes.
Cleaned up some of the GPU *WorkItem definitions.
上级 b9cefd12
...@@ -17,20 +17,14 @@ namespace pbrt { ...@@ -17,20 +17,14 @@ namespace pbrt {
// GPUPathIntegrator Camera Ray Methods // GPUPathIntegrator Camera Ray Methods
void GPUPathIntegrator::GenerateCameraRays(int y0, int sampleIndex) { void GPUPathIntegrator::GenerateCameraRays(int y0, int sampleIndex) {
// Define _generateRays_ lambda function
auto generateRays = [=](auto sampler) { auto generateRays = [=](auto sampler) {
using Sampler = std::remove_reference_t<decltype(*sampler)>; using Sampler = std::remove_reference_t<decltype(*sampler)>;
if constexpr (!std::is_same_v<Sampler, MLTSampler> && if constexpr (!std::is_same_v<Sampler, MLTSampler> &&
!std::is_same_v<Sampler, DebugMLTSampler>) !std::is_same_v<Sampler, DebugMLTSampler>)
GenerateCameraRays<Sampler>(y0, sampleIndex); GenerateCameraRays<Sampler>(y0, sampleIndex);
}; };
// Somewhat surprisingly, GenerateCameraRays() is specialized on the
// type of the Sampler being used and not on, say, the Camera. By
// specializing on the sampler type, the particular Sampler used can be
// stack allocated (rather than living in global memory), which in turn
// allows its state to be stored in registers in the
// GenerateCameraRays() kernel. There's little benefit from
// specializing on the Camera since its state is read-only and shared
// among all of the threads, so caches well in practice.
sampler.DispatchCPU(generateRays); sampler.DispatchCPU(generateRays);
} }
...@@ -39,18 +33,15 @@ void GPUPathIntegrator::GenerateCameraRays(int y0, int sampleIndex) { ...@@ -39,18 +33,15 @@ void GPUPathIntegrator::GenerateCameraRays(int y0, int sampleIndex) {
RayQueue *rayQueue = CurrentRayQueue(0); RayQueue *rayQueue = CurrentRayQueue(0);
GPUParallelFor( GPUParallelFor(
"Generate Camera rays", maxQueueSize, PBRT_GPU_LAMBDA(int pixelIndex) { "Generate Camera rays", maxQueueSize, PBRT_GPU_LAMBDA(int pixelIndex) {
// Initialize _pPixel_ and test against pixel bounds // Enqueue camera ray and set pixel state for sample
Vector2i resolution = film.PixelBounds().Diagonal(); // Compute pixel coordinates for _pixelIndex_
Bounds2i pixelBounds = film.PixelBounds(); Bounds2i pixelBounds = film.PixelBounds();
int xResolution = pixelBounds.pMax.x - pixelBounds.pMin.x;
Point2i pPixel(pixelBounds.pMin.x + int(pixelIndex) % resolution.x, Point2i pPixel(pixelBounds.pMin.x + pixelIndex % xResolution,
pixelBounds.pMin.y + y0 + int(pixelIndex) / resolution.x); y0 + pixelIndex / xResolution);
pixelSampleState.pPixel[pixelIndex] = pPixel; pixelSampleState.pPixel[pixelIndex] = pPixel;
// If we've split the image into multiple spans of scanlines, // Test pixel coordinates against pixel bounds
// then in the final pass, we may have a few more threads
// launched than there are remaining pixels. Bail out without
// enqueuing a ray if so.
if (!InsideExclusive(pPixel, pixelBounds)) if (!InsideExclusive(pPixel, pixelBounds))
return; return;
...@@ -72,7 +63,6 @@ void GPUPathIntegrator::GenerateCameraRays(int y0, int sampleIndex) { ...@@ -72,7 +63,6 @@ void GPUPathIntegrator::GenerateCameraRays(int y0, int sampleIndex) {
camera.GenerateRay(cameraSample, lambda); camera.GenerateRay(cameraSample, lambda);
// Initialize remainder of _PixelSampleState_ for ray // Initialize remainder of _PixelSampleState_ for ray
// Initialize the rest of the pixel sample's state.
pixelSampleState.L[pixelIndex] = SampledSpectrum(0.f); pixelSampleState.L[pixelIndex] = SampledSpectrum(0.f);
pixelSampleState.lambda[pixelIndex] = lambda; pixelSampleState.lambda[pixelIndex] = lambda;
pixelSampleState.filterWeight[pixelIndex] = cameraSample.weight; pixelSampleState.filterWeight[pixelIndex] = cameraSample.weight;
......
...@@ -167,8 +167,8 @@ void GPUPathIntegrator::SampleMediumInteraction(int depth) { ...@@ -167,8 +167,8 @@ void GPUPathIntegrator::SampleMediumInteraction(int depth) {
PBRT_DBG("Adding ray to escapedRayQueue pixel index %d depth %d\n", PBRT_DBG("Adding ray to escapedRayQueue pixel index %d depth %d\n",
ms.pixelIndex, depth); ms.pixelIndex, depth);
escapedRayQueue->Push(EscapedRayWorkItem{ escapedRayQueue->Push(EscapedRayWorkItem{
beta, uniPathPDF, lightPathPDF, lambda, ray.o, ray.d, ms.piPrev, beta, uniPathPDF, lightPathPDF, lambda, ray.o, ray.d,
ms.nPrev, ms.nsPrev, (int)ms.isSpecularBounce, ms.pixelIndex}); ms.prevIntrCtx, (int)ms.isSpecularBounce, ms.pixelIndex});
} }
} }
...@@ -178,12 +178,12 @@ void GPUPathIntegrator::SampleMediumInteraction(int depth) { ...@@ -178,12 +178,12 @@ void GPUPathIntegrator::SampleMediumInteraction(int depth) {
intr.mediumInterface = &ms.mediumInterface; intr.mediumInterface = &ms.mediumInterface;
Ray newRay = intr.SpawnRay(ray.d); Ray newRay = intr.SpawnRay(ray.d);
mediumTransitionQueue->Push(MediumTransitionWorkItem{ mediumTransitionQueue->Push(MediumTransitionWorkItem{
newRay, lambda, beta, uniPathPDF, lightPathPDF, ms.piPrev, ms.nPrev, newRay, lambda, beta, uniPathPDF, lightPathPDF, ms.prevIntrCtx,
ms.nsPrev, ms.isSpecularBounce, ms.anyNonSpecularBounces, ms.etaScale, ms.isSpecularBounce, ms.anyNonSpecularBounces, ms.etaScale,
ms.pixelIndex}); ms.pixelIndex});
#if 0 #if 0
// WHY NOT THIS? // WHY NOT THIS?
rayQueues[(depth + 1) & 1]->PushIndirect(newRay, ms.piPrev, ms.nPrev, ms.nsPrev, rayQueues[(depth + 1) & 1]->PushIndirect(newRay, ms.prevIntrCtx,
beta, uniPathPDF, lightPathPDF, lambda, ms.etaScale, beta, uniPathPDF, lightPathPDF, lambda, ms.etaScale,
ms.isSpecularBounce, ms.anyNonSpecularBounces, ms.isSpecularBounce, ms.anyNonSpecularBounces,
ms.pixelIndex); ms.pixelIndex);
...@@ -196,11 +196,10 @@ void GPUPathIntegrator::SampleMediumInteraction(int depth) { ...@@ -196,11 +196,10 @@ void GPUPathIntegrator::SampleMediumInteraction(int depth) {
"Ray hit an area light: adding to hitAreaLightQueue pixel index %d " "Ray hit an area light: adding to hitAreaLightQueue pixel index %d "
"depth %d\n", "depth %d\n",
ms.pixelIndex, depth); ms.pixelIndex, depth);
// TODO: intr.wo == -ray.d?
hitAreaLightQueue->Push(HitAreaLightWorkItem{ hitAreaLightQueue->Push(HitAreaLightWorkItem{
ms.areaLight, lambda, beta, uniPathPDF, lightPathPDF, Point3f(ms.pi), ms.areaLight, lambda, beta, uniPathPDF, lightPathPDF, Point3f(ms.pi),
ms.n, ms.uv, -ray.d, ms.piPrev, ray.d, ms.nPrev, ms.nsPrev, ms.n, ms.uv, -ray.d, ms.prevIntrCtx, ms.isSpecularBounce,
ms.isSpecularBounce, ms.pixelIndex}); ms.pixelIndex});
} }
FloatTextureHandle displacement = material.GetDisplacement(); FloatTextureHandle displacement = material.GetDisplacement();
...@@ -312,8 +311,7 @@ void GPUPathIntegrator::SampleMediumInteraction(int depth) { ...@@ -312,8 +311,7 @@ void GPUPathIntegrator::SampleMediumInteraction(int depth) {
bool anyNonSpecularBounces = true; bool anyNonSpecularBounces = true;
// Spawn indirect ray. // Spawn indirect ray.
nextRayQueue->PushIndirect(ray, Point3fi(ms.p), Normal3f(0, 0, 0), nextRayQueue->PushIndirect(ray, ctx, beta, uniPathPDF, lightPathPDF,
Normal3f(0, 0, 0), beta, uniPathPDF, lightPathPDF,
ms.lambda, ms.etaScale, isSpecularBounce, ms.lambda, ms.etaScale, isSpecularBounce,
anyNonSpecularBounces, ms.pixelIndex); anyNonSpecularBounces, ms.pixelIndex);
PBRT_DBG("Enqueuing indirect medium ray at depth %d pixel index %d\n", PBRT_DBG("Enqueuing indirect medium ray at depth %d pixel index %d\n",
...@@ -332,8 +330,8 @@ void GPUPathIntegrator::HandleMediumTransitions(int depth) { ...@@ -332,8 +330,8 @@ void GPUPathIntegrator::HandleMediumTransitions(int depth) {
// Why not? Basically boils down to current indirect enqueue (and other // Why not? Basically boils down to current indirect enqueue (and other
// places?)) // places?))
// TODO: figure this out... // TODO: figure this out...
rayQueue->PushIndirect(mt.ray, mt.piPrev, mt.nPrev, mt.nsPrev, mt.beta, rayQueue->PushIndirect(mt.ray, mt.prevIntrCtx, mt.beta, mt.uniPathPDF,
mt.uniPathPDF, mt.lightPathPDF, mt.lambda, mt.etaScale, mt.lightPathPDF, mt.lambda, mt.etaScale,
mt.isSpecularBounce, mt.anyNonSpecularBounces, mt.isSpecularBounce, mt.anyNonSpecularBounces,
mt.pixelIndex); mt.pixelIndex);
PBRT_DBG("Enqueuied ray after medium transition at depth %d pixel index %d", PBRT_DBG("Enqueuied ray after medium transition at depth %d pixel index %d",
......
...@@ -117,15 +117,15 @@ extern "C" __global__ void __raygen__findClosest() { ...@@ -117,15 +117,15 @@ extern "C" __global__ void __raygen__findClosest() {
r.ray.o.x, r.ray.o.y, r.ray.o.z, r.ray.d.x, r.ray.d.y, r.ray.d.z, r.ray.o.x, r.ray.o.y, r.ray.o.z, r.ray.d.x, r.ray.d.y, r.ray.d.z,
r.beta[0], r.beta[1], r.beta[2], r.beta[3]); r.beta[0], r.beta[1], r.beta[2], r.beta[3]);
params.mediumSampleQueue->Push(r.ray, Infinity, r.lambda, r.beta, r.uniPathPDF, params.mediumSampleQueue->Push(r.ray, Infinity, r.lambda, r.beta, r.uniPathPDF,
r.lightPathPDF, r.pixelIndex, r.piPrev, r.lightPathPDF, r.pixelIndex, r.prevIntrCtx,
r.nPrev, r.nsPrev, r.isSpecularBounce, r.isSpecularBounce,
r.anyNonSpecularBounces, r.etaScale); r.anyNonSpecularBounces, r.etaScale);
} else if (params.escapedRayQueue) { } else if (params.escapedRayQueue) {
PBRT_DBG("Adding ray to escapedRayQueue ray index %d pixel index %d\n", rayIndex, PBRT_DBG("Adding ray to escapedRayQueue ray index %d pixel index %d\n", rayIndex,
r.pixelIndex); r.pixelIndex);
params.escapedRayQueue->Push(EscapedRayWorkItem{ params.escapedRayQueue->Push(EscapedRayWorkItem{
r.beta, r.uniPathPDF, r.lightPathPDF, r.lambda, ray.o, ray.d, r.piPrev, r.nPrev, r.beta, r.uniPathPDF, r.lightPathPDF, r.lambda, ray.o, ray.d, r.prevIntrCtx,
r.nsPrev, (int)r.isSpecularBounce, r.pixelIndex}); (int)r.isSpecularBounce, r.pixelIndex});
} }
} }
} }
...@@ -166,9 +166,7 @@ static __forceinline__ __device__ void ProcessClosestIntersection( ...@@ -166,9 +166,7 @@ static __forceinline__ __device__ void ProcessClosestIntersection(
r.uniPathPDF, r.uniPathPDF,
r.lightPathPDF, r.lightPathPDF,
r.pixelIndex, r.pixelIndex,
r.piPrev, r.prevIntrCtx,
r.nPrev,
r.nsPrev,
r.isSpecularBounce, r.isSpecularBounce,
r.anyNonSpecularBounces, r.anyNonSpecularBounces,
r.etaScale, r.etaScale,
...@@ -201,7 +199,7 @@ static __forceinline__ __device__ void ProcessClosestIntersection( ...@@ -201,7 +199,7 @@ static __forceinline__ __device__ void ProcessClosestIntersection(
rayIndex, r.pixelIndex); rayIndex, r.pixelIndex);
Ray newRay = intr.SpawnRay(r.ray.d); Ray newRay = intr.SpawnRay(r.ray.d);
params.mediumTransitionQueue->Push(MediumTransitionWorkItem{ params.mediumTransitionQueue->Push(MediumTransitionWorkItem{
newRay, r.lambda, r.beta, r.uniPathPDF, r.lightPathPDF, r.piPrev, r.nPrev, r.nsPrev, newRay, r.lambda, r.beta, r.uniPathPDF, r.lightPathPDF, r.prevIntrCtx,
r.isSpecularBounce, r.anyNonSpecularBounces, r.etaScale, r.pixelIndex}); r.isSpecularBounce, r.anyNonSpecularBounces, r.etaScale, r.pixelIndex});
return; return;
} }
...@@ -213,8 +211,7 @@ static __forceinline__ __device__ void ProcessClosestIntersection( ...@@ -213,8 +211,7 @@ static __forceinline__ __device__ void ProcessClosestIntersection(
// TODO: intr.wo == -ray.d? // TODO: intr.wo == -ray.d?
params.hitAreaLightQueue->Push(HitAreaLightWorkItem{ params.hitAreaLightQueue->Push(HitAreaLightWorkItem{
intr.areaLight, r.lambda, r.beta, r.uniPathPDF, r.lightPathPDF, intr.p(), intr.n, intr.areaLight, r.lambda, r.beta, r.uniPathPDF, r.lightPathPDF, intr.p(), intr.n,
intr.uv, intr.wo, r.piPrev, ray.d, r.nPrev, r.nsPrev, intr.uv, intr.wo, r.prevIntrCtx, (int)r.isSpecularBounce, r.pixelIndex});
(int)r.isSpecularBounce, r.pixelIndex});
} }
FloatTextureHandle displacement = material.GetDisplacement(); FloatTextureHandle displacement = material.GetDisplacement();
......
...@@ -330,7 +330,9 @@ void GPUPathIntegrator::Render() { ...@@ -330,7 +330,9 @@ void GPUPathIntegrator::Render() {
++sampleIndex) { ++sampleIndex) {
// Render image for sample _sampleIndex_ // Render image for sample _sampleIndex_
LOG_VERBOSE("Starting to submit work for sample %d", sampleIndex); LOG_VERBOSE("Starting to submit work for sample %d", sampleIndex);
for (int y0 = 0; y0 < resolution.y; y0 += scanlinesPerPass) { Bounds2i pixelBounds = film.PixelBounds();
for (int y0 = pixelBounds.pMin.y; y0 < pixelBounds.pMax.y;
y0 += scanlinesPerPass) {
// Generate camera rays for current scanline range // Generate camera rays for current scanline range
RayQueue *cameraRayQueue = CurrentRayQueue(0); RayQueue *cameraRayQueue = CurrentRayQueue(0);
GPUDo( GPUDo(
...@@ -344,11 +346,13 @@ void GPUPathIntegrator::Render() { ...@@ -344,11 +346,13 @@ void GPUPathIntegrator::Render() {
"Update camera ray stats", "Update camera ray stats",
PBRT_GPU_LAMBDA() { stats->cameraRays += cameraRayQueue->Size(); }); PBRT_GPU_LAMBDA() { stats->cameraRays += cameraRayQueue->Size(); });
// Trace rays and estimate radiance up to maximum ray depth
for (int depth = 0; true; ++depth) { for (int depth = 0; true; ++depth) {
// Reset ray queues before tracing rays // Reset ray queues before tracing rays
RayQueue *resetQueue = NextRayQueue(depth); RayQueue *nextQueue = NextRayQueue(depth);
GPUDo( GPUDo(
"Reset queues before tracing rays", PBRT_GPU_LAMBDA() { "Reset queues before tracing rays", PBRT_GPU_LAMBDA() {
nextQueue->Reset();
// Reset queues before tracing next batch of rays // Reset queues before tracing next batch of rays
mediumTransitionQueue->Reset(); mediumTransitionQueue->Reset();
if (mediumSampleQueue) if (mediumSampleQueue)
...@@ -356,8 +360,6 @@ void GPUPathIntegrator::Render() { ...@@ -356,8 +360,6 @@ void GPUPathIntegrator::Render() {
if (mediumScatterQueue) if (mediumScatterQueue)
mediumScatterQueue->Reset(); mediumScatterQueue->Reset();
resetQueue->Reset();
if (escapedRayQueue) if (escapedRayQueue)
escapedRayQueue->Reset(); escapedRayQueue->Reset();
...@@ -402,6 +404,7 @@ void GPUPathIntegrator::Render() { ...@@ -402,6 +404,7 @@ void GPUPathIntegrator::Render() {
if (haveSubsurface) if (haveSubsurface)
SampleSubsurface(depth); SampleSubsurface(depth);
} }
UpdateFilm(); UpdateFilm();
// Copy updated film pixels to buffer for display // Copy updated film pixels to buffer for display
if (!Options->displayServer.empty()) if (!Options->displayServer.empty())
...@@ -457,7 +460,7 @@ void GPUPathIntegrator::HandleEscapedRays(int depth) { ...@@ -457,7 +460,7 @@ void GPUPathIntegrator::HandleEscapedRays(int depth) {
if (depth == 0 || er.specularBounce) { if (depth == 0 || er.specularBounce) {
L = er.beta * Le / er.uniPathPDF.Average(); L = er.beta * Le / er.uniPathPDF.Average();
} else { } else {
LightSampleContext ctx(er.piPrev, er.nPrev, er.nsPrev); LightSampleContext ctx = er.prevIntrCtx;
Float lightChoicePDF = lightSampler.PDF(ctx, envLight); Float lightChoicePDF = lightSampler.PDF(ctx, envLight);
Float lightPDF = lightChoicePDF * Float lightPDF = lightChoicePDF *
...@@ -495,9 +498,9 @@ void GPUPathIntegrator::HandleRayFoundEmission(int depth) { ...@@ -495,9 +498,9 @@ void GPUPathIntegrator::HandleRayFoundEmission(int depth) {
if (depth == 0 || he.isSpecularBounce) { if (depth == 0 || he.isSpecularBounce) {
L = he.beta * Le / he.uniPathPDF.Average(); L = he.beta * Le / he.uniPathPDF.Average();
} else { } else {
Vector3f wi = he.rayd; Vector3f wi = -he.wo;
LightSampleContext ctx(he.piPrev, he.nPrev, he.nsPrev); LightSampleContext ctx = he.prevIntrCtx;
Float lightChoicePDF = lightSampler.PDF(ctx, areaLight); Float lightChoicePDF = lightSampler.PDF(ctx, areaLight);
Float lightPDF = lightChoicePDF * Float lightPDF = lightChoicePDF *
......
...@@ -71,7 +71,6 @@ class GPUPathIntegrator { ...@@ -71,7 +71,6 @@ class GPUPathIntegrator {
RayQueue *NextRayQueue(int depth) { return rayQueues[(depth + 1) & 1]; } RayQueue *NextRayQueue(int depth) { return rayQueues[(depth + 1) & 1]; }
// GPUPathIntegrator Member Variables // GPUPathIntegrator Member Variables
// Various properties of the scene
bool initializeVisibleSurface; bool initializeVisibleSurface;
bool haveSubsurface; bool haveSubsurface;
bool haveMedia; bool haveMedia;
...@@ -91,8 +90,6 @@ class GPUPathIntegrator { ...@@ -91,8 +90,6 @@ class GPUPathIntegrator {
}; };
Stats *stats; Stats *stats;
int scanlinesPerPass, maxQueueSize;
FilterHandle filter; FilterHandle filter;
FilmHandle film; FilmHandle film;
SamplerHandle sampler; SamplerHandle sampler;
...@@ -100,10 +97,12 @@ class GPUPathIntegrator { ...@@ -100,10 +97,12 @@ class GPUPathIntegrator {
LightHandle envLight; LightHandle envLight;
LightSamplerHandle lightSampler; LightSamplerHandle lightSampler;
RayQueue *rayQueues[2] = {nullptr, nullptr}; int scanlinesPerPass, maxQueueSize;
SOA<PixelSampleState> pixelSampleState; SOA<PixelSampleState> pixelSampleState;
RayQueue *rayQueues[2];
MediumTransitionQueue *mediumTransitionQueue = nullptr; MediumTransitionQueue *mediumTransitionQueue = nullptr;
MediumSampleQueue *mediumSampleQueue = nullptr; MediumSampleQueue *mediumSampleQueue = nullptr;
MediumScatterQueue *mediumScatterQueue = nullptr; MediumScatterQueue *mediumScatterQueue = nullptr;
......
...@@ -12,32 +12,41 @@ ...@@ -12,32 +12,41 @@
namespace pbrt { namespace pbrt {
// GPUPathIntegrator Sampler Methods // GPUPathIntegrator Sampler Methods
void GPUPathIntegrator::GenerateRaySamples(int depth, int sampleIndex) {
auto generateSamples = [=](auto sampler) {
using Sampler = std::remove_reference_t<decltype(*sampler)>;
if constexpr (!std::is_same_v<Sampler, MLTSampler> &&
!std::is_same_v<Sampler, DebugMLTSampler>)
GenerateRaySamples<Sampler>(depth, sampleIndex);
};
// Call the appropriate GenerateRaySamples specialization based on the
// Sampler's actual type.
sampler.DispatchCPU(generateSamples);
}
template <typename Sampler> template <typename Sampler>
void GPUPathIntegrator::GenerateRaySamples(int depth, int sampleIndex) { void GPUPathIntegrator::GenerateRaySamples(int depth, int sampleIndex) {
std::string desc = std::string("Generate ray samples - ") + Sampler::Name(); std::string desc = std::string("Generate ray samples - ") + Sampler::Name();
RayQueue *rayQueue = CurrentRayQueue(depth); RayQueue *rayQueue = CurrentRayQueue(depth);
ForAllQueued( ForAllQueued(
desc.c_str(), rayQueue, maxQueueSize, desc.c_str(), rayQueue, maxQueueSize,
PBRT_GPU_LAMBDA(const RayWorkItem w, int index) { PBRT_GPU_LAMBDA(const RayWorkItem w, int index) {
// Figure out how many dimensions have been consumed so far: 5 // Generate samples for ray segment at current sample index
// are used for the initial camera sample and then either 7 or // Find first sample dimension
// 10 per ray, depending on whether there's subsurface
// scattering.
int dimension = 5 + 7 * depth; int dimension = 5 + 7 * depth;
if (haveSubsurface) if (haveSubsurface)
dimension += 3 * depth; dimension += 3 * depth;
// Initialize a Sampler // Initialize _Sampler_ for pixel, sample index, and dimension
Sampler pixelSampler = *sampler.Cast<Sampler>(); Sampler pixelSampler = *sampler.Cast<Sampler>();
Point2i pPixel = pixelSampleState.pPixel[w.pixelIndex]; Point2i pPixel = pixelSampleState.pPixel[w.pixelIndex];
pixelSampler.StartPixelSample(pPixel, sampleIndex, dimension); pixelSampler.StartPixelSample(pPixel, sampleIndex, dimension);
// Generate the samples for the ray and store them with it in // Initialize _RaySamples_ structure with sample values
// the ray queue.
RaySamples rs; RaySamples rs;
rs.direct.u = pixelSampler.Get2D(); rs.direct.u = pixelSampler.Get2D();
rs.direct.uc = pixelSampler.Get1D(); rs.direct.uc = pixelSampler.Get1D();
// Initialize indirect and possibly subsurface samples in _rs_
rs.indirect.u = pixelSampler.Get2D(); rs.indirect.u = pixelSampler.Get2D();
rs.indirect.uc = pixelSampler.Get1D(); rs.indirect.uc = pixelSampler.Get1D();
rs.indirect.rr = pixelSampler.Get1D(); rs.indirect.rr = pixelSampler.Get1D();
...@@ -47,20 +56,9 @@ void GPUPathIntegrator::GenerateRaySamples(int depth, int sampleIndex) { ...@@ -47,20 +56,9 @@ void GPUPathIntegrator::GenerateRaySamples(int depth, int sampleIndex) {
rs.subsurface.u = pixelSampler.Get2D(); rs.subsurface.u = pixelSampler.Get2D();
} }
// Store _RaySamples_ in pixel sample state
pixelSampleState.samples[w.pixelIndex] = rs; pixelSampleState.samples[w.pixelIndex] = rs;
}); });
} }
void GPUPathIntegrator::GenerateRaySamples(int depth, int sampleIndex) {
auto generateSamples = [=](auto sampler) {
using Sampler = std::remove_reference_t<decltype(*sampler)>;
if constexpr (!std::is_same_v<Sampler, MLTSampler> &&
!std::is_same_v<Sampler, DebugMLTSampler>)
GenerateRaySamples<Sampler>(depth, sampleIndex);
};
// Call the appropriate GenerateRaySamples specialization based on the
// Sampler's actual type.
sampler.DispatchCPU(generateSamples);
}
} // namespace pbrt } // namespace pbrt
...@@ -124,9 +124,10 @@ void GPUPathIntegrator::SampleSubsurface(int depth) { ...@@ -124,9 +124,10 @@ void GPUPathIntegrator::SampleSubsurface(int depth) {
// possible... // possible...
bool anyNonSpecularBounces = true; bool anyNonSpecularBounces = true;
nextRayQueue->PushIndirect(ray, intr.pi, intr.n, intr.ns, beta, LightSampleContext ctx(intr.pi, intr.n, intr.ns);
uniPathPDF, lightPathPDF, lambda, nextRayQueue->PushIndirect(ray, ctx, beta, uniPathPDF,
etaScale, bsdfSample->IsSpecular(), lightPathPDF, lambda, etaScale,
bsdfSample->IsSpecular(),
anyNonSpecularBounces, s.pixelIndex); anyNonSpecularBounces, s.pixelIndex);
PBRT_DBG( PBRT_DBG(
......
...@@ -173,7 +173,10 @@ void GPUPathIntegrator::EvaluateMaterialAndBSDF(TextureEvaluator texEval, ...@@ -173,7 +173,10 @@ void GPUPathIntegrator::EvaluateMaterialAndBSDF(TextureEvaluator texEval,
!bsdfSample->IsSpecular() || me.anyNonSpecularBounces; !bsdfSample->IsSpecular() || me.anyNonSpecularBounces;
// Spawn indriect ray. // Spawn indriect ray.
nextRayQueue->PushIndirect(ray, me.pi, me.n, ns, beta, uniPathPDF, LightSampleContext ctx(
me.pi, me.n,
ns); // Note: slightly different than context below. Problem?
nextRayQueue->PushIndirect(ray, ctx, beta, uniPathPDF,
lightPathPDF, lambda, etaScale, lightPathPDF, lambda, etaScale,
bsdfSample->IsSpecular(), bsdfSample->IsSpecular(),
anyNonSpecularBounces, me.pixelIndex); anyNonSpecularBounces, me.pixelIndex);
......
...@@ -20,6 +20,7 @@ namespace pbrt { ...@@ -20,6 +20,7 @@ namespace pbrt {
// RaySamples Definition // RaySamples Definition
struct RaySamples { struct RaySamples {
// RaySamples Public Members
struct { struct {
Point2f u; Point2f u;
Float uc; Float uc;
...@@ -28,7 +29,6 @@ struct RaySamples { ...@@ -28,7 +29,6 @@ struct RaySamples {
Float uc, rr; Float uc, rr;
Point2f u; Point2f u;
} indirect; } indirect;
bool haveSubsurface; bool haveSubsurface;
struct { struct {
Float uc; Float uc;
...@@ -99,11 +99,11 @@ struct SOA<RaySamples> { ...@@ -99,11 +99,11 @@ struct SOA<RaySamples> {
// PixelSampleState Definition // PixelSampleState Definition
struct PixelSampleState { struct PixelSampleState {
Float filterWeight; // PixelSampleState Public Members
Point2i pPixel; Point2i pPixel;
Float filterWeight;
SampledWavelengths lambda; SampledWavelengths lambda;
SampledSpectrum L; SampledSpectrum L, cameraRayWeight;
SampledSpectrum cameraRayWeight;
VisibleSurface visibleSurface; VisibleSurface visibleSurface;
RaySamples samples; RaySamples samples;
}; };
...@@ -114,9 +114,7 @@ struct RayWorkItem { ...@@ -114,9 +114,7 @@ struct RayWorkItem {
int pixelIndex; int pixelIndex;
SampledWavelengths lambda; SampledWavelengths lambda;
SampledSpectrum beta, uniPathPDF, lightPathPDF; SampledSpectrum beta, uniPathPDF, lightPathPDF;
Point3fi piPrev; LightSampleContext prevIntrCtx;
Normal3f nPrev;
Normal3f nsPrev;
Float etaScale; Float etaScale;
int isSpecularBounce; int isSpecularBounce;
int anyNonSpecularBounces; int anyNonSpecularBounces;
...@@ -128,8 +126,7 @@ struct EscapedRayWorkItem { ...@@ -128,8 +126,7 @@ struct EscapedRayWorkItem {
SampledWavelengths lambda; SampledWavelengths lambda;
Point3f rayo; Point3f rayo;
Vector3f rayd; Vector3f rayd;
Point3fi piPrev; LightSampleContext prevIntrCtx;
Normal3f nPrev, nsPrev;
int specularBounce; int specularBounce;
int pixelIndex; int pixelIndex;
}; };
...@@ -146,9 +143,7 @@ struct HitAreaLightWorkItem { ...@@ -146,9 +143,7 @@ struct HitAreaLightWorkItem {
Normal3f n; Normal3f n;
Point2f uv; Point2f uv;
Vector3f wo; Vector3f wo;
Point3fi piPrev; LightSampleContext prevIntrCtx;
Vector3f rayd;
Normal3f nPrev, nsPrev;
int isSpecularBounce; int isSpecularBounce;
int pixelIndex; int pixelIndex;
}; };
...@@ -256,8 +251,7 @@ struct MediumTransitionWorkItem { ...@@ -256,8 +251,7 @@ struct MediumTransitionWorkItem {
Ray ray; Ray ray;
SampledWavelengths lambda; SampledWavelengths lambda;
SampledSpectrum beta, uniPathPDF, lightPathPDF; SampledSpectrum beta, uniPathPDF, lightPathPDF;
Point3fi piPrev; LightSampleContext prevIntrCtx;
Normal3f nPrev, nsPrev;
int isSpecularBounce; int isSpecularBounce;
int anyNonSpecularBounces; int anyNonSpecularBounces;
Float etaScale; Float etaScale;
...@@ -277,9 +271,7 @@ struct MediumSampleWorkItem { ...@@ -277,9 +271,7 @@ struct MediumSampleWorkItem {
SampledSpectrum uniPathPDF; SampledSpectrum uniPathPDF;
SampledSpectrum lightPathPDF; SampledSpectrum lightPathPDF;
int pixelIndex; int pixelIndex;
Point3fi piPrev; LightSampleContext prevIntrCtx;
Normal3f nPrev;
Normal3f nsPrev;
int isSpecularBounce; int isSpecularBounce;
int anyNonSpecularBounces; int anyNonSpecularBounces;
Float etaScale; Float etaScale;
...@@ -335,9 +327,8 @@ class RayQueue : public WorkQueue<RayWorkItem> { ...@@ -335,9 +327,8 @@ class RayQueue : public WorkQueue<RayWorkItem> {
} }
PBRT_CPU_GPU PBRT_CPU_GPU
int PushIndirect(const Ray &ray, const Point3fi &piPrev, const Normal3f &nPrev, int PushIndirect(const Ray &ray, const LightSampleContext &prevIntrCtx,
const Normal3f &nsPrev, const SampledSpectrum &beta, const SampledSpectrum &beta, const SampledSpectrum &uniPathPDF,
const SampledSpectrum &uniPathPDF,
const SampledSpectrum &lightPathPDF, const SampledSpectrum &lightPathPDF,
const SampledWavelengths &lambda, Float etaScale, const SampledWavelengths &lambda, Float etaScale,
bool isSpecularBounce, bool anyNonSpecularBounces, int pixelIndex) { bool isSpecularBounce, bool anyNonSpecularBounces, int pixelIndex) {
...@@ -345,9 +336,7 @@ class RayQueue : public WorkQueue<RayWorkItem> { ...@@ -345,9 +336,7 @@ class RayQueue : public WorkQueue<RayWorkItem> {
DCHECK(!ray.HasNaN()); DCHECK(!ray.HasNaN());
this->ray[index] = ray; this->ray[index] = ray;
this->pixelIndex[index] = pixelIndex; this->pixelIndex[index] = pixelIndex;
this->piPrev[index] = piPrev; this->prevIntrCtx[index] = prevIntrCtx;
this->nPrev[index] = nPrev;
this->nsPrev[index] = nsPrev;
this->beta[index] = beta; this->beta[index] = beta;
this->uniPathPDF[index] = uniPathPDF; this->uniPathPDF[index] = uniPathPDF;
this->lightPathPDF[index] = lightPathPDF; this->lightPathPDF[index] = lightPathPDF;
...@@ -434,7 +423,7 @@ class MediumSampleQueue : public WorkQueue<MediumSampleWorkItem> { ...@@ -434,7 +423,7 @@ class MediumSampleQueue : public WorkQueue<MediumSampleWorkItem> {
PBRT_CPU_GPU PBRT_CPU_GPU
int Push(Ray ray, Float tMax, SampledWavelengths lambda, SampledSpectrum beta, int Push(Ray ray, Float tMax, SampledWavelengths lambda, SampledSpectrum beta,
SampledSpectrum uniPathPDF, SampledSpectrum lightPathPDF, int pixelIndex, SampledSpectrum uniPathPDF, SampledSpectrum lightPathPDF, int pixelIndex,
Point3fi piPrev, Normal3f nPrev, Normal3f nsPrev, int isSpecularBounce, LightSampleContext prevIntrCtx, int isSpecularBounce,
int anyNonSpecularBounces, Float etaScale) { int anyNonSpecularBounces, Float etaScale) {
int index = AllocateEntry(); int index = AllocateEntry();
this->ray[index] = ray; this->ray[index] = ray;
...@@ -444,9 +433,7 @@ class MediumSampleQueue : public WorkQueue<MediumSampleWorkItem> { ...@@ -444,9 +433,7 @@ class MediumSampleQueue : public WorkQueue<MediumSampleWorkItem> {
this->uniPathPDF[index] = uniPathPDF; this->uniPathPDF[index] = uniPathPDF;
this->lightPathPDF[index] = lightPathPDF; this->lightPathPDF[index] = lightPathPDF;
this->pixelIndex[index] = pixelIndex; this->pixelIndex[index] = pixelIndex;
this->piPrev[index] = piPrev; this->prevIntrCtx[index] = prevIntrCtx;
this->nPrev[index] = nPrev;
this->nsPrev[index] = nsPrev;
this->isSpecularBounce[index] = isSpecularBounce; this->isSpecularBounce[index] = isSpecularBounce;
this->anyNonSpecularBounces[index] = anyNonSpecularBounces; this->anyNonSpecularBounces[index] = anyNonSpecularBounces;
this->etaScale[index] = etaScale; this->etaScale[index] = etaScale;
......
...@@ -11,6 +11,7 @@ flat MediumHandle; ...@@ -11,6 +11,7 @@ flat MediumHandle;
flat int; flat int;
soa BSDF; soa BSDF;
soa LightSampleContext;
soa MediumInterface; soa MediumInterface;
soa Normal3f; soa Normal3f;
soa Point2f; soa Point2f;
...@@ -41,9 +42,7 @@ soa RayWorkItem { ...@@ -41,9 +42,7 @@ soa RayWorkItem {
int pixelIndex; int pixelIndex;
SampledWavelengths lambda; SampledWavelengths lambda;
SampledSpectrum beta, uniPathPDF, lightPathPDF; SampledSpectrum beta, uniPathPDF, lightPathPDF;
Point3fi piPrev; LightSampleContext prevIntrCtx;
Normal3f nPrev;
Normal3f nsPrev;
Float etaScale; Float etaScale;
int isSpecularBounce; int isSpecularBounce;
int anyNonSpecularBounces; int anyNonSpecularBounces;
...@@ -54,8 +53,7 @@ soa EscapedRayWorkItem { ...@@ -54,8 +53,7 @@ soa EscapedRayWorkItem {
SampledWavelengths lambda; SampledWavelengths lambda;
Point3f rayo; Point3f rayo;
Vector3f rayd; Vector3f rayd;
Point3fi piPrev; LightSampleContext prevIntrCtx;
Normal3f nPrev, nsPrev;
int specularBounce; int specularBounce;
int pixelIndex; int pixelIndex;
}; };
...@@ -68,9 +66,7 @@ soa HitAreaLightWorkItem { ...@@ -68,9 +66,7 @@ soa HitAreaLightWorkItem {
Normal3f n; Normal3f n;
Point2f uv; Point2f uv;
Vector3f wo; Vector3f wo;
Point3fi piPrev; LightSampleContext prevIntrCtx;
Vector3f rayd;
Normal3f nPrev, nsPrev;
int isSpecularBounce; int isSpecularBounce;
int pixelIndex; int pixelIndex;
}; };
...@@ -118,8 +114,7 @@ soa MediumTransitionWorkItem { ...@@ -118,8 +114,7 @@ soa MediumTransitionWorkItem {
Ray ray; Ray ray;
SampledWavelengths lambda; SampledWavelengths lambda;
SampledSpectrum beta, uniPathPDF, lightPathPDF; SampledSpectrum beta, uniPathPDF, lightPathPDF;
Point3fi piPrev; LightSampleContext prevIntrCtx;
Normal3f nPrev, nsPrev;
int isSpecularBounce; int isSpecularBounce;
int anyNonSpecularBounces; int anyNonSpecularBounces;
Float etaScale; Float etaScale;
...@@ -139,9 +134,7 @@ soa MediumSampleWorkItem { ...@@ -139,9 +134,7 @@ soa MediumSampleWorkItem {
Normal3f n; Normal3f n;
Vector3f wo; Vector3f wo;
Point2f uv; Point2f uv;
Point3fi piPrev; LightSampleContext prevIntrCtx;
Normal3f nPrev;
Normal3f nsPrev;
int isSpecularBounce; int isSpecularBounce;
MaterialHandle material; MaterialHandle material;
Normal3f ns; Normal3f ns;
......
...@@ -64,3 +64,8 @@ soa TabulatedBSSRDF { ...@@ -64,3 +64,8 @@ soa TabulatedBSSRDF {
const BSSRDFTable *table; const BSSRDFTable *table;
SampledSpectrum sigma_t, rho; SampledSpectrum sigma_t, rho;
}; };
soa LightSampleContext {
Point3fi pi;
Normal3f n, ns;
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册