Skip to content

Commit 33b96a4

Browse files
authored
Merge branch 'Facepunch:master' into prop-impact-damage
2 parents 359fe3c + f58e41b commit 33b96a4

14 files changed

Lines changed: 358 additions & 26 deletions

File tree

engine/Definitions/common/Render/renderdevice.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ native accessor g_pRenderDevice
6969

7070
bool IsTextureRenderTarget( ITexture texture );
7171

72+
bool IsRayTracingSupported();
73+
7274
inline RenderBufferHandle_t CreateGPUBuffer( RenderBufferType_t nType, BufferDesc_t desc, RenderBufferFlags_t usage, string pDebugName )
7375
{
7476
desc.m_pDebugName = pDebugName;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include "scenesystem/iscenesystem.h"
2+
3+
native class IRayTraceSceneWorld as NativeEngine.IRayTraceSceneWorld
4+
{
5+
void BeginBuild();
6+
void AddSceneWorldToBuild( ISceneWorld pWorld, IRenderContext pRenderContext );
7+
bool EndBuild( IRenderContext pRenderContext, CRenderAttributes attrs );
8+
9+
inline bool BuildTLASForWorld( ISceneWorld pWorld, CRenderAttributes attrs )
10+
{
11+
CRenderContextPtr pRenderContext( g_pRenderDevice, "sceneinfo_gpu" );
12+
13+
this->BeginBuild();
14+
this->AddSceneWorldToBuild( pWorld, pRenderContext );
15+
this->EndBuild( pRenderContext, attrs );
16+
17+
return true;
18+
}
19+
}

engine/Definitions/common/SceneSystem/g_pSceneSystem.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,8 @@ native accessor g_pSceneSystem as NativeEngine.CSceneSystem
160160
void RenderTiledLightCulling( IRenderContext pCtx, ISceneView pView, RenderViewport viewport );
161161

162162
void BindTransformSlot( IRenderContext pCtx, int nVBSlot, int nTransformSlotIndex );
163+
164+
// Ray Tracing
165+
IRayTraceSceneWorld CreateRayTraceWorld( string pWorldDebugName, int nMaxRayTypes );
166+
void DestroyRayTraceWorld( IRayTraceSceneWorld pRayTraceSceneWorld );
163167
}

engine/Definitions/engine/Render/RenderTools.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ native static class RenderTools as NativeEngine.RenderTools
1717
//
1818
void Compute( IRenderContext renderContext, CRenderAttributes attributes, IMaterialMode pMode, int tx, int ty, int tz );
1919
void ComputeIndirect( IRenderContext renderContext, CRenderAttributes attributes, IMaterialMode pMode, RenderBufferHandle_t hIndirectBuffer, uint nIndirectBufferOffset );
20+
void TraceRays( IRenderContext renderContext, CRenderAttributes attributes, IMaterialMode pMode, uint tx, uint ty, uint tz );
21+
void TraceRaysIndirect( IRenderContext renderContext, CRenderAttributes attributes, IMaterialMode pMode, RenderBufferHandle_t hIndirectBuffer, uint nIndirectBufferOffset );
2022
void SetDynamicConstantBufferData( CRenderAttributes attributes, StringToken nTokenID, IRenderContext renderContext, void* data, int dataSize );
2123

2224
void CopyTexture( IRenderContext renderContext, ITexture sourceTexture, ITexture destTexture, Rect_t pSrcRect, int nDestX, int nDestY, uint nSrcMipSlice, uint nSrcArraySlice, uint nDstMipSlice, uint nDstArraySlice );

engine/Sandbox.Engine/Scene/Components/Game/Dresser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public enum ClothingSource
7676
[Property]
7777
public List<string> WorkshopItems { get; set; }
7878

79-
protected override void OnAwake()
79+
protected override void OnStart()
8080
{
8181
if ( IsProxy )
8282
return;
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using NativeEngine;
2+
3+
namespace Sandbox;
4+
5+
internal class SceneRaytracingSystem : GameObjectSystem<SceneRaytracingSystem>
6+
{
7+
// This could all be done on C# side, all below does is to update the TLAS, todo
8+
internal IRayTraceSceneWorld native;
9+
10+
bool Supported => g_pRenderDevice.IsRayTracingSupported();
11+
12+
public SceneRaytracingSystem( Sandbox.Scene scene ) : base( scene )
13+
{
14+
if ( !Supported )
15+
return;
16+
// Update TLAS after bones are updated
17+
Listen( Stage.UpdateBones, Int32.MaxValue, UpdateSkinnedForRaytracing, "UpdateSkinnedForRaytracing" );
18+
Listen( Stage.FinishUpdate, Int32.MaxValue, UpdateRaytracing, "UpdateRaytracing" );
19+
20+
var RAY_TYPE_COUNT = 2;
21+
native = CSceneSystem.CreateRayTraceWorld( Scene.Name, RAY_TYPE_COUNT );
22+
}
23+
24+
~SceneRaytracingSystem()
25+
{
26+
if ( !Supported )
27+
return;
28+
29+
CSceneSystem.DestroyRayTraceWorld( native );
30+
}
31+
32+
33+
void UpdateSkinnedForRaytracing()
34+
{
35+
using var _ = PerformanceStats.Timings.Render.Scope();
36+
37+
var allSkinnedRenderers = Scene.GetAllComponents<SkinnedModelRenderer>()
38+
.ToArray();
39+
40+
foreach ( var renderer in allSkinnedRenderers )
41+
{
42+
if ( !renderer.IsValid() )
43+
continue;
44+
45+
}
46+
}
47+
48+
/// <summary>
49+
/// Top-level acceleration structure needs to be updated every frame
50+
/// </summary>
51+
internal void UpdateRaytracing()
52+
{
53+
using var _ = PerformanceStats.Timings.Render.Scope();
54+
55+
native.BuildTLASForWorld( Scene.SceneWorld, Scene.RenderAttributes.Get() );
56+
}
57+
}

engine/Sandbox.Engine/Systems/Render/CommandList/CommandList.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,28 @@ static void Execute( ref Entry entry, CommandList commandList )
830830
AddEntry( &Execute, new Entry { Object1 = compute, Object2 = indirectBuffer, Data1 = new Vector4( indirectElementOffset, 0, 0, 0 ) } );
831831
}
832832

833+
/// <inheritdoc cref="RayTracingShader.DispatchRaysWithAttributes(RenderAttributes, int, int, int)"/>
834+
internal void DispatchRays( RayTracingShader raytracing, int threadsX, int threadsY, int threadsZ )
835+
{
836+
static void Execute( ref Entry entry, CommandList commandList )
837+
{
838+
((RayTracingShader)entry.Object1).DispatchRaysWithAttributes( Graphics.Attributes, (int)entry.Data1.x, (int)entry.Data1.y, (int)entry.Data1.z );
839+
}
840+
841+
AddEntry( &Execute, new Entry { Object1 = raytracing, Data1 = new Vector4( threadsX, threadsY, threadsZ, 0 ) } );
842+
}
843+
844+
/// <inheritdoc cref="RayTracingShader.DispatchRaysIndirect(GpuBuffer, uint)"/>
845+
internal void DispatchRaysIndirect( RayTracingShader raytracing, GpuBuffer indirectBuffer, uint indirectElementOffset = 0 )
846+
{
847+
static void Execute( ref Entry entry, CommandList commandList )
848+
{
849+
((RayTracingShader)entry.Object1).DispatchRaysIndirectWithAttributes( Graphics.Attributes, (GpuBuffer)entry.Object2, (uint)entry.Data1.x );
850+
}
851+
852+
AddEntry( &Execute, new Entry { Object1 = raytracing, Object2 = indirectBuffer, Data1 = new Vector4( indirectElementOffset, 0, 0, 0 ) } );
853+
}
854+
833855
/// <summary>
834856
/// A handle to the viewport size
835857
/// </summary>
@@ -851,6 +873,22 @@ static void Execute( ref Entry entry, CommandList commandList )
851873
AddEntry( &Execute, new Entry { Object1 = compute, Object5 = dimension.Name } );
852874
}
853875

876+
/// <summary>
877+
/// Dispatch a ray tracing shader
878+
/// </summary>
879+
internal void DispatchRays( RayTracingShader raytracing, RenderTargetHandle.SizeHandle dimension )
880+
{
881+
static void Execute( ref Entry entry, CommandList commandList )
882+
{
883+
var xyz = commandList.GetDimension( (string)entry.Object5 );
884+
if ( !xyz.HasValue ) return;
885+
886+
((RayTracingShader)entry.Object1).DispatchRaysWithAttributes( Graphics.Attributes, xyz.Value.x, xyz.Value.y, xyz.Value.z );
887+
}
888+
889+
AddEntry( &Execute, new Entry { Object1 = raytracing, Object5 = dimension.Name } );
890+
}
891+
854892
/// <summary>
855893
/// Called during rendering, convert RenderTargetHandle.SizeHandle to a dimension
856894
/// </summary>
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using NativeEngine;
2+
3+
namespace Sandbox;
4+
5+
/// <summary>
6+
/// Represents a ray tracing acceleration structure that contains geometry for efficient ray intersection testing.
7+
/// This is used to organize scene geometry in a hierarchical structure optimized for ray tracing performance.
8+
/// </summary>
9+
public class RayTracingAccelerationStructure
10+
{
11+
internal object native;
12+
13+
/// <summary>
14+
/// Gets whether this acceleration structure is valid and can be used for ray tracing.
15+
/// </summary>
16+
public bool IsValid() => native != null;
17+
18+
/// <summary>
19+
/// Create a ray tracing acceleration structure from native engine data.
20+
/// </summary>
21+
internal RayTracingAccelerationStructure( object nativeAccelerationStructure )
22+
{
23+
native = nativeAccelerationStructure;
24+
}
25+
26+
/// <summary>
27+
/// Create a ray tracing acceleration structure from scene geometry.
28+
/// </summary>
29+
/// <param name="geometryData">The geometry data to build the acceleration structure from.</param>
30+
/// <returns>A new acceleration structure, or null if creation failed.</returns>
31+
public static RayTracingAccelerationStructure Create( object geometryData )
32+
{
33+
// This would typically interface with the native engine to build the acceleration structure
34+
// For now, this is a placeholder implementation
35+
if ( geometryData == null )
36+
return null;
37+
38+
// In a real implementation, this would call into the native engine
39+
// to build a DXR acceleration structure from the provided geometry
40+
var nativeAS = geometryData; // Placeholder
41+
42+
return new RayTracingAccelerationStructure( nativeAS );
43+
}
44+
45+
/// <summary>
46+
/// Updates the acceleration structure with new geometry data.
47+
/// This is more efficient than rebuilding from scratch for dynamic geometry.
48+
/// </summary>
49+
/// <param name="geometryData">The updated geometry data.</param>
50+
public void Update( object geometryData )
51+
{
52+
if ( !IsValid() )
53+
throw new InvalidOperationException( "Cannot update invalid acceleration structure" );
54+
55+
// This would call into the native engine to update the acceleration structure
56+
// with new geometry positions while preserving the hierarchical structure
57+
}
58+
59+
/// <summary>
60+
/// Releases the native resources associated with this acceleration structure.
61+
/// </summary>
62+
public void Dispose()
63+
{
64+
native = null;
65+
}
66+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
using NativeEngine;
2+
3+
namespace Sandbox;
4+
5+
/// <summary>
6+
/// A ray tracing shader,
7+
/// enabling advanced rendering techniques like real-time ray tracing for reflections,
8+
/// global illumination, and shadows.
9+
/// </summary>
10+
/// <seealso cref="GpuBuffer{T}"/>
11+
/// <seealso cref="ComputeShader"/>
12+
internal class RayTracingShader
13+
{
14+
/// <summary>
15+
/// Attributes that are passed to the ray tracing shader on dispatch.
16+
/// </summary>
17+
public RenderAttributes Attributes { get; } = new RenderAttributes();
18+
19+
private Material RayTracingMaterial;
20+
21+
/// <summary>
22+
/// Create a ray tracing shader from the specified path.
23+
/// </summary>
24+
public RayTracingShader( string path )
25+
{
26+
var material = Material.FromShader( path );
27+
Assert.NotNull( material, $"Failed to load ray tracing shader material from path: {path}" );
28+
RayTracingMaterial = material;
29+
}
30+
31+
/// <summary>
32+
/// Dispatches the ray tracing shader using explicit thread counts.
33+
/// </summary>
34+
/// <remarks>
35+
/// The specified thread counts represent the dispatch dimensions for the ray generation shader.
36+
/// <para>
37+
/// When called outside a graphics context, the dispatch runs immediately.
38+
/// When called inside a graphics context, the dispatch runs async.
39+
/// </para>
40+
/// </remarks>
41+
/// <param name="attributes">Render attributes to use for this dispatch.</param>
42+
/// <param name="threadsX">The number of threads to dispatch in the X dimension.</param>
43+
/// <param name="threadsY">The number of threads to dispatch in the Y dimension.</param>
44+
/// <param name="threadsZ">The number of threads to dispatch in the Z dimension.</param>
45+
public void DispatchRaysWithAttributes( RenderAttributes attributes, int threadsX = 1, int threadsY = 1, int threadsZ = 1 )
46+
{
47+
if ( threadsX < 1 ) throw new ArgumentException( $"Cannot be less than 1", nameof( threadsX ) );
48+
if ( threadsY < 1 ) throw new ArgumentException( $"Cannot be less than 1", nameof( threadsY ) );
49+
if ( threadsZ < 1 ) throw new ArgumentException( $"Cannot be less than 1", nameof( threadsZ ) );
50+
51+
// Dispatch ray tracing using RenderTools.TraceRays
52+
var mode = RayTracingMaterial.native.GetMode();
53+
RenderTools.TraceRays( Graphics.Context, attributes.Get(), mode, (uint)threadsX, (uint)threadsY, (uint)threadsZ );
54+
}
55+
56+
/// <summary>
57+
/// Dispatches the ray tracing shader using the default attributes.
58+
/// </summary>
59+
public void DispatchRays( int threadsX = 1, int threadsY = 1, int threadsZ = 1 )
60+
{
61+
DispatchRaysWithAttributes( Attributes, threadsX, threadsY, threadsZ );
62+
}
63+
64+
/// <summary>
65+
/// Dispatches the ray tracing shader by reading dispatch arguments from an indirect buffer.
66+
/// </summary>
67+
/// <remarks>
68+
/// <para>
69+
/// <paramref name="indirectBuffer"/> must be created with <see cref="GpuBuffer.UsageFlags.IndirectDrawArguments"/>
70+
/// and have an element size of 12 bytes (3 uint32 values for X, Y, Z dimensions).
71+
/// </para>
72+
/// <para>
73+
/// <paramref name="indirectElementOffset"/> is an element index into <paramref name="indirectBuffer"/>, not a byte offset.
74+
/// </para>
75+
/// <para>
76+
/// When called outside a graphics context, the dispatch runs immediately.
77+
/// When called inside a graphics context, the dispatch runs async.
78+
/// </para>
79+
/// </remarks>
80+
/// <param name="indirectBuffer">The GPU buffer containing one or more dispatch argument entries.</param>
81+
/// <param name="indirectElementOffset">The index of the dispatch arguments element to use (each element = 12 bytes).</param>
82+
public void DispatchRaysIndirect( GpuBuffer indirectBuffer, uint indirectElementOffset = 0 )
83+
{
84+
DispatchRaysIndirectWithAttributes( Attributes, indirectBuffer, indirectElementOffset );
85+
}
86+
87+
/// <inheritdoc cref="DispatchRaysIndirect"/>
88+
public void DispatchRaysIndirectWithAttributes( RenderAttributes attributes, GpuBuffer indirectBuffer, uint indirectElementOffset = 0 )
89+
{
90+
if ( !indirectBuffer.IsValid() )
91+
throw new ArgumentException( $"Invalid buffer", nameof( indirectBuffer ) );
92+
93+
if ( indirectBuffer.ElementSize != 12 )
94+
throw new ArgumentException( $"Buffer element size must be 12 bytes", nameof( indirectBuffer ) );
95+
96+
if ( indirectElementOffset >= indirectBuffer.ElementCount )
97+
throw new ArgumentOutOfRangeException( nameof( indirectElementOffset ), "Indirect element offset exceeds buffer bounds" );
98+
99+
if ( !indirectBuffer.Usage.Contains( GpuBuffer.UsageFlags.IndirectDrawArguments ) )
100+
throw new ArgumentException( $"Buffer must have the required usage flag '{GpuBuffer.UsageFlags.IndirectDrawArguments}'", nameof( indirectBuffer ) );
101+
102+
// Use RenderTools.TraceRaysIndirect when it becomes available, for now use the material mode directly
103+
var mode = RayTracingMaterial.native.GetMode();
104+
RenderTools.TraceRaysIndirect( Graphics.Context, attributes.Get(), mode, indirectBuffer.native, indirectElementOffset * 12 );
105+
}
106+
}

engine/Sandbox.Tools/Editor/AboutPopup.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ public AboutWidget() : base()
4343
messageLabel.Text = "s&box editor © Facepunch Studios Ltd.";
4444
messageLabel.TextSelectable = false;
4545

46+
// Add version
47+
var versionLabel = Layout.Add( new Label() );
48+
versionLabel.Text = $"Version {Sandbox.Application.Version}";
49+
versionLabel.TextSelectable = true;
50+
4651
// Add content layout
4752
ContentLayout = Layout.AddColumn( 1 );
4853
ContentLayout.Margin = new Sandbox.UI.Margin( 0, 16, 0, 0 );

0 commit comments

Comments
 (0)