From f25eee9cbb0f5730009945552a276767c074cca4 Mon Sep 17 00:00:00 2001 From: Alexander Johnston Date: Wed, 6 May 2026 17:11:31 +0100 Subject: [PATCH] Disable 16bit Store with RWByteAddressBuffer for SPIRV As we represent RWByteAddressBuffers in SPIRV as an array of uints we have no correct way to represent a 16bit store to the buffer. Currently we load a uint, mask values from it, write in our new 16 bits, then write to the buffer. This works for single threaded cases but if multiple threads are accessing adjacent shorts in the uint data is clobbered. This patch catches the write in Sema and errors instead of going on to produce invalid code. --- .../clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ tools/clang/lib/Sema/SemaHLSL.cpp | 12 ++++++++++++ .../rwbyteaddressbuffer-store-16bit-spirv.hlsl | 10 ++++++++++ 3 files changed, 24 insertions(+) create mode 100644 tools/clang/test/SemaHLSL/rwbyteaddressbuffer-store-16bit-spirv.hlsl diff --git a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index eaffd4ee79..c5edd7420d 100644 --- a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8069,6 +8069,8 @@ def err_hlsl_vk_pointer_cast_alignment: Error< "Vulkan buffer pointer cannot be cast to greater alignment">; def err_hlsl_vk_static_pointer_cast_type: Error< "vk::static_pointer_cast() content type must be base class of argument's content type">; +def err_hlsl_vk_rwbyteaddressbuffer_16bit_store : Error< + "RWByteAddressBuffer does not support storing 16bit types in Vulkan">; def warn_spirv_node_shaders_experimental : Warning< "SPIR-V implementation of node shaders is experimental and subject to change">; // SPIRV Change Ends diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 7df68f5a11..322cec820d 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -11332,6 +11332,18 @@ HLSLExternalSource::DeduceTemplateArgumentsForHLSL( IsBABLoad = intrinsicOp == (UINT)IntrinsicOp::MOP_Load; IsBABStore = intrinsicOp == (UINT)IntrinsicOp::MOP_Store; } +#ifdef ENABLE_SPIRV_CODEGEN + // We don't support 16 bit stores in SPIRV for RWByteAddressBuffer due to + // representing the buffer as a series of 32 bit values. + // See https://github.com/microsoft/DirectXShaderCompiler/issues/8172 + if (IsBABStore && getSema()->getLangOpts().SPIRV) { + if (getSema()->getASTContext().getIntWidth(argTypes[2]) == 16) { + getSema()->Diag(Args[1]->getLocStart(), + diag::err_hlsl_vk_rwbyteaddressbuffer_16bit_store); + return Sema::TemplateDeductionResult::TDK_Invalid; + } + } +#endif if (ExplicitTemplateArgs && ExplicitTemplateArgs->size() >= 1) { SourceLocation Loc = ExplicitTemplateArgs->getLAngleLoc(); if (!IsBABLoad && !IsBABStore) { diff --git a/tools/clang/test/SemaHLSL/rwbyteaddressbuffer-store-16bit-spirv.hlsl b/tools/clang/test/SemaHLSL/rwbyteaddressbuffer-store-16bit-spirv.hlsl new file mode 100644 index 0000000000..62572629cc --- /dev/null +++ b/tools/clang/test/SemaHLSL/rwbyteaddressbuffer-store-16bit-spirv.hlsl @@ -0,0 +1,10 @@ +// REQUIRES: spirv +// RUN: %dxc -T cs_6_2 -E main -spirv -enable-16bit-types -fcgl %s -verify + +RWByteAddressBuffer DstBuffer : register(u1); + +[numthreads(1, 1, 1)] +void main() +{ + DstBuffer.Store(0, 1); // expected-error {{RWByteAddressBuffer does not support storing 16bit types in Vulkan}} +}