"Determine when to sample counters when you encode Metal commands."
Metal 명령을 인코딩할 때 언제 카운터를 샘플링할지 결정합니다.
Metal 기기는 두 가지 샘플링 메소드를 지원합니다. 파이프라인 단계 경계에서 하는 것 혹은 서로 다른 Metal 명령 사이입니다. 샘플링 방법에 따라 GPU 카운터 샘플링에 있어 다른 전략을 사용해야 합니다.
MTLCounterSamplingPoint.atStageBoundary
샘플링 위치를 지원하는 Metal 기기 객체의 경우 Metal에게 연산, blit, 렌더링 전달의 단계마다 GPU 카운터를 샘플하길 알려줘야 합니다. GPU가 주어진 단계를 시작하거나 마무리할 때, 카운터를 샘플링하고 결과를 카운터 샘플 버퍼로 복사합니다.
전달을 설명하기 위해 MTLRenderPassDescriptor
, MTLComputePassDescriptor
, MTLBlitPassDescriptor
를 생성하시기 바랍니다. 기본값으로 Metal은 전달 동안 GPU 카운터를 샘플링하지 않습니다. sampleBufferAttachments
속성은 결과를 저장하기 위해 Metal을 위한 샘플 버퍼 내부에 목적지를 구체화합니다. 특정 단계에서 샘플링을 건너뛰려면 특수한 인덱스 값인 MTLCounterDontSample
을 사용하시기 바랍니다. 반대의 경우 제공된 카운터 집합 버퍼 내부에 맞는 인덱스들을 선택하시기 바랍니다. Metal은 단계 경계에서 샘플링을 지원하지 않는 기기 객체를 사용하는 경우 MTLCounterDontSample
외의 인덱스를 사용할 때 특정 동작을 정의하지 않습니다. Metal API 유효성 검증은 이와 같은 일을 시도할 때 이를 감지하고 경고합니다.
아래 코드는 카운터 정보를 샘플링하는 렌더링 전달 설명자를 생성합니다. 코드는 이전에 생성된 카운터 샘플 버퍼를 사용하고 위해, 그리고 각 단계에서 카운터 샘플 버퍼에 대한 다른 인덱스를 구체화하기 위해 렌더링 전달을 설정하고 있습니다.
renderPassDescriptor.sampleBufferAttachments[0].sampleBuffer = timestampCounterBuffer;
renderPassDescriptor.sampleBufferAttachments[0].startOfVertexSampleIndex = 0;
renderPassDescriptor.sampleBufferAttachments[0].endOfVertexSampleIndex = 1;
renderPassDescriptor.sampleBufferAttachments[0].startOfFragmentSampleIndex = 2;
renderPassDescriptor.sampleBufferAttachments[0].endOfFragmentSampleIndex = 3;
blit 혹은 연산 전달은 오직 하나의 단계만 갖습니다. 그렇기 때문에 이 설명자를 설정할 때 startOfEncoderSampleIndex
와 endOfEncoderSampleIndex
를 구체화할 수 있습니다.
MTLCounterSamplingPoint.atDrawBoundary
, MTLCounterSamplingPoint.atDispatchBoundary
, MTLCounterSamplingPoint.atBlitBoundary
, MTLCounterSamplingPoint.atTileDispatchBoundary
옵션을 지원하는 Metal 기기 객체의 경우 연산, blit, 렌더링 전달 동안 GPU 카운터를 샘플링하기 위해 특정 명령을 인코딩할 수 있습니다. GPU가 해당 명령에 도달하면 GPU는 카운터를 샘플링하고 결과를 카운터 샘플 버퍼로 복사합니다.
인코더 생성 후 인코더의 sampleCounters(sampleBuffer:sampleIndex:barrier:)
함수를 사용해서 카운터 샘플링을 위해 명령을 인코딩하시기 바랍니다. 이는 Metal이 샘플을 어느 곳에 써야 하는지를 구체화하면서 수행합니다. 아래 예시는 두 가지 다른 드로잉 명령으로 렌더링 전달의 부분을 인코딩하고 있습니다. 또한, 명령 사이에서 카운터를 샘플링하고 있습니다.
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle
vertexStart:0
vertexCount: totalVertexCount];
[renderEncoder sampleCountersInBuffer:timestampCounterBuffer atSampleIndex:0 withBarrier:NO];
...
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle
vertexStart:0
vertexCount: totalVertexCount];
MTLComputeCommandEncoder
와 MTLComputeCommandEncoder
는 커널 디스패치들 혹은 blit들 사이에서 샘플 명령 인코딩을 위한 동일한 함수를 제공합니다. barrier
파라미터는 Metal이 카운터 샘플링 전, 예전에 받았던 모든 명령을 완료해야 하는지를 제어합니다. barrier
를 삽입하는 것은 성능을 저하시키지만, 간결하고 반복적인 결과를 가져올 때 유용합니다.
필요한 샘플링 포인트를 지원하지 않는 Metal 기기 객체를 사용할 때 이러한 함수를 호출하면 Metal은 에러를 반환합니다.
샘플링 데이터를 저장하기 위해 GPU가 접근 가능한 메모리를 사용합니다.
https://developer.apple.com/documentation/metal/counter_sampling/creating_counter_sample_buffers_to_hold_counter_data
https://velog.io/@panther222128/Creating-Counter-Sample-Buffers-to-Hold-Counter-Data
카운터 샘플 버퍼 생성을 위해 사용되는 설정입니다.
https://developer.apple.com/documentation/metal/mtlcountersamplebufferdescriptor
https://velog.io/@panther222128/MTLCounterSampleBufferDescriptor