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.
 
 
 
 
 

499 lines
21 KiB

using System;
using System.Runtime.InteropServices;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.HighDefinition;
namespace UnityEngine.Rendering
{
partial class LineRendering
{
internal struct Arguments
{
public Camera camera;
public Vector3 cameraPosition;
public Frustum cameraFrustum; // TODO: Frustum us HDRP-specific, we should not use it here.
public RenderGraph renderGraph;
public TextureHandle depthTexture;
public SystemSettings settings;
public ShadingAtlas shadingAtlas;
public Vector2 viewport;
public Matrix4x4 matrixIVP;
public RenderTargets targets;
public int viewCount;
public int viewIndex;
}
internal struct SystemSettings
{
public int clusterCount;
public CompositionMode compositionMode;
public SortingQuality sortingQuality;
public float tileOpacityThreshold;
public int debugMode;
public MemoryBudget memoryBudget;
public bool executeAsync;
}
internal struct SystemResources
{
public GPUSort gpuSort;
public GPUPrefixSum gpuPrefixSum;
public ComputeShader stagePrepareCS;
public ComputeShader stageSetupSegmentCS;
public ComputeShader stageShadingSetupCS;
public ComputeShader stageRasterBinCS;
public ComputeShader stageWorkQueue;
public ComputeShader stageRasterFineCS;
}
/// <summary>
/// Determines the size of graphics memory allocations for high quality line rendering.
/// </summary>
[Serializable]
public enum MemoryBudget
{
/// <summary>Low Budget</summary>
MemoryBudgetLow = 128,
/// <summary>Medium Budget</summary>
MemoryBudgetMedium = 256,
/// <summary>High Budget</summary>
MemoryBudgetHigh = 512,
}
/// <summary>
/// List of line rendering debug views.
/// </summary>
[GenerateHLSL]
public enum DebugMode
{
/// <summary>Draw a heat value per tile representing the number of segments being computed in the tile.</summary>
SegmentsPerTile,
/// <summary>Draw the tile's compute index.</summary>
TileProcessorUV,
/// <summary>Draw the cluster index for each computed fragment.</summary>
ClusterDepth,
}
/// <summary>
/// Container for parameters defining a renderable instance for the line rendering system.
/// </summary>
[Serializable]
public struct RendererData
{
/// <summary>Mesh with line topology.</summary>
public Mesh mesh;
/// <summary>World Matrix.</summary>
public Matrix4x4 matrixW;
/// <summary>Previous World Matrix.</summary>
public Matrix4x4 matrixWP;
/// <summary>Material to draw the lines.</summary>
public Material material;
/// <summary>Compute asset for computing the vertex shader in a compute shader.</summary>
public ComputeShader vertexSetupCompute;
/// <summary>Merging group for sorting between multiple renderer datas.</summary>
public RendererGroup group;
/// <summary>Spherical harmonic coefficients for probe lighting.</summary>
public SphericalHarmonicsL2 probe;
/// <summary>Rendering mask.</summary>
public uint renderingLayerMask;
/// <summary>Motion vector parameters.</summary>
public Vector4 motionVectorParams;
/// <summary>Offscreen shading pass index.</summary>
public int offscreenShadingPass;
/// <summary>Handle to the line topology's index buffer resource.</summary>
public BufferHandle indexBuffer;
/// <summary>Distance to camera for sorting purposes.</summary>
public float distanceToCamera;
/// <summary>The number of lines in the mesh.</summary>
public int lineCount;
/// <summary>The number of segments-per-line.</summary>
public int segmentsPerLine;
/// <summary>Handle to a buffer for computing level of detail.</summary>
public BufferHandle lodBuffer;
/// <summary>Level of detail mode.</summary>
public RendererLODMode lodMode;
/// <summary>Percentage of strands to render.</summary>
public float lod;
/// <summary>Percentage of shading samples to compute.</summary>
public float shadingFraction;
/// <summary>Unique identifier for the renderer data.</summary>
public int hash;
/// <summary>Bounds of the renderer</summary>
public Bounds bounds;
}
/// <summary>
/// The method by which line renderer's level of detail will be computed.
/// </summary>
public enum RendererLODMode
{
/// <summary>No level of detail will be computed.</summary>
None,
/// <summary>Define level of detail with a fixed value.</summary>
Fixed,
/// <summary>Compute level of detail based on bounding box screen coverage.</summary>
ScreenCoverage,
/// <summary>Compute level of detail based on camera distance.</summary>
CameraDistance
}
/// <summary>
/// The group that line renderers will be merged into for better transparent sorting.
/// </summary>
public enum RendererGroup
{
/// <summary>No merging will occur with other line renderers.</summary>
None,
/// <summary>Group 0.</summary>
Group0,
/// <summary>Group 1.</summary>
Group1,
/// <summary>Group 2.</summary>
Group2,
/// <summary>Group 3.</summary>
Group3,
/// <summary>Group 4.</summary>
Group4,
}
internal struct RenderTargets
{
public TextureHandle color;
public TextureHandle depth;
public TextureHandle motion;
}
[GenerateHLSL(needAccessors = false, generateCBuffer = true)]
internal struct ShaderVariables
{
// Stage group sizes.
public const int NumLaneSegmentSetup = 1024;
public const int NumLaneRasterBin = 512;
// Due to structure alignment issues on certain API (Metal, Vulkan) we ensure 16-byte alignment
// like this to ensure there is no mismatch.
public Vector4 _Params0; // { Dim Bin X, Dim Bin Y, Segment Count, Bin Count }
public Vector4 _Params1; // { Size Screen, Inv. Size Screen }
public Vector4 _Params2; // { Size Bin, Inv. Size Bin }
public Vector4 _Params3; // { Vertex Count, Vertex Stride, Active Bin Count, Cluster Depth }
public Vector4 _Params4; // { Shading Atlas Dim, Cluster Count, Tile Opacity Threshold }
public Vector4 _Params5; // { View Index, Padding }
// Aliases
public Vector2 _DimBin
{
get => new Vector2(_Params0.x, _Params0.y);
set
{
_Params0.x = value.x;
_Params0.y = value.y;
}
}
public int _SegmentCount
{
get => (int)_Params0.z;
set => _Params0.z = (float)value;
}
public int _BinCount
{
get => (int)_Params0.w;
set => _Params0.w = (float)value;
}
public Vector4 _SizeScreen
{
get => _Params1;
set => _Params1 = value;
}
public Vector4 _SizeBin
{
get => _Params2;
set => _Params2 = value;
}
public int _VertexCount
{
get => (int)_Params3.x;
set => _Params3.x = (float)value;
}
public int _VertexStride
{
get => (int)_Params3.y;
set => _Params3.y = (float)value;
}
public int _ActiveBinCount
{
get => (int)_Params3.z;
set => _Params3.z = (float)value;
}
public int _ClusterDepth
{
get => (int)_Params3.w;
set => _Params3.w = (float)value;
}
public Vector2 _ShadingAtlasDimensions
{
get => new Vector2(_Params4.x, _Params4.y);
set
{
_Params4.x = value.x;
_Params4.y = value.y;
}
}
public int _ClusterCount
{
get => (int)_Params4.z;
set => _Params4.z = (float)value;
}
public float _TileOpacityThreshold
{
get => _Params4.w;
set => _Params4.w = value;
}
public int _ViewIndex
{
get => (int)_Params5.x;
set => _Params5.x = (float)value;
}
}
static unsafe int GetShaderVariablesSize()
{
return sizeof(ShaderVariables);
}
[GenerateHLSL(PackingRules.Exact, false)]
struct VertexRecord
{
public Vector4 positionCS;
public Vector4 previousPositionCS;
public Vector3 positionRWS;
public Vector3 tangentWS;
public Vector3 normalWS;
public uint texCoord0;
public uint texCoord1;
}
[GenerateHLSL(PackingRules.Exact, false)]
struct SegmentRecord
{
public Vector2 positionSS0;
public Vector2 positionSS1;
public float depthVS0;
public float depthVS1;
public uint vertexIndex0;
public uint vertexIndex1;
}
[GenerateHLSL(PackingRules.Exact, false)]
struct ClusterRecord
{
public uint segmentIndex;
public uint clusterIndex;
public uint clusterOffset;
}
internal class SharedPassData
{
public ShaderVariables shaderVariables;
public ConstantBuffer<ShaderVariables> shaderVariablesBuffer;
public TextureHandle depthRT;
public SystemResources systemResources;
public Buffers sharedBuffers;
internal struct Buffers
{
public BufferHandle vertexStream0; // Vertex Stream 0: Position CS
public BufferHandle vertexStream1; // Vertex Stream 1: Previous Position CS
public BufferHandle vertexStream2; // Vertex Stream 2: XY Tangent ZW Normal
public BufferHandle vertexStream3; // Vertex Stream 3: Texcoord
public BufferHandle viewSpaceDepthRange;
public BufferHandle counterBuffer;
public BufferHandle recordBufferSegment;
public TextureHandle groupShadingSampleAtlas;
public Vector2Int groupShadingSampleAtlasDimensions;
internal struct AllocationParameters
{
public int countSegment;
public int countVertex;
}
public static Buffers Allocate(RenderGraph renderGraph, AllocationParameters parameters)
{
BufferHandle CreateBuffer(int elementCount, int stride, GraphicsBuffer.Target target, string name)
{
return renderGraph.CreateBuffer(new BufferDesc(elementCount, stride, target) {name = name});
}
int shadingSampleAtlasWidth = Mathf.NextPowerOfTwo(Mathf.CeilToInt(Mathf.Sqrt(parameters.countVertex)));
shadingSampleAtlasWidth = Math.Max(shadingSampleAtlasWidth, 1);
int shadingSampleAtlasHeight = Mathf.NextPowerOfTwo(Mathf.CeilToInt(DivRoundUp(parameters.countVertex, shadingSampleAtlasWidth)));
var resource = new Buffers
{
vertexStream0 = CreateBuffer(16 * parameters.countVertex, sizeof(uint), GraphicsBuffer.Target.Raw, "Record Buffer [Vertex Stream 0]"),
vertexStream1 = CreateBuffer(16 * parameters.countVertex, sizeof(uint), GraphicsBuffer.Target.Raw, "Record Buffer [Vertex Stream 1]"),
vertexStream2 = CreateBuffer(16 * parameters.countVertex, sizeof(uint), GraphicsBuffer.Target.Raw, "Record Buffer [Vertex Stream 2]"),
vertexStream3 = CreateBuffer(8 * parameters.countVertex, sizeof(uint), GraphicsBuffer.Target.Raw, "Record Buffer [Vertex Stream 3]"),
counterBuffer = CreateBuffer(8, sizeof(uint), GraphicsBuffer.Target.Raw, "Counters"),
recordBufferSegment = CreateBuffer(4 * 2 * parameters.countSegment, sizeof(uint), GraphicsBuffer.Target.Raw, "Record Buffer [Segment]"),
viewSpaceDepthRange = CreateBuffer(2, sizeof(float), GraphicsBuffer.Target.Raw, "View Space Depth Range"),
groupShadingSampleAtlas = renderGraph.CreateTexture(new TextureDesc(shadingSampleAtlasWidth, shadingSampleAtlasHeight)
{
colorFormat = GraphicsFormat.R32G32B32A32_SFloat, enableRandomWrite = true
}),
groupShadingSampleAtlasDimensions = new Vector2Int(shadingSampleAtlasWidth, shadingSampleAtlasHeight)
};
return resource;
}
}
}
internal class GeometryPassData : SharedPassData
{
public Buffers transientBuffers;
public RendererData[] rendererData;
public ShadingAtlas shadingAtlas;
public Matrix4x4 matrixIVP;
public MaterialPropertyBlock materialPropertyBlock;
// TODO: Move into RendererData?
public int[] offsetsVertex;
public int[] offsetsSegment;
internal new struct Buffers
{
public const int SHADING_SAMPLE_HISTOGRAM_SIZE = 512; //needs to match the shader
public TextureHandle shadingScratchTexture;
public Vector2Int shadingScratchTextureDimensions;
public GPUPrefixSum.RenderGraphResources prefixResources;
public BufferHandle shadingScratchBuffer;
public BufferHandle shadingSampleHistogram;
internal struct AllocationParameters
{
public int countVertex;
public int countVertexMaxPerRenderer;
}
public static Buffers Allocate(RenderGraph renderGraph, RenderGraphBuilder builder, AllocationParameters parameters)
{
BufferHandle CreateBuffer(int elementCount, int stride, GraphicsBuffer.Target target, string name)
{
return builder.CreateTransientBuffer(new BufferDesc(elementCount, stride, target) { name = name });
}
int scratchTextureDimension = Mathf.NextPowerOfTwo(Mathf.CeilToInt(Mathf.Sqrt(parameters.countVertexMaxPerRenderer)));
int shadingScratchSize = parameters.countVertexMaxPerRenderer + 1;
int prefixMaxItems = Mathf.Max(SHADING_SAMPLE_HISTOGRAM_SIZE, shadingScratchSize);
var resource = new Buffers
{
shadingScratchBuffer = CreateBuffer(shadingScratchSize, sizeof(uint), GraphicsBuffer.Target.Raw, "Shading Scratch"),
shadingSampleHistogram = CreateBuffer(SHADING_SAMPLE_HISTOGRAM_SIZE + 1, sizeof(uint), GraphicsBuffer.Target.Raw, "Shading Sample Histogram"),
prefixResources = GPUPrefixSum.RenderGraphResources.Create(prefixMaxItems, renderGraph, builder),
shadingScratchTexture = builder.CreateTransientTexture(new TextureDesc(scratchTextureDimension, scratchTextureDimension)
{
colorFormat = GraphicsFormat.R32G32B32A32_SFloat, enableRandomWrite = true
}),
shadingScratchTextureDimensions = new Vector2Int(scratchTextureDimension, scratchTextureDimension),
};
return resource;
}
}
}
internal class RasterizationPassData : SharedPassData
{
public Buffers transientBuffers;
public RenderTargets renderTargets;
public int qualityModeIndex;
public int debugModeIndex;
#if UNITY_EDITOR
public bool renderDataStillHasShadersCompiling;
#endif
public int binCount;
public int clusterCount;
public int clusterDepth;
internal new struct Buffers
{
public BufferHandle counterBufferClusters;
public BufferHandle binCounters;
public BufferHandle binIndices;
public BufferHandle workQueueArgs;
public BufferHandle fineRasterArgs;
public BufferHandle workQueue;
public BufferHandle clusterCounters;
public BufferHandle clusterRanges;
public BufferHandle activeClusterIndices;
public BufferHandle binningIndirectArgs;
public BufferHandle recordBufferCluster;
public GPUPrefixSum.RenderGraphResources prefixResources;
public GPUSort.RenderGraphResources binSortResources;
internal struct AllocationParameters
{
public int countBin;
public int countCluster;
public int depthCluster;
public int countBinRecords;
public int countWorkQUeue;
}
public static Buffers Allocate(RenderGraph renderGraph, RenderGraphBuilder builder, AllocationParameters parameters)
{
BufferHandle CreateBuffer(int elementCount, int stride, GraphicsBuffer.Target target, string name)
{
return builder.CreateTransientBuffer(new BufferDesc(elementCount, stride, target) { name = name });
}
var resource = new Buffers
{
clusterCounters = CreateBuffer(parameters.countCluster, sizeof(uint), GraphicsBuffer.Target.Raw, "Cluster Counters"),
recordBufferCluster = CreateBuffer(parameters.countBinRecords, Marshal.SizeOf<ClusterRecord>(), GraphicsBuffer.Target.Structured, "Record Buffer [Cluster]"),
binCounters = CreateBuffer(parameters.countBin, sizeof(uint), GraphicsBuffer.Target.Raw | GraphicsBuffer.Target.CopySource, "Bin Counters"),
binIndices = CreateBuffer(parameters.countBin, sizeof(uint), GraphicsBuffer.Target.Raw | GraphicsBuffer.Target.CopySource, "Bin Indices"),
clusterRanges = CreateBuffer(2 * parameters.depthCluster, sizeof(float), GraphicsBuffer.Target.Raw, "Cluster Ranges"),
activeClusterIndices = CreateBuffer(parameters.countCluster, sizeof(uint), GraphicsBuffer.Target.Raw, "Active Cluster Indices"),
workQueueArgs = CreateBuffer(4, sizeof(uint), GraphicsBuffer.Target.IndirectArguments, "Work Queue Args"),
fineRasterArgs = CreateBuffer(4, sizeof(uint), GraphicsBuffer.Target.IndirectArguments, "Fine Raster Args"),
workQueue = CreateBuffer(parameters.countWorkQUeue, sizeof(uint), GraphicsBuffer.Target.Raw, "Segment Queue"),
binningIndirectArgs = CreateBuffer(4, sizeof(uint), GraphicsBuffer.Target.IndirectArguments, "Binning Args"),
prefixResources = GPUPrefixSum.RenderGraphResources.Create(parameters.countCluster, renderGraph, builder),
binSortResources = GPUSort.RenderGraphResources.Create(parameters.countBin, renderGraph, builder),
};
return resource;
}
}
}
}
}