Skip to content

Commit

Permalink
fix: light clustering issues (doodlum#708)
Browse files Browse the repository at this point in the history
* fix: VR light clusters

* style: 🎨 apply clang-format changes

* fix: light cluster race condition

---------

Co-authored-by: doodlum <doodlum@users.noreply.github.com>
  • Loading branch information
doodlum and doodlum authored Oct 30, 2024
1 parent 50d9bed commit 8252889
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ RWStructuredBuffer<LightGrid> lightGrid : register(u2);

groupshared StructuredLight sharedLights[GROUP_SIZE];

bool LightIntersectsCluster(StructuredLight light, ClusterAABB cluster, int eyeIndex = 0)
bool LightIntersectsCluster(float3 position, float radius, ClusterAABB cluster)
{
float3 closest = max(cluster.minPoint.xyz, min(light.positionVS[eyeIndex].xyz, cluster.maxPoint.xyz));
float3 closest = max(cluster.minPoint.xyz, min(position, cluster.maxPoint.xyz));

float3 dist = closest - light.positionVS[eyeIndex].xyz;
return dot(dist, dist) <= (light.radius * light.radius);
float3 dist = closest - position;
return dot(dist, dist) <= radius;
}

[numthreads(NUMTHREAD_X, NUMTHREAD_Y, NUMTHREAD_Z)] void main(
Expand All @@ -34,10 +34,6 @@ bool LightIntersectsCluster(StructuredLight light, ClusterAABB cluster, int eyeI
if (any(dispatchThreadId >= uint3(CLUSTER_BUILDING_DISPATCH_SIZE_X, CLUSTER_BUILDING_DISPATCH_SIZE_Y, CLUSTER_BUILDING_DISPATCH_SIZE_Z)))
return;

if (all(dispatchThreadId == 0)) {
lightIndexCounter[0] = 0;
}

uint visibleLightCount = 0;
uint visibleLightIndices[MAX_CLUSTER_LIGHTS];

Expand All @@ -58,15 +54,19 @@ bool LightIntersectsCluster(StructuredLight light, ClusterAABB cluster, int eyeI
for (uint i = 0; i < LightCount; i++) {
StructuredLight light = lights[i];

bool updateCluster = LightIntersectsCluster(light, cluster);
#ifdef VR
updateCluster = updateCluster || LightIntersectsCluster(light, cluster, 1);
#endif // VR
updateCluster = updateCluster && (visibleLightCount < MAX_CLUSTER_LIGHTS);
float radius = light.radius * light.radius;

if (updateCluster) {
#if defined(VR)
[branch] if (LightIntersectsCluster(light.positionVS[0], radius, cluster) || LightIntersectsCluster(light.positionVS[1], radius, cluster))
{
#else
[branch] if (LightIntersectsCluster(light.positionVS[0], radius, cluster))
{
#endif
visibleLightIndices[visibleLightCount] = i;
visibleLightCount++;
if (visibleLightCount >= MAX_CLUSTER_LIGHTS)
break;
}
}

Expand Down
23 changes: 13 additions & 10 deletions src/Features/LightLimitFix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,20 +185,20 @@ void LightLimitFix::SetupResources()
numElements = 1;
sbDesc.StructureByteStride = sizeof(uint32_t);
sbDesc.ByteWidth = sizeof(uint32_t) * numElements;
lightCounter = eastl::make_unique<Buffer>(sbDesc);
lightIndexCounter = eastl::make_unique<Buffer>(sbDesc);
srvDesc.Buffer.NumElements = numElements;
lightCounter->CreateSRV(srvDesc);
lightIndexCounter->CreateSRV(srvDesc);
uavDesc.Buffer.NumElements = numElements;
lightCounter->CreateUAV(uavDesc);
lightIndexCounter->CreateUAV(uavDesc);

numElements = clusterCount * CLUSTER_MAX_LIGHTS;
sbDesc.StructureByteStride = sizeof(uint32_t);
sbDesc.ByteWidth = sizeof(uint32_t) * numElements;
lightList = eastl::make_unique<Buffer>(sbDesc);
lightIndexList = eastl::make_unique<Buffer>(sbDesc);
srvDesc.Buffer.NumElements = numElements;
lightList->CreateSRV(srvDesc);
lightIndexList->CreateSRV(srvDesc);
uavDesc.Buffer.NumElements = numElements;
lightList->CreateUAV(uavDesc);
lightIndexList->CreateUAV(uavDesc);

numElements = clusterCount;
sbDesc.StructureByteStride = sizeof(LightGrid);
Expand Down Expand Up @@ -454,7 +454,7 @@ void LightLimitFix::Prepass()

ID3D11ShaderResourceView* views[3]{};
views[0] = lights->srv.get();
views[1] = lightList->srv.get();
views[1] = lightIndexList->srv.get();
views[2] = lightGrid->srv.get();
context->PSSetShaderResources(50, ARRAYSIZE(views), views);
}
Expand Down Expand Up @@ -991,14 +991,17 @@ void LightLimitFix::UpdateLights()
updateData.LightCount = lightCount;
lightCullingCB->Update(updateData);

UINT counterReset[4] = { 0, 0, 0, 0 };
context->ClearUnorderedAccessViewUint(lightIndexCounter->uav.get(), counterReset);

ID3D11Buffer* buffer = lightCullingCB->CB();
context->CSSetConstantBuffers(0, 1, &buffer);

ID3D11ShaderResourceView* srvs[] = { clusters->srv.get(), lights->srv.get() };
context->CSSetShaderResources(0, 2, srvs);
context->CSSetShaderResources(0, ARRAYSIZE(srvs), srvs);

ID3D11UnorderedAccessView* uavs[] = { lightCounter->uav.get(), lightList->uav.get(), lightGrid->uav.get() };
context->CSSetUnorderedAccessViews(0, 3, uavs, nullptr);
ID3D11UnorderedAccessView* uavs[] = { lightIndexCounter->uav.get(), lightIndexList->uav.get(), lightGrid->uav.get() };
context->CSSetUnorderedAccessViews(0, ARRAYSIZE(uavs), uavs, nullptr);

context->CSSetShader(clusterCullingCS, nullptr, 0);
context->Dispatch((clusterSize[0] + 15) / 16, (clusterSize[1] + 15) / 16, (clusterSize[2] + 3) / 4);
Expand Down
4 changes: 2 additions & 2 deletions src/Features/LightLimitFix.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ struct LightLimitFix : Feature

eastl::unique_ptr<Buffer> lights = nullptr;
eastl::unique_ptr<Buffer> clusters = nullptr;
eastl::unique_ptr<Buffer> lightCounter = nullptr;
eastl::unique_ptr<Buffer> lightList = nullptr;
eastl::unique_ptr<Buffer> lightIndexCounter = nullptr;
eastl::unique_ptr<Buffer> lightIndexList = nullptr;
eastl::unique_ptr<Buffer> lightGrid = nullptr;

std::uint32_t lightCount = 0;
Expand Down

0 comments on commit 8252889

Please sign in to comment.