Использование интерфейса CommandBuffer в графе рендеринга
Вы можете использовать график рендеринга AddUnsafePass API для использования CommandBuffer API интерфейса, такие как SetRenderTarget в графе рендеринга система рендеринга проходит.
AddUnsafePass API дает доступ к UnsafeCommandBuffer, который дает доступ к большему количеству функций CommandBuffer, чем RasterCommandBuffer API.
Примечание: Как AddUnsafePass, так и RasterCommandBuffer ограничивают доступ к некоторым функциям commandBuffer, чтобы RenderGraph мог лучше оптимизировать кадр. Самая важная функция UnsafeCommandbuffer предоставляет вам доступ к SetRenderTarget.
Если вы используете AddUnsafePass API, применяется следующее:
- Вы не можете использовать метод
SetRenderAttachmentв методеRecordRenderGraph. Вместо этого используйтеSetRenderTargetв методеSetRenderFunc. - Отображение может быть медленнее, потому что система графического отображения не может оптимизировать проход отображения. Например, если ваш проход отображения записывает в активный цветовой буфер, система графического отображения не может определить, записывает ли более поздний проход отображения в тот же буфер. В результате система графического отображения не может объединить два прохода отображения, и GPU ненужным образом передаёт буфер в память и из нее.
Создание небезопасного прохода отображения
Чтобы создать небезопасный проход отображения, выполните следующие действия.
-
В методе
RecordRenderGraphиспользуйте методAddUnsafePassвместо методаAddRasterRenderPass.Например:
using (var builder = renderGraph.AddUnsafePass<PassData>("My unsafe render pass", out var passData)) -
При вызове метода
SetRenderFuncиспользуйте типUnsafeGraphContextвместо типаRasterGraphContext.Например:
builder.SetRenderFunc( static (PassData passData, UnsafeGraphContext context) => ExecutePass(passData, context) ); -
Если ваш проход рендеринга пишет в текстуру, добавьте её как поле в класс данных прохода.
Например:
class PassData { public TextureHandle textureToWriteTo; } -
Если ваш проход рендеринга записывает текстуру, установите текстуру как записываемую с помощью метода
UseTexture.Например:
builder.UseTexture(passData.textureToWriteTo, AccessFlags.Write);
Теперь в своём методе можно использовать API интерфейса CommandBuffer SetRenderFunc метод.
Пример
В следующем примере используется интерфейс CommandBuffer SetRenderTarget API, чтобы установить цель рендеринга на активный цветовой буфер во время прохождения рендеринга, а затем нарисовать объекты, используя их поверхностные нормы в качестве цветов.
using UnityEngine;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class DrawNormalsToActiveColorTexture : ScriptableRendererFeature
{
DrawNormalsPass unsafePass;
public override void Create()
{
unsafePass = new DrawNormalsPass();
unsafePass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(unsafePass);
}
class DrawNormalsPass : ScriptableRenderPass
{
class PassData
{
public TextureHandle activeColorBuffer;
public TextureHandle cameraNormalsTexture;
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
{
using (var builder = renderGraph.AddUnsafePass<PassData>("Draw normals", out var passData))
{
// Make sure URP generates the normals texture
ConfigureInput(ScriptableRenderPassInput.Normal);
// Get the frame data
UniversalResourceData resourceData = frameContext.Get<UniversalResourceData>();
// Add the active color buffer to our pass data, and set it as writeable
passData.activeColorBuffer = resourceData.activeColorTexture;
builder.UseTexture(passData.activeColorBuffer, AccessFlags.Write);
// Add the camera normals texture to our pass data
passData.cameraNormalsTexture = resourceData.cameraNormalsTexture;
builder.UseTexture(passData.cameraNormalsTexture);
// Make sure the render graph system keeps the render pass, even if it's not used in the final frame.
// Don't use this in production code, because it prevents the render graph system from removing the render pass if it's not needed.
builder.AllowPassCulling(false);
builder.SetRenderFunc(static (PassData data, UnsafeGraphContext context) => ExecutePass(data, context));
}
}
static void ExecutePass(PassData passData, UnsafeGraphContext context)
{
// Create a command buffer for a list of rendering methods
CommandBuffer unsafeCommandBuffer = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd);
// Add a command to set the render target to the active color buffer so URP draws to it
context.cmd.SetRenderTarget(passData.activeColorBuffer);
// Add a command to copy the camera normals texture to the render target
Blitter.BlitTexture(unsafeCommandBuffer, passData.cameraNormalsTexture, new Vector4(1, 1, 0, 0), 0, false);
}
}
}
Другие примеры см. в примере, названном UnsafePass в примерах пакета Universal Render Pipeline (URP).