I have been testing this some more, and unfortunately the reload hack does not work when developing compute shaders. If I try to change a compute shader, even the smallest way, and recompile, I get some errors like
[ 00:14:22.928 ]: [Error] Failed to compile 'Compute'. ...ComputeShaderTest\Compute(22,32): error X3000: syntax error: unexpected end of file
[ 00:14:22.928 ]: [Error] Failed to compile 'CS_Main'
[ 00:14:22.928 ]: [Error] Shader compilation 'Compute' failed (profile: DirectX SM5)
[ 00:14:22.928 ]: [Error] Source: ...ComputeShaderTest/Cache/Shaders/Source/Compute.hlsl
[ 00:14:22.928 ]: [Error] Failed to compile shader 'FlaxEngine.Shader, 000002bc341dfc220000004300000065, ...ComputeShaderTest/Content/shaders/Compute.flax'
[ 00:14:22.928 ]: [Error] Cannot load 'FlaxEngine.Shader, 000002bc341dfc220000004300000065, ...ComputeShaderTest/Content/shaders/Compute.flax' shader cache.
[ 00:14:22.928 ]: [Error] Loading asset 'FlaxEngine.Shader, 000002bc341dfc220000004300000065, ...ComputeShaderTest/Content/shaders/Compute.flax' result: Failed.
In real there are no errors in the shader though. If I quit the editor and restart the project, the compute shader will be compiled as expected without errors, and the changes takes effect as expected.
This means that currently the only way I can develop a compute shader seems by doing the shader edits, then quit the editor, reload the project and test it.
Is this a known issue, or am I doing something wrong?
The test compute shader is quite basic:
#include "./Flax/Common.hlsl"
META_CB_BEGIN(0, Data)
float Brightness;
float3 _pad; // 16-byte row
META_CB_END;
Texture2D Input : register(t0);
RWTexture2D<float4> Output : register(u0);
META_CS(true, FEATURE_LEVEL_SM5)
[numthreads(8, 8, 1)]
void CS_Main(uint3 id : SV_DispatchThreadID)
{
uint2 size;
Output.GetDimensions(size.x, size.y);
if (id.x >= size.x || id.y >= size.y)
return;
float4 c = Input.Load(int3(id.xy, 0));
c.rgb *= Brightness;
Output[id.xy] = saturate(c);
}
And the C#
using System;
using System.Runtime.InteropServices;
using FlaxEngine;
public sealed class ComputeRenderer : PostProcessEffect
{
[StructLayout(LayoutKind.Sequential)]
private struct Data
{
public float Brightness;
public Float3 Pad; // matches float3 _pad
}
[Limit(0.0f, 4.0f, 0.01f)]
public float brightness = 1.0f;
public Shader shader;
private bool _hasCompute;
public override void OnEnable()
{
#if FLAX_EDITOR
shader?.Reload();
#endif
_hasCompute = GPUDevice.Instance.Limits.HasCompute;
MainRenderTask.Instance.AddCustomPostFx(this);
}
public override void OnDisable()
{
MainRenderTask.Instance?.RemoveCustomPostFx(this);
}
public override bool CanRender()
{
return base.CanRender() && _hasCompute && shader && shader.IsLoaded;
}
public override unsafe void Render(GPUContext context, ref RenderContext renderContext, GPUTexture input, GPUTexture output)
{
nint cb = shader.GPU.GetCB(0);
if (cb != IntPtr.Zero)
{
Data data;
data.Brightness = brightness;
data.Pad = Float3.Zero;
context.UpdateCB(cb, new IntPtr(&data));
context.BindCB(0, cb);
}
GPUTextureDescription desc = input.Description;
desc.Flags = GPUTextureFlags.UnorderedAccess | GPUTextureFlags.ShaderResource | GPUTextureFlags.RenderTarget;
GPUTexture temp = RenderTargetPool.Get(ref desc);
context.BindSR(0, input);
context.BindUA(0, temp.View());
nint cs = shader.GPU.GetCS("CS_Main");
uint groupsX = (uint)((output.Width + 7) / 8);
uint groupsY = (uint)((output.Height + 7) / 8);
context.Dispatch(cs, groupsX, groupsY, 1);
context.ResetUA();
context.ResetSR();
context.Draw(output, temp);
RenderTargetPool.Release(temp);
}
}