diff --git a/include/SharcCommon.h b/include/SharcCommon.h index 5531961..aee0cdc 100644 --- a/include/SharcCommon.h +++ b/include/SharcCommon.h @@ -564,6 +564,12 @@ void SharcUpdateMiss(in SharcParameters sharcParameters, in SharcState sharcStat for (int i = 0; i < sharcState.pathLength; ++i) { HashGridIndex hashGridIndex = sharcState.cacheIndices[i]; + // A full bucket makes HashGridInsertEntry return HASH_GRID_INVALID_CACHE_INDEX and SharcUpdateHit stores + // that sentinel into cacheIndices verbatim. It must be skipped before the responsive offset/mask block: + // masking it unconditionally rewrites it to SHARC_CACHE_INDEX_BIT_MASK, which is no longer INVALID, so + // SharcAddVoxelData's guard passes and the atomics land far past the end of the accumulation buffer + if (hashGridIndex == HASH_GRID_INVALID_CACHE_INDEX) + continue; bool isNewSample = false; #if SHARC_ENABLE_RESPONSIVE_LIGHTING if (isResponsiveLighting) @@ -659,6 +665,9 @@ bool SharcUpdateHit(in SharcParameters sharcParameters, inout SharcState sharcSt for (i = 0; i < sharcState.pathLength; ++i) { HashGridIndex tempHashGridIndex = sharcState.cacheIndices[i]; + // Skip full-bucket sentinels before the responsive offset/mask block — same reasoning as SharcUpdateMiss + if (tempHashGridIndex == HASH_GRID_INVALID_CACHE_INDEX) + continue; bool isNewSample = false; #if SHARC_ENABLE_RESPONSIVE_LIGHTING if (responsiveCacheIndex != HASH_GRID_INVALID_CACHE_INDEX) @@ -892,10 +901,13 @@ void SharcResolveEntry(uint entryIndex, SharcParameters sharcParameters, SharcRe // Performs hash map lookup to find existing entries in case previous insertions // encountered collisions and a different slot was assigned. - // Uses a fixed-size linear probe window + // Uses a fixed-size linear probe window, clamped to the table capacity: an application is allowed to + // allocate exactly `capacity` entries, so entries in the last window cannot blindly look forward — + // doing so reads past the end of the hash-entry and resolved buffers once those slots become occupied if (sampleNumPrev == 0) { - for (uint i = entryIndex + 1; i < entryIndex + 1 + SHARC_LINEAR_PROBE_WINDOW_SIZE; ++i) + uint probeEnd = min(entryIndex + 1 + SHARC_LINEAR_PROBE_WINDOW_SIZE, sharcParameters.hashGridData.capacity); + for (uint i = entryIndex + 1; i < probeEnd; ++i) { HashGridKey hashKeyOld = BUFFER_AT_OFFSET(sharcParameters.hashGridData.hashEntriesBuffer, i); if (hashKeyOld == hashGridKey)