What's the correct way to draw into a custom depth buffer in CustomPass

Unity 2022.2 + HDRP

I need to draw objects depth of a certain layer into a custom depth texture in CustomPass.
I’ve tried CustomPass’s custom depth buffer, and create my only buffer , neither of them works.
CustomPassUtils.RenderDepthFromCamera,
CustomPassUtils.RenderFromCamera,
CoreUtils.DrawRendererList
none of these APIs works either.
I tried to blit the buffer into a RenderTexture, the render texture shows the scene depth.
Tried to draw a fullscreen with the custom buffer , and the result shows all black.
So what would be the correct way to draw a custom depth? I’ve search through the offical CustomPass examples from github(in unity 2022), searched in google and can’t find any effective result.

Here’s one of the code I use, which is a mixed of the DrawRenderersCustomPass of HDRP and CopyPass from the CustomPass examples.

using System.Collections.Generic;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using System;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;

namespace CR
{
    /// <summary>
    /// DrawRenderers Custom Pass
    /// </summary>
    [System.Serializable]
    public class TestDrawRenderer : CustomPass
    {
        /// <summary>
        /// HDRP Shader passes
        /// </summary>
        public enum ShaderPass
        {
            // Ordered by frame time in HDRP
            ///<summary>Object Depth pre-pass, only the depth of the object will be rendered.</summary>
            DepthPrepass = 1,
            ///<summary>Forward pass, render the object color.</summary>
            Forward = 0,
        }

        // Used only for the UI to keep track of the toggle state
        [SerializeField] internal bool filterFoldout;
        [SerializeField] internal bool rendererFoldout;

        //Filter settings
        /// <summary>
        /// Render Queue filter to select which kind of object to render.
        /// </summary>
        public RenderQueueType renderQueueType = RenderQueueType.AllOpaque;
        /// <summary>
        /// Layer Mask filter, select which layer to render.
        /// </summary>
        public LayerMask layerMask = 1; // Layer mask Default enabled
        /// <summary>
        /// Sorting flags of the objects to render.
        /// </summary>
        public SortingCriteria sortingCriteria = SortingCriteria.CommonOpaque;

        /// <summary>
        /// Select which type of override to apply on the DrawRenderers pass.
        /// </summary>
        public enum OverrideMaterialMode
        {
            /// <summary> Disable the material override </summary>
            None,
            /// <summary> Override the material for all renderers </summary>
            Material,
            /// <summary> Override the shader for all renderers. This option keeps the material properties of the renderer and can be used like a replacement shader. </summary>
            Shader
        };

        /// <summary>
        /// Controls how the material on each renderer will be replaced. Material mode uses overrideMaterial. Shader mode uses overrideShader.
        /// </summary>
        public OverrideMaterialMode overrideMode = OverrideMaterialMode.Material; //default to Material as this was previously the only option

        // Override material
        /// <summary>
        /// Replaces the material of selected renders by this one, be sure to also set overrideMaterialPassName to a good value when using this property.
        /// </summary>
        public Material overrideMaterial = null;
        [SerializeField]
        int overrideMaterialPassIndex = 0;
        /// <summary>
        /// Select which pass will be used to render objects when using an override material.
        /// </summary>
        public string overrideMaterialPassName = "Forward";

        // Override shader
        /// <summary>
        /// Replaces the shader of selected renderers while using the current material properties.
        /// </summary>
        public Shader overrideShader = null;
        [SerializeField]
        int overrideShaderPassIndex = 0;
        ///<summary>
        /// Select whih pass will be used to render objects when using an override material.
        /// </summary>
        public string overrideShaderPassName = "Forward";

        /// <summary>
        /// When true, overrides the depth state of the objects.
        /// </summary>
        public bool overrideDepthState = false;
        /// <summary>
        /// Overrides the Depth comparison function, only used when overrideDepthState is true.
        /// </summary>
        public CompareFunction depthCompareFunction = CompareFunction.LessEqual;
        /// <summary>
        /// Overrides the Depth write, only used when overrideDepthState is true.
        /// </summary>
        public bool depthWrite = true;

        /// <summary>
        /// Override the stencil state of the objects.
        /// </summary>
        public bool overrideStencil = false;

        /// <summary>
        /// Stencil reference value. Be careful when using this value to write in the stencil buffer to not overwrite HDRP stencil bits.
        /// </summary>
        public int stencilReferenceValue = (int)UserStencilUsage.UserBit0;

        /// <summary>
        /// Write mask of the stencil.
        /// </summary>
        public int stencilWriteMask = (int)(UserStencilUsage.AllUserBits);

        /// <summary>
        /// Read mask of the stencil
        /// </summary>
        public int stencilReadMask = (int)(UserStencilUsage.AllUserBits);

        /// <summary>
        /// Comparison operation between the stencil buffer and the reference value.
        /// </summary>
        public CompareFunction stencilCompareFunction = CompareFunction.Always;

        /// <summary>
        /// Operation to execute if the stencil test passes.
        /// </summary>
        public StencilOp stencilPassOperation;

        /// <summary>
        /// Operation to execute if the stencil test fails.
        /// </summary>
        public StencilOp stencilFailOperation;

        /// <summary>
        /// Operation to execute if the depth test fails.
        /// </summary>
        public StencilOp stencilDepthFailOperation;

        /// <summary>
        /// Set the shader pass to use when the override material is null
        /// </summary>
        public ShaderPass shaderPass = ShaderPass.Forward;

        int fadeValueId;

        static ShaderTagId[] forwardShaderTags;
        static ShaderTagId[] depthShaderTags;

        // Cache the shaderTagIds so we don't allocate a new array each frame
        ShaderTagId[] cachedShaderTagIDs;

        //public RenderTexture depthTexture = null;
        public enum BufferType
        {
            Color,
            Normal,
            Roughness,
            Depth,
            CustomDepth,
            MotionVectors,
        }

        public RenderTexture outputRenderTexture;

        [SerializeField, HideInInspector]
        Shader customCopyShader;
        Material customCopyMaterial;

        public BufferType bufferType;

        protected override bool executeInSceneView => false;

        int normalPass;
        int roughnessPass;
        int depthPass;
       
       
        //RTHandle fpsDepthBuffer;
        /// <summary>
        /// Called before the first execution of the pass occurs.
        /// Allow you to allocate custom buffers.
        /// </summary>
        /// <param name="renderContext">The render context</param>
        /// <param name="cmd">Current command buffer of the frame</param>
        protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
        {
            fadeValueId = Shader.PropertyToID("_FadeValue");

            // In case there was a pass index assigned, we retrieve the name of this pass
            if (String.IsNullOrEmpty(overrideMaterialPassName) && overrideMaterial != null)
                overrideMaterialPassName = overrideMaterial.GetPassName(overrideMaterialPassIndex);
            if (String.IsNullOrEmpty(overrideShaderPassName) && overrideShader != null)
                overrideShaderPassName = new Material(overrideShader).GetPassName(overrideShaderPassIndex);

            forwardShaderTags = new ShaderTagId[]
            {
                HDShaderPassNames.s_ForwardName,            // HD Lit shader
                HDShaderPassNames.s_ForwardOnlyName,        // HD Unlit shader
                HDShaderPassNames.s_SRPDefaultUnlitName,    // Cross SRP Unlit shader
                HDShaderPassNames.s_EmptyName,              // Add an empty slot for the override material
            };

            depthShaderTags = new ShaderTagId[]
            {
                HDShaderPassNames.s_DepthForwardOnlyName,
                HDShaderPassNames.s_DepthOnlyName,
                HDShaderPassNames.s_EmptyName,              // Add an empty slot for the override material
            };
           
            if (customCopyShader == null)
                customCopyShader = Shader.Find("Hidden/FullScreen/CustomCopy");
            customCopyMaterial = CoreUtils.CreateEngineMaterial(customCopyShader);

            normalPass = customCopyMaterial.FindPass("Normal");
            roughnessPass = customCopyMaterial.FindPass("Roughness");
            depthPass = customCopyMaterial.FindPass("Depth");
           
            //
            // fpsDepthBuffer = RTHandles.Alloc(
            //     Vector2.one,
            //     TextureXR.slices,
            //     dimension: TextureXR.dimension,
            //     useDynamicScale: true,
            //     name: "Test Depth",
            //     enableRandomWrite: true
            // );
        }

        protected override void Cleanup()
        {
            CoreUtils.Destroy(customCopyMaterial);
            //fpsDepthBuffer.Release();
        }

        /// <summary>
        /// Use this method if you want to draw objects that are not visible in the camera.
        /// For example if you disable a layer in the camera and add it in the culling parameters, then the culling result will contains your layer.
        /// </summary>
        /// <param name="cullingParameters">Aggregate the parameters in this property (use |= for masks fields, etc.)</param>
        /// <param name="hdCamera">The camera where the culling is being done</param>
        protected override void AggregateCullingParameters(ref ScriptableCullingParameters cullingParameters, HDCamera hdCamera)
        {
            cullingParameters.cullingMask |= (uint)(int)layerMask;
        }

        ShaderTagId[] GetShaderTagIds()
        {
            if (shaderPass == ShaderPass.DepthPrepass)
                return depthShaderTags;
            else
                return forwardShaderTags;
        }

        /// <summary>
        /// Execute the DrawRenderers with parameters setup from the editor
        /// </summary>
        /// <param name="ctx">The context of the custom pass. Contains command buffer, render context, buffer, etc.</param>
        protected override void Execute(CustomPassContext ctx)
        {
            base.Execute(ctx);
            var shaderPasses = GetShaderTagIds();
            if (overrideMaterial != null)
            {
                shaderPasses[shaderPasses.Length - 1] = new ShaderTagId(overrideMaterialPassName);
                overrideMaterial.SetFloat(fadeValueId, fadeValue);
            }

            if (shaderPasses.Length == 0)
            {
                Debug.LogWarning("Attempt to call DrawRenderers with an empty shader passes. Skipping the call to avoid errors");
                return;
            }

            var mask = overrideDepthState ? RenderStateMask.Depth : 0;
            mask |= overrideDepthState && !depthWrite ? RenderStateMask.Stencil : 0;
            if (overrideStencil)
                mask |= RenderStateMask.Stencil;
            var stateBlock = new RenderStateBlock(mask)
            {
                depthState = new DepthState(depthWrite, depthCompareFunction),
                // We disable the stencil when the depth is overwritten but we don't write to it, to prevent writing to the stencil.
                stencilState = new StencilState(overrideStencil, (byte)stencilReadMask, (byte)stencilWriteMask, stencilCompareFunction, stencilPassOperation, stencilFailOperation, stencilDepthFailOperation),
                stencilReference = overrideStencil ? stencilReferenceValue : 0,
            };

            PerObjectData renderConfig = ctx.hdCamera.frameSettings.IsEnabled(FrameSettingsField.Shadowmask) ? HDUtils.GetBakedLightingWithShadowMaskRenderConfig() : HDUtils.GetBakedLightingRenderConfig();
            var overrideShaderMaterial = (overrideShader != null) ? new Material(overrideShader) : null;

            var result = new UnityEngine.Rendering.RendererUtils.RendererListDesc(shaderPasses, ctx.cullingResults, ctx.hdCamera.camera)
            {
                rendererConfiguration = renderConfig,
                renderQueueRange = GetRenderQueueRange(renderQueueType),
                sortingCriteria = sortingCriteria,
                excludeObjectMotionVectors = false,
                overrideShader = overrideMode == OverrideMaterialMode.Shader ? overrideShader : null,
                overrideMaterial = overrideMode == OverrideMaterialMode.Material ? overrideMaterial : null,
                overrideMaterialPassIndex = (overrideMaterial != null) ? overrideMaterial.FindPass(overrideMaterialPassName) : 0,
                overrideShaderPassIndex = (overrideShader != null) ? overrideShaderMaterial.FindPass(overrideShaderPassName) : 0,
                stateBlock = stateBlock,
                layerMask = layerMask,
            };

            UnityEngine.Object.DestroyImmediate(overrideShaderMaterial);
            var renderCtx = ctx.renderContext;
           
            //CoreUtils.SetRenderTarget(ctx.cmd, ctx.cameraColorBuffer, fpsDepthBuffer, ClearFlag.Depth);
            CoreUtils.DrawRendererList(ctx.renderContext, ctx.cmd, renderCtx.CreateRendererList(result));

            ExecuteCopyPass(ctx);
        }

        protected void ExecuteCopyPass(CustomPassContext ctx)
        {
            if (outputRenderTexture == null || customCopyMaterial == null)
                return;

            SyncRenderTextureAspect(outputRenderTexture, ctx.hdCamera.camera);

            var scale = RTHandles.rtHandleProperties.rtHandleScale;
            customCopyMaterial.SetVector("_Scale", scale);

            switch (bufferType)
            {
                default:
                case BufferType.Color:
                    ctx.cmd.Blit(ctx.cameraColorBuffer, outputRenderTexture, new Vector2(scale.x, scale.y), Vector2.zero, 0, 0);
                    break;
                case BufferType.Normal:
                    ctx.cmd.Blit(ctx.cameraNormalBuffer, outputRenderTexture, customCopyMaterial, normalPass);
                    break;
                case BufferType.Roughness:
                    ctx.cmd.Blit(ctx.cameraNormalBuffer, outputRenderTexture, customCopyMaterial, roughnessPass);
                    break;
                case BufferType.Depth:
                    ctx.cmd.Blit(ctx.cameraNormalBuffer, outputRenderTexture, customCopyMaterial, depthPass);
                    break;
                case BufferType.CustomDepth:
                    {
                        //ctx.cmd.Blit(fpsDepthBuffer, outputRenderTexture, customCopyMaterial, depthPass);
                        ctx.cmd.Blit(ctx.customDepthBuffer.Value, outputRenderTexture, customCopyMaterial, depthPass);
                    }
                    break;
                case BufferType.MotionVectors:
                    ctx.cmd.Blit(ctx.cameraMotionVectorsBuffer, outputRenderTexture, new Vector2(scale.x, scale.y), Vector2.zero, 0, 0);
                    break;
            }
        }
       
        /// <summary>
        /// List all the materials that need to be displayed at the bottom of the component.
        /// All the materials gathered by this method will be used to create a Material Editor and then can be edited directly on the custom pass.
        /// </summary>
        /// <returns>An enumerable of materials to show in the inspector. These materials can be null, the list is cleaned afterwards</returns>
        public override IEnumerable<Material> RegisterMaterialForInspector() { yield return overrideMaterial; }
       
        void SyncRenderTextureAspect(RenderTexture rt, Camera camera)
        {
            float aspect = rt.width / (float)rt.height;

            if (!Mathf.Approximately(aspect, camera.aspect))
            {
                rt.Release();
                rt.width = camera.pixelWidth;
                rt.height = camera.pixelHeight;
                rt.Create();
            }
        }
    }
}

The screenshot shows a background scene with a ball, the ball is of a special layer which’s not renderer by the camera, but drawn in custom pass.I want to draw the depth of the ball in to the custom depth buffer, but the left-top result shows that the custom depth buffer is the scene depth, not the ball’s depth.
(shader pass changed to Depth Prepass doesn’t work either)

did you ever find a solution to this?