Metal writes to buffer from vertex function

I am creating a 2D geometry for rendering an application in Metal.

Currently, the positions of the vertices are solved from the vertex function. I would like to write the allowed positions back to the buffer from within the same vertex function.

I get the impression that this is possible , although in my first attempt to do this ie:

vertex VertexOut basic_vertex(device VertexIn *vertices [[ buffer(0) ]], device VertexOut *solvedVertices [[ buffer(1) ]], vid [[ vertex_id ]]) { VertexIn in vertices[vid]; VertexOut out; out.position = ... // Solve the position of the vertex solvedVertices[vid] = out // Write to the buffer later to be read by CPU return out; } 

I was adorned with the presence of this compile-time error:

enter image description here

Ok, so I get a few solutions - I could solve for vertex positions in the first - non-rasterization pass through the vertex function declared as:

 vertex void solve_vertex(device VertexIn *unsolved [[ buffer(0) ]], device VertexOut *solved [[ buffer(1) ]], vid [[ vertex_id ]]) { solved[vid] = ... } 

And then drag these allowed vertices into the now much simpler - rasterizing - vertex function.

Another solution that may work, but seems less attractive, might be to solve them in a computational function.

So, what is the best way to advance in such a situation? From my small studies, I could trace that the same procedure is performed in Transform Feedback , but I was not lucky (except for the link when asking a question), finding examples in the Apple documentation / sample or elsewhere on the Internet for best practices when I come across this kind of problem.

+5
source share
1 answer

In order , it turns out that using the rasterization vertex function is the way to go. There are some things to note, however, for other future references:

A non-sterilizing vertex function is just a vertex function returning void ie:

 vertex void non_rasterizing_vertex(...) { } 

When performing non-rasterizing "rendering", the MTLRenderPassDescriptor pass MTLRenderPassDescriptor still have a set of textures - for example, in MTLRenderPassDescriptor colorAttachments[0].texture - for reasons that I do not know (I assume that this is simply due to the fixed nature of the GPU programming).

MTLRenderPipelineState must have the rasterizationEnabled property set to false , then you can assign it a non-rasterizing vertexFunction vertex vertexFunction . The fragmentFunction property may remain null as expected.

When actually skipping, one of the drawPrimitives: methods (the assignment of which may be misleading ) still needs to call the configured MTLRenderCommandEncoder . I ended up with the MTLPrimitiveType.Point rendering MTLPrimitiveType.Point , as it seems the most sensual.

Doing all of this sets up the "rendering" logic, ready to write back to vertex buffers from the vertex function if they are in the device address space:

 vertex void non_rasterizing_vertex(device float *writeableBuffer [[ buffer(0) ]], uint vid [[ vertex_id ]]) { writeableBuffer[vid] = 42; // Write away! } 

This "answer" is more like a blog post, but I hope it will be useful for future links.

Todo

I would still like to explore performance trade-offs between compute-y execution, as is the case in the computing pipeline, compared to the rendering pipeline, as shown above. As soon as I have some more time, I will update this answer.

+3
source

Source: https://habr.com/ru/post/1244303/


All Articles