// Copyright Epic Games, Inc. All Rights Reserved. /*============================================================================= LumenCardSceneLightingDebug.usf =============================================================================*/ #include "../Common.ush" #include "../ShaderPrint.ush" #include "LumenCardCommon.ush" #include "LumenCardTile.ush" #include "LumenSceneLighting.ush" /////////////////////////////////////////////////////////////////////////////////////////////////// #if SHADER_STATS uint LightingStatMode; StructuredBuffer PriorityHistogram; StructuredBuffer MaxUpdateBucket; StructuredBuffer CardPageTileAllocator; StructuredBuffer DirectLightingCardPageIndexAllocator; StructuredBuffer IndirectLightingCardPageIndexAllocator; void LumenSceneLightingStats(uint CardUpdateContext, StructuredBuffer CardPageIndexAllocator) { FShaderPrintContext Context = InitShaderPrintContext(true, float2(0.1, 0.1)); Newline(Context); LOOP for (uint BucketIndex = 0; BucketIndex < PRIORITY_HISTOGRAM_SIZE; ++BucketIndex) { Print(Context, PriorityHistogram[CardUpdateContext * PRIORITY_HISTOGRAM_SIZE + BucketIndex]); if ((BucketIndex + 1) % 8 == 0) { Newline(Context); } else { PrintSymbol(Context, _SPC_); } } const uint MaxUpdateBucketIndex = MaxUpdateBucket[MAX_UPDATE_BUCKET_STRIDE * CardUpdateContext + 0]; const uint MaxTilesFromMaxUpdateBucket = MaxUpdateBucket[MAX_UPDATE_BUCKET_STRIDE * CardUpdateContext + 1]; Newline(Context); Print(Context, TEXT("MaxBucket ")); Print(Context, MaxUpdateBucketIndex); Newline(Context); Print(Context, TEXT("MaxTilesFromMaxBucket ")); Print(Context, MaxTilesFromMaxUpdateBucket); Newline(Context); Print(Context, TEXT("Out ")); Newline(Context); Print(Context, TEXT(" Pages ")); Print(Context, CardPageIndexAllocator[0]); Newline(Context); Print(Context, TEXT(" Tiles ")); Print(Context, CardPageTileAllocator[CARD_PAGE_TILE_ALLOCATOR_STRIDE * CardUpdateContext + 0]); } /** * Print out various stats for debugging surface cache updates */ [numthreads(1, 1, 1)] void LumenSceneLightingStatsCS( uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_DispatchThreadID, uint3 GroupThreadId : SV_GroupThreadID) { if (LightingStatMode == 1) { LumenSceneLightingStats(CARD_UPDATE_CONTEXT_DIRECT_LIGHTING, DirectLightingCardPageIndexAllocator); } else { LumenSceneLightingStats(CARD_UPDATE_CONTEXT_INDIRECT_LIGHTING, IndirectLightingCardPageIndexAllocator); } } #endif /////////////////////////////////////////////////////////////////////////////////////////////////// #if SHADER_DEBUG uint NumLights; uint NumViews; uint NumBatchedLights; uint NumStandaloneLights; uint bHasRectLights; uint bHasLightFunctionLights; uint bHasIESLights; uint bStochastic; uint bHWRT; uint bValidDebugData; int2 AtlasResolution; int2 UpdateAtlasSize; uint MaxUpdateTiles; uint UpdateFactor; StructuredBuffer CompactedTraceAllocator; StructuredBuffer CardPageIndexAllocator; StructuredBuffer CardPageIndexData; StructuredBuffer CardTileAllocator; StructuredBuffer CardTiles; StructuredBuffer DebugDataBuffer; void DrawTile(inout FShaderPrintContext Ctx, uint InCardIndex, float2 UVMin, float2 UVMax, float4 Color) { const float Depth = 0.f; const FLumenCardData Card = GetLumenCardData(InCardIndex); const float3 P0 = GetCardWorldPosition(Card, float2(UVMin.x, UVMin.y), Depth); const float3 P1 = GetCardWorldPosition(Card, float2(UVMax.x, UVMin.y), Depth); const float3 P2 = GetCardWorldPosition(Card, float2(UVMax.x, UVMax.y), Depth); const float3 P3 = GetCardWorldPosition(Card, float2(UVMin.x, UVMax.y), Depth); AddQuadWS(Ctx, P0, P1, P2, P3, Color); } [numthreads(THREADGROUP_SIZE, THREADGROUP_SIZE, 1)] void LumenSceneDirectLightingStatsCS( uint3 GroupId : SV_GroupID, uint3 GroupThreadId : SV_GroupThreadID, uint3 DispatchThreadId : SV_DispatchThreadID) { if (all(DispatchThreadId == 0)) { FShaderPrintContext Ctx = InitShaderPrintContext(true, uint2(50, 50)); Print(Ctx, TEXT("Lumen Scene Direct Lighting"), FontEmerald); Newline(Ctx); Print(Ctx, TEXT("#Views : "), FontWhite); Print(Ctx, NumViews, FontYellow); Newline(Ctx); Print(Ctx, TEXT("#Lights : "), FontWhite); Print(Ctx, NumLights, FontYellow); Newline(Ctx); Newline(Ctx); Print(Ctx, TEXT("Lights"), FontEmerald); Newline(Ctx); Print(Ctx, TEXT("Batched Lights : "), FontWhite); Print(Ctx, NumBatchedLights, FontYellow); Newline(Ctx); Print(Ctx, TEXT("Standalone Lights: "), FontWhite); Print(Ctx, NumStandaloneLights, FontYellow); Newline(Ctx); Print(Ctx, TEXT("Rect lights : "), FontWhite); PrintBool(Ctx, bHasRectLights > 0); Newline(Ctx); Print(Ctx, TEXT("Light functions : "), FontWhite); PrintBool(Ctx, bHasLightFunctionLights > 0); Newline(Ctx); Print(Ctx, TEXT("IES lights : "), FontWhite); PrintBool(Ctx, bHasIESLights > 0); Newline(Ctx); Newline(Ctx); Print(Ctx, TEXT("Atlas"), FontEmerald); Newline(Ctx); Print(Ctx, TEXT("AtlasResolution: "), FontWhite); Print(Ctx, AtlasResolution, FontYellow); Newline(Ctx); Print(Ctx, TEXT("UpdateAtlasSize: "), FontWhite); Print(Ctx, UpdateAtlasSize, FontYellow); Newline(Ctx); Print(Ctx, TEXT("MaxUpdateTiles : "), FontWhite); Print(Ctx, MaxUpdateTiles, FontYellow); Newline(Ctx); Print(Ctx, TEXT("UpdateFactor : "), FontWhite); Print(Ctx, UpdateFactor, FontYellow); Newline(Ctx); Newline(Ctx); // For non-stochastic path CompactedTraceAllocator is an overestimate of the number of trace. const uint TraceCount = CompactedTraceAllocator[0]; Print(Ctx, TEXT("Trace"), FontEmerald); Newline(Ctx); Print(Ctx, TEXT("Method : "), FontWhite); if (bHWRT) { Print(Ctx, TEXT("Hardware"), FontYellow); } else { Print(Ctx, TEXT("Software"), FontYellow); } Newline(Ctx); Print(Ctx, TEXT("RT Traces : "), FontWhite); Print(Ctx, TraceCount, FontYellow); Newline(Ctx); Newline(Ctx); // TODO: dispatch one per lane instead of a LOOP const uint AllocatedCard = CardPageIndexAllocator[0]; const uint AllocatedCardTile = CardTileAllocator[0]; Print(Ctx, TEXT("Card"), FontEmerald); Newline(Ctx); Print(Ctx, TEXT("Updating Card : "), FontWhite); Print(Ctx, AllocatedCard, FontYellow); Newline(Ctx); Print(Ctx, TEXT("Updating Tiles : "), FontWhite); Print(Ctx, AllocatedCardTile, FontYellow); Newline(Ctx); const bool bViewCards = AddCheckbox(Ctx, TEXT("View Cards"), false, FontWhite); Newline(Ctx); const bool bViewCardTiles = AddCheckbox(Ctx, TEXT("View Tiles"), false, FontWhite); Newline(Ctx); FLumenSceneDebugData DebugData = InitLumenSceneDebugData(); if (bValidDebugData > 0) { DebugData = ReadDebugData(DebugDataBuffer); } // Tiles OBBs uint SelectedCardIndex = LUMEN_INVALID_CARD_INDEX; float2 SelectedUVMin = 0; float2 SelectedUVMax = 0; if (bViewCardTiles || DebugData.bValid) { for (uint CardTileIt=0; CardTileIt < AllocatedCardTile; ++CardTileIt) { const FCardTileData CardTile = UnpackCardTileData(CardTiles[CardTileIt]); const FLumenCardPageData CardPage = GetLumenCardPageData(CardTile.CardPageIndex); if (CardPage.CardIndex >= 0) { const uint2 SizeInTiles = CardPage.SizeInTexels / CARD_TILE_SIZE; const float2 UVMin = float2(CardTile.TileCoord) / SizeInTiles; const float2 UVMax = float2(CardTile.TileCoord + 1) / SizeInTiles; bool bSelected = false; if (CardTile.CardPageIndex == DebugData.CardPageIndex) //if (CardPage.CardIndex == DebugData.CardIndex) { if (all(DebugData.PhysicalAtlasUV >= CardPage.PhysicalAtlasUVRect.xy) && all(DebugData.PhysicalAtlasUV <= CardPage.PhysicalAtlasUVRect.zw)) { const float2 CardUV = (DebugData.PhysicalAtlasUV - CardPage.PhysicalAtlasUVRect.xy) / (CardPage.PhysicalAtlasUVRect.zw - CardPage.PhysicalAtlasUVRect.xy); if (all(CardUV >= UVMin) && all(CardUV < UVMax)) { SelectedCardIndex = CardPage.CardIndex; SelectedUVMin = UVMin; SelectedUVMax = UVMax; } } } if (bViewCardTiles) { DrawTile(Ctx, CardPage.CardIndex, UVMin, UVMax, ColorYellow); } } } } // Cards OBBs if (bViewCards) { // Card data for (uint CardIt=0; CardIt < AllocatedCard; ++CardIt) { const FLumenCardPageData CardPage = GetLumenCardPageData(CardPageIndexData[CardIt]); if (CardPage.CardIndex >= 0) { const bool bSelected = CardPage.CardIndex == DebugData.CardIndex; DrawTile(Ctx, CardPage.CardIndex, float2(0,0), float2(1,1), bSelected ? ColorRed : ColorGreen); } } } // Selected Tile // Drawn last for better visibility with lines overlapping if (SelectedCardIndex != LUMEN_INVALID_CARD_INDEX) { DrawTile(Ctx, SelectedCardIndex, SelectedUVMin, SelectedUVMax, ColorPurple); } } } #endif