Подтвердить что ты не робот

Почему записывается в буфер из фрагментарного шейдера, запрещенного в Metal?

Как указано в Руководстве по языку металлического затенения:

Записывает буфер или текстура не разрешается из функции фрагмента.

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

Добавление

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

Существуют и другие случаи, когда вы, возможно, захотите сделать ленивую запись в шейдере фрагмента, конечное местоположение которого основано на свойствах фрагмента, а не на точном месте фрагмента; эффективно, растеризация с побочными эффектами. Например, большинство Voxelization на основе графического процессора работает, создавая сцену с орфографической проекцией с некоторым желательным углом, а затем записывая в 3D-текстуру, отображая координаты XY фрагмента и связанное с ним значение глубины в месте в 3D-текстуре. Это описано здесь.

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

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

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

Поскольку я не получал ответов здесь, я закончил публикацию вопроса на форумах разработчиков Apple. У меня больше отзывов, но ответа пока нет. Если мне что-то не хватает, кажется, что практически каждое устройство OS X, официально поддерживающее Metal, имеет аппаратную поддержку этой функции. И, как я понимаю, эта функция впервые появилась в GPU в 2009 году. Это общая функция как в текущих DirectX, так и в OpenGL (даже не учитывая DX12 или Vulkan), поэтому Metal был бы единственным "передовым" API, который этого не имеет.

Я понимаю, что эта функция может не поддерживаться на оборудовании PowerVR, но у Apple не было проблем с дифференциацией языка металлического затенения набором функций. Например, Metal on iOS позволяет получать "свободные" фреймы фреймов фреймов в фрагментарных шейдерах, которые напрямую поддерживаются аппаратным обеспечением с помощью мощной архитектуры PowerVR. Эта функция проявляется непосредственно на языке металлического затенения, так как позволяет объявлять входы функции фрагмента с атрибутом атрибута [[color(m)]] для шейдеров iOS. Возможно, объявление декларации буферов с помощью классификатора пространства device или текстур с access::write в качестве вклада в шейдеры фрагментов не будет большим семантическим изменением языка, чем то, что Apple сделала для оптимизации iOS. Итак, насколько мне известно, отсутствие поддержки PowerVR не объясняет отсутствие функции, которую я ищу на OS X.

4b9b3361

Ответ 1

Я думаю, вы не можете писать произвольные пиксели или тексели в функции фрагмента OpenGL или DirectX. Одно дело - API-интерфейс рендеринга, а другие - функции фрагментов или вершин.

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

Есть веская причина не позволять вам писать произвольные пиксели/тексели: распараллеливание. Функция фрагмента выполняется обычно для множества разных пикселей/текселей одновременно на большинстве графических процессоров в очень высоком режиме распараллеливания, каждый графический процессор имеет свой собственный способ распараллеливания (SMP, векторный...), но все делают очень высокую паралелизацию, Таким образом, вы можете писать только путем возврата одного пиксельного или тексельного каналов в качестве возврата функции фрагмента, чтобы избежать общих проблем с распараллеливанием, таких как расы. Это применимо к каждой графической библиотеке, которую я знаю.

Ответ 2

В настоящее время поддерживается перезаписывание буферов из флеш-шейдеров, как указано в Что нового в iOS 10, tvOS 10 и macOS 10.12

Чтение параметров буфера функций Доступно в: iOS_GPUFamily3_v2, OSX_GPUFamily1_v2

Функции фрагмента теперь могут записываться в буферы. Считываемые буферы должны быть объявленный в адресном пространстве устройства и не должен быть const. использование динамическая индексация для записи в буфер.

Более того, строка, указывающая ограничение (из исходного вопроса), не существует в Спецификация металлического оттенка 2.0