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.
182 lines
7.9 KiB
182 lines
7.9 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEditor.Graphing;
|
|
using UnityEditor.Graphing.Util;
|
|
using UnityEditor.Rendering;
|
|
using UnityEditor.ShaderGraph.Drawing;
|
|
using UnityEditor.ShaderGraph.Internal;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace UnityEditor.ShaderGraph
|
|
{
|
|
// TODO: rename this file to VirtualTexturingFeedbackUtils
|
|
static class VirtualTexturingFeedbackUtils
|
|
{
|
|
// TODO: could get rid of this if we could run a codegen prepass (with proper keyword #ifdef)
|
|
public static void GenerateVirtualTextureFeedback(
|
|
List<AbstractMaterialNode> downstreamNodesIncludingRoot,
|
|
List<int>[] keywordPermutationsPerNode,
|
|
ShaderStringBuilder surfaceDescriptionFunction,
|
|
KeywordCollector shaderKeywords)
|
|
{
|
|
// A note on how we handle vt feedback in combination with keywords:
|
|
// We essentially generate a fully separate feedback path for each permutation of keywords
|
|
// so per permutation we gather variables contribution to feedback and we generate
|
|
// feedback gathering for each permutation individually.
|
|
|
|
var feedbackVariablesPerPermutation = PooledList<PooledList<string>>.Get();
|
|
try
|
|
{
|
|
if (shaderKeywords.permutations.Count >= 1)
|
|
{
|
|
for (int i = 0; i < shaderKeywords.permutations.Count; i++)
|
|
{
|
|
feedbackVariablesPerPermutation.Add(PooledList<string>.Get());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Create a dummy single permutation
|
|
feedbackVariablesPerPermutation.Add(PooledList<string>.Get());
|
|
}
|
|
|
|
int index = 0; //for keywordPermutationsPerNode
|
|
foreach (var node in downstreamNodesIncludingRoot)
|
|
{
|
|
if (node is SampleVirtualTextureNode vtNode)
|
|
{
|
|
if (vtNode.noFeedback) continue;
|
|
if (keywordPermutationsPerNode[index] == null)
|
|
{
|
|
feedbackVariablesPerPermutation[0].Add(vtNode.GetFeedbackVariableName());
|
|
}
|
|
else
|
|
{
|
|
foreach (int perm in keywordPermutationsPerNode[index])
|
|
{
|
|
feedbackVariablesPerPermutation[perm].Add(vtNode.GetFeedbackVariableName());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (node is SubGraphNode sgNode)
|
|
{
|
|
if (sgNode.asset == null) continue;
|
|
if (keywordPermutationsPerNode[index] == null)
|
|
{
|
|
foreach (var feedbackSlot in sgNode.asset.vtFeedbackVariables)
|
|
{
|
|
feedbackVariablesPerPermutation[0].Add(node.GetVariableNameForNode() + "_" + feedbackSlot);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (var feedbackSlot in sgNode.asset.vtFeedbackVariables)
|
|
{
|
|
foreach (int perm in keywordPermutationsPerNode[index])
|
|
{
|
|
feedbackVariablesPerPermutation[perm].Add(node.GetVariableNameForNode() + "_" + feedbackSlot);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
index++;
|
|
}
|
|
|
|
index = 0;
|
|
foreach (var feedbackVariables in feedbackVariablesPerPermutation)
|
|
{
|
|
// If it's a dummy single always-on permutation don't put an ifdef around the code
|
|
if (shaderKeywords.permutations.Count >= 1)
|
|
{
|
|
surfaceDescriptionFunction.AppendLine(KeywordUtil.GetKeywordPermutationConditional(index));
|
|
}
|
|
|
|
using (surfaceDescriptionFunction.BlockScope())
|
|
{
|
|
if (feedbackVariables.Count == 0)
|
|
{
|
|
string feedBackCode = "surface.VTPackedFeedback = float4(1.0f,1.0f,1.0f,1.0f);";
|
|
surfaceDescriptionFunction.AppendLine(feedBackCode);
|
|
}
|
|
else if (feedbackVariables.Count == 1)
|
|
{
|
|
string feedBackCode = "surface.VTPackedFeedback = GetPackedVTFeedback(" + feedbackVariables[0] + ");";
|
|
surfaceDescriptionFunction.AppendLine(feedBackCode);
|
|
}
|
|
else if (feedbackVariables.Count > 1)
|
|
{
|
|
surfaceDescriptionFunction.AppendLine("float4 VTFeedback_array[" + feedbackVariables.Count + "];");
|
|
|
|
int arrayIndex = 0;
|
|
foreach (var variable in feedbackVariables)
|
|
{
|
|
surfaceDescriptionFunction.AppendLine("VTFeedback_array[" + arrayIndex + "] = " + variable + ";");
|
|
arrayIndex++;
|
|
}
|
|
|
|
// TODO: should read from NDCPosition instead...
|
|
surfaceDescriptionFunction.AppendLine("uint pixelColumn = (IN.ScreenPosition.x / IN.ScreenPosition.w) * _ScreenParams.x;");
|
|
surfaceDescriptionFunction.AppendLine(
|
|
"surface.VTPackedFeedback = GetPackedVTFeedback(VTFeedback_array[(pixelColumn + _FrameCount) % (uint)" + feedbackVariables.Count + "]);");
|
|
}
|
|
}
|
|
|
|
if (shaderKeywords.permutations.Count >= 1)
|
|
{
|
|
surfaceDescriptionFunction.AppendLine("#endif");
|
|
}
|
|
|
|
index++;
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
foreach (var list in feedbackVariablesPerPermutation)
|
|
{
|
|
list.Dispose();
|
|
}
|
|
feedbackVariablesPerPermutation.Dispose();
|
|
}
|
|
}
|
|
|
|
// Automatically add a streaming feedback node and correctly connect it to stack samples are connected to it and it is connected to the master node output
|
|
public static List<string> GetFeedbackVariables(SubGraphOutputNode masterNode)
|
|
{
|
|
// TODO: make use a generic interface instead of hard-coding the node types that we need to look at here
|
|
var VTNodes = GraphUtil.FindDownStreamNodesOfType<SampleVirtualTextureNode>(masterNode);
|
|
var subGraphNodes = GraphUtil.FindDownStreamNodesOfType<SubGraphNode>(masterNode);
|
|
|
|
List<string> result = new List<string>();
|
|
|
|
// Early out if there are no nodes we care about in the graph
|
|
if (subGraphNodes.Count <= 0 && VTNodes.Count <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
// Add inputs to feedback node
|
|
foreach (var node in VTNodes)
|
|
{
|
|
if (node.noFeedback) continue;
|
|
result.Add(node.GetFeedbackVariableName());
|
|
}
|
|
|
|
foreach (var node in subGraphNodes)
|
|
{
|
|
if (node.asset == null) continue;
|
|
// TODO: subgraph.GetFeedbackVariableNames(...)
|
|
foreach (var feedbackSlot in node.asset.vtFeedbackVariables)
|
|
{
|
|
result.Add(node.GetVariableNameForNode() + "_" + feedbackSlot);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
}
|