Editor crash when dispatching compute shader after 32 keyword changes

I’m running into a weird crash with my compute shader. It has a few keywords to disable or enable certain features.

However, I noticed after changing the keywords and dispatching 32 times, the editor would crash.

I’ve managed to create a minimal reproduction of the issue, just a ComputeShader with 4 keywords (these can be local or global, both crash), and a script to change the keywords and dispatch every frame.

Script:

using UnityEngine;
using UnityEngine.Rendering;

public class ShaderRunner : MonoBehaviour
{
	[SerializeField] private ComputeShader _shader;

	private CommandBuffer _commandBuffer;
	private ComputeBuffer _resultBuffer;
	private GlobalKeyword[] _keywords;
	private uint[] _result = new uint[1];
	private uint _iteration = 0;

	private void OnEnable()
	{
		_commandBuffer = new CommandBuffer();

		_resultBuffer = new ComputeBuffer(1, sizeof(uint));
		_shader.SetBuffer(0, "Result", _resultBuffer);

		_keywords = new GlobalKeyword[]
		{
			GlobalKeyword.Create("EXAMPLE_A"),
			GlobalKeyword.Create("EXAMPLE_B"),
			GlobalKeyword.Create("EXAMPLE_C"),
			GlobalKeyword.Create("EXAMPLE_D"),
		};
	}

	private void OnDisable()
	{
		_commandBuffer.Dispose();
		_commandBuffer = null;

		_resultBuffer.Dispose();
		_resultBuffer = null;
	}

	void Update()
	{
		Debug.Log(_iteration);

		_commandBuffer.Clear();

		for (int i = 0; i < _keywords.Length; i++)
		{
			// Iterate over combinations of keywords
			_commandBuffer.SetKeyword(_keywords[i], ((_iteration >> i) & 0x1) == 0x1);
		}

		_commandBuffer.SetComputeFloatParam(_shader, "SomeNumber", Time.time);
		_commandBuffer.DispatchCompute(_shader, 0, 1, 1, 1);

		Graphics.ExecuteCommandBuffer(_commandBuffer);

		_iteration++;
	}
}

ComputeShader:

#pragma kernel CSMain

#pragma multi_compile __ EXAMPLE_A
#pragma multi_compile __ EXAMPLE_B
#pragma multi_compile __ EXAMPLE_C
#pragma multi_compile __ EXAMPLE_D

float SomeNumber;
RWStructuredBuffer<uint> Result;

[numthreads(1, 1, 1)]
void CSMain(uint id : SV_DispatchThreadID)
{
	float result = 0;
	
#ifdef EXAMPLE_A
	result += 1 * SomeNumber;
#endif
	
#ifdef EXAMPLE_B
	result += 2 * SomeNumber;
#endif
	
#ifdef EXAMPLE_C
	result += 4 * SomeNumber;
#endif
	
#ifdef EXAMPLE_D
	result += 8 * SomeNumber;
#endif
	
	Result[id] = result;
}

This always crashes the editor on the 32nd update loop on 2021.3.5f1.

Anyone experienced something similar or have an idea to work around this?

I tested the same on Unity 6000.0.21f1, and the crash still occurs but only once you click stop, rather than on the 32nd iteration.

Hi!
Please submit a bug report if you didn’t do so already.
Thank you!

Found a few more conditions. If using CommandBuffers, having 4 or more keywords will crash on the 32nd change. When using Shader.SetKeyword() and ComputeShader.Dispatch() instead, having 5 or more keywords will crash on the 64th change. (I’m trying everything to figure out a work around for this :cry:).

public class ShaderRunner : MonoBehaviour
{
	[SerializeField] private ComputeShader _shader;

	private void Start()
	{
		var keywords = new GlobalKeyword[]
		{
			GlobalKeyword.Create("EXAMPLE_A"),
			GlobalKeyword.Create("EXAMPLE_B"),
			GlobalKeyword.Create("EXAMPLE_C"),
			GlobalKeyword.Create("EXAMPLE_D"),
			GlobalKeyword.Create("EXAMPLE_E"),
		};

		using var buffer = new ComputeBuffer(1, sizeof(float));

		_shader.SetBuffer(0, "Result", buffer);
		_shader.SetFloat("SomeNumber", Time.time);

		for (int i = 0; i < 64; i++)
		{
			for (int k = 0; k < keywords.Length; k++)
			{
				// Iterate over combinations of keywords
				Shader.SetKeyword(keywords[k], ((i >> k) & 0x1) == 0x1);
			}

			Debug.Log(i);
			_shader.Dispatch(0, 1, 1, 1); // Crashes on the 64th iteration
		}
	}
}

Yep, have submitted one. IN-89937

You wouldn’t happen to know an alternative way to achieve this or know of a similar example? I.e. ~4/5 independent settings that I can switch between (ideally using command buffers and with the performance benefits of keywords).

We may find a workaround when we know, what the problem is.
I’ll get back to you when the bug report has reached us.

1 Like