Skip to content

[RenderStateCache] RSC loses non-main entry points when reserializing shaders for WebGPU PSO archives #813

Closed

Description

@hzqst

Problem

On WebGPU, RenderStateCacheImpl::SerializedPsoCIWrapperBase::SerializeShader() does not restore the actual WGSL entry point when reserializing an existing device shader for a PSO archive. The newly constructed ShaderCreateInfo therefore retains its default EntryPoint = "main", causing reflection to fail for valid shaders with other entry point names, such as vertexMain and fragmentMain.

Observed reproduction sequence

  1. Start the WebGPU backend and load the DrawTexturedRect vertex and pixel shaders from a previously saved archive.
  2. The log first reports Found ... in the archive for both shaders.
  3. During graphics PSO creation, the cache enters the branch in SerializeShader() where the shader's reference-counter owner does not expose IID_SerializedShader. It reconstructs a ShaderCreateInfo from the device shader's WGSL.
  4. The WGSL entry point is vertexMain, but the reconstructed descriptor requests the default main. Reflection fails, followed by failure to serialize the shader required by the PSO archive.

Log excerpt, with content hashes omitted:

Render state cache: Found shader 'DrawTexturedRect_vertexMain_... [...]' in the archive.
Render state cache: Found shader 'DrawTexturedRect_fragmentMain_... [...]' in the archive.
ERROR ... WGSLShaderResources.cpp, 818:
Entry point 'main' is not found in shader 'DrawTexturedRect_vertexMain_...'
ERROR ... RenderDeviceBase.hpp, 467:
Failed to create Shader 'DrawTexturedRect_vertexMain_...'
ERROR ... RenderStateCacheImpl.cpp, 604:
Failed to serialize shader 'DrawTexturedRect_vertexMain_...'.

Root cause and source locations

In RenderStateCacheImpl.cpp:566–605:

The entry point names were not lost during HLSL → SPIR-V → WGSL conversion. Inspection of the local DrawTexturedRect Vulkan SPIR-V cache shows OpEntryPoint names of vertexMain and fragmentMain. The final WebGPU WGSL artifacts also explicitly declare @vertex fn vertexMain(...) and @fragment fn fragmentMain(...). The missing information is the entry point selection in the subsequently reconstructed descriptor.

Expected and actual behavior

Expected: A valid WebGPU shader whose entry point is not named main can be added to a PSO archive while preserving its entry point selection.

Actual: Reserialization requests the default main, reports that the entry point does not exist, and then fails to serialize the shader.

The confirmed impact is failure in the shader / PSO archive serialization path. Since the implementation is shared, other WebGPU shaders with non-main entry points may also be affected; DrawTexturedRect is the observed case.

Suggested fix and regression coverage

  • Restore the actual entry point selection when reconstructing the WebGPU ShaderCreateInfo.
  • For WGSL known to contain exactly one entry point, consider setting EntryPoint = nullptr so the existing reflection logic can infer that entry point. Supporting multi-entry-point WGSL requires preserving the original selected entry point rather than unconditionally choosing the first one.
  • Add an actual WebGPU regression covering non-main VS/PS entry points → save RenderStateCache → destroy and recreate the device/cache → load the archive → create a PSO using the restored shaders, checking both PSO status and archive results.
  • Also cover device-created shaders entering the same serialization branch and compute shaders with non-main entry points.

Successful direct shader / pipeline creation alone does not exercise the reproduced archive-reload-and-reserialize path.

Activity

  1. TheMostDiligent commented on Oct 28, 2026

    @TheMostDiligent
    Contributor

    Fixed in #814

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions