2015-04-15 5 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. Не зная больше о том, что вы делаете на более высоком уровне, моим первым предложением было бы рассмотреть использование текстур массива 2d.

2d массивные текстуры по существу объединяют X 2D-текстуры в единую текстуру с X срезами к ней. Вам нужно передать только одну текстуру в Металл, и вы можете вычислить, какой фрагмент для выборки из шейдера точно так же, как вы уже делали, но при таком подходе вы избавитесь от всех ветвей 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 (ищите 'Texture Ломтики')

Также здесь: https://developer.apple.com/library/prerelease/ios/documentation/Metal/Reference/MTLTexture_Ref/index.html#//apple_ref/c/econst/MTLTextureType2DArray

языков Metal шейдерных DOCS здесь: https://developer.apple.com/library/ios/documentation/Metal/Reference/MetalShadingLanguageGuide/std-lib/std-lib.html#//apple_ref/doc/uid/TP40014364-CH5-SW17 (искать '2D Texture массива')

Смежные вопросы