Как объединить кодировщики команд рендеринга, использующие другой шейдер в Metal

#ios #swift #graphics #metal #stencil-buffer

#iOS #swift #графика #Металлические #буфер трафарета

Вопрос:

Я пишу графический движок на Metal и использую буфер трафарета для маскировки объемов, покрываемых сферическими гармоническими огнями в сцене. Для этого я использую два шейдера, и мне нужно 3 вызова draw для каждого источника света: один для задних граней, другой для передних граней и последний вызов draw с другим шейдером для фактического рендеринга источника света.

Но, если я хорошо понял документацию Metal, вам нужно определять все ваши проходы «статически», то есть вам нужен другой кодировщик команд рендеринга для каждого используемого вами шейдера и конфигураций поверхностей рендеринга. Правильно ли это?

Это означает, что в итоге я создал этот цикл для своих источников света, что выглядит довольно ужасно, потому что я создаю множество кодировщиков,

 for l in shLights {
    let descStencil = createLightAccumulationRenderPass()
    guard let encoderStencil = commandBuffer.makeRenderCommandEncoder(descriptor: descStencil) else {
        continue
    }
    drawSHLightStencil(l, encoder: encoderStencil)
    encoderStencil.endEncoding()
    let descColor = createLightAccumulationRenderPass()
    guard let encoderColor = commandBuffer.makeRenderCommandEncoder(descriptor: descColor) else {
        continue
    }
    drawSHLight(l, encoder: encoderColor)
    encoderColor.endEncoding()
}
  

Полный код здесь: https://github.com/endavid/VidEngine/blob/master/VidFramework/VidFramework/sdk/gfx/plugins/DeferredLightingPlugin.swift ( drawSHLights функция)

И если вам нужен дополнительный контекст о том, как это используется, пожалуйста, ознакомьтесь с этим сообщением в блоге: http://endavid.com/index.php?entry=85

Я также пробовал повторно использовать кодировщики, но если вы не вызываете endEncoding , Metal вылетает при следующем вызове makeRenderCommandEncoder .

Возможно ли каким-либо образом объединить эти кодировщики?

Редактировать: я сделал захват графического процессора, чтобы было легче видеть весь конвейер рендеринга. Вот скриншот,

Захват графического процессора

Он довольно маленький, но я поместил несколько надписей сверху. Белые метки соответствуют материалу в цикле. В сцене есть 3 источника света, и они освещают 3 сферы.

Ответ №1:

Но, если я хорошо понял документацию Metal, вам нужно определять все ваши проходы «статически», то есть вам нужен другой кодировщик команд рендеринга для каждого используемого вами шейдера и конфигураций поверхностей рендеринга. Правильно ли это?

Нет, это не совсем правильно. Вы заметите, что есть некоторые атрибуты кодировщика команд рендеринга, которые задаются через MTLRenderPassDescriptor во время создания кодировщика, и есть другие атрибуты, которые устанавливаются с помощью средств доступа к кодировщику после его создания. Первые неизменяемы в течение всего срока службы кодировщика. Последнее можно изменить.

Итак, вам действительно понадобится новый кодировщик команд, если вы измените цели рендеринга (вложения). Но вам не нужен новый кодировщик команд для изменения шейдеров. Шейдеры определяются состоянием конвейера рендеринга и могут быть изменены в существующем кодировщике команд с помощью setRenderPipelineState(_:) .

Определенно верно, что вы должны создавать свои объекты состояния конвейера рендеринга один раз за время существования приложения, если это вообще возможно. Но после этого вы можете использовать их так часто, как это необходимо.

Наконец, я бы не слишком беспокоился о создании нескольких кодировщиков команд рендеринга. Они разработаны так, чтобы быть относительно дешевыми в создании. Итак, хотя потратить немного усилий на объединение всей работы, которую можно выполнить с данным кодировщиком, — это нормально, не перегибайте палку назад, пытаясь сделать что-то «попроще», когда это противоречит принципу работы.

Комментарии:

1. Спасибо! Это очень полезно. Я меняю цели рендеринга. Я думаю, я мог бы попытаться использовать те же цели, но если кодировщики дешевы, как вы сказали, то, возможно, я был слишком параноидален. При захвате кадра GPU я получаю пару предупреждений в конце, но в цикле SH lights предупреждений о производительности нет. Я буду ждать, когда появится реальное приложение для поиска узких мест и оптимизации там, где это необходимо.