Skip to content

Commit

Permalink
probe hash-map: colision resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
Try committed Aug 27, 2023
1 parent 505b504 commit 8832b4e
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 52 deletions.
12 changes: 7 additions & 5 deletions game/graphics/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,13 @@ void Renderer::resetSwapchain() {
gi.probeDrawPso = &Shaders::inst().probeDraw;
gi.uboDraw = device.descriptors(*gi.probeDrawPso);

const uint32_t maxProbes = gi.maxProbes;
if(gi.hashTable.isEmpty()) {
gi.hashTable = device.ssbo(nullptr, 2'097'152*sizeof(uint32_t)); // 8MB
gi.voteTable = device.ssbo(nullptr, gi.hashTable.byteSize());
gi.probes = device.ssbo(nullptr, 8*1024*1024); // ~26K
gi.freeList = device.ssbo(nullptr, gi.probes.byteSize()); // TODO: fine size
gi.probes = device.ssbo(nullptr, maxProbes*128 + 64); // probes and header
gi.freeList = device.ssbo(nullptr, maxProbes*sizeof(uint32_t) + sizeof(int32_t));
// gi.probesGBuff = device.image3d(TextureFormat::RGBA8, maxProbes*16, 8, 2); // 16x8 tile
}

uint32_t zero = 0;
Expand Down Expand Up @@ -714,7 +716,7 @@ void Renderer::prepareGi(Tempest::Encoder<Tempest::CommandBuffer>& cmd, uint8_t
cmd.dispatchThreads(sceneDepth.size());

cmd.setUniforms(*gi.probeGCPso, gi.uboProbes);
cmd.dispatch(1024);
cmd.dispatchThreads(gi.maxProbes);

cmd.setUniforms(*gi.probeAllocPso, gi.uboProbes);
cmd.dispatchThreads(sceneDepth.size());
Expand All @@ -741,13 +743,13 @@ void Renderer::drawProbesDbg(Tempest::Encoder<Tempest::CommandBuffer>& cmd, uint
gi.uboDbg = device.descriptors(pso);
gi.uboDbg.set(0, wview->sceneGlobals().uboGlobal[SceneGlobals::V_Main]);
gi.uboDbg.set(1, gi.probes);
gi.uboDbg.set(2, gi.hashTable);
}
}

cmd.setDebugMarker("GI-dbg");
const size_t cnt = (gi.probes.byteSize()-sizeof(uint32_t))/(sizeof(float)*28);
cmd.setUniforms(pso, gi.uboDbg);
cmd.draw(36, 0, cnt);
cmd.draw(36, 0, gi.maxProbes);
}

void Renderer::drawAmbient(Encoder<CommandBuffer>& cmd, const WorldView& view) {
Expand Down
1 change: 1 addition & 0 deletions game/graphics/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ class Renderer final {
} hiz;

struct {
const uint32_t maxProbes = 65535-1;
Tempest::DescriptorSet uboDbg;

Tempest::ComputePipeline* probeClearPso = nullptr;
Expand Down
23 changes: 13 additions & 10 deletions shader/lighting/rt/probe_allocation.comp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ layout(binding = 0, std140) uniform UboScene {
layout(binding = 1) uniform sampler2D diffuse;
layout(binding = 2) uniform sampler2D normals;
layout(binding = 3) uniform sampler2D depth;
layout(binding = 4, std430) buffer Hbo0 { uint voteTable[]; };
layout(binding = 5, std430) buffer Hbo { Hash hashTable[]; };
layout(binding = 6, std430) buffer Pbo { ProbesHeader probeHeader; Probe probe[]; };
layout(binding = 7, std430) buffer Fbo0 { int cursor; uint list[]; } freeList;
layout(binding = 4, std430) buffer Hbo0 { uint voteTable[]; };
layout(binding = 5, std430) readonly buffer Hbo { Hash hashTable[]; };
layout(binding = 6, std430) buffer Pbo { ProbesHeader probeHeader; Probe probe[]; };
layout(binding = 7, std430) buffer Fbo0 { int cursor; uint list[]; } freeList;

ivec2 screenSize, fragCoord;
uint threadId;
Expand Down Expand Up @@ -68,6 +68,7 @@ bool reuseProbe(const uint h, vec3 pos) {
return false; // NOTE: reconstructed position may jitter a little

probe[probeId].bits |= REUSE_BIT;
probe[probeId].pNext = 0xFFFFFFFF;
return true;
}

Expand All @@ -93,6 +94,7 @@ void processProbe(ivec3 gridPos, vec3 pos, int lod, vec3 pixelPos, vec3 pixelNor
Probe p;
p.pos = pos;
p.bits = 0;
p.pNext = 0xFFFFFFFF;
probe[cursor] = p;
#endif
}
Expand All @@ -111,9 +113,8 @@ void main_process() {
if(z>=0.99995)
return; // sky

const float bias = 2.0;
const float dist = linearDepth(z, scene.clipInfo);
const vec3 pos = unprojectDepth(z) + norm*bias;
const vec3 pos = unprojectDepth(z) + norm*probeCageBias;
const int lod = probeGridLodFromDist(dist);

probeQuery pq;
Expand All @@ -130,13 +131,13 @@ void main_process() {
}

void main_clear() {
const uint laneID = gl_GlobalInvocationID.x;
const uint threadID = gl_GlobalInvocationID.x;

if(laneID<voteTable.length()) {
voteTable[laneID] = 0xFFFFFFFF;
if(threadID<voteTable.length()) {
voteTable[threadID] = 0xFFFFFFFF;
}

if(laneID==0) {
if(threadID==0) {
probeHeader.count = min(probeHeader.count, probe.length());
probeHeader.iterator = 0;
probeHeader.tracedCount = 0;
Expand All @@ -149,6 +150,8 @@ void main_gc() {
if(probeId>=probeHeader.count)
return;

probe[probeId].pNext = 0xFFFFFFFF;

if((probe[probeId].bits & REUSE_BIT)!=0)
return;

Expand Down
82 changes: 68 additions & 14 deletions shader/lighting/rt/probe_ambient.frag
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "lighting/rt/probe_common.glsl"
#include "lighting/tonemapping.glsl"
#include "lighting/purkinje_shift.glsl"
#include "scene.glsl"
#include "common.glsl"

Expand All @@ -30,19 +31,66 @@ vec3 unprojectDepth(const float z) {
return (ret.xyz/ret.w);
}

void processProbe(ivec3 gridPos, vec3 pos, int lod, vec3 pixelPos, vec3 pixelNorm, bool ignoreBad) {
const uint h = probeGridPosHash(gridPos) % hashTable.length();
const uint cursor = hashTable[h].value;
if(cursor>=probeHeader.count)
Probe mkZeroProbe() {
Probe px;
px.color[0][0] = vec4(0);
px.color[0][1] = vec4(0);
px.color[1][0] = vec4(0);
px.color[1][1] = vec4(0);
px.color[2][0] = vec4(0);
px.color[2][1] = vec4(0);
px.bits = UNUSED_BIT;
return px;
}

Probe readProbe(const ivec3 gridPos, const vec3 wpos) {
const uint h = probeGridPosHash(gridPos) % hashTable.length();
uint probeId = hashTable[h].value;

[[loop]]
for(int i=0; i<8; ++i) {
if(probeId>=probeHeader.count)
return mkZeroProbe();

const Probe p = probe[probeId];
if((p.bits & TRACED_BIT)==0)
return p;

const vec3 dp = wpos - p.pos;
if(dot(dp,dp)>1.0) {
probeId = p.pNext;
continue;
}
return p;
}

return mkZeroProbe();
}

void processProbe(ivec3 gridPos, vec3 wpos, int lod, vec3 pixelPos, vec3 pixelNorm, bool ignoreBad) {
const vec3 ldir = wpos-pixelPos;
if(dot(ldir, pixelNorm)<=0)
return;

const Probe p = probe[cursor];
const vec3 ldir = p.pos-pixelPos;
const Probe p = readProbe(gridPos, wpos);
if((p.bits & TRACED_BIT)==0)
return;

if((p.bits & BAD_BIT)!=0 && !ignoreBad)
return;
if(dot(ldir, pixelNorm)<=0)
return;

vec3 dp = wpos - p.pos;
if(dot(dp,dp)>1.0) {
// debug
// colorSum += vec4(vec3(0,0,1)*scene.GSunIntensity,1);
// return; // position is not what was expeted - hash collision
}

if(ivec3(p.pos/probeGridStep)!=gridPos) {
// debug
// colorSum += vec4(vec3(0,0,1)*scene.GSunIntensity,1);
// return;
}

float weight = 1;
// cosine weight from https://advances.realtimerendering.com/s2015/SIGGRAPH_2015_Remedy_Notes.pdf
Expand All @@ -56,12 +104,12 @@ void processProbe(ivec3 gridPos, vec3 pos, int lod, vec3 pixelPos, vec3 pixelNor
}

void gather(vec3 pos, vec3 norm, int lod, bool ignoreBad) {
colorSum = vec4(0);

probeQuery pq;
probeQueryInitialize(pq, pos, lod);
while(probeQueryProceed(pq)) {
vec3 wpos = probeQueryWorldPos(pq);
vec3 dir = (wpos-pos);

vec3 wpos = probeQueryWorldPos(pq);
ivec3 gPos = probeQueryGridPos(pq);
processProbe(gPos, wpos, lod, pos, norm, ignoreBad);
}
Expand All @@ -80,21 +128,27 @@ void main() {
const vec3 diff = texelFetch(gbufDiffuse, ivec2(gl_FragCoord.xy), 0).rgb;
const vec3 norm = normalize(texelFetch(gbufNormal,ivec2(gl_FragCoord.xy),0).xyz*2.0-vec3(1.0));

const float bias = 2.0;
const float dist = linearDepth(z, scene.clipInfo);
const vec3 pos = unprojectDepth(z) + norm*bias;
const vec3 pos = unprojectDepth(z) + norm*probeCageBias;
const int lod = probeGridLodFromDist(dist);

gather(pos, norm, lod, false);
if(colorSum.w<=0.000001) {
// maybe all probes do have bad-bit, check one LOD above for data
gather(pos, norm, lod, true);
}

if(colorSum.w<=0.000001) {
// debug
// colorSum = vec4(vec3(1,0,0)*scene.GSunIntensity,1);
colorSum = vec4(0,0,0,1);
}

const vec3 linear = textureAlbedo(diff);

vec3 color = colorSum.rgb/max(colorSum.w,0.000001);
color *= linear;
// night shift
color += purkinjeShift(color);
color *= scene.exposure;
// color = linear;
outColor = vec4(color, 1);
Expand Down
24 changes: 17 additions & 7 deletions shader/lighting/rt/probe_common.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,31 @@ const uint REUSE_BIT = 0x4;
const uint BAD_BIT = 0x8;
const uint NEW_BIT = 0x10; //for debug view

struct Probe {
struct ProbesHeader { // 64 bytes
uint count;
uint iterator;
uint tracedCount;
uint padd0;
uint padd1[12];
//uint padd2[16];
};

struct Probe { // 128 bytes
vec3 pos;
uint bits;
vec3 color[3][2]; // HL2-cube
//uvec2 gbuffer[128]; // x: normal[xy]; w - color[rgb]; normal[z]
uint pNext;
uint padd1[3];
vec4 color[3][2]; // HL2-cube
};

struct ProbesHeader {
uint count;
uint iterator;
uint tracedCount;
struct ProbeGBuffer {
uvec2 gbuffer[128]; // x: normal[xy]; w - color[rgb]; normal[z]
};

const float dbgViewRadius = 5;
const float probeGridStep = 50;
const float probeCageBias = 5.0;
const float probeBadHitT = 4.5;

uint probeGridPosHash(ivec3 gridPos) {
return (gridPos.x * 18397) + (gridPos.y * 20483) + (gridPos.z * 29303);
Expand Down
6 changes: 5 additions & 1 deletion shader/lighting/rt/probe_dbg.frag
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ layout(binding = 1, std430) readonly buffer Pbo { ProbesHeader probeHeader; Prob

layout(location = 0) in vec3 center;
layout(location = 1) in flat uint instanceIndex;
layout(location = 2) in flat uint isHashed;

layout(location = 0) out vec4 outColor;

Expand All @@ -27,7 +28,7 @@ vec3 unprojectDepth(float z) {
vec3 lodColor(const in Probe p, vec3 norm) {
float lamb = max(dot(scene.sunDir, norm), 0);
float light = lamb*0.7+0.3;
return p.color[0][0]*light;
return p.color[0][0].rgb*light;
}

void main(void) {
Expand All @@ -51,6 +52,9 @@ void main(void) {
if((p.bits & NEW_BIT)!=0)
clr = vec3(0,1,0);

if(isHashed==0)
clr = vec3(0,0,1);

outColor = vec4(clr,1.0);
// outColor = vec4(1,0,0,1.0);
}
14 changes: 11 additions & 3 deletions shader/lighting/rt/probe_dbg.vert
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ layout(binding = 0, std140) uniform UboScene {
SceneDesc scene;
};
layout(binding = 1, std430) readonly buffer Pbo { ProbesHeader probeHeader; Probe probe[]; };
layout(binding = 2, std430) buffer Hbo0 { Hash hashTable[]; };

layout(location = 0) out vec3 center;
layout(location = 1) out flat uint instanceIndex;
layout(location = 2) out flat uint isHashed;


const vec3 v[8] = {
Expand All @@ -37,17 +39,23 @@ const uint index[36] = {
};

void main() {
if(gl_InstanceIndex>=probeHeader.count) {
const uint probeId = gl_InstanceIndex;
if(probeId>=probeHeader.count) {
gl_Position = vec4(0);
return;
}

Probe p = probe[gl_InstanceIndex];
Probe p = probe[probeId];
//p.pos = vec3(0);

vec3 vert = v[index[gl_VertexIndex]];

gl_Position = scene.viewProject * vec4(p.pos + vert * dbgViewRadius, 1.0);
center = p.pos;
instanceIndex = gl_InstanceIndex;
instanceIndex = probeId;

const vec3 gridPos = probe[probeId].pos/probeGridStep;
const uint h = probeGridPosHash(ivec3(gridPos)) % hashTable.length();
const uint cursor = hashTable[h].value;
isHashed = (cursor==probeId) ? 1 : 0;
}
Loading

0 comments on commit 8832b4e

Please sign in to comment.