DirectXShaderCompiler icon indicating copy to clipboard operation
DirectXShaderCompiler copied to clipboard

[SPIR-V] Fatal error with validation on using bitfield uint64_t

Open deprilula28 opened this issue 1 year ago • 3 comments

Description

When using a shader with bitfield structs and uint64_t, getting invalid SPIR-V and failing.

Steps to Reproduce

For example, when using the following struct:

struct TransferRequest
{
    // This represents a transfer command/request
    uint64_t srcAddr;
    uint64_t dstAddr;
    uint64_t srcIndexAddr; // IOTA default
    uint64_t dstIndexAddr; // IOTA default
    uint64_t elementCount : 35; // allow up to 64GB IGPUBuffers
    uint64_t propertySize : 24; // all the leftover bits (just use bytes now)
    uint64_t fill;
    // 0=uint8, 1=uint16, 2=uint32, 3=uint64
    uint64_t srcIndexSizeLog2 : 2;
    uint64_t dstIndexSizeLog2 : 2;
};

And trying to set values to it.

(Error happens on this shader code: https://github.com/Devsh-Graphics-Programming/Nabla/tree/adc4d576d034b3e1fb31356645c0a0915beee817/include/nbl/builtin/hlsl/property_pool)

Actual Behavior Invalid SPIR-V causing fatal error on validation.

fatal error: generated SPIR-V is invalid: [VUID-StandaloneSpirv-Base-04781] Expected 32-bit int type for Base operand: BitFieldInsert
%58 = OpBitFieldInsert %ulong %42 %57 %uint_0 %uint_35

Environment

  • DXC version: From commit 7d2f9c74d53dcbb9de4e148b68c99e5986875be6
  • Host Operating System: Windows 11 version 22H2 build 22621.3155

deprilula28 avatar Feb 19 '24 17:02 deprilula28

Minimal reproducible example: https://godbolt.org/z/86j5fcKGf

cassiebeckley avatar Feb 20 '24 18:02 cassiebeckley

I think this might actually be a spirv-val error. If I'm reading https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpBitFieldInsert correctly OpBitFieldInsert is allowed to have a result type of any scalar or vector integer type, and base and insert must have the same type. There's nothing stating that it must have a specific bit width. I'll double check with some of the people who work on spirv-val.

cassiebeckley avatar Feb 20 '24 18:02 cassiebeckley

Okay, so apparently SPIR-V allows it for OpenCL but not for Vulkan. Looks like we'll have to update DXC to split the 64-bit int into two 32-bit ints before doing OpBitFieldInsert.

cassiebeckley avatar Feb 20 '24 19:02 cassiebeckley

Okay, so apparently SPIR-V allows it for OpenCL but not for Vulkan. Looks like we'll have to update DXC to split the 64-bit int into two 32-bit ints before doing OpBitFieldInsert.

Strange cause GL allows any type https://registry.khronos.org/OpenGL-Refpages/gl4/html/bitfieldInsert.xhtml

Hello!

The limitation comes from Vulkan: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/StandaloneSpirv.html

VUID-StandaloneSpirv-Base-04781
The Base operand of any OpBitCount, OpBitReverse, OpBitFieldInsert, OpBitFieldSExtract, or OpBitFieldUExtract instruction must be a 32-bit integer scalar or a vector of 32-bit integers

We should be able to support uint64_t with some shifts/bitwise to extract a 32bit value to insert the field in.

Keenuts avatar Mar 29 '24 13:03 Keenuts

oof, Vulkan cutting away regular OpenGL features strikes again!