S&box Wiki

Revision Difference

Compute_Shaders#547060

<cat>Code.Shader</cat>⤶ <title>Compute Shaders</title>⤶ ⤶ <note>⤶ TODO - this isn't finished, it's not an exhaustive example.. there's lots more to add here.⤶ </note>⤶ ⤶ You can use compute shaders to do stuff. ⤶ Here's how you can write a really simple compute texture to generate a texture on the GPU at runtime.⤶ ⤶ ## C# side⤶ ⤶ You'll first need to create a `SceneCustomObject` so that you can call `Dispatch` within the render loop:⤶ ⤶ ```⤶ public class MySceneObject : SceneCustomObject⤶ {⤶ private MyTextureGenerator myTextureGenerator;⤶ ⤶ public MySceneObject( SceneWorld sceneWorld ) : base( sceneWorld )⤶ {⤶ myTextureGenerator = new();⤶ }⤶ ⤶ public override void RenderSceneObject()⤶ {⤶ base.RenderSceneObject();⤶ myTextureGenerator.Render();⤶ }⤶ }⤶ ```⤶ ⤶ You'll also probably want to wrap your compute stuff in a nice class so that everything's nice and tidy:⤶ ⤶ ```⤶ public MyTextureGenerator()⤶ {⤶ // Create a texture that we can use⤶ texture = Texture.Create( 512, 512 )⤶ .WithUAVBinding() // Needs to have this if we're using it in a compute shader⤶ .WithFormat( ImageFormat.RGBA16161616F ) // Other formats are available :-)⤶ .Finish();⤶ ⤶ computeShader = new ComputeShader( "my_compute_shader" ); // This should be the name of your shader⤶ }⤶ ⤶ public void Render()⤶ {⤶ computeShader.Attributes.Set( "Texture", texture );⤶ computeShader.Dispatch( texture.Width, texture.Height, 1 );⤶ }⤶ ```⤶ ⤶ You also want to actually use that scene object in an entity... here's how you can do that:⤶ ⤶ ```⤶ public class MyModel : ModelEntity⤶ {⤶ private MySceneObject mySceneObject;⤶ ⤶ public override void Spawn()⤶ {⤶ base.Spawn();⤶ ⤶ Transmit = TransmitType.Always;⤶ }⤶ ⤶ public override void ClientSpawn()⤶ {⤶ mySceneObject = new( Map.Scene )⤶ {⤶ Transform = this.Transform,⤶ Position = this.Position,⤶ Bounds = this.CollisionBounds + this.Position⤶ };⤶ }⤶ ⤶ protected override void OnDestroy()⤶ {⤶ base.OnDestroy();⤶ ⤶ mySceneObject?.Delete();⤶ }⤶ }⤶ ```⤶ ⤶ Spawn your entity somewhere, make sure it's visible.⤶ ⤶ ## Shader⤶ ⤶ Compute shaders are similar to normal VS/FS shaders, but they're a bit shorter and you can forego a lot of the includes. ⤶ Here's a really simple one that'll generate a solid pink texture:⤶ ⤶ ```⤶ //=========================================================================================================================⤶ // Optional⤶ //=========================================================================================================================⤶ HEADER⤶ {⤶ CompileTargets = ( IS_SM_50 && ( PC || VULKAN ) );⤶ DevShader = true;⤶ Description = "My Cool Compute Shader";⤶ }⤶ ⤶ //=========================================================================================================================⤶ // Optional⤶ //=========================================================================================================================⤶ FEATURES⤶ {⤶ }⤶ ⤶ //=========================================================================================================================⤶ MODES⤶ {⤶ Default();⤶ }⤶ ⤶ //=========================================================================================================================⤶ COMMON⤶ {⤶ #include "common/shared.hlsl"⤶ }⤶ ⤶ //=========================================================================================================================⤶ CS⤶ {⤶ // Output texture⤶ RWTexture2D<float4> g_tOutput< Attribute( "Texture" ); >;⤶ ⤶ [numthreads(8, 8, 1)] ⤶ void MainCs( uint uGroupIndex : SV_GroupIndex, uint3 vThreadId : SV_DispatchThreadID )⤶ {⤶ g_tOutput[vThreadId.xy] = float4( 1, 0, 1, 1 );⤶ }⤶ }⤶ ```⤶ ⤶ ## Tips⤶ ⤶ If you're writing a compute shader you probably want to see its contents. You can do that really easily using `Render.Draw2D.Quad`.⤶ ⤶ ```⤶ public void RenderHud()⤶ {⤶ var draw = Render.Draw2D;⤶ ⤶ draw.Texture = texture;⤶ draw.Color = Color.White;⤶ ⤶ draw.Quad( new Vector2( 0, 0 ),⤶ new Vector2( 512, 0 ),⤶ new Vector2( 512, 512 ),⤶ new Vector2( 0, 512 ) );⤶ }⤶ ```⤶ ⤶ This'll draw your generated texture in the top left of the screen.