Cores/Nds/Compute/ComputeRenderer3D.Dispatch.cs
using Sandbox.Rendering;
namespace Emulotl.Nds;
public sealed partial class ComputeRenderer3D
{
private const uint SortWorkArgIndex = MaxVariants;
private readonly object _snapshotLock = new();
private bool _snapshotDirty;
private int _snapNumYSpans;
private int _snapNumSetupIndices;
private int _snapNumPolygons;
private int _snapNumVariants;
private bool _snapWBuffer;
private uint _snapDispCnt;
private readonly int[] _snapVarBlend = new int[MaxVariants];
private readonly int[] _snapVarBucket = new int[MaxVariants];
private readonly int[] _snapVarW = new int[MaxVariants];
private readonly int[] _snapVarH = new int[MaxVariants];
private readonly bool[] _snapVarTexture = new bool[MaxVariants];
private readonly bool[] _snapVarShadow = new bool[MaxVariants];
private readonly int[] _snapVarCapture = new int[MaxVariants];
private readonly int[] _snapVarCapYOffset = new int[MaxVariants];
public void Snapshot()
{
if ( !_gpuReady )
return;
lock ( _snapshotLock )
{
BuildSpanSetups();
FillMeta();
_snapNumYSpans = _numYSpans;
_snapNumSetupIndices = _numSetupIndices;
_snapNumPolygons = (int)_gpu.RenderNumPolygons;
_snapNumVariants = _numVariants;
_snapWBuffer = _gpu.RenderNumPolygons > 0 && _gpu.RenderPolygonRAM[0].WBuffer;
_snapDispCnt = _gpu.RenderDispCnt;
_snapshotDirty = true;
}
}
public bool BuildCommandList( CommandList cmd )
{
if ( !_gpuReady )
return false;
int numYSpans, numSetupIndices, numPolygons, numVariants;
bool wbuffer;
uint dispCnt;
lock ( _snapshotLock )
{
if ( !_snapshotDirty )
return false;
_bufIdx = (_bufIdx + 1) % BufRing;
_metaBuffer = _metaBufferR[_bufIdx];
_renderPolygonBuffer = _renderPolygonBufferR[_bufIdx];
_ySpanSetupBuffer = _ySpanSetupBufferR[_bufIdx];
_ySpanIndicesBuffer = _ySpanIndicesBufferR[_bufIdx];
_metaBuffer.SetData<uint>( _metaData );
numPolygons = _snapNumPolygons;
if ( numPolygons > 0 )
_renderPolygonBuffer.SetData<RenderPolygonGpu>( _renderPolygons.AsSpan( 0, numPolygons ) );
numYSpans = _snapNumYSpans;
numSetupIndices = _snapNumSetupIndices;
if ( numYSpans > 0 )
{
_ySpanSetupBuffer.SetData<SpanSetupY>( _ySpanSetups.AsSpan( 0, numYSpans ) );
_ySpanIndicesBuffer.SetData( _ySpanIndices );
}
numVariants = _snapNumVariants;
wbuffer = _snapWBuffer;
dispCnt = _snapDispCnt;
if ( numVariants > 0 )
{
Array.Copy( _varBlend, _snapVarBlend, numVariants );
Array.Copy( _varBucket, _snapVarBucket, numVariants );
Array.Copy( _varTexture, _snapVarTexture, numVariants );
Array.Copy( _varShadow, _snapVarShadow, numVariants );
Array.Copy( _varW, _snapVarW, numVariants );
Array.Copy( _varH, _snapVarH, numVariants );
Array.Copy( _varCapture, _snapVarCapture, numVariants );
Array.Copy( _varCapYOffset, _snapVarCapYOffset, numVariants );
}
if ( _texturesChanged )
{
_texBufIdx = (_texBufIdx + 1) % BufRing;
_texBufSmall = _texBufSmallR[_texBufIdx];
_texBufLarge = _texBufLargeR[_texBufIdx];
if ( _numLayersSmall > 0 )
_texBufSmall.SetData<uint>( _texDataSmall.AsSpan( 0, _numLayersSmall * SmallArea ) );
if ( _numLayersLarge > 0 )
_texBufLarge.SetData<uint>( _texDataLarge.AsSpan( 0, _numLayersLarge * LargeArea ) );
_texturesChanged = false;
}
_snapshotDirty = false;
}
int wb = wbuffer ? 1 : 0;
cmd.Reset();
BindCommon( cmd );
cmd.DispatchCompute( _csClearCoarseBinMask, _tilesPerLine * _tileLines, 1, 1 );
cmd.UavBarrier( _binResultBuffer );
if ( numYSpans > 0 )
{
cmd.DispatchCompute( _csClearIndirectWorkCount, numVariants, 1, 1 );
cmd.UavBarrier( _binResultBuffer );
cmd.Attributes.SetCombo( "D_WBUFFER", wb );
cmd.Attributes.Set( "YSpanSetups", _ySpanSetupBuffer );
cmd.Attributes.Set( "YSpanIndices", _ySpanIndicesBuffer );
cmd.DispatchCompute( _csInterpSpans, numSetupIndices, 1, 1 );
cmd.UavBarrier( _xSpanSetupBuffer );
cmd.DispatchCompute( _csBinCombined, numPolygons, _screenWidth / _coarseTileW, _screenHeight / _coarseTileH );
cmd.UavBarrier( _binResultBuffer );
cmd.UavBarrier( _workDescBuffer );
cmd.ResourceBarrierTransition( _indirectArgs, ResourceState.UnorderedAccess );
cmd.DispatchCompute( _csCalcWorkOffset, numVariants, 1, 1 );
cmd.UavBarrier( _binResultBuffer );
cmd.ResourceBarrierTransition( _indirectArgs, ResourceState.IndirectArgument );
cmd.DispatchComputeIndirect( _csSortWork, _indirectArgs, SortWorkArgIndex );
cmd.UavBarrier( _workDescBuffer );
cmd.Attributes.SetCombo( "D_WBUFFER", wb );
cmd.Attributes.Set( "TileColor", _tileMemory[0] );
cmd.Attributes.Set( "TileDepth", _tileMemory[1] );
cmd.Attributes.Set( "TileAttr", _tileMemory[2] );
cmd.Attributes.Set( "uScale", _scaleFactor );
if ( _cap128 != null )
{
cmd.Attributes.Set( "CaptureOut128", _cap128 );
cmd.Attributes.Set( "CaptureOut256", _cap256 );
}
for ( int i = 0; i < numVariants; i++ )
{
cmd.Attributes.Set( "CurrentTexture", _snapVarBucket[i] == 0 ? _texBufSmall : _texBufLarge );
cmd.Attributes.Set( "TexStride", _snapVarBucket[i] == 0 ? SmallSize : LargeSize );
cmd.Attributes.SetCombo( "D_TEXTURE", _snapVarTexture[i] ? 1 : 0 );
cmd.Attributes.SetCombo( "D_BLEND", _snapVarBlend[i] );
cmd.Attributes.SetCombo( "D_SHADOWMASK", _snapVarShadow[i] ? 1 : 0 );
cmd.Attributes.Set( "CurVariant", i );
cmd.Attributes.Set( "TexWidth", _snapVarW[i] );
cmd.Attributes.Set( "TexHeight", _snapVarH[i] );
cmd.Attributes.Set( "uIsCapture", _snapVarCapture[i] );
cmd.Attributes.Set( "uCapYOffset", _snapVarCapYOffset[i] );
cmd.DispatchComputeIndirect( _csRaster, _indirectArgs, (uint)i );
}
cmd.UavBarrier( _tileMemory[0] );
cmd.UavBarrier( _tileMemory[1] );
cmd.UavBarrier( _tileMemory[2] );
}
cmd.Attributes.SetCombo( "D_WBUFFER", wb );
cmd.Attributes.Set( "TileColor", _tileMemory[0] );
cmd.Attributes.Set( "TileDepth", _tileMemory[1] );
cmd.Attributes.Set( "TileAttr", _tileMemory[2] );
cmd.Attributes.Set( "FinalTile", _finalTileBuffer );
cmd.DispatchCompute( _csDepthBlend, _screenWidth, _screenHeight, 1 );
cmd.UavBarrier( _finalTileBuffer );
cmd.Attributes.SetCombo( "D_EDGEMARKING", (int)((dispCnt >> 5) & 1) );
cmd.Attributes.SetCombo( "D_FOG", (int)((dispCnt >> 7) & 1) );
cmd.Attributes.SetCombo( "D_AA", (int)((dispCnt >> 4) & 1) );
cmd.Attributes.Set( "FinalTile", _finalTileBuffer );
cmd.Attributes.Set( "OutputTex", _outputTex );
cmd.DispatchCompute( _csFinalPass, _screenWidth, _screenHeight, 1 );
cmd.UavBarrier( _outputTex );
return true;
}
private void BindCommon( CommandList cmd )
{
cmd.Attributes.Set( "MetaUniform", _metaBuffer );
cmd.Attributes.Set( "RenderPolygons", _renderPolygonBuffer );
cmd.Attributes.Set( "XSpanSetups", _xSpanSetupBuffer );
cmd.Attributes.Set( "BinResult", _binResultBuffer );
cmd.Attributes.Set( "WorkDesc", _workDescBuffer );
cmd.Attributes.Set( "IndirectArgs", _indirectArgs );
cmd.Attributes.Set( "TileSize", _tileSize );
cmd.Attributes.Set( "TilesPerLine", _tilesPerLine );
cmd.Attributes.Set( "TileLines", _tileLines );
cmd.Attributes.Set( "CoarseTileW", _coarseTileW );
cmd.Attributes.Set( "CoarseTileH", _coarseTileH );
cmd.Attributes.Set( "ScreenWidth", _screenWidth );
cmd.Attributes.Set( "ScreenHeight", _screenHeight );
cmd.Attributes.Set( "MaxWorkTiles", _maxWorkTiles );
}
}