暫無描述
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.

GpuDeformationSystem.cs 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. using System;
  2. using System.Collections.Generic;
  3. using Unity.Mathematics;
  4. using Unity.Collections;
  5. using Unity.Jobs;
  6. using Unity.Collections.LowLevel.Unsafe;
  7. using UnityEngine.U2D.Common;
  8. using UnityEngine.Assertions;
  9. namespace UnityEngine.U2D.Animation
  10. {
  11. internal class GpuDeformationSystem : BaseDeformationSystem
  12. {
  13. const string k_GpuSkinningShaderKeyword = "SKINNED_SPRITE";
  14. const string k_GlobalSpriteBoneBufferId = "_SpriteBoneTransforms";
  15. const int k_DefaultComputeBufferSize = 64;
  16. readonly Dictionary<int, Material> m_KeywordEnabledMaterials = new Dictionary<int, Material>();
  17. NativeArray<int> m_BoneTransformBufferSizes;
  18. ComputeBuffer m_BoneTransformsComputeBuffer;
  19. public override DeformationMethods deformationMethod => DeformationMethods.Gpu;
  20. internal static bool DoesShaderSupportGpuDeformation(Material material)
  21. {
  22. if (material == null)
  23. return false;
  24. var shader = material.shader;
  25. if (shader == null)
  26. return false;
  27. var supportedKeywords = shader.keywordSpace.keywords;
  28. for (var i = 0; i < supportedKeywords.Length; ++i)
  29. {
  30. if (supportedKeywords[i].name == k_GpuSkinningShaderKeyword)
  31. return true;
  32. }
  33. return false;
  34. }
  35. static bool IsComputeBufferValid(ComputeBuffer buffer) => buffer != null && buffer.IsValid();
  36. protected override void InitializeArrays()
  37. {
  38. base.InitializeArrays();
  39. const int startingCount = 0;
  40. m_BoneTransformBuffers = new NativeArray<IntPtr>(startingCount, Allocator.Persistent);
  41. m_BoneTransformBufferSizes = new NativeArray<int>(startingCount, Allocator.Persistent);
  42. }
  43. internal override void Cleanup()
  44. {
  45. base.Cleanup();
  46. m_BoneTransformBuffers.DisposeIfCreated();
  47. m_BoneTransformBufferSizes.DisposeIfCreated();
  48. CleanupComputeResources();
  49. }
  50. protected override void ResizeAndCopyArrays(int updatedCount)
  51. {
  52. base.ResizeAndCopyArrays(updatedCount);
  53. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_BoneTransformBuffers, updatedCount);
  54. NativeArrayHelpers.ResizeAndCopyIfNeeded(ref m_BoneTransformBufferSizes, updatedCount);
  55. if (updatedCount == 0)
  56. CleanupComputeResources();
  57. }
  58. void CleanupComputeResources()
  59. {
  60. if (IsComputeBufferValid(m_BoneTransformsComputeBuffer))
  61. m_BoneTransformsComputeBuffer.Release();
  62. m_BoneTransformsComputeBuffer = null;
  63. foreach(var material in m_KeywordEnabledMaterials.Values)
  64. material.DisableKeyword(k_GpuSkinningShaderKeyword);
  65. m_KeywordEnabledMaterials.Clear();
  66. }
  67. internal override void UpdateMaterial(SpriteSkin spriteSkin)
  68. {
  69. var sharedMaterial = spriteSkin.spriteRenderer.sharedMaterial;
  70. if (!sharedMaterial.IsKeywordEnabled(k_GpuSkinningShaderKeyword))
  71. sharedMaterial.EnableKeyword(k_GpuSkinningShaderKeyword);
  72. }
  73. internal override bool AddSpriteSkin(SpriteSkin spriteSkin)
  74. {
  75. var success = base.AddSpriteSkin(spriteSkin);
  76. var sharedMaterial = spriteSkin.spriteRenderer.sharedMaterial;
  77. if (!sharedMaterial.IsKeywordEnabled(k_GpuSkinningShaderKeyword))
  78. {
  79. sharedMaterial.EnableKeyword(k_GpuSkinningShaderKeyword);
  80. m_KeywordEnabledMaterials.TryAdd(sharedMaterial.GetInstanceID(), sharedMaterial);
  81. }
  82. if (!IsComputeBufferValid(m_BoneTransformsComputeBuffer))
  83. CreateComputeBuffer(k_DefaultComputeBufferSize);
  84. return success;
  85. }
  86. internal override void Update()
  87. {
  88. BatchRemoveSpriteSkins();
  89. BatchAddSpriteSkins();
  90. var count = m_SpriteSkins.Count;
  91. if (count == 0)
  92. return;
  93. Assert.AreEqual(m_IsSpriteSkinActiveForDeform.Length, count);
  94. Assert.AreEqual(m_PerSkinJobData.Length, count);
  95. Assert.AreEqual(m_SpriteSkinData.Length, count);
  96. Assert.AreEqual(m_BoundsData.Length, count);
  97. Assert.AreEqual(m_SpriteRenderers.Length, count);
  98. Assert.AreEqual(m_Buffers.Length, count);
  99. Assert.AreEqual(m_BufferSizes.Length, count);
  100. Assert.AreEqual(m_BoneTransformBuffers.Length, count);
  101. Assert.AreEqual(m_BoneTransformBufferSizes.Length, count);
  102. PrepareDataForDeformation(out var localToWorldJobHandle, out var worldToLocalJobHandle);
  103. if (!GotVerticesToDeform(out var vertexBufferSize))
  104. {
  105. localToWorldJobHandle.Complete();
  106. worldToLocalJobHandle.Complete();
  107. DeactivateDeformableBuffers();
  108. return;
  109. }
  110. var skinBatch = m_SkinBatchArray[0];
  111. ResizeBuffers(vertexBufferSize, in skinBatch);
  112. var batchCount = m_SpriteSkinData.Length;
  113. var jobHandle = SchedulePrepareJob(batchCount);
  114. Profiling.scheduleJobs.Begin();
  115. jobHandle = JobHandle.CombineDependencies(localToWorldJobHandle, worldToLocalJobHandle, jobHandle);
  116. jobHandle = ScheduleBoneJobBatched(jobHandle, skinBatch);
  117. m_DeformJobHandle = ScheduleSkinDeformBatchedJob(jobHandle, skinBatch);
  118. jobHandle = ScheduleCopySpriteRendererBuffersJob(m_DeformJobHandle, batchCount);
  119. jobHandle = ScheduleCopySpriteRendererBoneTransformBuffersJob(jobHandle, batchCount);
  120. jobHandle = ScheduleCalculateSpriteSkinAABBJob(jobHandle, batchCount);
  121. Profiling.scheduleJobs.End();
  122. JobHandle.ScheduleBatchedJobs();
  123. jobHandle.Complete();
  124. using (Profiling.setBoneTransformsArray.Auto())
  125. {
  126. InternalEngineBridge.SetBatchBoneTransformsAABBArray(m_SpriteRenderers, m_BoneTransformBuffers, m_BoneTransformBufferSizes, m_BoundsData);
  127. }
  128. SetComputeBuffer();
  129. foreach (var spriteSkin in m_SpriteSkins)
  130. {
  131. var didDeform = m_IsSpriteSkinActiveForDeform[spriteSkin.dataIndex];
  132. spriteSkin.PostDeform(didDeform);
  133. }
  134. DeactivateDeformableBuffers();
  135. }
  136. void ResizeBuffers(int vertexBufferSize, in PerSkinJobData skinBatch)
  137. {
  138. var noOfBones = skinBatch.bindPosesIndex.y;
  139. var noOfVerticesInBatch = skinBatch.verticesIndex.y;
  140. m_DeformedVerticesBuffer = BufferManager.instance.GetBuffer(m_ObjectId, vertexBufferSize);
  141. NativeArrayHelpers.ResizeIfNeeded(ref m_FinalBoneTransforms, noOfBones);
  142. NativeArrayHelpers.ResizeIfNeeded(ref m_BoneLookupData, noOfBones);
  143. NativeArrayHelpers.ResizeIfNeeded(ref m_VertexLookupData, noOfVerticesInBatch);
  144. if (!IsComputeBufferValid(m_BoneTransformsComputeBuffer) || m_BoneTransformsComputeBuffer.count < noOfBones)
  145. CreateComputeBuffer(noOfBones);
  146. }
  147. void CreateComputeBuffer(int bufferSize)
  148. {
  149. if (IsComputeBufferValid(m_BoneTransformsComputeBuffer))
  150. m_BoneTransformsComputeBuffer.Release();
  151. m_BoneTransformsComputeBuffer = new ComputeBuffer(bufferSize, UnsafeUtility.SizeOf<float4x4>(), ComputeBufferType.Default);
  152. SetComputeBuffer();
  153. }
  154. void SetComputeBuffer()
  155. {
  156. m_BoneTransformsComputeBuffer.SetData(m_FinalBoneTransforms, 0, 0, m_FinalBoneTransforms.Length);
  157. Shader.SetGlobalBuffer(k_GlobalSpriteBoneBufferId, m_BoneTransformsComputeBuffer);
  158. }
  159. unsafe JobHandle ScheduleCopySpriteRendererBoneTransformBuffersJob(JobHandle jobHandle, int batchCount)
  160. {
  161. var copySpriteRendererBoneTransformBuffersJob = new CopySpriteRendererBoneTransformBuffersJob()
  162. {
  163. isSpriteSkinValidForDeformArray = m_IsSpriteSkinActiveForDeform,
  164. spriteSkinData = m_SpriteSkinData,
  165. ptrBoneTransforms = (IntPtr)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(m_FinalBoneTransforms),
  166. perSkinJobData = m_PerSkinJobData,
  167. buffers = m_BoneTransformBuffers,
  168. bufferSizes = m_BoneTransformBufferSizes,
  169. };
  170. return copySpriteRendererBoneTransformBuffersJob.Schedule(batchCount, 16, jobHandle);
  171. }
  172. }
  173. }