mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-14 09:19:25 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
367 lines
13 KiB
C#
367 lines
13 KiB
C#
using System.Collections.Concurrent;
|
|
|
|
namespace Sandbox.Rendering;
|
|
|
|
public sealed partial class CommandList
|
|
{
|
|
public unsafe class AttributeAccess
|
|
{
|
|
private readonly ConcurrentDictionary<string, RenderTarget> _renderTargets = new();
|
|
|
|
internal Func<RenderAttributes> _get;
|
|
internal CommandList list;
|
|
|
|
RenderAttributes attributes => _get();
|
|
|
|
internal AttributeAccess( CommandList cmdlist, Func<RenderAttributes> _getter )
|
|
{
|
|
list = cmdlist;
|
|
_get = _getter;
|
|
}
|
|
|
|
public void Set( StringToken token, float f )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, entry.Data1.x );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object4 = this, Data1 = new Vector4( f, 0, 0, 0 ) } );
|
|
}
|
|
|
|
public void Set( StringToken token, double f ) => Set( token, (float)f );
|
|
|
|
public void Set( StringToken token, Vector2 vector2 )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, new Vector2( entry.Data1.x, entry.Data1.y ) );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object4 = this, Data1 = new Vector4( vector2.x, vector2.y, 0, 0 ) } );
|
|
}
|
|
|
|
public void Set( StringToken token, Vector3 vector3 )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, new Vector3( entry.Data1.x, entry.Data1.y, entry.Data1.z ) );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object4 = this, Data1 = new Vector4( vector3.x, vector3.y, vector3.z, 0 ) } );
|
|
}
|
|
|
|
public void Set( StringToken token, Vector4 vector4 )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, entry.Data1 );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object4 = this, Data1 = vector4 } );
|
|
}
|
|
|
|
public void Set( StringToken token, int i )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, (int)entry.Data1.x );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object4 = this, Data1 = new Vector4( i, 0, 0, 0 ) } );
|
|
}
|
|
|
|
public void Set( StringToken token, bool b )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, (int)entry.Data1.x != 0 );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object4 = this, Data1 = new Vector4( b ? 1 : 0, 0, 0, 0 ) } );
|
|
}
|
|
|
|
public void Set( StringToken token, Matrix matrix )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, (Matrix)entry.Object2 );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object2 = matrix, Object4 = this } );
|
|
}
|
|
|
|
public void Set( StringToken token, GpuBuffer buffer )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, (GpuBuffer)entry.Object2 );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object2 = buffer, Object4 = this } );
|
|
}
|
|
|
|
public void Set( StringToken token, Texture texture, int mip = -1 )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, (Texture)entry.Object2, (int)entry.Data1.x );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object2 = texture, Object4 = this, Data1 = new Vector4( mip, 0, 0, 0 ) } );
|
|
}
|
|
|
|
public void Set( StringToken token, SamplerState samplerState )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, (SamplerState)entry.Object2 );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object2 = samplerState, Object4 = this } );
|
|
}
|
|
|
|
public void SetCombo( StringToken token, int value )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.SetCombo( (StringToken)entry.Object1, (int)entry.Data1.x );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object4 = this, Data1 = new Vector4( value, 0, 0, 0 ) } );
|
|
}
|
|
|
|
public void SetCombo( StringToken token, bool value )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.SetCombo( (StringToken)entry.Object1, (int)entry.Data1.x != 0 );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object4 = this, Data1 = new Vector4( value ? 1 : 0, 0, 0, 0 ) } );
|
|
}
|
|
|
|
public void SetCombo<T>( StringToken token, T t ) where T : unmanaged, Enum
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.SetComboEnum( (StringToken)entry.Object1, (T)entry.Object2 );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object2 = t, Object4 = this } );
|
|
}
|
|
|
|
public void SetData<T>( StringToken token, T data ) where T : unmanaged
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.SetData( (StringToken)entry.Object1, (T)entry.Object2 );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object2 = data, Object4 = this } );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set a special value
|
|
/// </summary>
|
|
public void SetValue( StringToken token, RenderValue value )
|
|
{
|
|
switch ( value )
|
|
{
|
|
case RenderValue.ColorTarget:
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, Graphics.SceneLayer.GetColorTarget() );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object4 = this } );
|
|
}
|
|
break;
|
|
|
|
case RenderValue.DepthTarget:
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, Graphics.SceneLayer.GetDepthTarget() );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object4 = this } );
|
|
}
|
|
break;
|
|
|
|
case RenderValue.MsaaCombo:
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.SetCombo( (StringToken)entry.Object1, Graphics.IdealMsaaLevel != MultisampleAmount.MultisampleNone ? 1 : 0 );
|
|
}
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object4 = this } );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the color texture from this named render target to this attribute
|
|
/// </summary>
|
|
public void Set( StringToken token, RenderTargetHandle.ColorTextureRef buffer, int mip = -1 )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
if ( commandList.state.GetRenderTarget( (string)entry.Object5 ) is not { } target )
|
|
{
|
|
Log.Warning( $"[{commandList.DebugName ?? "CommandList"}] Unknown rt: {(string)entry.Object5}" );
|
|
return;
|
|
}
|
|
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, target.ColorTarget, (int)entry.Data1.x );
|
|
}
|
|
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object5 = buffer.Name, Object4 = this, Data1 = new Vector4( mip, 0, 0, 0 ) } );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the color texture from this named render target to this attribute
|
|
/// </summary>
|
|
public void Set( StringToken token, RenderTargetHandle.ColorIndexRef buffer )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
if ( commandList.state.GetRenderTarget( (string)entry.Object5 ) is not { } target )
|
|
{
|
|
Log.Warning( $"[{commandList.DebugName ?? "CommandList"}] Unknown rt: {(string)entry.Object5}" );
|
|
return;
|
|
}
|
|
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
attrAccess.attributes.Set( (StringToken)entry.Object1, target.ColorTarget.Index );
|
|
}
|
|
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object5 = buffer.Name, Object4 = this } );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the size of this named render target to this float2 attribute
|
|
/// </summary>
|
|
public void Set( StringToken token, RenderTargetHandle.SizeHandle size, bool inverse = false )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
if ( commandList.state.GetRenderTarget( (string)entry.Object5 ) is not { } target )
|
|
{
|
|
Log.Warning( $"[{commandList.DebugName ?? "CommandList"}] Unknown rt: {(string)entry.Object5}" );
|
|
return;
|
|
}
|
|
|
|
var s = target.ColorTarget.Size;
|
|
|
|
var attrAccess = (AttributeAccess)entry.Object4;
|
|
if ( (int)entry.Data1.x != 0 ) attrAccess.attributes.Set( (StringToken)entry.Object1, new Vector2( 1.0f / s.x, 1.0f / s.y ) );
|
|
else attrAccess.attributes.Set( (StringToken)entry.Object1, s );
|
|
}
|
|
|
|
list.AddEntry( &Execute, new Entry { Object1 = token, Object5 = size.Name, Object4 = this, Data1 = new Vector4( inverse ? 1 : 0, 0, 0, 0 ) } );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Takes a copy of the current viewport's color texture and stores it in targetName on renderAttributes.
|
|
/// </summary>
|
|
public RenderTargetHandle GrabFrameTexture( string token = "FrameTexture", bool withMips = false )
|
|
{
|
|
return GrabFrameTexture( token, withMips ? Graphics.DownsampleMethod.GaussianBlur : Graphics.DownsampleMethod.None );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Takes a copy of the current viewport's color texture and stores it in targetName on renderAttributes.
|
|
/// </summary>
|
|
public RenderTargetHandle GrabFrameTexture( string token, Graphics.DownsampleMethod downsampleMethod )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object2;
|
|
var temp = Graphics.GrabFrameTexture( (string)entry.Object5, attrAccess.attributes, (Graphics.DownsampleMethod)(int)entry.Data1.x );
|
|
commandList.state.renderTargets[(string)entry.Object5] = temp;
|
|
attrAccess._renderTargets[(string)entry.Object5] = temp;
|
|
}
|
|
|
|
list.AddEntry( &Execute, new Entry { Object5 = token, Object2 = this, Data1 = new Vector4( (int)downsampleMethod, 0, 0, 0 ) } );
|
|
|
|
return new RenderTargetHandle { Name = token };
|
|
}
|
|
|
|
/// <summary>
|
|
/// Takes a copy of the current viewport's depth texture and stores it in targetName on renderAttributes.
|
|
/// </summary>
|
|
public RenderTargetHandle GrabDepthTexture( string token = "DepthTexture" )
|
|
{
|
|
static void Execute( ref Entry entry, CommandList commandList )
|
|
{
|
|
var attrAccess = (AttributeAccess)entry.Object2;
|
|
var temp = Graphics.GrabDepthTexture( (string)entry.Object5, attrAccess.attributes );
|
|
commandList.state.renderTargets[(string)entry.Object5] = temp;
|
|
attrAccess._renderTargets[(string)entry.Object5] = temp;
|
|
}
|
|
|
|
list.AddEntry( &Execute, new Entry { Object5 = token, Object2 = this } );
|
|
|
|
return new RenderTargetHandle { Name = token };
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the actual render target by name. Useful for externals that need to access the render target directly.
|
|
/// </summary>
|
|
public RenderTarget GetRenderTarget( string name )
|
|
{
|
|
if ( _renderTargets.TryGetValue( name, out var rt ) )
|
|
return rt;
|
|
return null;
|
|
}
|
|
|
|
internal void ClearRenderTargets()
|
|
{
|
|
_renderTargets.Clear();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// These are the attributes for the current view. Setting a variable here will let you pass it down to
|
|
/// other places in the render pipeline.
|
|
/// </summary>
|
|
public AttributeAccess GlobalAttributes { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Access to the local attributes. What these are depends on where the command list is being called.
|
|
/// If we're calling from a renderable, these are the attributes for that renderable.
|
|
/// </summary>
|
|
public AttributeAccess Attributes { get; private set; }
|
|
|
|
RenderAttributes GetFrameAttributes() => Graphics.FrameAttributes;
|
|
RenderAttributes GetLocalAttributes() => Graphics.Attributes;
|
|
|
|
}
|
|
|
|
|
|
public enum RenderValue
|
|
{
|
|
/// <summary>
|
|
/// The color texure we're currently rendering to
|
|
/// </summary>
|
|
ColorTarget,
|
|
|
|
/// <summary>
|
|
/// The depth texture we're currently rendering to
|
|
/// </summary>
|
|
DepthTarget,
|
|
|
|
/// <summary>
|
|
/// Will set the named combo to 1 if MSAA is active, otherwise 0.
|
|
/// </summary>
|
|
MsaaCombo,
|
|
}
|
|
|
|
|
|
|