You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
8.5 KiB
181 lines
8.5 KiB
#if ENABLE_VIRTUALTEXTURES
|
|
using VirtualTexturing = UnityEngine.Rendering.VirtualTexturing;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Rendering.RenderGraphModule;
|
|
|
|
namespace UnityEngine.Rendering.HighDefinition
|
|
{
|
|
class VTBufferManager
|
|
{
|
|
public static TextureHandle CreateVTFeedbackBuffer(RenderGraph renderGraph, MSAASamples msaaSamples)
|
|
{
|
|
bool msaa = msaaSamples != MSAASamples.None;
|
|
#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, msaaSamples = msaa ? msaaSamples : MSAASamples.None, 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.R16G16_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; // This texture needs to be persistent because we do async gpu readback on it.
|
|
ComputeShader m_DownSampleCS = null;
|
|
int m_DownsampleKernel;
|
|
int m_DownsampleKernelMSAA;
|
|
|
|
public VTBufferManager()
|
|
{
|
|
}
|
|
|
|
public void Cleanup()
|
|
{
|
|
m_Resolver.Dispose();
|
|
m_ResolverMsaa.Dispose();
|
|
|
|
RTHandles.Release(m_LowresResolver);
|
|
m_LowresResolver = null;
|
|
}
|
|
|
|
public void BeginRender(HDCamera hdCamera)
|
|
{
|
|
// Lazy creation because creating this texture in the constructor can happen outside of proper RTHandleSystem initialization
|
|
// This can happen for example when cinemachine gets the HDCamera and ends up constructing VTBufferManager before HDRP is even initialized.
|
|
if (m_LowresResolver == null)
|
|
m_LowresResolver = RTHandles.Alloc(m_ResolverScale, colorFormat: GraphicsFormat.R8G8B8A8_UNorm, enableRandomWrite: true, autoGenerateMips: false, name: "VTFeedback lowres");
|
|
|
|
if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.VirtualTexturing))
|
|
{
|
|
int width = hdCamera.actualWidth;
|
|
int height = hdCamera.actualHeight;
|
|
bool msaa = hdCamera.msaaEnabled;
|
|
GetResolveDimensions(ref width, ref height);
|
|
|
|
if (msaa)
|
|
{
|
|
CalculateResolverDimensions(ref width, ref height, m_ResolverMsaa);
|
|
m_ResolverMsaa.UpdateSize(width, height);
|
|
}
|
|
else
|
|
{
|
|
CalculateResolverDimensions(ref width, ref height, m_Resolver);
|
|
m_Resolver.UpdateSize(width, height);
|
|
}
|
|
}
|
|
}
|
|
|
|
class ResolveVTData
|
|
{
|
|
public int width, height;
|
|
public int lowresWidth, lowresHeight;
|
|
public VirtualTexturing.Resolver resolver;
|
|
public ComputeShader downsampleCS;
|
|
public int downsampleKernel;
|
|
|
|
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 = GraphicsSettings.GetRenderPipelineSettings<HDRenderPipelineRuntimeShaders>().VTFeedbackDownsample;
|
|
m_DownsampleKernel = m_DownSampleCS.FindKernel("KMain");
|
|
m_DownsampleKernelMSAA = m_DownSampleCS.FindKernel("KMainMSAA");
|
|
}
|
|
|
|
using (var builder = renderGraph.AddUnsafePass<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);
|
|
|
|
bool msaa = hdCamera.msaaEnabled;
|
|
passData.width = hdCamera.actualWidth;
|
|
passData.height = hdCamera.actualHeight;
|
|
passData.lowresWidth = passData.width;
|
|
passData.lowresHeight = passData.height;
|
|
GetResolveDimensions(ref passData.lowresWidth, ref passData.lowresHeight);
|
|
passData.resolver = msaa ? m_ResolverMsaa : m_Resolver;
|
|
passData.downsampleCS = m_DownSampleCS;
|
|
passData.downsampleKernel = msaa ? m_DownsampleKernelMSAA : m_DownsampleKernel;
|
|
|
|
passData.input = input;
|
|
builder.UseTexture(passData.input, AccessFlags.Read);
|
|
passData.lowres = renderGraph.ImportTexture(m_LowresResolver);
|
|
builder.UseTexture(passData.lowres, AccessFlags.Write);
|
|
|
|
builder.SetRenderFunc(
|
|
(ResolveVTData data, UnsafeGraphContext ctx) =>
|
|
{
|
|
var natCmd = CommandBufferHelpers.GetNativeCommandBuffer(ctx.cmd);
|
|
RTHandle lowresBuffer = data.lowres;
|
|
RTHandle buffer = data.input;
|
|
|
|
Debug.Assert(data.lowresWidth <= data.resolver.CurrentWidth && data.lowresHeight <= data.resolver.CurrentHeight);
|
|
Debug.Assert(data.lowresWidth <= lowresBuffer.referenceSize.x && data.lowresHeight <= lowresBuffer.referenceSize.y);
|
|
|
|
int inputID = (buffer.isMSAAEnabled) ? HDShaderIDs._InputTextureMSAA : HDShaderIDs._InputTexture;
|
|
|
|
natCmd.SetComputeTextureParam(data.downsampleCS, data.downsampleKernel, inputID, buffer);
|
|
natCmd.SetComputeTextureParam(data.downsampleCS, data.downsampleKernel, HDShaderIDs._OutputTexture, lowresBuffer);
|
|
var resolveCounter = 0;
|
|
var startOffsetX = (resolveCounter % kResolveScaleFactor);
|
|
var startOffsetY = (resolveCounter / kResolveScaleFactor) % kResolveScaleFactor;
|
|
natCmd.SetComputeVectorParam(data.downsampleCS, HDShaderIDs._Params, new Vector4(kResolveScaleFactor, startOffsetX, startOffsetY, /*unused*/ -1));
|
|
natCmd.SetComputeVectorParam(data.downsampleCS, HDShaderIDs._Params1, new Vector4(data.width, data.height, data.lowresWidth, data.lowresHeight));
|
|
var TGSize = 8; //Match shader
|
|
natCmd.DispatchCompute(data.downsampleCS, data.downsampleKernel, ((int)data.lowresWidth + (TGSize - 1)) / TGSize, ((int)data.lowresHeight + (TGSize - 1)) / TGSize, 1);
|
|
|
|
data.resolver.Process(natCmd, lowresBuffer, 0, data.lowresWidth, 0, data.lowresHeight, 0, 0);
|
|
|
|
VirtualTexturing.System.Update();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
void CalculateResolverDimensions(ref int w, ref int h, VirtualTexturing.Resolver resolver)
|
|
{
|
|
//RT handles don't downscale in the editor but render with subrects.
|
|
#if UNITY_EDITOR
|
|
int currentWidth = resolver.CurrentWidth;
|
|
int currentHeight = resolver.CurrentHeight;
|
|
|
|
if (currentWidth < w || currentHeight < h)
|
|
{
|
|
w = currentWidth < w ? w : currentWidth;
|
|
h = currentHeight < h ? h : currentHeight;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
#endif
|