2017-10-07 18 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는 어디에서 오는가?

나는 다른 크기와 쉐이더에 더 많은 데이터를 보낼 수 있습니다 : VertexBuffer에 3 개 요소를 가지고 있으며, vertexBuffer2 10 개 요소 ...을 가지고

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

경우 정점 기능은 몇 번이라고? 10?

감사합니다.

답변

3

렌더링 명령 인코더에서 그리기 호출을 통해 결정됩니다. 간단한 그리기 방법을 가지고 :

drawPrimitives(type:vertexStart:vertexCount:) 

vertexCount는 정점 함수가 호출 횟수를 결정합니다. 버텍스 함수에 전달 된 버텍스 ID는 vertexStart에서 vertexStart + 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를 사용하여 버퍼에 인덱스하지 않음). 금속 자체는 이것을 알지 못합니다.