我有一个运行速度极慢的金属应用程序,需要运行得更快。我相信问题是我创建了太多的 MTLCommandBuffer 对象。
我创建这么多 MTLCommandBuffer 对象的原因是我需要向像素着色器发送不同的统一值。我粘贴了一段代码来说明下面的问题。
for (int obj_i = 0 ; obj_i < n ; ++obj_i)
{
// I create one render command buffer per object I draw so I can use different uniforms
id <MTLCommandBuffer> mtlCommandBuffer = [metal_info.g_commandQueue commandBuffer];
id <MTLRenderCommandEncoder> renderCommand = [mtlCommandBuffer renderCommandEncoderWithDescriptor:<#(MTLRenderPassDescriptor *)#>]
// glossing over details, but this call has per object specific data
memcpy([global_uniform_buffer contents], per_object_data, sizeof(per_data_object));
[renderCommand setVertexBuffer:object_vertices offset:0 atIndex:0];
// I am reusing a single buffer for all shader calls
// this is killing performance
[renderCommand setVertexBuffer:global_uniform_buffer offset:0 atIndex:1];
[renderCommand drawIndexedPrimitives:MTLPrimitiveTypeTriangle
indexCount:per_object_index_count
indexType:MTLIndexTypeUInt32
indexBuffer:indicies
indexBufferOffset:0];
[renderCommand endEncoding];
[mtlCommandBuffer presentDrawable:frameDrawable];
[mtlCommandBuffer commit];
}
上面的代码按预期绘制,但速度非常慢。我猜是因为有比为每个对象创建一个 MTLCommandBuffer 更好的方法来强制像素着色器评估。
我考虑过简单地分配一个比单个着色器传递所需的缓冲区大得多的缓冲区,并简单地使用偏移量在一个渲染命令编码器中将多个调用排队,然后执行它们。这种方法看起来很不正统,我想确保我正在解决需要以金属友好的方式发送每个对象的自定义数据的问题。
使用每次调用自定义统一数据使用同一像素/顶点着色器的多个通道进行渲染的最快方法是什么?