Как указано в Руководстве по языку металлического затенения:
Записывает буфер или текстура не разрешается из функции фрагмента.
Я понимаю, что это так, но мне любопытно, почему. Возможность писать в буфер из фрагментарного шейдера невероятно полезна; Я понимаю, что на аппаратной стороне скорее всего сложнее не знать заранее, какое конечное местоположение памяти записывает для определенного потока, который вы не всегда знаете с помощью 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.