2021-09-09 20:42:29 -04:00

166 lines
7.7 KiB
C#

#if ENABLE_VIRTUALTEXTURES
using VirtualTexturing = UnityEngine.Rendering.VirtualTexturing;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.RenderGraphModule;
namespace UnityEngine.Rendering.HighDefinition
{
class VTBufferManager
{
public static TextureHandle CreateVTFeedbackBuffer(RenderGraph renderGraph, bool msaa)
{
#if UNITY_2020_2_OR_NEWER
FastMemoryDesc colorFastMemDesc;
colorFastMemDesc.inFastMemory = true;
colorFastMemDesc.residencyFraction = 1.0f;
colorFastMemDesc.flags = FastMemoryFlags.SpillTop;
#endif
return renderGraph.CreateTexture(
new TextureDesc(Vector2.one, true, true)
{
colorFormat = GetFeedbackBufferFormat(), enableRandomWrite = !msaa, bindTextureMS = msaa, enableMSAA = msaa, clearBuffer = true, clearColor = Color.white, name = msaa ? "VTFeedbackMSAA" : "VTFeedback", fallBackToBlackTexture = true
#if UNITY_2020_2_OR_NEWER
,
fastMemoryDesc = colorFastMemDesc
#endif
});
}
public static GraphicsFormat GetFeedbackBufferFormat()
{
return GraphicsFormat.R8G8B8A8_UNorm;
}
const int kResolveScaleFactor = 16;
VirtualTexturing.Resolver m_Resolver = new VirtualTexturing.Resolver();
VirtualTexturing.Resolver m_ResolverMsaa = new VirtualTexturing.Resolver();
Vector2 m_ResolverScale = new Vector2(1.0f / (float)kResolveScaleFactor, 1.0f / (float)kResolveScaleFactor);
RTHandle m_LowresResolver;
ComputeShader m_DownSampleCS = null;
int m_DownsampleKernel;
int m_DownsampleKernelMSAA;
public VTBufferManager()
{
// This texture needs to be persistent because we do async gpu readback on it.
m_LowresResolver = RTHandles.Alloc(m_ResolverScale, colorFormat: GraphicsFormat.R8G8B8A8_UNorm, enableRandomWrite: true, autoGenerateMips: false, name: "VTFeedback lowres");
}
public void Cleanup()
{
m_Resolver.Dispose();
m_ResolverMsaa.Dispose();
RTHandles.Release(m_LowresResolver);
m_LowresResolver = null;
}
public void BeginRender(HDCamera hdCamera)
{
if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.VirtualTexturing))
{
int width = hdCamera.actualWidth;
int height = hdCamera.actualHeight;
bool msaa = hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA);
GetResolveDimensions(ref width, ref height);
if (msaa)
m_ResolverMsaa.UpdateSize(width, height);
else
m_Resolver.UpdateSize(width, height);
}
}
class ResolveVTData
{
public ResolveVTParameters parameters;
public TextureHandle input;
public TextureHandle lowres;
}
public void Resolve(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle input)
{
if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.VirtualTexturing))
{
if (m_DownSampleCS == null)
{
m_DownSampleCS = HDRenderPipeline.currentAsset.renderPipelineResources.shaders.VTFeedbackDownsample;
m_DownsampleKernel = m_DownSampleCS.FindKernel("KMain");
m_DownsampleKernelMSAA = m_DownSampleCS.FindKernel("KMainMSAA");
}
using (var builder = renderGraph.AddRenderPass<ResolveVTData>("Resolve VT", out var passData, ProfilingSampler.Get(HDProfileId.VTFeedbackDownsample)))
{
// The output is never read outside the pass but is still useful for the VT system so we can't cull this pass.
builder.AllowPassCulling(false);
passData.parameters = PrepareResolveVTParameters(hdCamera);
passData.input = builder.ReadTexture(input);
passData.lowres = builder.WriteTexture(renderGraph.ImportTexture(m_LowresResolver));
builder.SetRenderFunc(
(ResolveVTData data, RenderGraphContext ctx) =>
{
ResolveVTDispatch(data.parameters, ctx.cmd, data.input, data.lowres);
VirtualTexturing.System.Update();
});
}
}
}
struct ResolveVTParameters
{
public int width, height;
public int lowresWidth, lowresHeight;
public VirtualTexturing.Resolver resolver;
public ComputeShader downsampleCS;
public int downsampleKernel;
}
ResolveVTParameters PrepareResolveVTParameters(HDCamera hdCamera)
{
bool msaa = hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA);
var parameters = new ResolveVTParameters();
parameters.width = hdCamera.actualWidth;
parameters.height = hdCamera.actualHeight;
parameters.lowresWidth = parameters.width;
parameters.lowresHeight = parameters.height;
GetResolveDimensions(ref parameters.lowresWidth, ref parameters.lowresHeight);
parameters.resolver = msaa ? m_ResolverMsaa : m_Resolver;
parameters.downsampleCS = m_DownSampleCS;
parameters.downsampleKernel = msaa ? m_DownsampleKernelMSAA : m_DownsampleKernel;
return parameters;
}
static void ResolveVTDispatch(in ResolveVTParameters parameters, CommandBuffer cmd, RTHandle buffer, RTHandle lowresBuffer)
{
Debug.Assert(parameters.lowresWidth <= parameters.resolver.CurrentWidth && parameters.lowresHeight <= parameters.resolver.CurrentHeight);
Debug.Assert(parameters.lowresWidth <= lowresBuffer.referenceSize.x && parameters.lowresHeight <= lowresBuffer.referenceSize.y);
string mainFunction = (buffer.isMSAAEnabled) ? "KMainMSAA" : "KMain";
int inputID = (buffer.isMSAAEnabled) ? HDShaderIDs._InputTextureMSAA : HDShaderIDs._InputTexture;
cmd.SetComputeTextureParam(parameters.downsampleCS, parameters.downsampleKernel, inputID, buffer.nameID);
cmd.SetComputeTextureParam(parameters.downsampleCS, parameters.downsampleKernel, HDShaderIDs._OutputTexture, lowresBuffer);
var resolveCounter = 0;
var startOffsetX = (resolveCounter % kResolveScaleFactor);
var startOffsetY = (resolveCounter / kResolveScaleFactor) % kResolveScaleFactor;
cmd.SetComputeVectorParam(parameters.downsampleCS, HDShaderIDs._Params, new Vector4(kResolveScaleFactor, startOffsetX, startOffsetY, /*unused*/ -1));
cmd.SetComputeVectorParam(parameters.downsampleCS, HDShaderIDs._Params1, new Vector4(parameters.width, parameters.height, parameters.lowresWidth, parameters.lowresHeight));
var TGSize = 8; //Match shader
cmd.DispatchCompute(parameters.downsampleCS, parameters.downsampleKernel, ((int)parameters.lowresWidth + (TGSize - 1)) / TGSize, ((int)parameters.lowresHeight + (TGSize - 1)) / TGSize, 1);
parameters.resolver.Process(cmd, lowresBuffer, 0, parameters.lowresWidth, 0, parameters.lowresHeight, 0, 0);
}
void GetResolveDimensions(ref int w, ref int h)
{
w = Mathf.Max(Mathf.RoundToInt(m_ResolverScale.x * w), 1);
h = Mathf.Max(Mathf.RoundToInt(m_ResolverScale.y * h), 1);
}
}
}
#endif