Skip to content

Commit 7830cda

Browse files
committed
Merge branch 'dev/jerrans/nee-cache-packing' into 'main'
Raise primitive id bitcount at cost of reducing range bits. Refactor to make changes consistent. See merge request lightspeedrtx/dxvk-remix-nv!2288
2 parents a6c0b54 + 425c1fa commit 7830cda

5 files changed

Lines changed: 44 additions & 32 deletions

File tree

src/dxvk/shaders/rtx/algorithm/nee_cache.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,12 @@ struct NEECandidate
226226

227227
int getPrimitiveID()
228228
{
229-
return m_data.y & 0xffffff;
229+
return m_data.y & PRIMITIVE_INDEX_MAX_VALUE;
230230
}
231231

232232
[mutating] void setPrimitiveID(int primitiveID)
233233
{
234-
m_data.y = (m_data.y & 0xff000000) | primitiveID;
234+
m_data.y = (m_data.y & ~PRIMITIVE_INDEX_MAX_VALUE) | primitiveID;
235235
}
236236

237237
uint2 getIDData()
@@ -253,12 +253,12 @@ struct NEECandidate
253253

254254
int getRange()
255255
{
256-
return (m_data.y >> 24) & 0xff;
256+
return (m_data.y >> PRIMITIVE_INDEX_BIT_COUNT) & NEE_RANGE_MAX;
257257
}
258258

259259
[mutating] void setRange(uint range)
260260
{
261-
m_data.y = (m_data.y & 0xffffff) | (range << 24);
261+
m_data.y = (m_data.y & PRIMITIVE_INDEX_MAX_VALUE) | (range << PRIMITIVE_INDEX_BIT_COUNT);
262262
}
263263

264264
static NEECandidate create(uint surfaceID, uint primitiveID, uint range)
@@ -385,16 +385,19 @@ struct NEECell
385385

386386
static bool isLightTask(uint2 value)
387387
{
388-
return (value.x & (1 << 24)) != 0;
388+
return (value.x & (1 << NEE_ISLIGHT_BIT)) != 0;
389389
}
390390

391391
void insertSlotTask(uint task, vec3 radiance, bool isLightTask) {
392+
if (!isLightTask && task > PRIMITIVE_INDEX_MAX_VALUE) {
393+
return;
394+
}
392395
float accumulateValue = calcBt709Luminance(radiance);
393396
float randomOffset = (reversebits(asuint(accumulateValue)) >> 22) / 1024.0f;
394397
uint index = getSlotBinHash(task + cb.frameIdx);
395398
int taskAddress = getHashTaskAddress(index);
396399
uint sortValueI = firstbithigh(uint(min(accumulateValue, 50) / 0.001));
397-
task |= (sortValueI << 25) | (isLightTask ? (1 << 24) : 0);
400+
task |= (sortValueI << NEE_SORT_SHIFT) | (isLightTask ? (1 << NEE_ISLIGHT_BIT) : 0);
398401

399402
// Clamp min/max value before accumulation to improve stability.
400403
// The min value is required because floating point atomics is not supported on all platforms,

src/dxvk/shaders/rtx/algorithm/nee_cache_data.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* DEALINGS IN THE SOFTWARE.
2121
*/
2222
#pragma once
23+
#include "rtx/pass/instance_definitions.h"
2324

2425
#define NEE_CACHE_PROBE_RESOLUTION 32
2526
#define NEE_CACHE_TOTAL_PROBE (NEE_CACHE_PROBE_RESOLUTION * NEE_CACHE_PROBE_RESOLUTION * NEE_CACHE_PROBE_RESOLUTION)

src/dxvk/shaders/rtx/algorithm/nee_cache_light.slangh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323

2424
#include "rtx/concept/light/light_helper.slangh"
2525
#include "rtx/concept/light/light.slangh"
26-
#define NEE_CACHE_INVALID_ID 0xffffff
26+
#include "rtx/pass/instance_definitions.h"
27+
#define NEE_CACHE_INVALID_ID PRIMITIVE_INDEX_MAX_VALUE
2728

2829
struct NEECacheUtils
2930
{
@@ -241,7 +242,7 @@ struct NEECacheUtils
241242
{
242243
trianglePdf /= float(range);
243244
float triangleExplorationProbability = cb.neeCacheArgs.triangleExplorationProbability;
244-
if (uvw.z < triangleExplorationProbability && range < 255)
245+
if (uvw.z < triangleExplorationProbability && range < NEE_RANGE_MAX)
245246
{
246247
// Sample a triangle outside the given range with a low probability to search potential emissive triangles.
247248
// The code here is slightly biased because we use the probability for triangles inside the range,

src/dxvk/shaders/rtx/pass/instance_definitions.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,21 @@
138138

139139
// Engine-wide index limits.
140140
// SurfaceIndex: 21 bits (fits in the 24-bit instanceCustomIndex alongside 2-bit material type + 1-bit view-model flag).
141-
// PrimitiveIndex: 26 bits (max ~67M triangles per scene).
141+
// PrimitiveIndex: 27 bits (max 134M triangles per scene). Other packing constants are derived from this value.
142142
#define SURFACE_INDEX_BIT_COUNT 21
143143
#define SURFACE_INDEX_MAX_VALUE ((1 << SURFACE_INDEX_BIT_COUNT) - 1)
144-
#define PRIMITIVE_INDEX_BIT_COUNT 26
144+
#define PRIMITIVE_INDEX_BIT_COUNT 27
145145
#define PRIMITIVE_INDEX_MAX_VALUE ((1 << PRIMITIVE_INDEX_BIT_COUNT) - 1)
146146

147+
// NEE packing constants
148+
// The sort key packed above this shift is limited to 32 - PRIMITIVE_INDEX_BIT_COUNT - 1 (for NEE_ISLIGHT_BIT)
149+
// Current max value in nee_cache.h is: firstbithigh(50 / 0.001); which requires 4 bits so with a PRIMITIVE_INDEX_BIT_COUNT
150+
// of 27 there is no capacity to increase the PRIMITIVE_INDEX_BIT_COUNT, only to reduce it (or change the structure)
151+
#define NEE_ISLIGHT_BIT PRIMITIVE_INDEX_BIT_COUNT
152+
#define NEE_SORT_SHIFT (NEE_ISLIGHT_BIT + 1)
153+
#define NEE_RANGE_BITS (32 - PRIMITIVE_INDEX_BIT_COUNT)
154+
#define NEE_RANGE_MAX ((1 << NEE_RANGE_BITS) - 1)
155+
147156
// Custom Index encoding (24-bit VkAccelerationStructureInstanceKHR.instanceCustomIndex)
148157
// Bits 0..20 : surface index (CUSTOM_INDEX_SURFACE_MASK)
149158
// Bits 21..22 : material type (CUSTOM_INDEX_MATERIAL_TYPE_MASK)

src/dxvk/shaders/rtx/pass/nee_cache/update_nee_cache.comp.slang

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@
4343
#define UPDATE_NEE_CACHE 1
4444
#include "rtx/algorithm/nee_cache.h"
4545

46-
#define INVALID_ID 0xffffff
47-
4846
#define CANDIDATE_LENGTH NEE_CACHE_ELEMENTS * 2
4947
#define CANDIDATE_GROUP_SIZE 16
5048
#define BATCH_SIZE 8
@@ -226,8 +224,8 @@ void updateTriangleTask(NEECell cell, uint2 localIndex)
226224
int taskID = localIndex.x;
227225
uint2 value = cell.getSlotTaskValue(taskID);
228226
int surfaceID, primitiveID;
229-
uint oldRange = (value.x & 0xff000000);
230-
value.x = convertToThisFramePrefixSumID(value.x & 0xffffff, surfaceID, primitiveID);
227+
uint oldRange = (value.x & ~PRIMITIVE_INDEX_MAX_VALUE);
228+
value.x = convertToThisFramePrefixSumID(value.x & PRIMITIVE_INDEX_MAX_VALUE, surfaceID, primitiveID);
231229
value.x |= oldRange;
232230
int delta = max(value.y * cb.neeCacheArgs.learningRate, 1);
233231
value.y = clamp(int(value.y) - delta, 0, 1 << 25);
@@ -264,7 +262,7 @@ void updateTriangleTask(NEECell cell, uint2 localIndex)
264262
{
265263
continue;
266264
}
267-
value.x &= 0xffffff;
265+
value.x &= PRIMITIVE_INDEX_MAX_VALUE;
268266
int surfaceID, primitiveID;
269267
value.x = convertToThisFramePrefixSumID(value.x, surfaceID, primitiveID);
270268
value.y = min(maxDeltaValue, value.y);
@@ -288,8 +286,8 @@ void updateTriangleTask(NEECell cell, uint2 localIndex)
288286
bool found = false;
289287
for (int j = 0; j < existingCount; ++j)
290288
{
291-
int firstPrimitiveID = (s_candidateList[j][localIndex.y].x & 0xffffff);
292-
int range = (s_candidateList[j][localIndex.y].x >> 24);
289+
int firstPrimitiveID = (s_candidateList[j][localIndex.y].x & PRIMITIVE_INDEX_MAX_VALUE);
290+
int range = (s_candidateList[j][localIndex.y].x >> PRIMITIVE_INDEX_BIT_COUNT);
293291
if (value.x >= firstPrimitiveID && value.x < firstPrimitiveID + range)
294292
{
295293
s_candidateList[j][localIndex.y].y += value.y;
@@ -300,7 +298,7 @@ void updateTriangleTask(NEECell cell, uint2 localIndex)
300298

301299
if (!found)
302300
{
303-
value.x = ((1 << 24) | value.x);
301+
value.x = ((1 << PRIMITIVE_INDEX_BIT_COUNT) | value.x);
304302
insertTask(value, localIndex.y);
305303
}
306304
}
@@ -314,9 +312,9 @@ void updateTriangleTask(NEECell cell, uint2 localIndex)
314312
for (int i = localIndex.x; i < NEE_CACHE_HASH_TASK_COUNT && cb.neeCacheArgs.triangleExplorationProbability > 0; i += CANDIDATE_GROUP_SIZE)
315313
{
316314
uint2 data = s_candidateList[i][localIndex.y];
317-
uint range = (data.x >> 24);
318-
uint primitiveID = (data.x & 0xffffff);
319-
uint2 newData = uint2(data.y, (primitiveID << 8) | range);
315+
uint range = (data.x >> PRIMITIVE_INDEX_BIT_COUNT);
316+
uint primitiveID = (data.x & PRIMITIVE_INDEX_MAX_VALUE);
317+
uint2 newData = uint2(data.y, (primitiveID << NEE_RANGE_BITS) | range);
320318
s_candidateList[i][localIndex.y] = newData;
321319
}
322320

@@ -335,8 +333,8 @@ void updateTriangleTask(NEECell cell, uint2 localIndex)
335333
for (int i = 0; i < count; i++)
336334
{
337335
uint2 data = s_candidateList[i][localIndex.y];
338-
uint newRange = (data.y & 0xff);
339-
uint newPrefixSumID = (data.y >> 8);
336+
uint newRange = (data.y & NEE_RANGE_MAX);
337+
uint newPrefixSumID = (data.y >> NEE_RANGE_BITS);
340338
uint newValue = data.x;
341339
totalValue += newValue;
342340
}
@@ -350,24 +348,24 @@ void updateTriangleTask(NEECell cell, uint2 localIndex)
350348
for (int i = 0; i < count; i++)
351349
{
352350
uint2 data = s_candidateList[i][localIndex.y];
353-
uint newRange = (data.y & 0xff);
354-
uint newPrefixSumID = (data.y >> 8);
351+
uint newRange = (data.y & NEE_RANGE_MAX);
352+
uint newPrefixSumID = (data.y >> NEE_RANGE_BITS);
355353
uint newValue = data.x;
356354

357355
int newSurfaceID, newPrimitiveID;
358356
NEECacheUtils.convertPrefixSumIDToID(newPrefixSumID, PrimitiveIDPrefixSum, newSurfaceID, newPrimitiveID);
359357
int primitiveCount = NEECacheUtils.getSurfacePrimitiveCount(newSurfaceID, PrimitiveIDPrefixSum);
360358
int gab = min(cb.neeCacheArgs.triangleExplorationMaxRange, cb.neeCacheArgs.triangleExplorationRangeRatio * primitiveCount) *
361359
cb.neeCacheArgs.triangleExplorationAcceptRangeRatio + 1;
362-
if (newSurfaceID == oldSurfaceID && oldPrimitiveID < newPrimitiveID + newRange + gab && oldPrimitiveID + oldRange - newPrimitiveID < 255 &&
360+
if (newSurfaceID == oldSurfaceID && oldPrimitiveID < newPrimitiveID + newRange + gab && oldPrimitiveID + oldRange - newPrimitiveID < NEE_RANGE_MAX &&
363361
oldValue + newValue < maxMergeValue)
364362
{
365363
// Merge
366364
oldRange = oldPrimitiveID + oldRange - newPrimitiveID;
367365
oldPrefixSumID = newPrefixSumID;
368366
oldPrimitiveID = newPrimitiveID;
369367
oldValue += newValue;
370-
s_candidateList[oldIndex][localIndex.y] = uint2((oldRange << 24) | oldPrefixSumID, oldValue);
368+
s_candidateList[oldIndex][localIndex.y] = uint2((oldRange << PRIMITIVE_INDEX_BIT_COUNT) | oldPrefixSumID, oldValue);
371369
newValue = 0;
372370
newRange = 0;
373371
}
@@ -382,7 +380,7 @@ void updateTriangleTask(NEECell cell, uint2 localIndex)
382380
oldValue = newValue;
383381
}
384382

385-
s_candidateList[i][localIndex.y] = uint2((newRange << 24) | newPrefixSumID, newValue);
383+
s_candidateList[i][localIndex.y] = uint2((newRange << PRIMITIVE_INDEX_BIT_COUNT) | newPrefixSumID, newValue);
386384
}
387385
}
388386

@@ -400,7 +398,7 @@ void updateTriangleTask(NEECell cell, uint2 localIndex)
400398
if (cb.neeCacheArgs.triangleExplorationProbability == 0.0)
401399
{
402400
uint2 task = s_candidateList[localIndex.x][localIndex.y];
403-
task.x = (task.x & 0xffffff) | (1 << 24);
401+
task.x = (task.x & PRIMITIVE_INDEX_MAX_VALUE) | (1 << PRIMITIVE_INDEX_BIT_COUNT);
404402

405403
s_candidateList[localIndex.x][localIndex.y].x = task.x;
406404
GroupMemoryBarrierWithGroupSync();
@@ -421,8 +419,8 @@ void updateTriangleTask(NEECell cell, uint2 localIndex)
421419
int candidateID = localIndex.x;
422420
uint2 task = s_candidateList[candidateID][localIndex.y];
423421
int surfaceID, primitiveID;
424-
NEECacheUtils.convertPrefixSumIDToID(task.x & 0xffffff, PrimitiveIDPrefixSum, surfaceID, primitiveID);
425-
NEECandidate candidate = NEECandidate.create(surfaceID, primitiveID, max(1, task.x >> 24));
422+
NEECacheUtils.convertPrefixSumIDToID(task.x & PRIMITIVE_INDEX_MAX_VALUE, PrimitiveIDPrefixSum, surfaceID, primitiveID);
423+
NEECandidate candidate = NEECandidate.create(surfaceID, primitiveID, max(1, task.x >> PRIMITIVE_INDEX_BIT_COUNT));
426424

427425
candidate.setSampleProbability(s_candidateLight[candidateID][localIndex.y]);
428426
cell.setCandidate(candidateID, candidate);
@@ -539,7 +537,7 @@ void updateLightTask(NEECell cell, uint2 localIndex)
539537
{
540538
continue;
541539
}
542-
value.x &= 0xffffff;
540+
value.x &= PRIMITIVE_INDEX_MAX_VALUE;
543541
value.x = convertLightIndex(value.x);
544542
value.y = min(maxDeltaValue, value.y);
545543

0 commit comments

Comments
 (0)