【发布时间】:2021-12-21 09:35:15
【问题描述】:
有没有一种基于 Metal 2 的方法可以像“Direct X”12 API“ExecuteIndirect”那样执行“Multi Indirect Draw”? Metal 2 有一些 API 可以进行单次间接绘制,但似乎找不到多次间接绘制。
【问题讨论】:
标签: graphics 3d game-engine metal
有没有一种基于 Metal 2 的方法可以像“Direct X”12 API“ExecuteIndirect”那样执行“Multi Indirect Draw”? Metal 2 有一些 API 可以进行单次间接绘制,但似乎找不到多次间接绘制。
【问题讨论】:
标签: graphics 3d game-engine metal
您可以使用MTLIndirectCommandBuffer 在 CPU 或 GPU 上对绘制或调度命令进行编码。
您创建一个带有MTLIndirectCommandBufferDescriptor 的MTLIndirectCommandBuffer,该MTLIndirectCommandBufferDescriptor 具有最大数量的命令集,以及命令类型和其他属性,例如管道和缓冲区绑定继承。请记住,您不能混合和匹配不同“阶段”的命令。这意味着,您可以有两种不同类型的渲染命令,但不能在同一个缓冲区中同时拥有渲染和计算命令。
之后,你有两种编码方式。
首先是在 CPU 上进行。您可以通过indirectRenderCommandAtIndex: 调用或计算对象MTLIndirectComputeCommand 通过indirectComputeCommandAtIndex: 调用从ICB 请求MTLIndirectRenderCommand 对象。它有点像命令编码器,但只针对单个命令。
第二种方法是在 GPU 上进行。您可以使用参数缓冲区将间接命令缓冲区传递到着色器。您将使用MTLArgumentEncoders setIndirectCommandBuffer:atIndex: 方法将其写入那里。之后,您可以使用类似于 CPU 端 API 的 API。您可以从着色器的参数缓冲区中的索引和command_buffer 对象创建render_command 或compute_command。这个command 结构有很多方法来设置缓冲区、管道状态和编码绘图或计算命令。然后,您将调度一个带有一些线程的内核,这些线程将使用它们在网格中的位置来计算命令缓冲区的索引并在那里对命令进行编码。
尽管间接命令看起来有点像命令编码器,但请记住,索引处的单个命令仅包含一个实际命令,因此与编码器相比,您对绘制或计算命令所做的任何更改覆盖之前的内容。
在 CPU 或 GPU 上对命令进行编码后,您必须执行它。根据您拥有的命令类型,您将在MTLRenderCommandEncoder 或MTLComputeCommandEncoder 上调用executeCommandsInBuffer:indirectBuffer:indirectBufferOffset:。
这应该涵盖基础知识。更深入的了解,有这两篇文章:Encoding Indirect Command Buffers on the CPU 和 Encoding Indirect Command Buffers on the GPU ,还有这篇 Modern Rendering with Metal Sample 大量使用了这些 ICB。
【讨论】:
executeCommandsInBuffer。这是同一个概念。