2017-03-17 39 views
2

下面是一個簡單的頂點和片段着色器組合,其中metal表示64個相同的2D四邊形。通過更改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); 
}; 

採樣是使用歸一化的座標,以便dudv的範圍可以從0到1,並控制如何大紋理的剪輯的將被採樣開始在左下角。

看來我對如何在金屬中進行取樣工作存在誤解。無論dudv是什麼值,我都希望計算成本保持不變。但是,當我將dudv增加到1時,幀頻下降。我沒有使用任何mipmapping,也沒有更改屏幕上柵格化四邊形的大小。線性濾波的影響更加劇烈,但最接近的濾波也會發生。在我看來,由於繪製到屏幕上的像素數量相同,因此GPU上的負載不應取決於dudv。我錯過了什麼?

編輯:這是我的採樣器和附色:

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

在哪個設備和操作系統版本? – warrenm

回答

0

當你增加dudv您的股四頭肌是顯示您更多的質感。 GPU傾向於使用紋理數據的小型高速緩存,並且當您顯示更多紋理時,您將更多地丟棄和重新填充該高速緩存。

抖動紋理緩存將使用更多的內存帶寬,這是一個相當有限的資源,通常紋理內存帶寬不是瓶頸,但由於您的片段着色器除了紋理拾取幾乎沒有什麼功能,所以並不意外這是你的瓶頸。因此,改變你的紫外線對性能有影響並不奇怪。

令人驚訝的是,在這些非常強大的設備上,當你所做的只是渲染64個四邊形(特別是iPad Pro是一個非常強大的設備)時,幀速率會降到60以下。也就是說,也許如果所有64個四邊形都覆蓋了大部分屏幕,那麼幀率下降可能是可以理解的。

爲了提高性能,您需要減少需要由GPU剷除的紋理數據量。從32位紋理格式(8888)更改爲16位(565/4444)或4位(PVRTC壓縮紋理)會產生很大的影響。

真正的大贏家可能是啓用mipmapping。假設dudv的值很高,最終會使紋理最小化,然後使用mipmapping可以提供巨大的性能優勢,並且作爲額外的好處,紋理也會更加美觀(它將修復混疊)。 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