2017-10-07 49 views
1

我一直在學習了一些基本金屬呈現和我堅持一些基本概念:用金屬調用頂點着色器多少次?

我知道我們可以使用頂點數據發送到着色器:

renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0) 

然後我們可以找回與着色器:

vertex float4 basic_vertex(const device VertexIn* vertexIn [[ buffer(0) ]], unsigned int vid [[ vertex_id ]]) 

據我瞭解,頂點功能將被稱爲每次每個頂點一次,vertex_id將更新每次調用包含頂點索引。

問題是,從哪裏來的vertex_id?

我可以用不同的尺寸發送到着色器更多的數據:

renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0) 
renderEncoder.setVertexBuffer(vertexBuffer2, offset: 0, index: 1) 

如果vertexBuffer有3個要素,vertexBuffer2有10個元素......多少次被稱爲頂點功能? 10?

謝謝!

回答

3

這是由您在渲染命令編碼器上繪製的調用確定的。就拿最簡單的繪製方法:

drawPrimitives(type:vertexStart:vertexCount:) 

vertexCount決定了你的頂點函數調用多少次。傳遞給頂點函數的頂點ID是從vertexStartvertexStart + vertexCount - 1的範圍。

如果考慮另一種繪製方法:

drawPrimitives(type:vertexStart:vertexCount:instanceCount:) 

那雲在相同範圍內的頂點的ID。但是,它會調用您的頂點函數vertexCount * instanceCount次。將會有instanceCount調用,頂點ID爲vertexStart。這些調用的實例ID範圍將從0到instanceCount - 1。同樣,將會有instanceCount調用,其頂點ID爲vertexStart + 1(假設vertexCount >= 2),其中一個具有[0..instanceCount-1]中的每個實例ID。等

其他繪製方法有其他各種選項,但它們大多不影響頂點函數被調用的次數。例如,baseInstance會移動實例ID的範圍,但不移動其大小。

各種drawIndexedPrimitives()方法從緩衝區獲取特定的頂點ID,而不是枚舉範圍內的所有頂點ID。該緩衝區可能包含多個位置中的給定頂點ID。對於這種情況,我認爲它沒有定義頂點函數是否可以針對相同的頂點ID和實例ID多次調用。 Metal可能會嘗試避免重複工作,但即使多個這樣的索引最終成爲相同的頂點ID,它可能最終只會爲索引緩衝區中的每個索引調用頂點函數。

您傳遞給頂點處理階段的緩衝區中的頂點和數據之間的關係完全取決於您。你根本不需要傳遞任何緩衝區。例如,頂點函數可以從頂點ID和實例ID完全計算生成頂點信息。

當然,至少某些緩衝區包含使用頂點ID索引到的每個頂點數據的數組是很常見的。其他緩衝區可能是統一的數據,對於所有頂點都是相同的(也就是說,您不使用頂點ID將其索引到該緩衝區中)。不過,金屬本身並不知道這一點。