2017-03-17 15 views
2

다음은 동일한 똑같은 2D 쿼드를 렌더링하는 metal의 간단한 정점 및 조각 셰이더 콤보입니다. uv 좌표를 변경하여 예기치 않은 성능의 금속을 맞 춥니 다

vertex VertexOut vertexMain(uint k [[ vertex_id ]], 
          uint ii [[instance_id]], 
          device float2* tex [[buffer(2)]], 
          device float2* position [[buffer(1)]], 
          device float* state [[buffer(0)]]){ 
    VertexOut output; 
    int i = 4*ii+1; 
    float2 pos = position[k]; 
    pos *= float2(state[i+2],state[i+3]); 
    pos += float2(state[i],state[i+1]); 
    pos.x *= state[0]; 
    output.position = float4(pos,0,1); 
    output.tex = tex[k]*float2(du,dv); 
    return output; 
}; 
fragment float4 fragmentMain(VertexOut input [[stage_in]], 
          texture2d<float> texture [[texture(0)]], 
          sampler sam [[sampler(0)]]){ 
    return texture.sample(sam, input.tex); 
}; 

샘플러

는 0 내지 1 범위 및 왼쪽 하단부터 샘플링 방법 질감의 클립의 큰 정규화 좌표 제어 할 수 있으므로 dudv를 사용한다.

금속에서 샘플링이 어떻게 작동하는지에 대한 오해가있는 것 같습니다. 나는 계산 값이 어떤 값 dudv에 상관없이 일정하게 유지 될 것으로 기대한다. 그러나 dudv을 1로 늘리면 프레임 속도가 떨어집니다. mipmapping을 사용하지 않고 화면에서 래스터 화 된 쿼드의 크기를 변경합니다. 영향은 선형 필터링에서는 더욱 극적이지만 가장 근접한 필터링에서도 발생합니다. 화면에 그려지는 픽셀 수가 동일하기 때문에 GPU의 부하는 dudv에 의존해서는 안됩니다. 내가 뭘 놓치고 있니?

편집 : 당신이 du 증가로

let samplerDescriptor = MTLSamplerDescriptor() 
    samplerDescriptor.normalizedCoordinates = true 
    samplerDescriptor.minFilter = .linear 
    samplerDescriptor.magFilter = .linear 
    let sampler = device.makeSamplerState(descriptor: samplerDescriptor) 

    let attachment = pipelineStateDescriptor.colorAttachments[0] 
      attachment?.isBlendingEnabled = true 
      attachment?.sourceRGBBlendFactor = .one 
      attachment?.destinationRGBBlendFactor = .oneMinusSourceAlpha 
+0

얼마나 많은 프레임 속도 드롭을 경험할 수 있습니까? – warrenm

+0

선형 샘플링이 가능한 60에서 40까지. 가장 가까운 샘플링과 함께 60에서 50. – gloo

+0

어떤 장치 및 OS 버전입니까? – warrenm

답변

0

dv 대퇴사 두근이 당신의 질감을 더 표시됩니다 여기 내 샘플러 및 색상 첨부 파일입니다. GPU는 텍스처 데이터 용으로 작은 캐시를 사용하는 경향이 있으며 텍스처를 많이 표시 할 때 캐시를 삭제하고 다시 채 웁니다.

텍스처 캐시를 스 래싱하면 메모리 대역폭이 더 많이 사용되지만 제한된 리소스 일뿐 아니라 텍스처 메모리 대역폭이 병목 현상이 아닌 경우가 있습니다. 그러나 조각 쉐이더가 텍스처 가져 오기 이외의 작업을 거의 수행하지 않는 것은 놀랄 일이 아닙니다. 그것은 당신의 병목입니다. 따라서 UV를 변경하는 것이 성능에 영향을 미치는 것은 놀랄 일이 아닙니다.

놀랍게도 놀랍게도 매우 강력한 장치에서 프레임 속도가 60 이하로 떨어지면 64 개의 쿼드 (iPad Pro는 특히 매우 강력한 장치)가 렌더링 될 때입니다. 즉, 모든 64 개의 쿼드가 화면의 대부분을 차지하고 있다면 프레임 율 저하가 이해할 수 있습니다.

성능을 향상 시키려면 GPU에서 주변을 둘러 볼 필요가있는 텍스처 데이터의 양을 줄여야합니다. 32 비트 텍스처 형식 (8888)에서 16 비트 (565/4444) 또는 4 비트 (PVRTC 압축 텍스처)로 변경하면 큰 효과가 있습니다.

정말 큰 밉은 아마도 밉 매핑을 사용하는 것입니다. du 및 의 높은 값으로 가정하면 텍스처를 최소화 한 다음 밉 매핑을 사용하면 거대한 성능상의 이점을 얻게되며 텍스처가 더 좋게 보일 것입니다 (앨리어싱이 수정 됨). 33 % 텍스처 메모리 증가에 대한 나쁜 결과는 아닙니다.

+0

매우 흥미 롭습니다. 인스턴스 렌더링을 사용하고 있는데, 이는 모든 64 개의 쿼드가 단일 텍스처 바인딩 및 단일 그리기 호출과 함께 그려지는 것을 의미합니다. 이 캐싱 문제가 여전히이 시나리오에서 발생합니까? – gloo

+0

예, 텍스처 캐시는 일반적으로 몇 KB에 불과하며 대부분의 텍스처는 수백 KB입니다. 이것은 좋은 입문서입니다 : https : //fgiesen.wordpress.com/2011/07/04/a-trip-through-the-graphics-pipeline-2011-part-4/ 렌더링 시나리오를 더 잘 이해하는 것이 도움이 될 수 있습니다. 당신이 60fps를 명중 할 수없는 경우에 64의 작은 쿼드는 무언가이고 재미 있은 무언가는 계속되고있다. 64 개의 쿼드가 각각 화면 전체를 덮으면 문제를 이해할 수 있습니다. – Columbo

+0

각 쿼드는 화면의 1 %만을 차지합니다. 내 파이프 라인을 설명하는 몇 가지 코드를 추가했습니다. – gloo