112 lines
4.0 KiB
HLSL
112 lines
4.0 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
VirtualShadowMapCompactViews.usf:
|
|
=============================================================================*/
|
|
|
|
#include "../Common.ush"
|
|
#include "/Engine/Shared/VirtualShadowMapDefinitions.h"
|
|
#include "/Engine/Shared/SceneCullingDefinitions.h"
|
|
|
|
#define NANITE_MULTI_VIEW 1
|
|
#include "../Nanite/NaniteDataDecode.ush"
|
|
|
|
RWStructuredBuffer< FPackedNaniteView > CompactedViewsOut;
|
|
RWStructuredBuffer< uint > CompactedViewsAllocationOut;
|
|
|
|
RWStructuredBuffer< FViewDrawGroup > InOutViewDrawRanges;
|
|
uint NumViewRanges;
|
|
|
|
// Cube map (6 faces) with max mips is the current limiter
|
|
// In theory clipmaps could go to higher counts but they are practically limited to 32 currently
|
|
// due to the coarse page bitmask and a few other things
|
|
#define VSM_MAX_VIEWS_PER_GROUP (VSM_MAX_MIP_LEVELS*6)
|
|
|
|
groupshared uint OutputViewId[VSM_MAX_VIEWS_PER_GROUP];
|
|
groupshared uint OutputViewCount;
|
|
groupshared uint OutputViewRangeOffset;
|
|
|
|
uint PackViewIdMip(uint PrimaryViewId, uint MipLevel)
|
|
{
|
|
return (PrimaryViewId << 4) | MipLevel;
|
|
}
|
|
|
|
uint2 UnpackViewIdMip(uint Packed)
|
|
{
|
|
return uint2(Packed >> 4, Packed & 0xF);
|
|
}
|
|
|
|
[numthreads(VSM_MAX_VIEWS_PER_GROUP, 1, 1)]
|
|
void CompactViewsVSM_CS(
|
|
uint GroupId : SV_GroupID,
|
|
uint ThreadId : SV_GroupIndex)
|
|
{
|
|
// Order-preserving compaction
|
|
// Could be a wave ops, but portable wave size assumptions are inconvenient here
|
|
// Fast enough to just do this scalar as long a we vectorize the actual copy below
|
|
if (ThreadId == 0)
|
|
{
|
|
const uint ViewGroupIndex = GroupId.x;
|
|
uint OutputViewOffset = 0U;
|
|
|
|
FViewDrawGroup ViewDrawGroup = InOutViewDrawRanges[ViewGroupIndex];
|
|
for (uint PrimaryViewId = ViewDrawGroup.FirstView; PrimaryViewId < ViewDrawGroup.FirstView + ViewDrawGroup.NumViews; ++PrimaryViewId)
|
|
{
|
|
FNaniteView PrimaryNaniteView = GetNaniteView(PrimaryViewId);
|
|
|
|
for (uint MipLevel = 0; MipLevel < (uint)PrimaryNaniteView.TargetNumMipLevels; MipLevel++)
|
|
{
|
|
uint4 RectPages = VirtualShadowMap.UncachedPageRectBounds[PrimaryNaniteView.TargetLayerIndex * VSM_MAX_MIP_LEVELS + MipLevel];
|
|
if (all(RectPages.zw >= RectPages.xy))
|
|
{
|
|
OutputViewId[OutputViewOffset] = PackViewIdMip(PrimaryViewId, MipLevel);
|
|
OutputViewOffset += 1U;
|
|
}
|
|
}
|
|
}
|
|
|
|
OutputViewCount = OutputViewOffset;
|
|
|
|
InterlockedAdd(CompactedViewsAllocationOut[1], OutputViewCount, OutputViewRangeOffset);
|
|
{
|
|
FViewDrawGroup ViewDrawGroupResult;
|
|
ViewDrawGroupResult.FirstView = OutputViewRangeOffset;
|
|
ViewDrawGroupResult.NumViews = OutputViewCount;
|
|
InOutViewDrawRanges[ViewGroupIndex] = ViewDrawGroupResult;
|
|
}
|
|
}
|
|
|
|
GroupMemoryBarrierWithGroupSync();
|
|
|
|
// Copy/generate any views that survived into their compacted locations
|
|
if (ThreadId < OutputViewCount)
|
|
{
|
|
uint CompactedOutputOffset = OutputViewRangeOffset + ThreadId;
|
|
|
|
// Load associated primary view
|
|
uint2 PrimaryViewIdMipLevel = UnpackViewIdMip(OutputViewId[ThreadId]);
|
|
uint PrimaryViewId = PrimaryViewIdMipLevel.x;
|
|
uint MipLevel = PrimaryViewIdMipLevel.y;
|
|
FPackedNaniteView PrimaryNaniteView = InViews[PrimaryViewId];
|
|
|
|
// Modify a few fields to make it the appropriate mip view
|
|
FPackedNaniteView MipView = PrimaryNaniteView;
|
|
MipView.TargetLayerIdX_AndMipLevelY_AndNumMipLevelsZ.y = MipLevel;
|
|
|
|
uint MipDim = VSM_VIRTUAL_MAX_RESOLUTION_XY >> MipLevel;
|
|
MipView.ViewRect = uint4(0, 0, MipDim, MipDim);
|
|
MipView.HZBTestViewRect = MipView.ViewRect;
|
|
MipView.ViewSizeAndInvSize = float4(MipDim, MipDim, 1.0f / MipDim, 1.0f / MipDim);
|
|
|
|
float ScaleFactor = 1.0f / float(1U << MipLevel);
|
|
MipView.LODScales = ScaleFactor * PrimaryNaniteView.LODScales;
|
|
MipView.ClipSpaceScaleOffset.x = PrimaryNaniteView.ClipSpaceScaleOffset.x * ScaleFactor;
|
|
MipView.ClipSpaceScaleOffset.y = PrimaryNaniteView.ClipSpaceScaleOffset.y * ScaleFactor;
|
|
MipView.ClipSpaceScaleOffset.z = MipView.ClipSpaceScaleOffset.x - 1.0f;
|
|
MipView.ClipSpaceScaleOffset.w = -MipView.ClipSpaceScaleOffset.y + 1.0f;
|
|
|
|
// Write final mip view
|
|
CompactedViewsOut[CompactedOutputOffset] = MipView;
|
|
}
|
|
}
|