Skip to content

Instantly share code, notes, and snippets.

@FreyaHolmer
Created August 17, 2024 00:24
Show Gist options
  • Select an option

  • Save FreyaHolmer/62e076182204db5e85b850db0ac5e3bc to your computer and use it in GitHub Desktop.

Select an option

Save FreyaHolmer/62e076182204db5e85b850db0ac5e3bc to your computer and use it in GitHub Desktop.
Cursed compute shader issue in unity. Plop Ashl onto a game object, assign the compute shader in the inspector, and watch the console. You might need to save a scene and restart unity to see the red log messages!
////////////////////////////////////////////////////////////
// Ashl.cs
using UnityEditor;
using UnityEngine;
[ExecuteAlways]
public class Ashl : MonoBehaviour { // add this to a game object
public ComputeShader cs; // assign the compute shader in the inspector
private static GraphicsBuffer gpuBuffer;
static uint frameid;
void OnEnable() => SceneView.duringSceneGui += SceneViewOnduringSceneGui;
void OnDisable() { SceneView.duringSceneGui -= SceneViewOnduringSceneGui;
gpuBuffer?.Dispose(); gpuBuffer = null;
}
void SceneViewOnduringSceneGui( SceneView obj ) {
// on every 20th GUI frame, run apply instead of preview
if( Event.current.type == EventType.Repaint )
Dispatch( frameid++ % 20 == 0 ? BoxAction.Apply : BoxAction.Preview );
SceneView.RepaintAll(); // <-- just to make it re-trigger repaint like an update loop
}
void Dispatch( BoxAction action ) {
gpuBuffer ??= new GraphicsBuffer( GraphicsBuffer.Target.Structured, 1024, 4 );
cs.SetBuffer( 0, "_gBufSelection", gpuBuffer );
cs.SetInt( "_BoxAction", (int)action );
cs.Dispatch( 0, 1024 / 64, 1, 1 ); // run the compute shader
if( action == BoxAction.Apply ) {
uint[] dataAll = new uint[gpuBuffer.count];
gpuBuffer.GetData( dataAll ); // downloads the data from the GPU
uint data = dataAll[0];
// the data SHOULD be 0xFFFFFFFF at this point
bool works = data == 0xFFFFFFFF;
string color = works ? "ffffffaa" : "ff2222ff";
string msg = works ? "works fine so far" : "BUG HAPPENED";
Debug.Log( $"<color=#{color}>{msg}: {data:X}</color>" );
}
}
enum BoxAction { Preview = 1, Apply = 2 }
}
////////////////////////////////////////////////////////////
// shader.compute
#pragma kernel CSMain
#pragma exclude_renderers d3d11_9x
#pragma exclude_renderers d3d9
uint _BoxAction;
RWStructuredBuffer<uint> _gBufSelection;
#define BOX_APPLY 2
[numthreads(64,1,1)]
void CSMain(const uint chunkId : SV_DispatchThreadID) {
uint dims, stride;
_gBufSelection.GetDimensions(dims, stride);
if (chunkId >= dims)
return;
if (chunkId < 10) {
if (_BoxAction == BOX_APPLY)
_gBufSelection[chunkId] = 0xFFFFFFFF;
else
_gBufSelection[chunkId] = 0xAAAAAAAA;
} else
_gBufSelection[chunkId] = 0;
}
@aras-p
Copy link

aras-p commented Aug 18, 2024

My testing:

  • Unity 5.6.7: does not finish trying to activate the license lol
  • Unity 2017.4.40: works fine (the script does not compile out of the box since 2017 lacks some of the APIs; had to change ExecuteAlways->ExecuteInEditMode, GraphicsBuffer->ComputeBuffer, duringSceneGui->onSceneGUIDelegate, and remove some of more modern C# features).
  • All versions starting with Unity 2018.4: have the bug.

So my guess is that yes, this is an actual Unity bug that started happening in 2018, probably because of some sort of DX11 specific optimization that tries to reuse constant buffers or whatever, and occasionally fails.

All the replies on the internet suggesting that "GetData probably needs some sort of flush call from you, and/or you should use async readback" are mostly cargo culting. This seems very much just like a bug within Unity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment