2015-04-15 51 views
1

我已經獲得了下面的着色器(爲了長度和清晰度而刪除了這些作品),並且希望找到更好的方法來完成此操作。我想將大小可變的紋理數組發送到我的金屬着色器。我將對頂點位置進行一些計算,然後確定要使用的紋理。向金屬發送紋理數組的最佳方法

目前我剛硬編碼的東西,並使用幾個if語句,但這是醜陋的(我猜測不快)。有什麼方法可以計算i,然後用i作爲紋理下標(如tex[i].sample)?

// Current code - its ugly 
fragment half4 SimpleTextureFragment(VertextOut inFrag [[stage_in]], 
            texture2d<half> tex0 [[ texture(0) ]] 
            texture2d<half> tex1 [[ texture(1) ]] 
            texture2d<half> tex2 [[ texture(2) ]] 
            ... 
            texture2d<half> texN [[ texture(N) ]] 
            ) 
{ 
    constexpr sampler quad_sampler; 
    int i = (Compute_Correct_Texture_to_Use); 
    if(i==0) 
    { 
     half4 color = tex0.sample(quad_sampler, inFrag.tex_coord); 
    } 
    else if(i==1) 
    { 
     half4 color = tex1.sample(quad_sampler, inFrag.tex_coord); 
    } 
    ... 
    else if(i==n) 
    { 
     half4 color = texN.sample(quad_sampler, inFrag.tex_coord); 
    } 
    return color; 
} 

回答

2

你是對的,你的方法不會很快。最好的情況是,着色器會有很多分支(這是不好的),更糟的情況是,着色器會從所有紋理中抽​​樣,然後放棄它不使用的結果(這會更慢)。

這不是GPU處理得特別好的情況,所以我的建議是稍微重構一下你的方法,使GPU更友好。在不知道更高層次上你在做什麼的情況下,我的第一個建議是考慮使用二維數組紋理

二維數組紋理基本上將X 2D紋理合併到一個具有X片的紋理中。您只需將一個紋理傳遞給Metal,並且您可以完全按照您已經在做的那樣計算在着色器中從哪個樣片中進行採樣,但是通過這種方法,您將擺脫所有'if'分支,只需要調用樣本一次是這樣的:tex.sample(my_sampler, inFrag.tex_coord, i);

如果你的紋理都是相同的大小和格式,那麼這將很容易工作。您只需將每個2D紋理複製到陣列紋理的一個片段中即可。如果您的紋理在大小或格式上不同,則可能需要通過拉伸一些以使它們最終達到相同的尺寸。

看到這裏的文檔:https://developer.apple.com/library/ios/documentation/Miscellaneous/Conceptual/MetalProgrammingGuide/Mem-Obj/Mem-Obj.html#//apple_ref/doc/uid/TP40014221-CH4-SW10 (尋找 '紋理切片')

另外這裏:https://developer.apple.com/library/prerelease/ios/documentation/Metal/Reference/MTLTexture_Ref/index.html#//apple_ref/c/econst/MTLTextureType2DArray

金屬着色器語言文檔瀏覽:https://developer.apple.com/library/ios/documentation/Metal/Reference/MetalShadingLanguageGuide/std-lib/std-lib.html#//apple_ref/doc/uid/TP40014364-CH5-SW17(尋找 '2D紋理陣列')