2015-05-06 82 views
1

我有一個非常慢的工作金屬應用程序,需要運行得更快。我相信問題是我創建了太多的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更好的強制像素着色評估的方法。

我認爲簡單地分配一個比單個着色器通道所需要的大得多的緩衝區,並簡單地使用偏移量在一個渲染命令編碼器中排隊幾個調用,然後執行它們。這種方法看起來非常非常規,我想確保我正在解決需要以金屬友好的方式爲每個對象發送自定義數據的問題。

什麼是使用同一個像素/頂點着色器的多個通道渲染每個調用自定義統一數據的最快方式?

回答

3

不要爲每個對象重用相同的統一緩衝區。這樣做會破壞CPU和GPU之間的所有並行性並導致常規同步點。

取而代之的是,您要在框架中呈現每個對象的單獨統一緩衝區。實際上,您應該在每個對象之間創建2個對象,並在它們之間交替,以便在準備CPU上的下一個幀時,GPU可以渲染最後一個幀。

做完這些之後,您只需重構您的循環,以便命令緩衝區和渲染命令每幀完成一次。你的循環應該只包括複製統一數據,設置頂點緩衝區和調用繪製原語。