// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Common.ush" #ifdef OVERRIDE_HTILELOOKUP_USH #include "/Platform/Private/HTileLookup.ush" #else uint ComputeTileOffset(uint2 PixelPos, uint PixelsWide, uint PlatformConfig) { return 0; } #endif #ifndef PLATFORM_SUPPORTS_HTILE_LOOKUP #define PLATFORM_SUPPORTS_HTILE_LOOKUP 0 #endif // Optimized version for no hi-stencil, just min and max depth. uint EncodeTileMinMaxDepth(float MinDepth, float MaxDepth) { // Convert min and max depth to UNORM14. #if COMPILER_SUPPORTS_PACK_INTRINSICS const uint HTileValue = PackFloat32ToUNorm16(MinDepth - 0.5 / 65535.0, MaxDepth + 3.5 / 65535.0); #else const float MaxDepthRange = float((1 << 14) - 1); const uint ZMin = uint(floor(MinDepth * MaxDepthRange)); const uint ZMax = uint( ceil(MaxDepth * MaxDepthRange)); const uint HTileValue = (ZMin << 18) | (ZMax << 4); #endif // Shift up min by 2 bits, then set all four low bits. return BitFieldInsertU32(BitFieldMaskU32(14, 18), HTileValue, HTileValue << 2) | 0xF /* expanded tile ZMask */; } // TODO: Optimize (branchless, bit scan, etc.) uint EncodeTileStencilZBaseDelta(float MinDepth, float MaxDepth, uint XX, uint SMem, uint SR0, uint SR1) { const float MaxDepthRange = float((1 << 14) - 1); const uint ZMask = 0xF; // Expanded const uint ZMin = uint(floor(MinDepth * MaxDepthRange)); const uint ZMax = uint( ceil(MaxDepth * MaxDepthRange)); const uint ZDiff = ZMax - ZMin; uint ZDelta = 0; if ((ZDiff & BitFieldMaskU32(1, 13)) != 0) { ZDelta = (0xFu << 2u) | BitFieldExtractU32(ZDiff, 2, 11); } else if ((ZDiff & BitFieldMaskU32(1, 12)) != 0) { ZDelta = (0xEu << 2u) | BitFieldExtractU32(ZDiff, 2, 10); } else if ((ZDiff & BitFieldMaskU32(1, 11)) != 0) { ZDelta = (0xDu << 2u) | BitFieldExtractU32(ZDiff, 2, 9); } else if ((ZDiff & BitFieldMaskU32(1, 10)) != 0) { ZDelta = (0xCu << 2u) | BitFieldExtractU32(ZDiff, 2, 8); } else if ((ZDiff & BitFieldMaskU32(1, 9)) != 0) { ZDelta = (0xBu << 2u) | BitFieldExtractU32(ZDiff, 2, 7); } else if ((ZDiff & BitFieldMaskU32(1, 8)) != 0) { ZDelta = (0xAu << 2u) | BitFieldExtractU32(ZDiff, 2, 6); } else if ((ZDiff & BitFieldMaskU32(1, 7)) != 0) { ZDelta = (0x9u << 2u) | BitFieldExtractU32(ZDiff, 2, 5); } else if ((ZDiff & BitFieldMaskU32(1, 6)) != 0) { ZDelta = (0x8u << 2u) | BitFieldExtractU32(ZDiff, 2, 4); } else if ((ZDiff & BitFieldMaskU32(1, 5)) != 0) { ZDelta = (0x3u << 3u) | BitFieldExtractU32(ZDiff, 3, 2); } else if ((ZDiff & BitFieldMaskU32(1, 4)) != 0) { ZDelta = (0x2u << 3u) | BitFieldExtractU32(ZDiff, 3, 1); } else { ZDelta = (0x0u << 4u) | BitFieldExtractU32(ZDiff, 4, 0); } uint HTileValue = 0; // 0:3 HTileValue |= ZMask; // 4:5 HTileValue |= (SR0 << 4); // 6:7 HTileValue |= (SR1 << 6); // 8:9 HTileValue |= (SMem << 8); // 10:11 HTileValue |= (XX << 10); // 12:17 HTileValue |= (ZDelta << 12); // 18:31 HTileValue |= (ZMin << 18); return HTileValue; } // Decodes 6 bit depth delta coding for hi-stencil. uint DecodeDepthDelta(uint DeltaZ) { // 000DDD -> 00000000000DDD // 001DDD -> 00000000001DDD // 010DDD -> 0000000001DDD1 // 011DDD -> 000000001DDD11 // 1000DD -> 00000001DD1111 // 1001DD -> 0000001DD11111 // 1010DD -> 000001DD111111 // 1011DD -> 00001DD1111111 // 1100DD -> 0001DD11111111 // 1101DD -> 001DD111111111 // 1110DD -> 01DD1111111111 // 1111DD -> 1DD11111111111 const bool TwoBitDelta = BitFieldExtractU32(DeltaZ, 1, 5); const uint DeltaBits = TwoBitDelta ? 2 : 3; const uint Delta = BitFieldExtractU32(DeltaZ, DeltaBits, 0); const uint Code = BitFieldExtractU32(DeltaZ, 3, DeltaBits); const uint LeadingOne = Code + (TwoBitDelta ? 6 : 2); const uint Ones = (1u << (LeadingOne + 1)) - 1; const uint DeltaStart = (LeadingOne >= DeltaBits) ? (LeadingOne - DeltaBits) : 0; const uint Mask = BitFieldMaskU32(DeltaBits, DeltaStart); return BitFieldInsertU32(Mask, Delta << DeltaStart, Ones); } // Decodes the hi-z information in the tile as a 14 bit integer min and max. uint2 DecodeTileMinMax(uint HTileValue, bool HiStencil, bool CompareMinZ) { uint MinZ; uint MaxZ; if (HiStencil) { const uint ZBase = BitFieldExtractU32(HTileValue, 14, 18); // 14 bit fixed point. const uint ZDelta = BitFieldExtractU32(HTileValue, 6, 12); // 6 bit delta coding. // Base is closest to near plane; delta is towards far plane. MinZ = CompareMinZ ? (ZBase - DecodeDepthDelta(ZDelta)) : ZBase; MaxZ = CompareMinZ ? ZBase : (ZBase + DecodeDepthDelta(ZDelta)); } else { // Both values are 14 bit fixed point. MinZ = BitFieldExtractU32(HTileValue, 14, 4); MaxZ = BitFieldExtractU32(HTileValue, 14, 18); } return uint2(MinZ, MaxZ); } // Decodes the hi-stencil information in the tile as a pair of 2 bit values. uint2 ExtractTileHiStencil(uint HTileValue, bool HiStencil) { uint HiStencil0; uint HiStencil1; if (HiStencil) { HiStencil0 = BitFieldExtractU32(HTileValue, 2, 4); HiStencil1 = BitFieldExtractU32(HTileValue, 2, 6); } else { HiStencil0 = 0; HiStencil1 = 0; } return uint2(HiStencil0, HiStencil1); }