Мифический текстурный шейдер (мексиканская история)
А, собственно, зачем? Казалось бы, всё итак успешно можно решать прямо на уровне пиксельных шейдеров.
Такая абстракция очевидно толще, чем позволяет формат мексиканской истории, особенно в 5 утра. (Здесь аффтор долго думает грустные мысли о том, кому и зачем он всё это пишет). Как обычно читателям придётся много додумать, но в этот раз, мне кажется, уместно нетривиальное обсуждение.
Начнём, впрочем, с конца. Внятная новая абстракция кроме собственно инноваций очевидно успешно решает уже имеющиеся проблемы.
Сперва абстракция. Итак float4 TexBlah(float4 coordinates). Будем резать. Очевидных линий отреза две: прямо на уровне TexBlah, либо на уровень ниже фильтрации. Нужен-ли шейдер фильтрации я буду думать потом, а пока что отрежем на уровне текстурного сэмпла. float4 SampleTexBlah(int4 coordinates). Уровень TexBlah имеет свои приимущества, но идёт вопреки идее грубой силы – и потому лесом.
Теперь немножко про зачем. И про почему. Шейдеры остаются не менее унифицированные, добавляется дополнительный паралеллизм. На каждый TexBlah сэмплов будет чаще всего значительно больше одного. С очень когерентными coordinates. Появляется дополнительное кеширование. SampleTexBlah определённо функция без сайд-эффектов.
Кеширование, кстати, ставит интересный вопрос. Float4 SampleTexBlah(int4 coordinates) очевидно проигрывает byte4 SampleTexBlah(int4 coordinates) – формат результата зависит от формата текстуры, а для случая DXT1 (которое на современном железе хранится в кеше в нераспакованом виде) придумать внятный формат результата у меня почти не получается. Т-е вопрос исключительно эффективности кеша, и здесь однозначного мнения у меня нет (интруция говорит ограничимся byte4 снизу и float4 сверху). Собственно здесь снова встаёт вопрос шейдера фильтрации, но это, пожалуй, единственный имеющийся у меня use-case.
В итоге очередной кусок специализированного железа (а есть ли он там?) получает равноправное унифициорванное применение. Пусть будет 2x нитей, а не ещё несколько текстурных блоков. Такая система будет значительно лучше масштабироваться.
Как всё это может выглядеть? Ну, например, вот так
byte4 palette[256];
byte [] index_map;
int width, height;
byte4 main ( int2 coordinates )
{
byte index = index_map[coordinates.x+coordinates.y*width];
return palette[index];
}
Теперь, когда как-то понятно, где оно работает, вернёмся снова к предмету обсуждения. А, собственно, зачем?
Пример выше иллюстрирует мой самый первый use-case. А именно поддержка текстур с палитрой на современном железе. Я ничего не буду говорить про компрессию, мегатекстуры, фрагментацию текстурной памяти и прочие самоочевидные вещи. Замечу, только, что работать такое будет значительно лучше, чем сколь угодно продуманный фиксированный API. Меньше всего я хочу удвидеть очередную видеокарту с аппаратной поддержкой мегатекстур. Надеюсь имеющиеся “фенечки” про стенсильный буфер тоже когда-нибудь кто-нибудь выкинет на свалку истории, хотя-бы какими-нибудь бленд-шейдерами. Но это уже тема совсем другой истории.
P.S. ужасно уродливый шейдер про текстуру с палитрой и билинейной фильтрацией могу отдать в хорошие руки.
Pingback: highly professional scums » Blog Archive » шейдер интерполятора()