resurrected global ray sorting + refactor

This commit is contained in:
Turanszki Janos
2020-01-27 21:10:49 +00:00
parent 96938f32f2
commit 1dfcf14f22
11 changed files with 69 additions and 16 deletions
+5 -1
View File
@@ -8,7 +8,11 @@ static const uint RAYTRACING_TRACE_GROUPSIZE = 64;
static const uint RAYTRACING_SORT_GROUPSIZE = 1024;
static const uint RAYTRACE_INDIRECT_OFFSET_TRACE = 0;
static const uint RAYTRACE_INDIRECT_OFFSET_SORT = 4 * 3;
static const uint RAYTRACE_INDIRECT_OFFSET_TILESORT = 4 * 3;
// Whether to sort global ray buffer or only smaller bundles (tiles).
// The global sorting is slower, but on some GPUs, it is still worth to to this because the raytracing will be faster (more coherent)
#define RAYTRACING_SORT_GLOBAL
CBUFFER(RaytracingCB, CBSLOT_RENDERER_TRACED)
-1
View File
@@ -1,6 +1,5 @@
#include "globals.hlsli"
#include "ShaderInterop_BVH.h"
#include "ShaderInterop_Raytracing.h"
// This shader builds scene triangle data and performs BVH classification:
// - This shader is run per object.
+13 -1
View File
@@ -9,9 +9,13 @@ STRUCTUREDBUFFER(rayBuffer_READ, RaytracingStoredRay, TEXSLOT_ONDEMAND9);
RWRAWBUFFER(counterBuffer_WRITE, 0);
RWSTRUCTUREDBUFFER(rayBuffer_WRITE, RaytracingStoredRay, 1);
#ifdef RAYTRACING_SORT_GLOBAL
RWSTRUCTUREDBUFFER(rayIndexBuffer_WRITE, uint, 2);
RWSTRUCTUREDBUFFER(raySortBuffer_WRITE, float, 3);
#endif // RAYTRACING_SORT_GLOBAL
// This enables reduced atomics into global memory.
//#define ADVANCED_ALLOCATION
#define ADVANCED_ALLOCATION
#ifdef ADVANCED_ALLOCATION
static const uint GroupActiveRayMaskBucketCount = RAYTRACING_TRACE_GROUPSIZE / 32;
@@ -83,6 +87,10 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex )
uint dest;
counterBuffer_WRITE.InterlockedAdd(0, 1, dest);
rayBuffer_WRITE[dest] = CreateStoredRay(ray);
#ifdef RAYTRACING_SORT_GLOBAL
rayIndexBuffer_WRITE[dest] = dest;
raySortBuffer_WRITE[dest] = CreateRaySortCode(ray);
#endif // RAYTRACING_SORT_GLOBAL
#endif // ADVANCED_ALLOCATION
}
}
@@ -136,6 +144,10 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex )
const uint dest = GroupRayWriteOffset + activePrefixSum - 1; // -1 because activePrefixSum includes current thread, but arrays start from 0!
rayBuffer_WRITE[dest] = CreateStoredRay(ray);
#ifdef RAYTRACING_SORT_GLOBAL
rayIndexBuffer_WRITE[dest] = dest;
raySortBuffer_WRITE[dest] = CreateRaySortCode(ray);
#endif // RAYTRACING_SORT_GLOBAL
}
#endif // ADVANCED_ALLOCATION
}
+1 -1
View File
@@ -14,7 +14,7 @@ void main( uint3 DTid : SV_DispatchThreadID )
// write the indirect dispatch arguments:
indirectBuffer.Store3(RAYTRACE_INDIRECT_OFFSET_TRACE, uint3((rayCount + RAYTRACING_TRACE_GROUPSIZE - 1) / RAYTRACING_TRACE_GROUPSIZE, 1, 1));
indirectBuffer.Store3(RAYTRACE_INDIRECT_OFFSET_SORT, uint3((rayCount + RAYTRACING_SORT_GROUPSIZE - 1) / RAYTRACING_SORT_GROUPSIZE, 1, 1));
indirectBuffer.Store3(RAYTRACE_INDIRECT_OFFSET_TILESORT, uint3((rayCount + RAYTRACING_SORT_GROUPSIZE - 1) / RAYTRACING_SORT_GROUPSIZE, 1, 1));
// Reset counter buffer for this step:
counterBuffer_WRITE.Store(0, 0);
+4 -3
View File
@@ -14,10 +14,11 @@ void main( uint3 DTid : SV_DispatchThreadID )
// Create starting ray:
Ray ray = CreateCameraRay(uv);
ray.pixelID = flatten2D(DTid.xy, xTraceResolution.xy);
ray.pixelID = (DTid.x & 0xFFFF) | ((DTid.y & 0xFFFF) << 16);
// The launch writes each ray to the pixel location:
rayIndexBuffer[ray.pixelID] = ray.pixelID;
rayBuffer[ray.pixelID] = CreateStoredRay(ray);
const uint rayIndex = flatten2D(DTid.xy, xTraceResolution.xy);
rayIndexBuffer[rayIndex] = rayIndex;
rayBuffer[rayIndex] = CreateStoredRay(ray);
}
}
+4 -6
View File
@@ -18,14 +18,12 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
const uint rayIndex = rayIndexBuffer_READ[DTid.x];
//const uint rayIndex = DTid.x;
Ray ray = LoadRay(rayBuffer[rayIndex]);
// Compute real pixel coords from flattened:
uint2 coords2D = unflatten2D(ray.pixelID, xTraceResolution.xy);
uint2 pixel = uint2(ray.pixelID & 0xFFFF, (ray.pixelID >> 16) & 0xFFFF);
if (any(ray.energy))
{
float3 bounceResult = 0;
float2 uv = float2((coords2D + xTracePixelOffset) * xTraceResolution_rcp.xy * 2.0f - 1.0f) * float2(1, -1);
float2 uv = float2((pixel + xTracePixelOffset) * xTraceResolution_rcp.xy * 2.0f - 1.0f) * float2(1, -1);
float seed = xTraceRandomSeed;
TriangleData tri = TriangleData_Unpack(primitiveBuffer[ray.primitiveID], primitiveDataBuffer[ray.primitiveID]);
@@ -282,12 +280,12 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
// Pre-clear result texture for first bounce and first accumulation sample:
if (xTraceUserData.x == 1)
{
resultTexture[coords2D] = 0;
resultTexture[pixel] = 0;
}
if (!any(ray.energy) || xTraceUserData.y == 1)
{
// If the ray is killed or last bounce, we write to accumulation texture:
resultTexture[coords2D] = lerp(resultTexture[coords2D], float4(ray.color, 1), xTraceAccumulationFactor);
resultTexture[pixel] = lerp(resultTexture[pixel], float4(ray.color, 1), xTraceAccumulationFactor);
}
else
{
+1 -1
View File
@@ -45,7 +45,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
[branch]
if (DTid.x < counterBuffer_READ.Load(0))
{
sortcode = rayBuffer_READ[DTid.x].primitiveID;
sortcode = CreateRaySortCode(LoadRay(rayBuffer_READ[DTid.x]));
}
Array[groupIndex] = uint2(sortcode, DTid.x);
+22
View File
@@ -36,6 +36,28 @@ struct Ray
}
};
inline uint CreateRaySortCode(in Ray ray)
{
// Sorting purely based on morton code works best so far:
return morton3D((ray.origin - g_xFrame_WorldBoundsMin) * g_xFrame_WorldBoundsExtents_rcp);
//return ray.primitiveID;
//uint hash = 0;
//// quantize direction [-1; 1] on 8x4x8 grid (3 + 2 + 3 = 8 bits):
//hash |= (uint)clamp(ray.direction.x * 4 + 4, 0, 7) << 0;
//hash |= (uint)clamp(ray.direction.y * 2 + 2, 0, 3) << 3;
//hash |= (uint)clamp(ray.direction.z * 4 + 4, 0, 7) << 5;
//// quantize origin [0, 1] on 256x256x256 grid (8 bits per component):
//const float3 origin = (ray.origin - g_xFrame_WorldBoundsMin) * g_xFrame_WorldBoundsExtents_rcp;
//hash |= ((uint)abs(origin.x * 255) % 256) << 8;
//hash |= ((uint)abs(origin.x * 255) % 256) << 16;
//hash |= ((uint)abs(origin.x * 255) % 256) << 24;
//return (float)hash;
}
inline RaytracingStoredRay CreateStoredRay(in Ray ray)
{
RaytracingStoredRay storedray;
+17 -1
View File
@@ -7334,6 +7334,13 @@ void RayBuffers::Create(GraphicsDevice* device, uint32_t newRayCapacity)
device->CreateBuffer(&desc, nullptr, &rayIndexBuffer[1]);
device->SetName(&rayIndexBuffer[1], "rayIndexBuffer[1]");
#ifdef RAYTRACING_SORT_GLOBAL
desc.StructureByteStride = sizeof(float); // sorting needs float now
desc.ByteWidth = desc.StructureByteStride * rayCapacity;
device->CreateBuffer(&desc, nullptr, &raySortBuffer);
device->SetName(&raySortBuffer, "raySortBuffer");
#endif // RAYTRACING_SORT_GLOBAL
desc.StructureByteStride = sizeof(RaytracingStoredRay);
desc.ByteWidth = desc.StructureByteStride * rayCapacity;
device->CreateBuffer(&desc, nullptr, &rayBuffer[0]);
@@ -7496,6 +7503,10 @@ void RayTraceScene(
// Sort rays to achieve more coherency:
{
device->EventBegin("Ray Sorting", cmd);
#ifdef RAYTRACING_SORT_GLOBAL
wiGPUSortLib::Sort(rayBuffers->rayCapacity, rayBuffers->raySortBuffer, rayBuffers->rayCountBuffer[__readBufferID], 0, rayBuffers->rayIndexBuffer[__readBufferID], cmd);
#else
device->BindComputeShader(&computeShaders[CSTYPE_RAYTRACE_TILESORT], cmd);
const GPUResource* res[] = {
@@ -7508,10 +7519,11 @@ void RayTraceScene(
};
device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd);
device->DispatchIndirect(&indirectBuffer, RAYTRACE_INDIRECT_OFFSET_SORT, cmd);
device->DispatchIndirect(&indirectBuffer, RAYTRACE_INDIRECT_OFFSET_TILESORT, cmd);
device->Barrier(&GPUBarrier::Memory(), 1, cmd);
device->UnbindUAVs(0, arraysize(uavs), cmd);
#endif // RAYTRACING_SORT_GLOBAL
device->EventEnd(cmd);
}
@@ -7578,6 +7590,10 @@ void RayTraceScene(
const GPUResource* uavs[] = {
&rayBuffers->rayCountBuffer[__writeBufferID],
&rayBuffers->rayBuffer[__writeBufferID],
#ifdef RAYTRACING_SORT_GLOBAL
&rayBuffers->rayIndexBuffer[__writeBufferID],
&rayBuffers->raySortBuffer,
#endif // RAYTRACING_SORT_GLOBAL
};
device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd);
+1
View File
@@ -316,6 +316,7 @@ namespace wiRenderer
wiGraphics::GPUBuffer rayBuffer[2];
wiGraphics::GPUBuffer rayIndexBuffer[2];
wiGraphics::GPUBuffer rayCountBuffer[2];
wiGraphics::GPUBuffer raySortBuffer;
void Create(wiGraphics::GraphicsDevice* device, uint32_t newRayCapacity);
};
// Generate rays for every pixel of the internal resolution
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates
const int minor = 36;
// minor bug fixes, alterations, refactors, updates
const int revision = 46;
const int revision = 47;
long GetVersion()