diff --git a/com.unity.render-pipelines.core/Runtime/Common/ConstantBuffer.cs b/com.unity.render-pipelines.core/Runtime/Common/ConstantBuffer.cs index 17f40a20d6e..ca626faf352 100644 --- a/com.unity.render-pipelines.core/Runtime/Common/ConstantBuffer.cs +++ b/com.unity.render-pipelines.core/Runtime/Common/ConstantBuffer.cs @@ -19,7 +19,7 @@ public class ConstantBuffer /// Shader porperty id to bind the constant buffer to. public static void PushGlobal(CommandBuffer cmd, in CBType data, int shaderId) where CBType : struct { - var cb = TypedConstantBuffer.instance; + var cb = ConstantBufferSingleton.instance; cb.UpdateData(cmd, data); cb.SetGlobal(cmd, shaderId); @@ -35,7 +35,7 @@ public static void PushGlobal(CommandBuffer cmd, in CBType data, int sha /// Shader porperty id to bind the constant buffer to. public static void Push(CommandBuffer cmd, in CBType data, ComputeShader cs, int shaderId) where CBType : struct { - var cb = TypedConstantBuffer.instance; + var cb = ConstantBufferSingleton.instance; cb.UpdateData(cmd, data); cb.Set(cmd, cs, shaderId); @@ -51,7 +51,7 @@ public static void Push(CommandBuffer cmd, in CBType data, ComputeShader /// Shader porperty id to bind the constant buffer to. public static void Push(CommandBuffer cmd, in CBType data, Material mat, int shaderId) where CBType : struct { - var cb = TypedConstantBuffer.instance; + var cb = ConstantBufferSingleton.instance; cb.UpdateData(cmd, data); cb.Set(mat, shaderId); @@ -65,7 +65,7 @@ public static void Push(CommandBuffer cmd, in CBType data, Material mat, /// Input data of the constant buffer. public static void UpdateData(CommandBuffer cmd, in CBType data) where CBType : struct { - var cb = TypedConstantBuffer.instance; + var cb = ConstantBufferSingleton.instance; cb.UpdateData(cmd, data); } @@ -78,7 +78,7 @@ public static void UpdateData(CommandBuffer cmd, in CBType data) where C /// Shader porperty id to bind the constant buffer to. public static void SetGlobal(CommandBuffer cmd, int shaderId) where CBType : struct { - var cb = TypedConstantBuffer.instance; + var cb = ConstantBufferSingleton.instance; cb.SetGlobal(cmd, shaderId); } @@ -92,7 +92,7 @@ public static void SetGlobal(CommandBuffer cmd, int shaderId) where CBTy /// Shader porperty id to bind the constant buffer to. public static void Set(CommandBuffer cmd, ComputeShader cs, int shaderId) where CBType : struct { - var cb = TypedConstantBuffer.instance; + var cb = ConstantBufferSingleton.instance; cb.Set(cmd, cs, shaderId); } @@ -105,13 +105,13 @@ public static void Set(CommandBuffer cmd, ComputeShader cs, int shaderId /// Shader porperty id to bind the constant buffer to. public static void Set(Material mat, int shaderId) where CBType : struct { - var cb = TypedConstantBuffer.instance; + var cb = ConstantBufferSingleton.instance; cb.Set(mat, shaderId); } /// - /// Release all currently allocated constant buffers. + /// Release all currently allocated singleton constant buffers. /// This needs to be called before shutting down the application. /// public static void ReleaseAll() @@ -122,86 +122,148 @@ public static void ReleaseAll() m_RegisteredConstantBuffers.Clear(); } - internal abstract class ConstantBufferBase - { - public abstract void Release(); - } - internal static void Register(ConstantBufferBase cb) { m_RegisteredConstantBuffers.Add(cb); } + } - class TypedConstantBuffer : ConstantBufferBase where CBType : struct - { - // Used to track all global bindings used by this CB type. - HashSet m_GlobalBindings = new HashSet(); - // Array is required by the ComputeBuffer SetData API - CBType[] m_Data = new CBType[1]; + /// + /// The base class of Constant Buffer. + /// + public abstract class ConstantBufferBase + { + /// + /// Release the constant buffer. + /// + public abstract void Release(); + } - static TypedConstantBuffer s_Instance = null; - internal static TypedConstantBuffer instance - { - get - { - if (s_Instance == null) - s_Instance = new TypedConstantBuffer(); - return s_Instance; - } - set - { - s_Instance = value; - } - } - ComputeBuffer m_GPUConstantBuffer = null; - TypedConstantBuffer() - { - m_GPUConstantBuffer = new ComputeBuffer(1, UnsafeUtility.SizeOf(), ComputeBufferType.Constant); - ConstantBuffer.Register(this); - } + /// + /// An instance of a constant buffer. + /// + /// The type of structure representing the constant buffer data. + public class ConstantBuffer : ConstantBufferBase where CBType : struct + { + // Used to track all global bindings used by this CB type. + HashSet m_GlobalBindings = new HashSet(); + // Array is required by the ComputeBuffer SetData API + CBType[] m_Data = new CBType[1]; - public void UpdateData(CommandBuffer cmd, in CBType data) - { - m_Data[0] = data; + + ComputeBuffer m_GPUConstantBuffer = null; + + /// + /// Constant Buffer constructor. + /// + public ConstantBuffer() + { + m_GPUConstantBuffer = new ComputeBuffer(1, UnsafeUtility.SizeOf(), ComputeBufferType.Constant); + } + + /// + /// Update the GPU data of the constant buffer. + /// + /// Command Buffer used to execute the graphic commands. + /// Input data of the constant buffer. + public void UpdateData(CommandBuffer cmd, in CBType data) + { + m_Data[0] = data; #if UNITY_2021_1_OR_NEWER - cmd.SetBufferData(m_GPUConstantBuffer, m_Data); + cmd.SetBufferData(m_GPUConstantBuffer, m_Data); #else - cmd.SetComputeBufferData(m_GPUConstantBuffer, m_Data); + cmd.SetComputeBufferData(m_GPUConstantBuffer, m_Data); #endif - } + } - public void SetGlobal(CommandBuffer cmd, int shaderId) - { - m_GlobalBindings.Add(shaderId); - cmd.SetGlobalConstantBuffer(m_GPUConstantBuffer, shaderId, 0, m_GPUConstantBuffer.stride); - } + /// + /// Bind the constant buffer globally. + /// + /// Command Buffer used to execute the graphic commands. + /// Shader porperty id to bind the constant buffer to. + public void SetGlobal(CommandBuffer cmd, int shaderId) + { + m_GlobalBindings.Add(shaderId); + cmd.SetGlobalConstantBuffer(m_GPUConstantBuffer, shaderId, 0, m_GPUConstantBuffer.stride); + } - public void Set(CommandBuffer cmd, ComputeShader cs, int shaderId) - { - cmd.SetComputeConstantBufferParam(cs, shaderId, m_GPUConstantBuffer, 0, m_GPUConstantBuffer.stride); - } + /// + /// Bind the constant buffer to a compute shader. + /// + /// Command Buffer used to execute the graphic commands. + /// Compute shader to which the constant buffer should be bound. + /// Shader porperty id to bind the constant buffer to. + public void Set(CommandBuffer cmd, ComputeShader cs, int shaderId) + { + cmd.SetComputeConstantBufferParam(cs, shaderId, m_GPUConstantBuffer, 0, m_GPUConstantBuffer.stride); + } + + /// + /// Bind the constant buffer to a material. + /// + /// Material to which the constant buffer should be bound. + /// Shader porperty id to bind the constant buffer to. + public void Set(Material mat, int shaderId) + { + // This isn't done via command buffer because as long as the buffer itself is not destroyed, + // the binding stays valid. Only the commit of data needs to go through the command buffer. + // We do it here anyway for now to simplify user API. + mat.SetConstantBuffer(shaderId, m_GPUConstantBuffer, 0, m_GPUConstantBuffer.stride); + } + + /// + /// Update the GPU data of the constant buffer and bind it globally. + /// + /// Command Buffer used to execute the graphic commands. + /// Input data of the constant buffer. + /// Shader porperty id to bind the constant buffer to. + public void PushGlobal(CommandBuffer cmd, in CBType data, int shaderId) + { + UpdateData(cmd, data); + SetGlobal(cmd, shaderId); + } + + /// + /// Release the constant buffers. + /// + public override void Release() + { + // Depending on the device, globally bound buffers can leave stale "valid" shader ids pointing to a destroyed buffer. + // In DX11 it does not cause issues but on Vulkan this will result in skipped drawcalls (even if the buffer is not actually accessed in the shader). + // To avoid this kind of issues, it's good practice to "unbind" all globally bound buffers upon destruction. + foreach (int shaderId in m_GlobalBindings) + Shader.SetGlobalConstantBuffer(shaderId, (ComputeBuffer)null, 0, 0); + m_GlobalBindings.Clear(); - public void Set(Material mat, int shaderId) + CoreUtils.SafeRelease(m_GPUConstantBuffer); + } + } + + class ConstantBufferSingleton : ConstantBuffer where CBType : struct + { + static ConstantBufferSingleton s_Instance = null; + internal static ConstantBufferSingleton instance + { + get { - // This isn't done via command buffer because as long as the buffer itself is not destroyed, - // the binding stays valid. Only the commit of data needs to go through the command buffer. - // We do it here anyway for now to simplify user API. - mat.SetConstantBuffer(shaderId, m_GPUConstantBuffer, 0, m_GPUConstantBuffer.stride); + if (s_Instance == null) + { + s_Instance = new ConstantBufferSingleton(); + ConstantBuffer.Register(s_Instance); + } + return s_Instance; } - - public override void Release() + set { - // Depending on the device, globally bound buffers can leave stale "valid" shader ids pointing to a destroyed buffer. - // In DX11 it does not cause issues but on Vulkan this will result in skipped drawcalls (even if the buffer is not actually accessed in the shader). - // To avoid this kind of issues, it's good practice to "unbind" all globally bound buffers upon destruction. - foreach (int shaderId in m_GlobalBindings) - Shader.SetGlobalConstantBuffer(shaderId, (ComputeBuffer)null, 0, 0); - m_GlobalBindings.Clear(); - - CoreUtils.SafeRelease(m_GPUConstantBuffer); - s_Instance = null; + s_Instance = value; } } + + public override void Release() + { + base.Release(); + s_Instance = null; + } } } diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index b7f3585c201..4ebad941f3c 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -162,6 +162,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fixed undo of some properties on light editor. - Fixed an issue where auto baking of ambient and reflection probe done for builtin renderer would cause wrong baking in HDRP. - Fixed some reference to old frame settings names in HDRP Wizard. +- Fixed issue with constant buffer being stomped on when async tasks run concurrently to shadows. ### Changed - Changed Window/Render Pipeline/HD Render Pipeline Wizard to Window/Rendering/HDRP Wizard diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDCachedShadowAtlas.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDCachedShadowAtlas.cs index 1363debe46c..16a7d15075f 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDCachedShadowAtlas.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDCachedShadowAtlas.cs @@ -77,9 +77,9 @@ public HDCachedShadowAtlas(ShadowMapType type) m_ShadowType = type; } - public override void InitAtlas(HDRenderPipelineRuntimeResources renderPipelineResources, RenderGraph renderGraph, bool useSharedTexture, int width, int height, int atlasShaderID, Material clearMaterial, int maxShadowRequests, HDShadowInitParameters initParams, BlurAlgorithm blurAlgorithm = BlurAlgorithm.None, FilterMode filterMode = FilterMode.Bilinear, DepthBits depthBufferBits = DepthBits.Depth16, RenderTextureFormat format = RenderTextureFormat.Shadowmap, string name = "") + public override void InitAtlas(HDShadowAtlasInitParameters atlasInitParams) { - base.InitAtlas(renderPipelineResources, renderGraph, useSharedTexture, width, height, atlasShaderID, clearMaterial, maxShadowRequests, initParams, blurAlgorithm, filterMode, depthBufferBits, format, name); + base.InitAtlas(atlasInitParams); m_IsACacheForShadows = true; m_AtlasResolutionInSlots = HDUtils.DivRoundUp(width, m_MinSlotSize); @@ -91,7 +91,7 @@ public override void InitAtlas(HDRenderPipelineRuntimeResources renderPipelineRe // Note: If changing the characteristics of the atlas via HDRP asset, the lights OnEnable will not be called again so we are missing them, however we can explicitly // put them back up for placement. If this is the first Init of the atlas, the lines below do nothing. - DefragmentAtlasAndReRender(initParams); + DefragmentAtlasAndReRender(atlasInitParams.initParams); m_CanTryPlacement = true; m_NeedOptimalPacking = true; } diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDCachedShadowManager.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDCachedShadowManager.cs index 373228d662d..56ff0ffaea9 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDCachedShadowManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDCachedShadowManager.cs @@ -274,18 +274,16 @@ private HDCachedShadowManager() areaShadowAtlas = new HDCachedShadowAtlas(ShadowMapType.AreaLightAtlas); } - internal void InitPunctualShadowAtlas(HDRenderPipelineRuntimeResources renderPipelineResources, RenderGraph renderGraph, bool useSharedTexture, int width, int height, int atlasShaderID, Material clearMaterial, int maxShadowRequests, HDShadowInitParameters initParams, - HDShadowAtlas.BlurAlgorithm blurAlgorithm = HDShadowAtlas.BlurAlgorithm.None, FilterMode filterMode = FilterMode.Bilinear, DepthBits depthBufferBits = DepthBits.Depth16, RenderTextureFormat format = RenderTextureFormat.Shadowmap, string name = "") + internal void InitPunctualShadowAtlas(HDShadowAtlas.HDShadowAtlasInitParameters atlasInitParams) { - m_InitParams = initParams; - punctualShadowAtlas.InitAtlas(renderPipelineResources, renderGraph, useSharedTexture, width, height, atlasShaderID, clearMaterial, maxShadowRequests, initParams, blurAlgorithm, filterMode, depthBufferBits, format, name); + m_InitParams = atlasInitParams.initParams; + punctualShadowAtlas.InitAtlas(atlasInitParams); } - internal void InitAreaLightShadowAtlas(HDRenderPipelineRuntimeResources renderPipelineResources, RenderGraph renderGraph, bool useSharedTexture, int width, int height, int atlasShaderID, Material clearMaterial, int maxShadowRequests, HDShadowInitParameters initParams, - HDShadowAtlas.BlurAlgorithm blurAlgorithm = HDShadowAtlas.BlurAlgorithm.None, FilterMode filterMode = FilterMode.Bilinear, DepthBits depthBufferBits = DepthBits.Depth16, RenderTextureFormat format = RenderTextureFormat.Shadowmap, string name = "") + internal void InitAreaLightShadowAtlas(HDShadowAtlas.HDShadowAtlasInitParameters atlasInitParams) { - m_InitParams = initParams; - areaShadowAtlas.InitAtlas(renderPipelineResources, renderGraph, useSharedTexture, width, height, atlasShaderID, clearMaterial, maxShadowRequests, initParams, blurAlgorithm, filterMode, depthBufferBits, format, name); + m_InitParams = atlasInitParams.initParams; + areaShadowAtlas.InitAtlas(atlasInitParams); } internal void RegisterLight(HDAdditionalLightData lightData) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDDynamicShadowAtlas.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDDynamicShadowAtlas.cs index 223980d4b26..ace58ae366e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDDynamicShadowAtlas.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDDynamicShadowAtlas.cs @@ -12,10 +12,10 @@ partial class HDDynamicShadowAtlas : HDShadowAtlas float m_RcpScaleFactor = 1; HDShadowResolutionRequest[] m_SortedRequestsCache; - public HDDynamicShadowAtlas(HDRenderPipelineRuntimeResources renderPipelineResources, RenderGraph renderGraph, bool useSharedTexture, int width, int height, int atlasShaderID, Material clearMaterial, int maxShadowRequests, HDShadowInitParameters initParams, BlurAlgorithm blurAlgorithm = BlurAlgorithm.None, FilterMode filterMode = FilterMode.Bilinear, DepthBits depthBufferBits = DepthBits.Depth16, RenderTextureFormat format = RenderTextureFormat.Shadowmap, string name = "") - : base(renderPipelineResources, renderGraph, useSharedTexture, width, height, atlasShaderID, clearMaterial, maxShadowRequests, initParams, blurAlgorithm, filterMode, depthBufferBits, format, name) + public HDDynamicShadowAtlas(HDShadowAtlasInitParameters atlaInitParams) + : base(atlaInitParams) { - m_SortedRequestsCache = new HDShadowResolutionRequest[Mathf.CeilToInt(maxShadowRequests)]; + m_SortedRequestsCache = new HDShadowResolutionRequest[Mathf.CeilToInt(atlaInitParams.maxShadowRequests)]; } internal void ReserveResolution(HDShadowResolutionRequest shadowRequest) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowAtlas.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowAtlas.cs index 40a51ebd18c..2ac8b9dc930 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowAtlas.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowAtlas.cs @@ -7,6 +7,47 @@ namespace UnityEngine.Rendering.HighDefinition { abstract class HDShadowAtlas { + internal struct HDShadowAtlasInitParameters + { + internal HDRenderPipelineRuntimeResources renderPipelineResources; + internal RenderGraph renderGraph; + internal bool useSharedTexture; + internal int width; + internal int height; + internal int atlasShaderID; + internal int maxShadowRequests; + internal string name; + + internal Material clearMaterial; + internal HDShadowInitParameters initParams; + internal BlurAlgorithm blurAlgorithm; + internal FilterMode filterMode; + internal DepthBits depthBufferBits; + internal RenderTextureFormat format; + internal ConstantBuffer cb; + + internal HDShadowAtlasInitParameters(HDRenderPipelineRuntimeResources renderPipelineResources, RenderGraph renderGraph, bool useSharedTexture, int width, int height, int atlasShaderID, + Material clearMaterial, int maxShadowRequests, HDShadowInitParameters initParams, ConstantBuffer cb) + { + this.renderPipelineResources = renderPipelineResources; + this.renderGraph = renderGraph; + this.useSharedTexture = useSharedTexture; + this.width = width; + this.height = height; + this.atlasShaderID = atlasShaderID; + this.clearMaterial = clearMaterial; + this.maxShadowRequests = maxShadowRequests; + this.initParams = initParams; + this.blurAlgorithm = BlurAlgorithm.None; + this.filterMode = FilterMode.Bilinear; + this.depthBufferBits = DepthBits.Depth16; + this.format = RenderTextureFormat.Shadowmap; + this.name = ""; + + this.cb = cb; + } + } + public enum BlurAlgorithm { None, @@ -35,6 +76,9 @@ public enum BlurAlgorithm // Moment shadow data BlurAlgorithm m_BlurAlgorithm; + // This is only a reference that is hold by the atlas, but its lifetime is responsibility of the shadow manager. + ConstantBuffer m_GlobalConstantBuffer; + // This must be true for atlas that contain cached data (effectively this // drives what to do with mixed cached shadow map -> if true we filter with only static // if false we filter only for dynamic) @@ -52,31 +96,33 @@ public TextureDesc GetShadowMapTextureDesc() public HDShadowAtlas() {} - public virtual void InitAtlas(HDRenderPipelineRuntimeResources renderPipelineResources, RenderGraph renderGraph, bool useSharedTexture, int width, int height, int atlasShaderID, Material clearMaterial, int maxShadowRequests, HDShadowInitParameters initParams, BlurAlgorithm blurAlgorithm = BlurAlgorithm.None, FilterMode filterMode = FilterMode.Bilinear, DepthBits depthBufferBits = DepthBits.Depth16, RenderTextureFormat format = RenderTextureFormat.Shadowmap, string name = "") + public virtual void InitAtlas(HDShadowAtlasInitParameters initParams) { - this.width = width; - this.height = height; - m_FilterMode = filterMode; - m_DepthBufferBits = depthBufferBits; - m_Format = format; - m_Name = name; + this.width = initParams.width; + this.height = initParams.height; + m_FilterMode = initParams.filterMode; + m_DepthBufferBits = initParams.depthBufferBits; + m_Format = initParams.format; + m_Name = initParams.name; // With render graph, textures are "allocated" every frame so we need to prepare strings beforehand. m_MomentName = m_Name + "Moment"; m_MomentCopyName = m_Name + "MomentCopy"; m_IntermediateSummedAreaName = m_Name + "IntermediateSummedArea"; m_SummedAreaName = m_Name + "SummedAreaFinal"; - m_AtlasShaderID = atlasShaderID; - m_ClearMaterial = clearMaterial; - m_BlurAlgorithm = blurAlgorithm; - m_RenderPipelineResources = renderPipelineResources; + m_AtlasShaderID = initParams.atlasShaderID; + m_ClearMaterial = initParams.clearMaterial; + m_BlurAlgorithm = initParams.blurAlgorithm; + m_RenderPipelineResources = initParams.renderPipelineResources; m_IsACacheForShadows = false; - InitializeRenderGraphOutput(renderGraph, useSharedTexture); + m_GlobalConstantBuffer = initParams.cb; + + InitializeRenderGraphOutput(initParams.renderGraph, initParams.useSharedTexture); } - public HDShadowAtlas(HDRenderPipelineRuntimeResources renderPipelineResources, RenderGraph renderGraph, bool useSharedTexture, int width, int height, int atlasShaderID, Material clearMaterial, int maxShadowRequests, HDShadowInitParameters initParams, BlurAlgorithm blurAlgorithm = BlurAlgorithm.None, FilterMode filterMode = FilterMode.Bilinear, DepthBits depthBufferBits = DepthBits.Depth16, RenderTextureFormat format = RenderTextureFormat.Shadowmap, string name = "") + public HDShadowAtlas(HDShadowAtlasInitParameters initParams) { - InitAtlas(renderPipelineResources, renderGraph, useSharedTexture, width, height, atlasShaderID, clearMaterial, maxShadowRequests, initParams, blurAlgorithm, filterMode, depthBufferBits, format, name); + InitAtlas(initParams); } TextureDesc GetMomentAtlasDesc(string name) @@ -190,7 +236,8 @@ class RenderShadowMapsPassData { public TextureHandle atlasTexture; - public ShaderVariablesGlobal globalCB; + public ShaderVariablesGlobal globalCBData; + public ConstantBuffer globalCB; public ShadowDrawingSettings shadowDrawSettings; public List shadowRequests; public Material clearMaterial; @@ -198,11 +245,12 @@ class RenderShadowMapsPassData public bool isRenderingOnACache; } - TextureHandle RenderShadowMaps(RenderGraph renderGraph, CullingResults cullResults, in ShaderVariablesGlobal globalCB, FrameSettings frameSettings, string shadowPassName) + TextureHandle RenderShadowMaps(RenderGraph renderGraph, CullingResults cullResults, in ShaderVariablesGlobal globalCBData, FrameSettings frameSettings, string shadowPassName) { using (var builder = renderGraph.AddRenderPass("Render Shadow Maps", out var passData, ProfilingSampler.Get(HDProfileId.RenderShadowMaps))) { - passData.globalCB = globalCB; + passData.globalCBData = globalCBData; + passData.globalCB = m_GlobalConstantBuffer; passData.shadowRequests = m_ShadowRequests; passData.clearMaterial = m_ClearMaterial; passData.debugClearAtlas = m_LightingDebugSettings.clearShadowAtlas; @@ -259,14 +307,14 @@ TextureHandle RenderShadowMaps(RenderGraph renderGraph, CullingResults cullResul // Setup matrices for shadow rendering: Matrix4x4 viewProjection = shadowRequest.deviceProjectionYFlip * shadowRequest.view; - data.globalCB._ViewMatrix = shadowRequest.view; - data.globalCB._InvViewMatrix = shadowRequest.view.inverse; - data.globalCB._ProjMatrix = shadowRequest.deviceProjectionYFlip; - data.globalCB._InvProjMatrix = shadowRequest.deviceProjectionYFlip.inverse; - data.globalCB._ViewProjMatrix = viewProjection; - data.globalCB._InvViewProjMatrix = viewProjection.inverse; - - ConstantBuffer.PushGlobal(ctx.cmd, data.globalCB, HDShaderIDs._ShaderVariablesGlobal); + data.globalCBData._ViewMatrix = shadowRequest.view; + data.globalCBData._InvViewMatrix = shadowRequest.view.inverse; + data.globalCBData._ProjMatrix = shadowRequest.deviceProjectionYFlip; + data.globalCBData._InvProjMatrix = shadowRequest.deviceProjectionYFlip.inverse; + data.globalCBData._ViewProjMatrix = viewProjection; + data.globalCBData._InvViewProjMatrix = viewProjection.inverse; + + data.globalCB.PushGlobal(ctx.cmd, data.globalCBData, HDShaderIDs._ShaderVariablesGlobal); ctx.cmd.SetGlobalVectorArray(HDShaderIDs._ShadowFrustumPlanes, shadowRequest.frustumPlanes); diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowManager.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowManager.cs index 72569f623f7..de9625a0ba2 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowManager.cs @@ -276,6 +276,7 @@ internal struct ShadowResult public TextureHandle cachedAreaShadowResult; } + class HDShadowManager { public const int k_DirectionalShadowCascadeCount = 4; @@ -306,6 +307,8 @@ class HDShadowManager Material m_ClearShadowMaterial; Material m_BlitShadowMaterial; + ConstantBuffer m_GlobalShaderVariables; + public static HDCachedShadowManager cachedShadowManager { get { return HDCachedShadowManager.instance; } } public void InitShadowManager(HDRenderPipelineRuntimeResources renderPipelineResources, HDShadowInitParameters initParams, RenderGraph renderGraph, Shader clearShader) @@ -329,27 +332,70 @@ public void InitShadowManager(HDRenderPipelineRuntimeResources renderPipelineRes m_ShadowRequests = new HDShadowRequest[initParams.maxShadowRequests]; m_CachedDirectionalShadowData = new HDDirectionalShadowData[1]; // we only support directional light shadow + m_GlobalShaderVariables = new ConstantBuffer(); + for (int i = 0; i < initParams.maxShadowRequests; i++) { m_ShadowResolutionRequests[i] = new HDShadowResolutionRequest(); } + + HDShadowAtlas.HDShadowAtlasInitParameters punctualAtlasInitParams = new HDShadowAtlas.HDShadowAtlasInitParameters(renderPipelineResources, renderGraph, useSharedTexture: false, initParams.punctualLightShadowAtlas.shadowAtlasResolution, + initParams.punctualLightShadowAtlas.shadowAtlasResolution, HDShaderIDs._ShadowmapAtlas, m_ClearShadowMaterial, initParams.maxShadowRequests, initParams, m_GlobalShaderVariables); + punctualAtlasInitParams.name = "Shadow Map Atlas"; + // The cascade atlas will be allocated only if there is a directional light - m_Atlas = new HDDynamicShadowAtlas(renderPipelineResources, renderGraph, useSharedTexture: false, initParams.punctualLightShadowAtlas.shadowAtlasResolution, initParams.punctualLightShadowAtlas.shadowAtlasResolution, - HDShaderIDs._ShadowmapAtlas, m_ClearShadowMaterial, initParams.maxShadowRequests, initParams, depthBufferBits: initParams.punctualLightShadowAtlas.shadowAtlasDepthBits, name: "Shadow Map Atlas"); + m_Atlas = new HDDynamicShadowAtlas(punctualAtlasInitParams); // Cascade atlas render texture will only be allocated if there is a shadow casting directional light HDShadowAtlas.BlurAlgorithm cascadeBlur = GetDirectionalShadowAlgorithm() == DirectionalShadowAlgorithm.IMS ? HDShadowAtlas.BlurAlgorithm.IM : HDShadowAtlas.BlurAlgorithm.None; - m_CascadeAtlas = new HDDynamicShadowAtlas(renderPipelineResources, renderGraph, useSharedTexture: false, 1, 1, HDShaderIDs._ShadowmapCascadeAtlas, m_ClearShadowMaterial, initParams.maxShadowRequests, initParams, cascadeBlur, depthBufferBits: initParams.directionalShadowsDepthBits, name: "Cascade Shadow Map Atlas"); + + HDShadowAtlas.HDShadowAtlasInitParameters dirAtlasInitParams = punctualAtlasInitParams; + dirAtlasInitParams.useSharedTexture = false; + dirAtlasInitParams.width = 1; + dirAtlasInitParams.height = 1; + dirAtlasInitParams.atlasShaderID = HDShaderIDs._ShadowmapCascadeAtlas; + dirAtlasInitParams.blurAlgorithm = cascadeBlur; + dirAtlasInitParams.depthBufferBits = initParams.directionalShadowsDepthBits; + dirAtlasInitParams.name = "Cascade Shadow Map Atlas"; + + m_CascadeAtlas = new HDDynamicShadowAtlas(dirAtlasInitParams); + + HDShadowAtlas.HDShadowAtlasInitParameters areaAtlasInitParams = punctualAtlasInitParams; if (ShaderConfig.s_AreaLights == 1) - m_AreaLightShadowAtlas = new HDDynamicShadowAtlas(renderPipelineResources, renderGraph, useSharedTexture: false, initParams.areaLightShadowAtlas.shadowAtlasResolution, initParams.areaLightShadowAtlas.shadowAtlasResolution, - HDShaderIDs._ShadowmapAreaAtlas, m_ClearShadowMaterial, initParams.maxShadowRequests, initParams, HDShadowAtlas.BlurAlgorithm.EVSM, depthBufferBits: initParams.areaLightShadowAtlas.shadowAtlasDepthBits, name: "Area Light Shadow Map Atlas"); + { + areaAtlasInitParams.useSharedTexture = false; + areaAtlasInitParams.width = initParams.areaLightShadowAtlas.shadowAtlasResolution; + areaAtlasInitParams.height = initParams.areaLightShadowAtlas.shadowAtlasResolution; + areaAtlasInitParams.atlasShaderID = HDShaderIDs._ShadowmapAreaAtlas; + areaAtlasInitParams.blurAlgorithm = HDShadowAtlas.BlurAlgorithm.EVSM; + areaAtlasInitParams.depthBufferBits = initParams.areaLightShadowAtlas.shadowAtlasDepthBits; + areaAtlasInitParams.name = "Area Light Shadow Map Atlas"; - cachedShadowManager.InitPunctualShadowAtlas(renderPipelineResources, renderGraph, useSharedTexture: true, initParams.cachedPunctualLightShadowAtlas, initParams.cachedPunctualLightShadowAtlas, - HDShaderIDs._CachedShadowmapAtlas, m_ClearShadowMaterial, initParams.maxShadowRequests, initParams: initParams, depthBufferBits: initParams.punctualLightShadowAtlas.shadowAtlasDepthBits, name: "Cached Shadow Map Atlas"); + + m_AreaLightShadowAtlas = new HDDynamicShadowAtlas(areaAtlasInitParams); + } + + HDShadowAtlas.HDShadowAtlasInitParameters cachedPunctualAtlasInitParams = punctualAtlasInitParams; + cachedPunctualAtlasInitParams.useSharedTexture = true; + cachedPunctualAtlasInitParams.width = initParams.cachedPunctualLightShadowAtlas; + cachedPunctualAtlasInitParams.height = initParams.cachedPunctualLightShadowAtlas; + cachedPunctualAtlasInitParams.atlasShaderID = HDShaderIDs._CachedShadowmapAtlas; + cachedPunctualAtlasInitParams.name = "Cached Shadow Map Atlas"; + + + cachedShadowManager.InitPunctualShadowAtlas(cachedPunctualAtlasInitParams); if (ShaderConfig.s_AreaLights == 1) - cachedShadowManager.InitAreaLightShadowAtlas(renderPipelineResources, renderGraph, useSharedTexture: true, initParams.cachedAreaLightShadowAtlas, initParams.cachedAreaLightShadowAtlas, - HDShaderIDs._CachedAreaLightShadowmapAtlas, m_ClearShadowMaterial, initParams.maxShadowRequests, initParams: initParams, HDShadowAtlas.BlurAlgorithm.EVSM, depthBufferBits: initParams.areaLightShadowAtlas.shadowAtlasDepthBits, name: "Cached Area Light Shadow Map Atlas"); + { + HDShadowAtlas.HDShadowAtlasInitParameters cachedAreaAtlasInitParams = areaAtlasInitParams; + areaAtlasInitParams.useSharedTexture = true; + areaAtlasInitParams.width = initParams.cachedAreaLightShadowAtlas; + areaAtlasInitParams.height = initParams.cachedAreaLightShadowAtlas; + areaAtlasInitParams.atlasShaderID = HDShaderIDs._CachedAreaLightShadowmapAtlas; + areaAtlasInitParams.name = "Cached Area Light Shadow Map Atlas"; + + cachedShadowManager.InitAreaLightShadowAtlas(cachedAreaAtlasInitParams); + } } public void Cleanup(RenderGraph renderGraph) @@ -367,6 +413,8 @@ public void Cleanup(RenderGraph renderGraph) CoreUtils.Destroy(m_ClearShadowMaterial); cachedShadowManager.Cleanup(renderGraph); + + m_GlobalShaderVariables.Release(); } // Keep in sync with both HDShadowSampling.hlsl