Чтение пользовательского формата текстуры в фрагментном шейдере - PullRequest
0 голосов
/ 11 июня 2018

Я создаю эмулятор NES и экспериментирую с идеей разгрузки функциональности (при необходимости) в графический процессор.Одна идея, которая меня поразила, - выводить пиксели экрана в буфер в произвольном формате таким образом, чтобы кодировать свойства для каждого пикселя, чтобы шейдер мог определить, как их отображать.Это избавит вас от некоторой логики / ветвления одной из самых популярных функций в эмуляторе.

Вот пример того, как может выглядеть кодировка для одного пикселя, используя 2 байта на пиксель:

Байт 1 (индексы палитры) : bbbb ssss

  • b: индекс палитры пикселей фона
  • s: индекс палитры пикселей спрайта

байт 2 (свойства пикселей) : bbss rgbp

  • b: 2-битное значение фонового пикселя
  • s: 2-битное значение спрайтового пикселя
  • r:Выделение красного
  • g: выделение зеленого
  • b: выделение синего
  • p: приоритет пикселей спрайта

I 'Я относительно новичок в написании шейдеров, поэтому мой первый вопрос: возможно ли это?В проведенном мной исследовании кажется, что текстуры должны быть в определенном формате, чтобы считывать информацию о цвете с каждого пикселя, а мой пользовательский 2-байтовый «цветной» формат даже не представляет цветовойи-о себе.Если это возможно, какой подход высокого уровня можно использовать для достижения этой цели?Я планирую использовать vulkan, но любой подход, который применяется более широко (в отношении шейдеров), приветствуется.

1 Ответ

0 голосов
/ 12 июня 2018

Графика изменилась с 2000 года. Шейдеры - это (в основном) произвольные программы, которые вычисляют значения.То, что эти значения могут иногда интерпретироваться как цвета, не имеет значения.Шейдеры - это программы;они делают то, что вам нужно.

Аналогично, текстуры не содержат цветов, если только ваш шейдер не решит интерпретировать их как цвета.Текстуры - это не что иное, как таблицы поиска значений.Опять же, эти значения могут быть цветами, но не могут.Все зависит от того, как ваш шейдер использует эти значения.

Вы можете создавать текстуры, которые используют целочисленные форматы (в отличие от нормализованных целых).Затем вы можете делать любые битовые манипуляции, которые вам нравятся, в вашем шейдере.Ничто из описанного выше не будет особенно трудным для шейдеров.

В вашем случае текстура, вероятно, будет двухканальным форматом с 8 битами на канал, использующим целочисленные значения без знака.В OpenGL этот формат будет записан GL_RG8UI: красный / зеленый (название двух каналов), 8 бит на канал и целочисленные значения без знака.OpenGL может называть эти каналы «красными» и «зелеными», но важно то, что ваш шейдер делает с ними, а не то, как они называются.

В Vulkan этот формат записан VK_FORMAT_R8G8_UINT: два 8-битные каналы беззнаковых целочисленных значений.

Принципиальная проблема, с которой вы столкнетесь, - это не формат изображения и не шейдер.Он эффективно передает данные в графический процессор.

В OpenGL у вас нет выбора, кроме как постоянно передавать данные DMA из памяти, доступной для ЦП, в текстуры, доступные для графического процессора.В Vulkan вам, возможно, не придется делать это.

Реализации Vulkan могут сказать, что линейные текстуры могут храниться в памяти, доступной как для CPU , так и для GPU.Они не обязаны предоставлять это, но многие могут это сделать.В таких реализациях нет необходимости в DMA;GPU может напрямую читать то, что написал CPU.Вам по-прежнему нужно будет выполнять двойную буферизацию таких изображений (чтобы минимизировать синхронизацию GPU / CPU. Вы записываете в одно, когда GPU читает данные предыдущего кадра), но это должно улучшить производительность по сравнению с версией DMA.

Конечно, вам все еще понадобится кодовая дорожка для реализаций, где это невозможно.

...