BatchingHelper.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #if UNITY_5_6_OR_NEWER
  2. #define VLB_GPU_INSTANCING_SUPPORT
  3. #endif
  4. // Force isDepthBlendEnabled at true when GPU Instancing is enabled, to prevent from breaking the batch if 1 beam has it at 0 and 1 has it at > 0
  5. #define FORCE_ENABLE_DEPTHBLEND_FOR_BATCHING
  6. using UnityEngine;
  7. namespace VLB
  8. {
  9. public static class BatchingHelper
  10. {
  11. /// <summary>
  12. /// Returns if GPU Instancing feature is supported on this Unity version or not.
  13. /// </summary>
  14. #if VLB_GPU_INSTANCING_SUPPORT
  15. public const bool isGpuInstancingSupported = true;
  16. #else
  17. public static bool isGpuInstancingSupported { get; private set; }
  18. #endif
  19. #if FORCE_ENABLE_DEPTHBLEND_FOR_BATCHING
  20. public static bool forceEnableDepthBlend { get { return Config.Instance.actualRenderingMode == RenderingMode.GPUInstancing || Config.Instance.actualRenderingMode == RenderingMode.SRPBatcher; } }
  21. #else
  22. public const bool forceEnableDepthBlend = false;
  23. #endif
  24. public static bool IsGpuInstancingEnabled(Material material)
  25. {
  26. #if VLB_GPU_INSTANCING_SUPPORT
  27. return material.enableInstancing;
  28. #else
  29. return false;
  30. #endif
  31. }
  32. public static void SetMaterialProperties(Material material, bool enableGpuInstancing)
  33. {
  34. #if VLB_GPU_INSTANCING_SUPPORT
  35. Debug.Assert(material != null);
  36. material.enableInstancing = enableGpuInstancing;
  37. #endif
  38. }
  39. public static bool CanBeBatched(VolumetricLightBeam beamA, VolumetricLightBeam beamB, ref string reasons)
  40. {
  41. #pragma warning disable 0162 // warning CS0162: Unreachable code detected
  42. if (Config.Instance.renderPipeline == RenderPipeline.BuiltIn && !isGpuInstancingSupported)
  43. {
  44. reasons = "'GPU Instancing' is not supported on your setup.";
  45. return false;
  46. }
  47. #pragma warning restore 0162
  48. if (Config.Instance.actualRenderingMode != RenderingMode.GPUInstancing && Config.Instance.actualRenderingMode != RenderingMode.SRPBatcher)
  49. {
  50. reasons = string.Format("Current Render Pipeline is '{0}'. To enable batching, use 'GPU Instancing'", Config.Instance.renderPipeline);
  51. if(Config.Instance.renderPipeline != RenderPipeline.BuiltIn)
  52. reasons += " or 'SRP Batcher'";
  53. return false;
  54. }
  55. bool ret = true;
  56. if (!CanBeBatched(beamA, ref reasons))
  57. ret = false;
  58. if (!CanBeBatched(beamB, ref reasons))
  59. ret = false;
  60. if (Config.Instance.featureEnabledDynamicOcclusion)
  61. {
  62. if ((beamA.GetComponent<DynamicOcclusionAbstractBase>() == null) != (beamB.GetComponent<DynamicOcclusionAbstractBase>() == null))
  63. {
  64. AppendErrorMessage(ref reasons, string.Format("{0}/{1}: dynamically occluded and non occluded beams cannot be batched together", beamA.name, beamB.name));
  65. ret = false;
  66. }
  67. }
  68. if (Config.Instance.featureEnabledColorGradient != FeatureEnabledColorGradient.Off && beamA.colorMode != beamB.colorMode)
  69. {
  70. AppendErrorMessage(ref reasons, string.Format("'Color Mode' mismatch: {0} / {1}", beamA.colorMode, beamB.colorMode));
  71. ret = false;
  72. }
  73. if (beamA.blendingMode != beamB.blendingMode)
  74. {
  75. AppendErrorMessage(ref reasons, string.Format("'Blending Mode' mismatch: {0} / {1}", beamA.blendingMode, beamB.blendingMode));
  76. ret = false;
  77. }
  78. if (Config.Instance.featureEnabledNoise3D && beamA.isNoiseEnabled != beamB.isNoiseEnabled)
  79. {
  80. AppendErrorMessage(ref reasons, string.Format("'3D Noise' enabled mismatch: {0} / {1}", beamA.noiseMode, beamB.noiseMode));
  81. ret = false;
  82. }
  83. if (Config.Instance.featureEnabledDepthBlend && !forceEnableDepthBlend)
  84. {
  85. #pragma warning disable 0162
  86. if ((beamA.depthBlendDistance > 0) != (beamB.depthBlendDistance > 0))
  87. {
  88. AppendErrorMessage(ref reasons, string.Format("'Opaque Geometry Blending' mismatch: {0} / {1}", beamA.depthBlendDistance, beamB.depthBlendDistance));
  89. ret = false;
  90. }
  91. #pragma warning restore 0162
  92. }
  93. if (Config.Instance.featureEnabledShaderAccuracyHigh && beamA.shaderAccuracy != beamB.shaderAccuracy)
  94. {
  95. AppendErrorMessage(ref reasons, string.Format("'Shader Accuracy' mismatch: {0} / {1}", beamA.shaderAccuracy, beamB.shaderAccuracy));
  96. ret = false;
  97. }
  98. return ret;
  99. }
  100. public static bool CanBeBatched(VolumetricLightBeam beam, ref string reasons)
  101. {
  102. bool ret = true;
  103. if (Config.Instance.actualRenderingMode == RenderingMode.GPUInstancing)
  104. {
  105. if (beam.geomMeshType != MeshType.Shared)
  106. {
  107. AppendErrorMessage(ref reasons, string.Format("{0} is not using shared mesh", beam.name));
  108. ret = false;
  109. }
  110. }
  111. if (Config.Instance.featureEnabledDynamicOcclusion && beam.GetComponent<DynamicOcclusionDepthBuffer>() != null)
  112. {
  113. AppendErrorMessage(ref reasons, string.Format("{0} is using the DynamicOcclusion DepthBuffer feature", beam.name));
  114. ret = false;
  115. }
  116. return ret;
  117. }
  118. static void AppendErrorMessage(ref string message, string toAppend)
  119. {
  120. if (message != "") message += "\n";
  121. message += "- " + toAppend;
  122. }
  123. }
  124. }