diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index 19c0d75174..9a58281d4e 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -22,23 +22,27 @@ The included licenses apply to the following files: Place release notes for the upcoming release below this line and remove this line upon naming the release. Refer to previous for appropriate section names. -#### Bug Fixes - -- Fixed derivative operations being moved into divergent control flow, which - could produce incorrect results - [#8001](https://github.com/microsoft/DirectXShaderCompiler/issues/8001). -- SPIR-V: Fixed an invalid `OpSelect` being generated when optimizing for - SPIR-V 1.3 and earlier - [#8603](https://github.com/microsoft/DirectXShaderCompiler/issues/8603). - #### HLSL Language - Casting a scalar to a struct or array containing a resource is now an error instead of crashing [#6661](https://github.com/microsoft/DirectXShaderCompiler/issues/6661). +#### SPIR-V + +- Functions can now be decorated with inline SPIR-V. `[[vk::ext_capability]]` + and `[[vk::ext_extension]]` are now honored on ordinary functions + [#8616](https://github.com/microsoft/DirectXShaderCompiler/pull/8616) + [#8719](https://github.com/microsoft/DirectXShaderCompiler/pull/8719). + #### Bug Fixes +- Fixed derivative operations being moved into divergent control flow, which + could produce incorrect results + [#8001](https://github.com/microsoft/DirectXShaderCompiler/issues/8001). +- SPIR-V: Fixed an invalid `OpSelect` being generated when optimizing for + SPIR-V 1.3 and earlier + [#8603](https://github.com/microsoft/DirectXShaderCompiler/issues/8603). - Fixed internal compiler errors when a member method is called on a ray payload or on one of its fields with payload access qualifiers enabled [#6464](https://github.com/microsoft/DirectXShaderCompiler/issues/6464). diff --git a/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp b/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp index 3a88334ffc..59730ab7ef 100644 --- a/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp +++ b/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp @@ -1826,16 +1826,12 @@ SpirvFunction *DeclResultIdMapper::getOrRegisterFn(const FunctionDecl *fn) { spv::LinkageType::Export, fn->getLocation()); } - // Honor inline-SPIR-V attributes placed directly on a function. The - // entry-point path handles these only for entry functions, and the - // vk::ext_instruction path only for functions lowered to an instruction, so a - // plain function was previously skipped and these attributes silently - // dropped. These reuse the same helpers as the variable/parameter paths: - // [[vk::ext_decorate(d, ...)]] -> OpDecorate targeting the OpFunction - // [[vk::ext_capability(c)]] -> OpCapability for the module - // [[vk::ext_extension("...")]] -> OpExtension for the module - decorateWithIntrinsicAttrs(fn, spirvFunction); - registerCapabilitiesAndExtensionsForDecl(fn); + // Note: inline-SPIR-V attributes placed directly on a function + // ([[vk::ext_decorate]] / [[vk::ext_capability]] / [[vk::ext_extension]]) are + // applied in SpirvEmitter::doFunctionDecl, which excludes entry points. For + // an entry point, those attributes are consumed by the stage-variable path + // (they decorate the entry's interface variables, not its OpFunction), so + // they must not be applied to the source function here. // No need to dereference to get the pointer. Function returns that are // stand-alone aliases are already pointers to values. All other cases should diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.cpp b/tools/clang/lib/SPIRV/SpirvEmitter.cpp index f05c0d9553..180d813b2b 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.cpp +++ b/tools/clang/lib/SPIRV/SpirvEmitter.cpp @@ -1635,6 +1635,21 @@ void SpirvEmitter::doFunctionDecl(const FunctionDecl *decl) { } } + // Apply inline-SPIR-V attributes written directly on an ordinary function: + // [[vk::ext_decorate(d, ...)]] -> OpDecorate targeting the OpFunction + // [[vk::ext_capability(c)]] -> OpCapability for the module + // [[vk::ext_extension("...")]] -> OpExtension for the module + // Entry points are excluded because both are already handled for them: + // - decorations: by the stage-variable path (applied to the entry's + // interface variables) + // - capabilities/extensions: by processInlineSpirvAttributes + // Doing it here would mis-target any decorations and redundantly + // re-register capabilities/extensions. + if (!isEntry) { + declIdMapper.decorateWithIntrinsicAttrs(decl, func); + declIdMapper.registerCapabilitiesAndExtensionsForDecl(decl); + } + if (spirvOptions.debugInfoRich) { if (srcDebugFunction) { spvContext.pushDebugLexicalScope(info, srcDebugFunction); diff --git a/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.intrinsicDecorate.entry.hlsl b/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.intrinsicDecorate.entry.hlsl new file mode 100644 index 0000000000..28536668b8 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.intrinsicDecorate.entry.hlsl @@ -0,0 +1,16 @@ +// RUN: %dxc -T ps_6_0 -E main -fcgl -Vd %s -spirv | FileCheck %s --implicit-check-not "OpDecorate %src_main" + +// A function-level inline-SPIR-V decoration on an *entry point* is consumed by +// the stage-variable path and applied to the entry's interface variable, not to +// the source OpFunction. (An ordinary function is handled in another way, see +// spv.intrinsicDecorate.function.hlsl.) +// +// The --implicit-check-not above asserts the source function (%src_main) was +// not decorated by the inline assembly intended for the stage variables. + +// CHECK: OpDecorate %out_var_SV_Target Location 23 + +[[vk::ext_decorate(/* Location */ 30, 23)]] +float4 main() : SV_Target { + return 1.0; +} diff --git a/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.intrinsicDecorate.function.error.hlsl b/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.intrinsicDecorate.function.error.hlsl index 019628d34b..c209ca7d92 100644 --- a/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.intrinsicDecorate.function.error.hlsl +++ b/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.intrinsicDecorate.function.error.hlsl @@ -2,19 +2,19 @@ // vk::ext_decorate_id and vk::ext_decorate_string decorate a value-id target // and have no OpFunction-target form, so applying either to a function must be -// diagnosed rather than silently dropped. +// diagnosed rather than silently dropped. Both are placed on one function so a +// single compilation reports both (translation stops after the first function +// that errors, so separate functions would only surface one). -// CHECK: error: vk::ext_decorate_string is not supported on functions -[[vk::ext_decorate_string(/* UserTypeGOOGLE */ 5636, "myType")]] -[noinline] uint DecorateString(uint x) { return x; } - -// CHECK: error: vk::ext_decorate_id is not supported on functions +// CHECK-DAG: error: vk::ext_decorate_id is not supported on functions +// CHECK-DAG: error: vk::ext_decorate_string is not supported on functions [[vk::ext_decorate_id(/* UniformId */ 27, 13)]] -[noinline] uint DecorateId(uint x) { return x; } +[[vk::ext_decorate_string(/* UserTypeGOOGLE */ 5636, "myType")]] +[noinline] uint Decorated(uint x) { return x; } RWStructuredBuffer buf; [numthreads(1, 1, 1)] void main(uint3 tid : SV_DispatchThreadID) { - buf[0] = DecorateString(tid.x) + DecorateId(tid.x); + buf[0] = Decorated(tid.x); } diff --git a/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.intrinsicDecorate.hlsl b/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.intrinsicDecorate.hlsl index 9e69257956..3380d855ab 100644 --- a/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.intrinsicDecorate.hlsl +++ b/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.intrinsicDecorate.hlsl @@ -1,4 +1,8 @@ -// RUN: %dxc -T ps_6_0 -E main -fcgl -Vd -spirv -fcgl %s -spirv | FileCheck %s +// RUN: %dxc -T ps_6_0 -E main -fcgl -Vd -spirv -fcgl %s -spirv | FileCheck %s --implicit-check-not "OpDecorate %src_main" + +// The --implicit-check-not above asserts the entry's source function is not +// decorated by [[vk::ext_decorate]] (e.g. Location 23 below) intended for the +// interface variable. [[vk::ext_decorate(1, 0)]] bool b0;