Как реализовать / использовать атомный счетчик в шейдерном фрагменте Metal?

Я хочу реализовать алгоритм A-Buffer для прозрачности, независимой от порядка, в моем приложении Metal. В описании техники упоминается использование атомного счетчика. Я никогда не использовал ни одного из них или даже слышал о них. Я только что прочитал об атомарных переменных в спецификации языка металлического шейдинга, но не могу понять, как их реализовать или использовать.

У кого-нибудь есть опыт работы с этим в металле? Можете ли вы указать мне пример того, как установить и использовать простой целочисленный счетчик? По сути, при каждом проходе рендеринга мне нужно иметь возможность увеличивать целое число из фрагмента шейдера, начиная с нуля. Это используется для индексации в A-Buffer.

Спасибо!

1 ответ

Решение

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

Во всяком случае, атомный счетчик является переменной типа atomic_uint (или же atomic_int если вам нужен знак). Чтобы быть полезным, переменная должна быть общей для определенного адресного пространства. Ваш пример звучит так, как нужно device адресное пространство. Итак, вы хотели бы device Переменная поддерживается буфером. Вы бы объявили это как:

fragment FragmentOut my_fragment_func(device atomic_uint &counter [[buffer(0)]], ...)
{
    ...
}

Вы также можете использовать тип структуры для параметра и иметь поле структуры, которое будет вашим atomic_uint переменная.

Чтобы атомарно увеличить атомную переменную на 1 и получить предыдущее значение, вы можете сделать это:

    uint value = atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);

Начальное значение атомарной переменной берется из содержимого буфера в точке перед выполнением команды рисования или отправки. Это не задокументировано как таковое в спецификации, но размер и битовая интерпретация атомарного типа, кажется, соответствуют соответствующему неатомарному типу. То есть вы бы написали uint (ака unsigned int или же uint32_t) в буфер для инициализации atomic_uint,

Другие вопросы по тегам