Hello! I’m trying to do some simple mesh deformation using Unity’s new GraphicsBuffers and a compute shader. I’m using Unity version 2021.2.13f1 and building for WebGL version 2. So far everything works in the editor but not in build version. Right after it finishes loading, it throws this error:
RuntimeError: index out of bounds
BufferManagerGLES::AcquireBuffer(unsigned long, DataBufferGLES::BufferUsage, bool)@http://localhost:64826/Build/Build.wasm:wasm-function[9427]:0x4255d6
GfxDeviceGLES::InitializeBufferInternal(GfxBuffer*, void const*, GfxUpdateBufferFlags)@http://localhost:64826/Build/Build.wasm:wasm-function[9340]:0x41aaa1
Mesh::CreateMesh()@http://localhost:64826/Build/Build.wasm:wasm-function[10544]:0x4bcb2e
...
From the error I’m guessing that the GraphicsBuffer API isn’t supported in WebGL builds. Still, I’ve wanted to ask and confirm if that is really the case. I know this is a relatively new feature, so I’ve tried to look up all limitations that apply to WebGL and shaders, but I haven’t found anything about GraphicsBuffers. Just to be sure, here is my simple compute shader:
#pragma kernel CSMain
float Time;
RWByteAddressBuffer Vertices;
[numthreads(1,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
uint y = id.x / 2;
uint x = id.x % 2;
uint rawId = id * 3 << 2;
float3 pos = float3(x, y, sin(Time + id.x));
Vertices.Store3(rawId, asuint(pos));
}
and the code that dispatches this shader (I’ve made attempts to fix it so it’s a bit messy):
using UnityEngine;
using UnityEngine.Rendering;
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class ShaderDispatcher : MonoBehaviour
{
[SerializeField] private Mesh mesh;
[SerializeField] private ComputeShader shader;
private MeshFilter _meshFilter;
private GraphicsBuffer _vertexBuffer;
private void Awake()
{
_meshFilter = GetComponent<MeshFilter>();
}
void Start()
{
mesh = new Mesh();
mesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
mesh.indexBufferTarget |= GraphicsBuffer.Target.Raw;
mesh.SetVertexBufferParams(3, new VertexAttributeDescriptor(VertexAttribute.Position, dimension: 3, stream: 0));
mesh.SetIndexBufferParams(
3,
IndexFormat.UInt32
);
mesh.SetIndexBufferData(new uint[] {0, 1, 2}, 0, 0, 3);
mesh.subMeshCount = 1;
mesh.SetSubMesh(
0,
new SubMeshDescriptor(0, 3),
MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices
);
_vertexBuffer = mesh.GetVertexBuffer(0);
_meshFilter.mesh = mesh;
}
private void Update()
{
shader.SetFloat("Time", Time.time);
shader.SetBuffer(0, "Vertices", _vertexBuffer);
shader.Dispatch(0, 3, 1, 1);
}
}
Please, I would be grateful if anyone could confirm that is indeed the case, or pinpoint any mistakes or alternatives I could have made while writing this code. Thank you kind strangers!