123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- using System;
- using Unity.Burst;
- using Unity.Collections;
- using Unity.Jobs;
- using Unity.Mathematics;
-
- namespace UnityEngine.Rendering.Universal
- {
- [BurstCompile(FloatMode = FloatMode.Fast, DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
- struct ZBinningJob : IJobFor
- {
- // Do not use this for the innerloopBatchCount (use 1 for that). Use for dividing the arrayLength when scheduling.
- public const int batchSize = 128;
-
- public const int headerLength = 2;
-
- [NativeDisableParallelForRestriction]
- public NativeArray<uint> bins;
-
- [ReadOnly]
- public NativeArray<float2> minMaxZs;
-
- public float zBinScale;
-
- public float zBinOffset;
-
- public int binCount;
-
- public int wordsPerTile;
-
- public int lightCount;
-
- public int reflectionProbeCount;
-
- public int batchCount;
-
- public int viewCount;
-
- public bool isOrthographic;
-
- static uint EncodeHeader(uint min, uint max)
- {
- return (min & 0xFFFF) | ((max & 0xFFFF) << 16);
- }
-
- static (uint, uint) DecodeHeader(uint zBin)
- {
- return (zBin & 0xFFFF, (zBin >> 16) & 0xFFFF);
- }
-
- public void Execute(int jobIndex)
- {
- var batchIndex = jobIndex % batchCount;
- var viewIndex = jobIndex / batchCount;
-
- var binStart = batchSize * batchIndex;
- var binEnd = math.min(binStart + batchSize, binCount) - 1;
-
- var binOffset = viewIndex * binCount;
-
- var emptyHeader = EncodeHeader(ushort.MaxValue, ushort.MinValue);
- for (var binIndex = binStart; binIndex <= binEnd; binIndex++)
- {
- bins[(binOffset + binIndex) * (headerLength + wordsPerTile) + 0] = emptyHeader;
- bins[(binOffset + binIndex) * (headerLength + wordsPerTile) + 1] = emptyHeader;
- }
-
- // Regarding itemOffset: minMaxZs contains [lights view 0, lights view 1, probes view 0, probes view 1] when
- // using XR single pass instanced, and otherwise [lights, probes]. So we figure out what the offset is based
- // on the view count and index.
-
- // Fill ZBins for lights.
- FillZBins(binStart, binEnd, 0, lightCount, 0, viewIndex * lightCount, binOffset);
-
- // Fill ZBins for reflection probes.
- FillZBins(binStart, binEnd, lightCount, lightCount + reflectionProbeCount, 1, lightCount * (viewCount - 1) + viewIndex * reflectionProbeCount, binOffset);
- }
-
- void FillZBins(int binStart, int binEnd, int itemStart, int itemEnd, int headerIndex, int itemOffset, int binOffset)
- {
- for (var index = itemStart; index < itemEnd; index++)
- {
- var minMax = minMaxZs[itemOffset + index];
- var minBin = math.max((int)((isOrthographic ? minMax.x : math.log2(minMax.x)) * zBinScale + zBinOffset), binStart);
- var maxBin = math.min((int)((isOrthographic ? minMax.y : math.log2(minMax.y)) * zBinScale + zBinOffset), binEnd);
-
- var wordIndex = index / 32;
- var bitMask = 1u << (index % 32);
-
- for (var binIndex = minBin; binIndex <= maxBin; binIndex++)
- {
- var baseIndex = (binOffset + binIndex) * (headerLength + wordsPerTile);
- var (minIndex, maxIndex) = DecodeHeader(bins[baseIndex + headerIndex]);
- minIndex = math.min(minIndex, (uint)index);
- maxIndex = math.max(maxIndex, (uint)index);
- bins[baseIndex + headerIndex] = EncodeHeader(minIndex, maxIndex);
- bins[baseIndex + headerLength + wordIndex] |= bitMask;
- }
- }
- }
- }
- }
|