microsoft / microsoft/DirectXShaderCompiler

[SPIR-V] DXC crashes during the internal `spirv-opt` validation pass.

Open
#8,861 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug needs-triage spirv
Dominant language
C++
Stars
3.7k
Forks
900
Avg merge
2d 11h
Merged PRs (30d)
44

Description

Description
When compiling an HLSL compute shader to SPIR-V targeting Vulkan 1.1 environment, DXC crashes during the internal spirv-opt validation pass.

The crash occurs when custom explicit SPIR-V opcodes mapping via [vk::ext_instruction(333)] is combined with standard wave control-flow builtins like WaveIsFirstLane() and WaveReadLaneFirst() interacting with an indexed structured buffer array parameter. The internal optimizer emits a malformed instruction length header for sub-group instructions, leading to validation termination.

Compiler Flags used:

-T cs_6_6 -spirv -fspv-target-env=vulkan1.1 -E main

Steps to Reproduce
source hlsl:

struct DrawIndexedIndirectCommand
{
	uint indexCount;
	uint instanceCount;
	uint firstIndex;
	int vertexOffset;
	uint firstInstance;
};

struct CBData
{
	uint numInstanceObjects;
};

cbuffer CBuffer
{
	CBData cbData;
};
[[vk::binding(1, 0)]] RWStructuredBuffer<DrawIndexedIndirectCommand> numObjects : register(u0);
[[vk::binding(2, 0)]] RWStructuredBuffer<uint> instanceId : register(u1);

[[vk::ext_instruction(333)]]
uint subgroup_add(uint scope, uint operation, uint value);
#define WavePrefixCountBits(visible_bool) subgroup_add(3, 1, uint(visible_bool))
#define WaveActiveCountBits(visible_bool) subgroup_add(3, 0, uint(visible_bool))

inline float SignedDistanceToPoint(in float4 plane, in float3 p)
{
	return dot(plane.xyz, p) + plane.w;
}

[numthreads(32, 1, 1)]
void main(uint3 DTid : SV_DispatchThreadID, uint group_index : SV_GroupIndex)
{
	uint index = DTid.x;
	if (index >= cbData.numInstanceObjects)
	{
		return;
	}
	bool visible = (index % 2u) == 0u;
	uint local_index = WavePrefixCountBits(visible);
	uint wave_count = WaveActiveCountBits(visible);
	uint wave_offset = 0;
	if (wave_count && WaveIsFirstLane())
	{
		InterlockedAdd(numObjects[0].instanceCount, wave_count, wave_offset);
	}
	wave_offset = WaveReadLaneFirst(wave_offset);
	if (visible)
	{
		instanceId[wave_offset + local_index] = index;
	}
}

Actual Behavior
fatal error: failed to optimize SPIR-V: Invalid instruction OpGroupNonUniformElect starting at word 1707: expected no more operands after 4 words, but stated word count is 6.
note: please file a bug report on https://github.com/Microsoft/DirectXShaderCompiler/issues with source code if possible

Compiler returned: 5

Environment

  • DXC version trunk, 1.10.2605.24, last version, 1.9(5402-0d3ee6b5)(1.9.0.5402) - 1.9.0.5402 (0d3ee6b55-dirty)
  • Windows 11

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the supplied HLSL reproducer with DXC using the listed Vulkan 1.1 and SPIR-V flags, then inspect the SPIR-V optimization and validation path for the malformed OpGroupNonUniformElect instruction. Done means the reproducer compiles without the internal spirv-opt failure and produces valid SPIR-V.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers, computer-graphics
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.