I am working on a project that performs manual skinning for meshes. For performance reasons this is currently running on the GPU through Compute Shaders. The resulting vertices are fed to a vertex shader through Compute Buffers. This is clearly not ideal. I would much prefer a way to update the mesh data directly, on the GPU, so that no changes to shaders are needed.
I noticed that a new GraphicsBuffer type has been introduced recently, which is used to supply an index buffer in a call to DrawProcedural.
Are there are any plans to allow users to get the GraphicsBuffer containing the vertex data of a mesh? And will GraphicsBuffer be compatible with Compute Shaders?
I realize this has been asked before, for instance in this topic:
However, seeing as how that topic is in an archived beta section, I wanted to request this feature here as well.
Our current alpha (2020.1) contains improvements in this area:
All API that takes a ComputeBuffer now can take GraphicsBuffer too
Can write to a GraphicsBuffer from Compute then use it in Graphics.DrawProcedural as an index buffer, by creating the buffer with Target.Index | Target.Raw flags.
I’m not sure if the mesh API has the required pieces in it yet to let you read/write its vertices in a compute shader though. I’ll ask the team
Yes. It’s everything that ComputeBuffer ever was, plus the ability to behave like things that have nothing to do with Compute, such as Vertex and Index Buffers.
For example, you should be able to fill a buffer in Compute, then draw that same buffer like it was a Vertex Buffer. (data appears in the shader as POSITION, COLOR, TEXCOORD0, etc) That’s the goal we are working towards, and having a buffer type that doesn’t have “Compute” in the name is an important step towards that.
So what I am getting from this is the GraphicsBuffer can be used to render an index array generated from the compute buffer with Graphics.DrawProcedural?
But in the material shader, I should be able to use the “uint vertexId : SV_VertexI” vertex program input to read from a Compute Buffer containing the vertex positions, and set the vert position from inside the vertex program.
When can we expect to see GraphicsBuffer.Target.Vertex to be working in a public beta?
Am I correct that a GraphicsBuffer.Target.Vertex will finally make it possible to use DrawProcedural and ShaderGraph together? If the vertices are provided like a mesh with vertex shader semantics I don’t see why not.
What is the fate of ComputeBuffer? Will it be phased out? GraphicsBuffer.Target seems to cover what ComputeBufferType did and more. So why keep it? And if that is the case, why didn’t you expand the features of ComputeBuffer instead of adding a new type?
Sorry I don’t know when it will land, or how hard we are pushing to add this ability at the moment.
For this, all I think is needed is for Shader Graph to let you work with the vertex index semantic (SV_VertexID in DX11, each platform has its own name for it) I don’t think GraphicsBuffer/ComputeBuffer is related at all
Yes ComputeBuffer will (one day…) disappear. But usage is almost 100% today. So it is not any day soon. Why not extend ComputeBuffer? Because ComputeBuffer is badly named - it implies it has something to do with Compute and Compute Shaders. GraphicsBuffer is for any type of rendering buffer. Extending ComputeBuffer would be confusing.
If GraphicBuffer vertices support vertex shader semantics, wouldn’t that eliminate the need for binding custom vertex ComputeBuffers to shaders for use with DrawProcedural? And wound’t that mean that default shaders as well as ShaderGraph compiled shaders would accept GraphicBuffer verticies through DrawProcedural just like they accept Meshes through MeshFilter and MeshRenderer?
Oh I guess you are meaning if we also added a new script API version of DrawProcedural that took a “vertex” GraphicsBuffer, rather than our current options of Index, and vert/instance counts? Yeah if we also added that, you could draw meshes with only DrawProcedural, and they would work with ShaderGraph because ShaderGraph understands the common vertex inputs like position, texcoord, normal etc.
Exactly! This is exactly what we need. It would be an amazing feature for anyone working with procedural/generative content. There are many benefits from doing this … perhaps the greatest being that that code for GPU bound procedural content creation can be decoupled from specific SRPs, or perhaps that every existing shader would work with GPU bound procedural content. Currently, it is a pain to write DrawProcedural compatible shaders for HDRP. And for URP, although there is an API for it, things like shadows are not even supported at the moment.
In this example, you set the vertex from inside the compute shader and it can be read from inside the graphics shader with the DrawProcedural call. However, you set the GraphicsBuffer from inside C# rather than inside the compute shader. Was this due the same issue I came across? The issue I’m having with the version I made for my project, however, is that when I create a graphics Buffer for indices (using sizeof(int)), Assign it to a RWStructuredBuffer, I am unable to pull data out of the compute shader. If, in the C# end, I turn
GraphicsBuffer g_buff = new GraphicsBuffer(GraphicsBuffer.Target.Index, indexBuff_size, sizeof(int));
to
ComputeBuffer g_buff = new ComputeBuffer(indexBuff_size, sizeof(int));
It works; With ComputeBuffer g_buff.GetData(), I get an array with valid data. With the GraphicsBuffer, I get an array of all zeros.
richardkettlewell, is GraphicsBuffer actually able to be written to from a compute shader yet?
It depends. In 2019.3, it can only be used as an index buffer.
In 2020.1, yes, you can write to them in compute shaders.
You haven’t set up this graphics buffer to be writable from compute. you have only said you want to use it as an index buffer. You probably need to add GraphicsBuffer.Target.Raw, to write from compute (assuming it is declared as a RWByteAddressBuffer in the compute shader. Use Structured instead of Raw if its a RWStructuredBuffer inside the shader.)
But this requires Unity 2020.1.
Hi Richard,
thanks for the help! However when I try to use
var indexBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Index | GraphicsBuffer.Target.Structured, count, sizeof(int));
I get following errors:
Failed to create Compute Buffer UAV, HRESULT: 0x80070057
Failed to create Compute Buffer SRV, HRESULT: 0x80070057
When I use GraphicsBuffer.Target.Raw instead of GraphicsBuffer.Target.Structured it works, but I like to use a RWStructuredBuffer … any idea how to fix that?
Btw.: I’m using Unity 2020.1.0.b13.
Also Graphics.DrawProceduralIndirect(_goMat, _mesh.bounds, MeshTopology.Triangles, _indexBuffer, _bufferWithArgs); is not working!