here are some code-snippets to define a Compute Shader which writes into a RW-Buffer
To define a Compute Shader like in your .h:
class FWriteBufferCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER( FWriteBufferCS );
SHADER_USE_PARAMETER_STRUCT( FWriteBufferCS , FGlobalShader );
BEGIN_SHADER_PARAMETER_STRUCT( FParameters, )
SHADER_PARAMETER( int, BufferSize )
SHADER_PARAMETER_UAV( RWStructuredBuffer<float>, BufferTarget )
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation( const FGlobalShaderPermutationParameters& Parameters ) {
return IsFeatureLevelSupported( Parameters.Platform, ERHIFeatureLevel::SM5 );
}
static void ModifyCompilationEnvironment( const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment ) {
OutEnvironment.SetDefine( TEXT( "SOMECONSTANT" ), 123 );
}
};
dont forget to âimplementâ the shader file:
IMPLEMENT_SHADER_TYPE( , FWriteBufferCS , TEXT( "/Plugin/YourPlugin/WriteBuffer.usf" ), TEXT( "MainCS " ), SF_Compute )
Setting the Shader Parameters and Dispatch the Compute Shader in .cpp (in the RHI Thread):
FIntVector ThreadGroupAmount;
ThreadGroupAmount.X = FMath::DivideAndRoundUp( BufferSize .X, 64 /*ThreadGroupSize*/ );
ThreadGroupAmount.Y = 1;
ThreadGroupAmount.Z = 1;
FWriteBufferCS::FParameters ShaderParameters;
ShaderParameters.BufferTarget = BufferTarget;
ShaderParameters.BufferSize = BufferSize;
TShaderMapRef< FWriteBufferCS> ComputeShader( GetGlobalShaderMap( GMaxRHIFeatureLevel ) );
FComputeShaderUtils::Dispatch( RHICmdList, ComputeShader, ShaderParameters, ThreadGroupAmount );
in the .usf
RWStructuredBuffer<float> BufferTarget;
[ numthreads( 64, 1, 1 ) ]
void MainCS( uint ThreadId : SV_DispatchThreadID )
{
if( ThreadId >= BufferSize )
return;
BufferTarget[ ThreadId ] = sin( (float)ThreadId * 0.123f );
}
to create a Buffer/UAV you can do kinda this (i think this also works on the Game-Thread) (setting the Resource-Array is optional, since you write the buffer on the gpu anyway, otherwise a MemCpy is best):
FRHIResourceCreateInfo CreateInfo( TEXT( "WriteBuffer" ) );
TResourceArray< float > ResourceArray;
ResourceArray.SetNumZeroed( BufferSize );
CreateInfo.ResourceArray = &ResourceArray;
FStructuredBufferRHIRef BufferSource = RHICreateStructuredBuffer(
sizeof( float ),
sizeof( float ) * BufferSize ,
BUF_UnorderedAccess | BUF_ShaderResource,
CreateInfo
);
FUnorderedAccessViewRHIRef BufferTarget = RHICreateUnorderedAccessView( BufferSource , false, false );
when you just read data in the gpu-buffer, you can use an SHADER_PARAMETER_SRV( StructuredBuffer<float>, BufferSource )
, skipping the âRWâ prefixes and just pass the BufferSource into the shader parameters.
Anyway you may call some TransitionResource
, WaitForDispatch
, or FlushRenderingCommands
.
hope that helps, sorry for any typos xD