A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using Unity.Collections;
4using Unity.Jobs;
5using Unity.Jobs.LowLevel.Unsafe;
6using Unity.Burst;
7using UnityEngine.Profiling;
8using Unity.Mathematics;
9using UnityEngine.Assertions;
10
11namespace UnityEngine.Rendering
12{
13 internal partial class GPUResidentBatcher : IDisposable
14 {
15 private ParallelBitArray m_ProcessedThisFrameTreeBits;
16
17 private void ProcessTrees()
18 {
19 int treeInstancesCount = m_BatchersContext.GetAliveInstancesOfType(InstanceType.SpeedTree);
20
21 if (treeInstancesCount == 0)
22 return;
23
24 ParallelBitArray compactedVisibilityMasks = m_InstanceCullingBatcher.GetCompactedVisibilityMasks(syncCullingJobs: false);
25
26 if (!compactedVisibilityMasks.IsCreated)
27 return;
28
29 Profiler.BeginSample("GPUResidentInstanceBatcher.ProcessTrees");
30
31 int maxInstancesCount = m_BatchersContext.aliveInstances.Length;
32
33 if(!m_ProcessedThisFrameTreeBits.IsCreated)
34 m_ProcessedThisFrameTreeBits = new ParallelBitArray(maxInstancesCount, Allocator.TempJob);
35 else if(m_ProcessedThisFrameTreeBits.Length < maxInstancesCount)
36 m_ProcessedThisFrameTreeBits.Resize(maxInstancesCount);
37
38 bool becomeVisibleOnly = !Application.isPlaying;
39 var visibleTreeRendererIDs = new NativeList<int>(Allocator.TempJob);
40 var visibleTreeInstances = new NativeList<InstanceHandle>(Allocator.TempJob);
41
42 m_BatchersContext.GetVisibleTreeInstances(compactedVisibilityMasks, m_ProcessedThisFrameTreeBits, visibleTreeRendererIDs, visibleTreeInstances,
43 becomeVisibleOnly, out var becomeVisibleTreeInstancesCount);
44
45 if (visibleTreeRendererIDs.Length > 0)
46 {
47 Profiler.BeginSample("GPUResidentInstanceBatcher.UpdateSpeedTreeWindAndUploadWindParamsToGPU");
48
49 // Become visible trees is a subset of visible trees.
50 var becomeVisibleTreeRendererIDs = visibleTreeRendererIDs.AsArray().GetSubArray(0, becomeVisibleTreeInstancesCount);
51 var becomeVisibleTreeInstances = visibleTreeInstances.AsArray().GetSubArray(0, becomeVisibleTreeInstancesCount);
52
53 if (becomeVisibleTreeRendererIDs.Length > 0)
54 UpdateSpeedTreeWindAndUploadWindParamsToGPU(becomeVisibleTreeRendererIDs, becomeVisibleTreeInstances, history: true);
55
56 UpdateSpeedTreeWindAndUploadWindParamsToGPU(visibleTreeRendererIDs.AsArray(), visibleTreeInstances.AsArray(), history: false);
57
58 Profiler.EndSample();
59 }
60
61 visibleTreeRendererIDs.Dispose();
62 visibleTreeInstances.Dispose();
63
64 Profiler.EndSample();
65 }
66
67 private unsafe void UpdateSpeedTreeWindAndUploadWindParamsToGPU(NativeArray<int> treeRendererIDs, NativeArray<InstanceHandle> treeInstances, bool history)
68 {
69 if (treeRendererIDs.Length == 0)
70 return;
71
72 Assert.AreEqual(treeRendererIDs.Length, treeInstances.Length);
73 Assert.AreEqual(m_BatchersContext.renderersParameters.windParams.Length, (int)SpeedTreeWindParamIndex.MaxWindParamsCount);
74
75 var gpuInstanceIndices = new NativeArray<GPUInstanceIndex>(treeInstances.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
76 m_BatchersContext.instanceDataBuffer.CPUInstanceArrayToGPUInstanceArray(treeInstances, gpuInstanceIndices);
77
78 if (!history)
79 m_BatchersContext.UpdateInstanceWindDataHistory(gpuInstanceIndices);
80
81 GPUInstanceDataBufferUploader uploader = m_BatchersContext.CreateDataBufferUploader(treeInstances.Length, InstanceType.SpeedTree);
82 uploader.AllocateUploadHandles(treeInstances.Length);
83
84 var windParams = new SpeedTreeWindParamsBufferIterator();
85 windParams.bufferPtr = uploader.GetUploadBufferPtr();
86 for (int i = 0; i < (int)SpeedTreeWindParamIndex.MaxWindParamsCount; ++i)
87 windParams.uintParamOffsets[i] = uploader.PrepareParamWrite<Vector4>(m_BatchersContext.renderersParameters.windParams[i].index);
88 windParams.uintStride = uploader.GetUIntPerInstance();
89 windParams.elementOffset = 0;
90 windParams.elementsCount = treeInstances.Length;
91
92 SpeedTreeWindManager.UpdateWindAndWriteBufferWindParams(treeRendererIDs, windParams, history);
93 m_BatchersContext.SubmitToGpu(gpuInstanceIndices, ref uploader, submitOnlyWrittenParams: true);
94
95 gpuInstanceIndices.Dispose();
96 uploader.Dispose();
97 }
98 }
99}