Vertex Color Feature only works in editor

With Unity 2021.3.25f1 (using URP) I use a Custom Vertex Colors Feature to generate Outlines for a shader. This works perfectly fine in the editor but breaks in the windows build.

Using the Frame debugger I can see the problem lies in the Vertex Color Prepass

What it should looks like:

What it looks like:

The ScriptableRendererFeature:

// using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

[System.Serializable]
public class VertexColorsFeature : ScriptableRendererFeature
{

    class VertexColorsPass : ScriptableRenderPass {
        int kDepthBufferBits = 32;
        private RenderTargetHandle depthAttachmentHandle { get; set; }
        internal RenderTextureDescriptor descriptor { get; private set; }

        private Material internalVertexColorsMaterial = null;
        
        private FilteringSettings m_FilteringSettings;
        string m_ProfilerTag = "Vertex Color Prepass";
        ShaderTagId m_ShaderTagId = new ShaderTagId("DepthOnly");

        public VertexColorsPass(RenderQueueRange renderQueueRange, LayerMask layerMask, Material material)
        {
            m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);
            internalVertexColorsMaterial = material;
        }

        public void Setup(RenderTextureDescriptor baseDescriptor, RenderTargetHandle depthAttachmentHandle)
        {
            this.depthAttachmentHandle = depthAttachmentHandle;
            baseDescriptor.colorFormat = RenderTextureFormat.ARGB32;
            baseDescriptor.depthBufferBits = kDepthBufferBits;
            descriptor = baseDescriptor;
        }

        // This method is called before executing the render pass.
        // It can be used to configure render targets and their clear state. Also to create temporary render target textures.
        // When empty this render pass will render to the active camera render target.
        // You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
        // The render pipeline will ensure target setup and clearing happens in an performance manner.
        public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
        {
            cmd.GetTemporaryRT(depthAttachmentHandle.id, descriptor, FilterMode.Point);
            ConfigureTarget(depthAttachmentHandle.Identifier());
            ConfigureClear(ClearFlag.All, Color.black);
        }

        // Here you can implement the rendering logic.
        // Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers
        // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html
        // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.
        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
            ProfilingSampler sampler = new ProfilingSampler(m_ProfilerTag);
            using (new UnityEngine.Rendering.ProfilingScope(cmd, sampler))
            {
                context.ExecuteCommandBuffer(cmd);
                cmd.Clear();

                var sortFlags = renderingData.cameraData.defaultOpaqueSortFlags;
                // sortFlags = sortingFlags;
                var drawSettings = CreateDrawingSettings(m_ShaderTagId, ref renderingData, sortFlags);
                drawSettings.perObjectData = PerObjectData.None;


                // ref CameraData cameraData = ref renderingData.cameraData;
                // Camera camera = cameraData.camera;
                // if (cameraData.isStereoEnabled)
                //     context.StartMultiEye(camera);


                drawSettings.overrideMaterial = internalVertexColorsMaterial;


                context.DrawRenderers(renderingData.cullResults, ref drawSettings,
                    ref m_FilteringSettings);

                cmd.SetGlobalTexture("_CameraVertexColorsTexture", depthAttachmentHandle.id);
            }

            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
        }

        /// Cleanup any allocated resources that were created during the execution of this render pass.
        public override void FrameCleanup(CommandBuffer cmd)
        {
            if (depthAttachmentHandle != RenderTargetHandle.CameraTarget)
            {
                cmd.ReleaseTemporaryRT(depthAttachmentHandle.id);
                depthAttachmentHandle = RenderTargetHandle.CameraTarget;
            }
        }
    }

    VertexColorsPass vertexColorsPass;
    RenderTargetHandle vertexColorsTexture;
    [SerializeField] Material vertexColorsMaterial;
    [SerializeField] LayerMask layerMask;
    // [SerializeField] Shader vertexColorShader;

    private Material vertexMaterialCopy;
    public override void Create(){
        // try{
           vertexMaterialCopy = new Material(vertexColorsMaterial);
            // vertexColorsMaterial = CoreUtils.CreateEngineMaterial(vertexColorShader);//"Shader Graphs/VertexColor");
            // vertexColorsMaterial = CoreUtils.CreateEngineMaterial("Shader Graphs/VertexColor");
            vertexColorsPass = new VertexColorsPass(RenderQueueRange.opaque, layerMask, vertexMaterialCopy);
            vertexColorsPass.renderPassEvent = RenderPassEvent.AfterRenderingPrePasses;
            vertexColorsTexture.Init("_CameraVertexColorsTexture");
        // }catch (System.Exception){ 
        //     Debug.Log("mute boot error");
        // }
        
        
    }


    // Here you can inject one or multiple render passes in the renderer.
    // This method is called when setting up the renderer once per-camera.
    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        vertexColorsPass.Setup(renderingData.cameraData.cameraTargetDescriptor, vertexColorsTexture);
        renderer.EnqueuePass(vertexColorsPass);
    }
}

I’ve experienced this kind of shader bug in the windows build, not in the editor.
I recommend you to include your Vertex Color shader in Project Settings/ Graphics / Always Included Shaders. I am sure it will work.

Here are a few potential troubleshooting steps you can try:

Verify shader compatibility: Ensure that the shader being used for the VertexColorsFeature is compatible with the rendering pipeline (URP) and the target platform (Windows build). Some shader features or syntax may differ between different rendering pipelines or platforms, leading to unexpected behavior. Make sure the shader you’re using is compatible with URP and has the necessary functionality for the Windows build.

Check material settings: Double-check the settings of the vertexColorsMaterial being used in the VertexColorsFeature. Verify that the material properties, shaders, and textures are set correctly and compatible with URP and the Windows build.

Verify render queue and layer mask settings: Review the renderQueueRange and layerMask settings in the VertexColorsFeature. Ensure that they are correctly configured to target the desired objects and render in the correct order. Incorrect settings in these areas can lead to issues with rendering and the Vertex Color Prepass.

Test on different hardware: Try running the Windows build on different hardware configurations to determine if the issue is specific to a particular system or GPU. This can help identify if the issue is related to hardware compatibility.

Update Unity and URP: Ensure that you are using the latest version of Unity and URP. It’s possible that the issue you’re experiencing has been addressed in a newer version or through bug fixes.

Debug and log information: Add debug logs or debug draw calls in the relevant parts of the code to gather more information about the issue. This can help you pinpoint where the problem occurs and provide more context for troubleshoot

@Gearknacks Replying to your answer seems broken so imma try it this way:

Thank you so much for the detailed list of things to try! I’ll try to answer each as best I can.

Verify shader compatibility: Ensure
that the shader being used for the
VertexColorsFeature is compatible with
the rendering pipeline (URP) and the
target platform (Windows build). Some
shader features or syntax may differ
between different rendering pipelines
or platforms, leading to unexpected
behavior. Make sure the shader you’re
using is compatible with URP and has
the necessary functionality for the
Windows build.
The shader is a shadergraph that pipes the vertex color node directly into the base color of an unlit material

Check material settings: Double-check
the settings of the
vertexColorsMaterial being used in the
VertexColorsFeature. Verify that the
material properties, shaders, and
textures are set correctly and
compatible with URP and the Windows
build.

The material is generated by the scriptable render feature. (using the aforementioned shader)

Verify render queue and layer mask
settings: Review the renderQueueRange
and layerMask settings in the
VertexColorsFeature. Ensure that they
are correctly configured to target the
desired objects and render in the
correct order. Incorrect settings in
these areas can lead to issues with
rendering and the Vertex Color
Prepass.

The layermask is set to “Everything” I’ve also tried just using -1 as a layermask, same result

Test on different hardware: Try
running the Windows build on different
hardware configurations to determine
if the issue is specific to a
particular system or GPU. This can
help identify if the issue is related
to hardware compatibility.
Tried running it on a multitude of hardware.

Update Unity and URP: Ensure that you
are using the latest version of Unity
and URP. It’s possible that the issue
you’re experiencing has been addressed
in a newer version or through bug
fixes.

Using the latest LTS version of 2021.3, all packages are up to date

Debug and log information: Add debug
logs or debug draw calls in the
relevant parts of the code to gather
more information about the issue. This
can help you pinpoint where the
problem occurs and provide more
context for troubleshoot

Looking at the developer build neither the console nor the frame debugger shows a difference.

The only error happens in the profiler itself as:

Missing Profiler.EndSample (Every BeginSample call must have a subsequent EndSample call within the same frame): Vertex Color Prepass
Previous 5 samples:
	Vertex Color Prepass
	Vertex Color Prepass
	RenderLoop.CleanupNodeQueue
	RenderTexture.SetActive
	RenderLoop.CleanupNodeQueue
In the scope:
	Vertex Color Prepass
	Vertex Color Prepass
	ScriptableRenderer.Execute: UniversalRenderPipelineAsset _Renderer
	UniversalRenderPipeline.RenderSingleCamera: Camera
	Inl_ScriptableRenderContext.Submit

but a quick google confirms this is a known bug

After further experimentation the only way to get this to work in build is putting the Vertex Color Material on an object in the scene which forces unity to include it in the build.