Singularity/Library/PackageCache/com.unity.render-pipelines..../Runtime/RenderGraph/RenderGraphResources.cs
2024-05-06 11:45:45 -07:00

156 lines
5.4 KiB
C#

using System;
using System.Diagnostics;
using UnityEngine.Rendering;
namespace UnityEngine.Experimental.Rendering.RenderGraphModule
{
// RendererList is a different case so not represented here.
internal enum RenderGraphResourceType
{
Texture = 0,
ComputeBuffer,
Count
}
internal struct ResourceHandle
{
// Note on handles validity.
// PassData classes used during render graph passes are pooled and because of that, when users don't fill them completely,
// they can contain stale handles from a previous render graph execution that could still be considered valid if we only checked the index.
// In order to avoid using those, we incorporate the execution index in a 16 bits hash to make sure the handle is coming from the current execution.
// If not, it's considered invalid.
// We store this validity mask in the upper 16 bits of the index.
const uint kValidityMask = 0xFFFF0000;
const uint kIndexMask = 0xFFFF;
uint m_Value;
static uint s_CurrentValidBit = 1 << 16;
static uint s_SharedResourceValidBit = 0x7FFF << 16;
public int index { get { return (int)(m_Value & kIndexMask); } }
public RenderGraphResourceType type { get; private set; }
public int iType { get { return (int)type; } }
internal ResourceHandle(int value, RenderGraphResourceType type, bool shared)
{
Debug.Assert(value <= 0xFFFF);
m_Value = ((uint)value & kIndexMask) | (shared ? s_SharedResourceValidBit : s_CurrentValidBit);
this.type = type;
}
public static implicit operator int(ResourceHandle handle) => handle.index;
public bool IsValid()
{
var validity = m_Value & kValidityMask;
return validity != 0 && (validity == s_CurrentValidBit || validity == s_SharedResourceValidBit);
}
static public void NewFrame(int executionIndex)
{
uint previousValidBit = s_CurrentValidBit;
// Scramble frame count to avoid collision when wrapping around.
s_CurrentValidBit = (uint)(((executionIndex >> 16) ^ (executionIndex & 0xffff) * 58546883) << 16);
// In case the current valid bit is 0, even though perfectly valid, 0 represents an invalid handle, hence we'll
// trigger an invalid state incorrectly. To account for this, we actually skip 0 as a viable s_CurrentValidBit and
// start from 1 again.
// In the same spirit, s_SharedResourceValidBit is reserved for shared textures so we should never use it otherwise
// resources could be considered valid at frame N+1 (because shared) even though they aren't.
if (s_CurrentValidBit == 0 || s_CurrentValidBit == s_SharedResourceValidBit)
{
// We need to make sure we don't pick the same value twice.
uint value = 1;
while (previousValidBit == (value << 16))
value++;
s_CurrentValidBit = (value << 16);
}
}
}
class IRenderGraphResource
{
public bool imported;
public bool shared;
public bool sharedExplicitRelease;
public bool requestFallBack;
public uint writeCount;
public int cachedHash;
public int transientPassIndex;
public int sharedResourceLastFrameUsed;
protected IRenderGraphResourcePool m_Pool;
public virtual void Reset(IRenderGraphResourcePool pool)
{
imported = false;
shared = false;
sharedExplicitRelease = false;
cachedHash = -1;
transientPassIndex = -1;
sharedResourceLastFrameUsed = -1;
requestFallBack = false;
writeCount = 0;
m_Pool = pool;
}
public virtual string GetName()
{
return "";
}
public virtual bool IsCreated()
{
return false;
}
public virtual void IncrementWriteCount()
{
writeCount++;
}
public virtual bool NeedsFallBack()
{
return requestFallBack && writeCount == 0;
}
public virtual void CreatePooledGraphicsResource() { }
public virtual void CreateGraphicsResource(string name = "") { }
public virtual void ReleasePooledGraphicsResource(int frameIndex) { }
public virtual void ReleaseGraphicsResource() { }
public virtual void LogCreation(RenderGraphLogger logger) { }
public virtual void LogRelease(RenderGraphLogger logger) { }
public virtual int GetSortIndex() { return 0; }
}
[DebuggerDisplay("Resource ({GetType().Name}:{GetName()})")]
abstract class RenderGraphResource<DescType, ResType>
: IRenderGraphResource
where DescType : struct
where ResType : class
{
public DescType desc;
public ResType graphicsResource;
protected RenderGraphResource()
{
}
public override void Reset(IRenderGraphResourcePool pool)
{
base.Reset(pool);
graphicsResource = null;
}
public override bool IsCreated()
{
return graphicsResource != null;
}
public override void ReleaseGraphicsResource()
{
graphicsResource = null;
}
}
}