2024-12-26 14:17:41 +08:00

248 lines
10 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using NVStreamline;
namespace NVStreamline
{
[AddComponentMenu("NVIDIA/Streamline DLSS-G Builtin")]
public class StreamlineDLSSG : MonoBehaviour
{
private CommandBuffer m_cmdCopyDepthAndMVecs;
private CommandBuffer m_cmdCopyHudlessColor;
private Camera m_camera;
private uint m_id;
public bool DLSSGFeatureAvailable { get; private set; } = false;
#if false
//Put 5x3Compute shader in test project and drag onto this in editor
public ComputeShader TESTcs5x3 = null;
#endif
private void AttachCamera()
{
m_camera.AddCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, m_cmdCopyDepthAndMVecs);
m_camera.AddCommandBuffer(CameraEvent.AfterEverything, m_cmdCopyHudlessColor);
ClearCommandLists();
}
private void DetachCamera()
{
ClearCommandLists();
m_camera.RemoveCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, m_cmdCopyDepthAndMVecs);
m_camera.RemoveCommandBuffer(CameraEvent.AfterEverything, m_cmdCopyHudlessColor);
}
private void CreateCommandLists()
{
m_cmdCopyDepthAndMVecs = new CommandBuffer();
m_cmdCopyDepthAndMVecs.name = "Streamline DLSSG CopyDepthMVecs";
//Command list still required for sending Null tag
m_cmdCopyHudlessColor = new CommandBuffer();
m_cmdCopyHudlessColor.name = "Streamline DLSSG CopyHudlessColor";
}
private void DestroyCommandLists()
{
}
void ClearCommandLists()
{
m_cmdCopyDepthAndMVecs.Clear();
m_cmdCopyHudlessColor.Clear();
#if !UNITY_EDITOR && UNITY_2019_1_OR_NEWER
// On DX12 up until 2020.2 command lists that are being generated do not get flushed.
// This causes incorrect ordering of plugin side command lists.
// i.e. After submitted lists but before currently being generated lists.
// We can force a flush in non-editor mode by creating a fence but never waiting for it.
// Editor mode does not support GPUFence.
GraphicsFence fence1 = m_cmdCopyDepthAndMVecs.CreateGraphicsFence(GraphicsFenceType.AsyncQueueSynchronisation, SynchronisationStageFlags.AllGPUOperations);
GraphicsFence fence2 = m_cmdCopyHudlessColor.CreateGraphicsFence(GraphicsFenceType.AsyncQueueSynchronisation, SynchronisationStageFlags.AllGPUOperations);
#endif
}
void SetupTextureBlits()
{
uint frameIndex = (uint)Time.frameCount;
if (StreamlineDLSSGCore.DLSSGEnabled)
{
// Using this scale and bias rather than the draw&view rects as they were only relevant for editor rendering and Unity2019.4
// doesn't have the same Blit commands as 2021 (src and dest bias/scale)
Vector2 scale = new Vector2(1.0f, -1.0f);
Vector2 offset = new Vector2(0.0f, 1.0f);
RenderTexture targetDepth = StreamlineDLSSGCore.GetTargetDepthTexture();
RenderTexture targetMVecs = StreamlineDLSSGCore.GetTargetMVecsTexture();
RenderTexture targetHudlessColor = StreamlineDLSSGCore.GetTargetHudlessColorTexture();
// Copy flipped textures
bool deferred = m_camera.actualRenderingPath == RenderingPath.DeferredShading;
RenderTargetIdentifier srcRtid = new RenderTargetIdentifier(deferred ? BuiltinRenderTextureType.ResolvedDepth : BuiltinRenderTextureType.Depth);
m_cmdCopyDepthAndMVecs.Blit(srcRtid, targetDepth.colorBuffer, scale, offset);
m_cmdCopyDepthAndMVecs.Blit(new RenderTargetIdentifier(BuiltinRenderTextureType.MotionVectors), targetMVecs, scale, offset);
if (StreamlineDLSSGCore.UseHudlessColor)
{
m_cmdCopyHudlessColor.Blit(new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget), targetHudlessColor, scale, offset);
}
#if false
if (TESTcs5x3)
{
int kernel = TESTcs5x3.FindKernel("Font5x3Draw");
int w = (4 * 6 * 32);
int h = (5 * 32);
Vector4 offsetsh = new Vector4(targetDepth.width / 3, targetDepth.height / 2, 0, 0);
m_cmdCopyDepthAndMVecs.SetComputeTextureParam(TESTcs5x3, kernel, "_OutputDTexture", targetDepth, 0, RenderTextureSubElement.Color);
m_cmdCopyDepthAndMVecs.SetComputeIntParam(TESTcs5x3, "_InputValue", (int)frameIndex);
m_cmdCopyDepthAndMVecs.SetComputeIntParam(TESTcs5x3, "_Phase", 0);
m_cmdCopyDepthAndMVecs.SetComputeVectorParam(TESTcs5x3, "_Offset", offsetsh);
m_cmdCopyDepthAndMVecs.DispatchCompute(TESTcs5x3, kernel, w, h, 1);
m_cmdCopyDepthAndMVecs.SetComputeTextureParam(TESTcs5x3, kernel, "_OutputMTexture", targetMVecs, 0, RenderTextureSubElement.Color);
m_cmdCopyDepthAndMVecs.SetComputeIntParam(TESTcs5x3, "_InputValue", (int)frameIndex);
m_cmdCopyDepthAndMVecs.SetComputeIntParam(TESTcs5x3, "_Phase", 1);
m_cmdCopyDepthAndMVecs.SetComputeVectorParam(TESTcs5x3, "_Offset", offsetsh);
m_cmdCopyDepthAndMVecs.DispatchCompute(TESTcs5x3, kernel, w, h, 1);
if (StreamlineDLSSGCore.UseHudlessColor)
{
m_cmdCopyHudlessColor.SetComputeTextureParam(TESTcs5x3, kernel, "_OutputHTexture", targetHudlessColor, 0, RenderTextureSubElement.Color);
m_cmdCopyHudlessColor.SetComputeIntParam(TESTcs5x3, "_InputValue", (int)frameIndex);
m_cmdCopyHudlessColor.SetComputeIntParam(TESTcs5x3, "_Phase", 2);
m_cmdCopyHudlessColor.SetComputeVectorParam(TESTcs5x3, "_Offset", offsetsh);
m_cmdCopyHudlessColor.DispatchCompute(TESTcs5x3, kernel, w, h, 1);
}
}
#endif
}
}
public void SetupDepthAndMVecTextureTags(CommandBuffer cmd)
{
uint frameIndex = (uint)Time.frameCount;
if (StreamlineDLSSGCore.DLSSGEnabled)
{
RenderTexture targetDepth = StreamlineDLSSGCore.GetTargetDepthTexture();
RenderTexture targetMVecs = StreamlineDLSSGCore.GetTargetMVecsTexture();
StreamlineCore.SetTag(cmd, frameIndex, m_id, targetDepth, StreamlineCore.BufferType.eBufferTypeDepth, 0);
StreamlineCore.SetTag(cmd, frameIndex, m_id, targetMVecs, StreamlineCore.BufferType.eBufferTypeMVec, 0);
}
else
{
StreamlineCore.SetTag(cmd, frameIndex, m_id, null, StreamlineCore.BufferType.eBufferTypeDepth, 0);
StreamlineCore.SetTag(cmd, frameIndex, m_id, null, StreamlineCore.BufferType.eBufferTypeMVec, 0);
}
}
public void SetupHudlessColorTextureTags(CommandBuffer cmd)
{
uint frameIndex = (uint)Time.frameCount;
if (StreamlineDLSSGCore.DLSSGEnabled && StreamlineDLSSGCore.UseHudlessColor)
{
RenderTexture targetHudlessColor = StreamlineDLSSGCore.GetTargetHudlessColorTexture();
StreamlineCore.SetTag(cmd, frameIndex, m_id, targetHudlessColor, StreamlineCore.BufferType.eBufferTypeHUDLessColor, 0);
//StreamlineCore.SetTag(cmd, frameIndex, m_id, null, StreamlineCore.BufferType.eBufferTypeHUDLessColor, 0);
}
else
{
StreamlineCore.SetTag(cmd, frameIndex, m_id, null, StreamlineCore.BufferType.eBufferTypeHUDLessColor, 0);
}
}
void Awake()
{
DLSSGFeatureAvailable = false;
if (!StreamlineCore.IsFeatureSupported(StreamlineCore.Feature.eFeatureDLSS_G))
{
Debug.Log("DLSSG is not supported");
return;
}
int id = StreamlineCore.CreateFeature(StreamlineCore.Feature.eFeatureDLSS_G);
if (id != 0) //CreateFeature must return 0 for DLSSG
{
Debug.LogError("DLSSG Awake FAILED to get feature id");
return;
}
m_id = (uint)id;
DLSSGFeatureAvailable = true;
m_camera = GetComponent<Camera>();
m_camera.depthTextureMode |= DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
CreateCommandLists();
}
void OnDestroy()
{
if (DLSSGFeatureAvailable && m_id == 0)
{
StreamlineCore.DestroyFeature((int)m_id);
}
}
void OnEnable()
{
if (DLSSGFeatureAvailable)
{
AttachCamera();
}
}
void OnDisable()
{
if (DLSSGFeatureAvailable)
{
DetachCamera();
}
}
// Update is called once per frame
void LateUpdate()
{
if (DLSSGFeatureAvailable)
{
StreamlineDLSSGCore.ProcessDisposals();
if (StreamlineDLSSGCore.UpdateDrawRects(m_camera))
{
//reallocate tagged textures
StreamlineDLSSGCore.TaggedTextureDimensions tdd = StreamlineDLSSGCore.GetTaggedTextureDimensionsRef();
StreamlineDLSSGCore.AllocateTextures(tdd.m_currentDrawRect, tdd.m_currentViewRect, false, tdd.m_desktopScale, StreamlineDLSSGCore.UseHudlessColor);
}
if (GraphicsSettings.defaultRenderPipeline == null) //Built in only
{
ClearCommandLists();
SetupTextureBlits();
SetupDepthAndMVecTextureTags(m_cmdCopyDepthAndMVecs);
SetupHudlessColorTextureTags(m_cmdCopyHudlessColor);
StreamlineDLSSGCore.SetupDLSSGFeatureConstants(m_cmdCopyDepthAndMVecs, m_camera, m_id, (uint)Time.frameCount);
}
}
}
}
}