Created
August 17, 2024 00:24
-
-
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!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////////////////// | |
// 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; | |
} |
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
this is a compute shader representing a box selection, which can either just set bits for preview/hover purposes, or, actually apply the selection (sets selection bits), which is then downloaded to the CPU
the bug is that, the dispatch where _BoxAction is supposed to be 2 (apply), it's executed with a value of 1 (preview), before it's downloaded to the CPU
weird workarounds that magically make it work: