156 lines
5.4 KiB
C#
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;
|
||
|
}
|
||
|
}
|
||
|
}
|