2

I have a basic question about allocating new Metal device buffers. Most of the sample codes I see create MTLBuffer at setup time and do not modify it. But I wonder if the vertex data is changing at every render call, is it okay to every time create a new MTLBuffer (using -[MTLBuffer newBufferWithBytes:length:option]) for sending data to shaders running on GPU, OR, should MTLBuffer of given size be created once but it's bytes modified on every render call? What's the recommended way as per best practices?

Deepak Sharma
  • 5,577
  • 7
  • 55
  • 131

1 Answers1

3

If it is a small amount of data (under 4K) I believe you can use setVertexBytes() and setFragmentBytes(): https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515846-setvertexbytes

For larger amounts of data that changes every frame, they recommend that you use a triple-buffered approach so that successive frames' access to the buffer do not interfere: https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/TripleBuffering.html

This tutorial shows how to set up triple buffering: https://www.raywenderlich.com/146418/metal-tutorial-swift-3-part-3-adding-texture

That's actually like the third part of the tutorial but it is the part that shows the triple-buffering setup, under "Reusing Uniform Buffers".

What I am unsure about is whether it is better/faster to use triple-buffering on small amounts of data as well -- they do it in that tutorial for only a couple of matrices, so maybe it is better to always triple buffer.

bsabiston
  • 721
  • 6
  • 22
  • Thanks for the answer. That was simple for passing an array of vertices. How do I use the same approach to pass a struct using setFragmentBytes? – Deepak Sharma Apr 05 '18 at 20:36
  • 1
    You can just do it the same way -- pass the address of the struct: renderEncoder.setFragmentBytes(&myStruct, length: MemoryLayout< myStruct >.stride, index: uniforms_index) – bsabiston Apr 05 '18 at 20:39
  • It crashes when sending vertices, "failed assertion `Bytes are being bound at index 0 to a shader argument with write access enabled.'" – Deepak Sharma Apr 05 '18 at 20:56
  • 5
    Change the address space of the buffer parameter to `constant` instead of `device`. – warrenm Apr 05 '18 at 21:08