Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,19 @@ void CullUnusedRenderPasses()
// Remove the connections from the list so they won't be visited again
if (pass.culled)
{
// If the culled pass was supposed to generate the latest version of a given resource,
// we need to decrement the latestVersionNumber of this resource
// because its last version will never be created due to its producer being culled
foreach (ref readonly var output in pass.Outputs(ctx))
{
var outputResource = output.resource;
bool isOutputLastVersion = (outputResource.version == ctx.UnversionedResourceData(outputResource).latestVersionNumber);

if (isOutputLastVersion)
ctx.UnversionedResourceData(outputResource).latestVersionNumber--;
}

// Notifying the versioned resources that this pass is no longer reading them
foreach (ref readonly var input in pass.Inputs(ctx))
{
var inputResource = input.resource;
Expand Down Expand Up @@ -567,10 +580,14 @@ void FindResourceUsageRanges()
if (pass.waitOnGraphicsFencePassId == -1)
{
ref var pointToVer = ref ctx.VersionedResourceData(inputResource);
ref var wPass = ref ctx.passData.ElementAt(pointToVer.writePassId);
if (wPass.asyncCompute != pass.asyncCompute)
// If no RG pass writes to the resource, no need to wait for anyone
if (pointToVer.written)
{
pass.waitOnGraphicsFencePassId = wPass.passId;
ref var wPass = ref ctx.passData.ElementAt(pointToVer.writePassId);
if (wPass.asyncCompute != pass.asyncCompute)
{
pass.waitOnGraphicsFencePassId = wPass.passId;
}
}
}
}
Expand Down Expand Up @@ -1247,6 +1264,11 @@ private void ExecuteDestroyResource(InternalRenderGraphContext rgContext, Render
{
using (new ProfilingScope(ProfilingSampler.Get(NativeCompilerProfileId.NRPRGComp_ExecuteDestroyResources)))
{
// Unsafe pass might use temporary render targets,
// users can also use temporary data in their render graph execute nodes using public RenderGraphObjectPool API
// In both cases, we need to release these resources after the node execution
rgContext.renderGraphPool.ReleaseAllTempAlloc();

if (pass.type == RenderGraphPassType.Raster && pass.nativePassIndex >= 0)
{
// For raster passes we need to destroy resources after all the subpasses at the end of the native renderpass
Expand Down Expand Up @@ -1280,7 +1302,7 @@ private void ExecuteDestroyResource(InternalRenderGraphContext rgContext, Render
}
}

internal unsafe void SetRandomWriteTarget(in CommandBuffer cmd, RenderGraphResourceRegistry resources, int index, ResourceHandle resource, bool preserveCounterValue = true)
internal unsafe void ExecuteSetRandomWriteTarget(in CommandBuffer cmd, RenderGraphResourceRegistry resources, int index, ResourceHandle resource, bool preserveCounterValue = true)
{
if (resource.type == RenderGraphResourceType.Texture)
{
Expand Down Expand Up @@ -1387,7 +1409,7 @@ public void ExecuteGraph(InternalRenderGraphContext rgContext, RenderGraphResour
}

var nrpBegan = false;
if (isRaster == true && pass.mergeState <= PassMergeState.Begin)
if (isRaster && pass.mergeState <= PassMergeState.Begin)
{
if (pass.nativePassIndex >= 0)
{
Expand Down Expand Up @@ -1417,7 +1439,7 @@ public void ExecuteGraph(InternalRenderGraphContext rgContext, RenderGraphResour
{
foreach (var randomWriteAttachment in pass.RandomWriteTextures(contextData))
{
SetRandomWriteTarget(rgContext.cmd, resources, randomWriteAttachment.index, randomWriteAttachment.resource);
ExecuteSetRandomWriteTarget(rgContext.cmd, resources, randomWriteAttachment.index, randomWriteAttachment.resource);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ internal struct ResourceUnversionedData
public readonly int volumeDepth;
public readonly int msaaSamples;

public readonly int latestVersionNumber;
public int latestVersionNumber; // mostly readonly, can be decremented only if all passes using the last version are culled

public readonly bool clear; // graph.m_Resources.GetTextureResourceDesc(fragment.resource).clearBuffer;
public readonly bool discard; // graph.m_Resources.GetTextureResourceDesc(fragment.resource).discardBuffer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,12 @@ internal void ReleaseAllTempAlloc()

m_AllocatedMaterialPropertyBlocks.Clear();
}


internal bool IsEmpty()
{
return m_AllocatedArrays.Count == 0 && m_AllocatedMaterialPropertyBlocks.Count == 0;
}

// Regular pooling API. Only internal use for now
internal T Get<T>() where T : class, new()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ abstract class RenderGraphResourcePool<Type> : IRenderGraphResourcePool where Ty
protected Dictionary<int, SortedList<int, (Type resource, int frameIndex)>> m_ResourcePool = new Dictionary<int, SortedList<int, (Type resource, int frameIndex)>>();

// This list allows us to determine if all resources were correctly released in the frame when validity checks are enabled.
// This is useful to warn in case of user error or avoid leaks when a render graph execution errors occurs for example.
// This is useful to warn in case of user error or avoid leaks when a render graph execution error occurs for example.
List<(int, Type)> m_FrameAllocatedResources = new List<(int, Type)>();
const int kStaleResourceLifetime = 10;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1317,5 +1317,37 @@ public void UpdateSubpassAttachmentIndices_WhenDepthAttachmentIsAdded()
Assert.IsTrue(subPassDesc3.inputs.Length == 1);
Assert.IsTrue(subPassDesc3.inputs[0] == 3);
}

[Test]
public void DecreaseResourceVersionIfLastPassIsCulled()
{
var g = AllocateRenderGraph();
var buffers = ImportAndCreateBuffers(g);

// Bumping version of extraBuffer within RG to 1 as we write to it in first pass
using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData))
{
builder.SetRenderAttachment(buffers.extraBuffers[0], 0);
builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { });
builder.AllowPassCulling(false);
}

// Bumping version of extraBuffer within RG to 2 as we write to it in second pass
using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData))
{
builder.SetRenderAttachment(buffers.extraBuffers[0], 0);
builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { });
builder.AllowPassCulling(true);
}

// First pass is preserved as requested but second pass is culled
var result = g.CompileNativeRenderGraph(g.ComputeGraphHash());
var passes = result.contextData.GetNativePasses();

// Second pass has been culled
Assert.IsTrue(passes != null && passes.Count == 1 && passes[0].numGraphPasses == 1);
// extraBuffer version has decreased to 1 as it is only used by the first pass
Assert.AreEqual(passes[0].attachments[0].handle.version, 1);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1469,5 +1469,48 @@ public void Cleanup_RenderAgain_AfterCallingCleanup()
// Ensure that the Render Graph data structures can be reinitialized at runtime, even native ones
Assert.DoesNotThrow(() => m_Camera.Render());
}

class TempAllocTestData
{
public TextureHandle whiteTexture;
}

[Test]
public void GetTempMaterialPropertyBlockAreReleasedAfterRenderGraphNodeExecution()
{
m_RenderGraphTestPipeline.recordRenderGraphBody = (context, camera, cmd) =>
{
using (var builder = m_RenderGraph.AddUnsafePass<TempAllocTestData>("MPBPass", out var passData))
{
builder.AllowPassCulling(false);
passData.whiteTexture = m_RenderGraph.defaultResources.whiteTexture;

builder.SetRenderFunc((TempAllocTestData data, UnsafeGraphContext context) =>
{
// no temp alloc yet
Assert.IsTrue(context.renderGraphPool.IsEmpty());

var mpb = context.renderGraphPool.GetTempMaterialPropertyBlock();
mpb.SetTexture(k_DefaultWhiteTextureID, data.whiteTexture);

// memory temporarily allocated
Assert.IsFalse(context.renderGraphPool.IsEmpty());
});
}

using (var builder = m_RenderGraph.AddUnsafePass<TempAllocTestData>("PostPass", out var passData))
{
builder.AllowPassCulling(false);

builder.SetRenderFunc((TempAllocTestData data, UnsafeGraphContext context) =>
{
// memory has been deallocated at the end of the previous RG node, no leak
Assert.IsTrue(context.renderGraphPool.IsEmpty());
});
}
};

m_Camera.Render();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ private void ValidateDeviceComputeGroupSize(int requiredComputeGroupSizeX)
}

[Test]
[Ignore("Unstable: https://jira.unity3d.com/browse/UUM-111743")]
public void WaveTest([Values]Kernel kernel, [Values]WaveSizeKeyword waveSizeKeyword)
{
int groupSize = (int)GroupSizeKeyword.GROUP_SIZE_128;
Expand Down Expand Up @@ -210,7 +209,6 @@ public void WaveTest([Values]Kernel kernel, [Values]WaveSizeKeyword waveSizeKeyw
}

[Test]
[Ignore("Unstable: https://jira.unity3d.com/browse/UUM-111749")]
public void GroupTest([Values]Kernel kernel, [Values]GroupSizeKeyword groupSizeKeyword)
{
int groupSize = (int)groupSizeKeyword;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ public override VisualElement CreateInspectorGUI()
//Prepare metallic toggles for material mode
for(int i=0; i<12;i++)
{
Toggle metallicToggle = new Toggle() { name ="metallic" + i, label = "is Metallic", tabIndex = i};
Toggle metallicToggle = new Toggle() { name ="metallic" + i, label = "Metallic", tabIndex = i};
metallicToggle.Q<Label>().style.minWidth = 60;
metallicToggle.bindingPath="isMetalBools.Array.data["+i+"]";
metallicToggle.style.display = UnityEngine.UIElements.DisplayStyle.None;//hidden in UI until used
root.Add(metallicToggle);
Expand All @@ -94,6 +95,7 @@ public override VisualElement CreateInspectorGUI()
self.UpdateMaterial();
};


onChange(self, root); // Initialize
return root;
}
Expand Down Expand Up @@ -127,12 +129,19 @@ void CreateColorFields(ColorCheckerTool target, VisualElement root, Color32[] co
//Creates the Rows Containers
for (int i = 0; i < rows; i++)
{
VisualElement newRow = new VisualElement() { name = "colorfieldsRow" + i };
newRow.style.flexDirection = UnityEngine.UIElements.FlexDirection.Row;
newRow.style.alignItems = UnityEngine.UIElements.Align.FlexStart;
newRow.style.justifyContent = UnityEngine.UIElements.Justify.SpaceAround;
newRow.style.alignSelf = UnityEngine.UIElements.Align.Stretch;
newRow.style.maxHeight = 22;
VisualElement newRow = new()
{
name = "colorfieldsRow" + i,
style =
{
flexDirection = UnityEngine.UIElements.FlexDirection.Row,
alignItems = UnityEngine.UIElements.Align.FlexStart,
justifyContent = UnityEngine.UIElements.Justify.SpaceAround,
alignSelf = UnityEngine.UIElements.Align.Stretch,
maxHeight = 22,
flexWrap = Wrap.Wrap
}
};
colorfieldsRoot.Add(newRow);
}

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading