Skip to content

Instantly share code, notes, and snippets.

@slipster216
Created December 7, 2023 08:20
Show Gist options
  • Save slipster216/06c4ea4cf6003958f9e602473a8a25b7 to your computer and use it in GitHub Desktop.
Save slipster216/06c4ea4cf6003958f9e602473a8a25b7 to your computer and use it in GitHub Desktop.
Append Buffer Async Readback broken
Compute Shader:
// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CSMain
// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
AppendStructuredBuffer<float> Result;
[numthreads(256,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
if (id.x < 3000)
{
Result.Append(1);
}
}
Script:
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Rendering;
[ExecuteAlways]
public class TestAppendBuffer : MonoBehaviour
{
public enum Mode
{
MonoAllocating,
AsyncReadback,
AsyncReadbackBlocking
}
public Mode mode = Mode.MonoAllocating;
NativeArray<float> asArray;
GraphicsBuffer outputBuf;
private void OnEnable()
{
int numToDo = 3000;
outputBuf = new GraphicsBuffer(GraphicsBuffer.Target.Append, numToDo, 4);
outputBuf.SetCounterValue(0);
ComputeShader cs = Resources.Load<ComputeShader>("TestAppendBuffer");
int kernel = cs.FindKernel("CSMain");
cs.SetBuffer(kernel, "Result", outputBuf);
cs.Dispatch(kernel, Mathf.CeilToInt(numToDo / 256.0f), 1, 1);
if (mode == Mode.MonoAllocating)
{
var data = new float[3000];
outputBuf.GetData(data, 0, 0, 3000);
int valid = 0;
int invalid = 0;
foreach (var m in data)
{
if (m == 0)
{
invalid++;
}
else
valid++;
}
if (valid == 3000)
{
Debug.Log("Working Correctly, all 3000 entries processed");
}
else
{
Debug.Log("Failed, " + valid + " entries processed, " + invalid + " not processed");
}
outputBuf.Dispose();
return;
}
else if (mode == Mode.AsyncReadback)
{
asArray = new NativeArray<float>(numToDo, Allocator.Persistent);
var req = AsyncGPUReadback.RequestIntoNativeArray(ref asArray, outputBuf, numToDo, 0);
req.WaitForCompletion();
int valid = 0;
int invalid = 0;
foreach (var m in asArray)
{
if (m == 0)
{
invalid++;
}
else
valid++;
}
if (valid == 3000)
{
Debug.Log("Working Correctly, all 3000 entries processed");
}
else
{
Debug.Log("Failed, " + valid + " entries processed, " + invalid + " not processed");
}
outputBuf.Dispose();
asArray.Dispose();
}
else
{
asArray = new NativeArray<float>(numToDo, Allocator.Persistent);
var req = AsyncGPUReadback.RequestIntoNativeArray(ref asArray, outputBuf, numToDo, 0, callback);
}
}
private void callback(AsyncGPUReadbackRequest request)
{
var data = request.GetData<float>();
int valid = 0;
int invalid = 0;
foreach (var m in data)
{
if (m == 0)
{
invalid++;
}
else
valid++;
}
if (valid == 3000)
{
Debug.Log("Working Correctly, all 3000 entries processed");
}
else
{
Debug.Log("Failed, " + valid + " entries processed, " + invalid + " not processed");
}
outputBuf.Dispose();
asArray.Dispose();
}
}
@slipster216
Copy link
Author

To repro: Add the component and put the compute shader in a Resource folder. Toggle enable on/off to test. Change modes to try different modes, all the aync/non-allocating versions are broken.

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