microsoft / DirectXShaderCompiler

This repo hosts the source for the DirectX Shader Compiler which is based on LLVM/Clang.
Other
3.07k stars 686 forks source link

Bitfield initialization unclear #5587

Open mstrgram opened 1 year ago

mstrgram commented 1 year ago

Description It is unclear to me how to initialize a bitfield to all 0 in HLSL. It appears a simple syntax works in some cases, but not others.

Steps to Reproduce test.hlsl file contains:

RWStructuredBuffer<uint> g_Buffer : register(u1);

enum SomeEnum
{
    SomeEnum_val0,
    SomeEnum_val1,
    SomeEnum_val2,
    SomeEnum_val3
};

struct SomeBitfield
{
    SomeEnum field1 : 2;
    uint32_t rest : 30;
};

[RootSignature("UAV(u1)")]
[numthreads(1, 1, 1)]
void main(uint3 DTid : SV_DispatchThreadID)
{
    SomeBitfield val = (SomeBitfield)0;
    g_Buffer[0] = (uint)val;
}

Compile with:

dxc -T cs_6_6 -HV 2021 -E main test.hlsl

Actual Behavior You get this output:

test.hlsl:21:24: error: cannot convert from 'literal int' to 'SomeBitfield'
    SomeBitfield val = (SomeBitfield)0;

However, if I switch the order of the field1 and rest members in SomeBitfield, it seemingly works and the generated code looks correct. Is the SomeBitfield val = (SomeBitfield)0 syntax meant to be valid? If yes, it doesn't seem to work reliably. If no, how to I easily (and most efficiently) initialize all members of a bitfield to 0?

Environment

llvm-beanz commented 1 year ago

Adding a few bits of context. This is not a valid initializer in C++: https://godbolt.org/z/6T38Pv6Ka

This would be valid with C/C++ initialization rules: https://godbolt.org/z/a4E5TbrWb

In HLSL the struct gets treated as a vector initializer, which is… extremely odd.

The current workaround for HLSL would be to initialize each member: https://godbolt.org/z/7oMejaTzz

I suspect the bug here is in how HLSL flattened initializers work. We may be able to implement a hacky fix that resolves this issue but the correct long-term solution would be to adopt C/C++ initialization rules, which we have a rough feature proposal for.

mstrgram commented 1 year ago

It would be great if it was possible to do zero-initialization like C++:

SomeBitfield val = {};

But not sure if that messes with other vector intialization rules.

llvm-beanz commented 1 year ago

That would be supported if we adopted C++ initialization rules, which is my hope for the future.

damyanp commented 4 days ago

Related: https://github.com/microsoft/hlsl-specs/issues/310