From ec46355121b3487980334b910fd0a3d70eedcd02 Mon Sep 17 00:00:00 2001 From: Steven Perron Date: Tue, 19 Nov 2024 11:16:21 -0500 Subject: [PATCH 1/3] [NNNN] Design for inline SPIR-V function attributes This add the design for the following attributes for inline SPIR-V: ``` vk::ext_instruction(uint opcode, [string extended_instruction_set]) vk::ext_execution_mode(uint execution_mode, ...) vk::ext_extension(string extension_name) vk::ext_capability(uint capability) vk::ext_reference vk::ext_literal ``` See the inline SPIR-V documentation in DXC for details of what they do. https://github.com/microsoft/DirectXShaderCompiler/wiki/GL_EXT_spirv_intrinsics-for-SPIR-V-code-gen --- .../NNNN-inline-spirv-function-attributes.md | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 proposals/NNNN-inline-spirv-function-attributes.md diff --git a/proposals/NNNN-inline-spirv-function-attributes.md b/proposals/NNNN-inline-spirv-function-attributes.md new file mode 100644 index 0000000..2e16e91 --- /dev/null +++ b/proposals/NNNN-inline-spirv-function-attributes.md @@ -0,0 +1,74 @@ + + +# Inline SPIR-V function attributes + +* Proposal: [NNNN](NNNN-inline-spirv-function-attributes.md) +* Author(s): [Steven Perron](https://github.com/s-perron) +* Status: **Design In Progress** + +*During the review process, add the following fields as needed:* + +* PRs: [#NNNN](https://github.com/llvm/llvm-project/pull/NNNN) +* Issues: [#NNNN](https://github.com/llvm/llvm-project/issues/NNNN) +* Posts: [LLVM Discourse](https://discourse.llvm.org/) + +## Introduction + +The inline SPIR-V extension to HLSL allows users to use most SPIR-V features +without a new compiler release. This allows vendors to quickly deploy extensions +without the overhead of upstreaming changes to the main compiler, enabling +faster iteration and hardware support. + +One part of inline SPIR-V is a series of attributes that apply to functions, and +they should be implemented in clang. + +## Motivation + +The inline SPIR-V feature defines 6 attributes that attach to function or +function parameters: + +```hlsl +vk::ext_instruction(uint opcode, [string extended_instruction_set]) +vk::spvexecutionmode(uint execution_mode, ...) +vk::ext_extension(string extension_name) +vk::ext_capability(uint capability) +vk::ext_reference +vk::ext_literal +``` + +They enable vendors to enable a new hardware features to be defined in header +file. This reduces technical debt in the compiler by delegating +extension-specific logic to an HLSL header file separate from the compiler. It +also allows faster release of hardware features because users do not have to +wait for a new version of the compiler to be released. + +## Proposed solution + +The `vk::ext_instruction`, `vk:spvexecutionmode`, `vk::ext_capability`, and +`vk::ext_extension` will become target attributes on the functions to which they +apply. Then the backend can generate the appropriate SPIR-V. Note that +`vk::ext_capability` and `vk::ext_extension` can apply to variables and type +aliases, but that will be part of another proposal. The `vk::literal` attribute +will be turned in to a target attribute on the function parameter. + +The `vk::ext_reference` attribute can be handled in Clang but changing the type +in the AST to a reference type. TODO: Need to figure out how address spaces work +with this. + +The following table explains which target attribute each HLSL attribute will +correspond to, and how it will be interpreted in the backend. + +HLSL Attribute | Applicable to | llvm-ir target attribute | Attribute Description +--------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------ | --------------------- +`vk::ext_instruction(uint opcode, [string extended_instruction_set])` | Function declarations with no definition. | `"spv.ext_instruction"=","` | Calls to functions with this attribute are replaced by a single SPIR-V instruction.
If `` is the empty string, then it will generate the core SPIR-V instruction with the given opcode.
Otherwise, it will create an `OpExtInst` instruction, where the instruction is `` in the given instruction set. +`vk::spvexecutionmode(uint execution_mode, ...)` | Entry point functions | `"spv.executionmode"=":..."` | For each execution mode, a separate `OpExecuteMode` instruction is generated with the given operands. The operands are interpreted as literal integers. +`vk::ext_extension(string extension_name)` | Applicable to entry point functions and functions with `vk::ext_instruction`. | `"spv.extextension"=",,..."` | A separate `OpExtension` instruction is added for each extension name. The extension is added to the list of allowed extensions in the SPIR-V backend. +`vk::ext_capability(uint capability)` | Applicable to entry point functions and functions with `vk::ext_instruction`. | `"spv.extcapability"=": ..."` | A separate `OpCapability` instruction is added for each capability. The capability is added to the list of allowed capabilities in the SPIR-V backend. +`vk::ext_literal` | Parameters of functions with `vk::ext_instruction` | `"spv.literal"` | The parameter is encoded as a literal in the SPIR-V instruction instead of generating an `OpConstant`. +`vk::ext_reference` | Parameters of functions with `vk::ext_instruction` | N/A (handled in Clang) | The parameter's type is modified to a reference type in the Clang AST. (Address space handling needs further investigation.) + +## Detailed design + +## Alternatives considered (Optional) + + From 58f8f7d404eb9acf0a7bb9d4aabe5de2e2bb3fa6 Mon Sep 17 00:00:00 2001 From: Steven Perron Date: Thu, 28 Nov 2024 11:36:10 -0500 Subject: [PATCH 2/3] Add alternatives --- .../NNNN-inline-spirv-function-attributes.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/proposals/NNNN-inline-spirv-function-attributes.md b/proposals/NNNN-inline-spirv-function-attributes.md index 2e16e91..2f27c1f 100644 --- a/proposals/NNNN-inline-spirv-function-attributes.md +++ b/proposals/NNNN-inline-spirv-function-attributes.md @@ -67,8 +67,33 @@ HLSL Attribute | Applicab `vk::ext_literal` | Parameters of functions with `vk::ext_instruction` | `"spv.literal"` | The parameter is encoded as a literal in the SPIR-V instruction instead of generating an `OpConstant`. `vk::ext_reference` | Parameters of functions with `vk::ext_instruction` | N/A (handled in Clang) | The parameter's type is modified to a reference type in the Clang AST. (Address space handling needs further investigation.) +TODO: Discuss optimizations. + ## Detailed design ## Alternatives considered (Optional) +When implementing the extension and capability attributes, they could be +represented as a target type: `target("spv.capability", )` and +`target("spv.extension.")`. We could then have some way of add these as +extra parameter to the function. This is not a desirable solution for functions +because it is less straight forward. The llvm-ir will be harder to read, and the +code to generate the function will contain code that does not follow common code +patterns. + +Another alternative is to add metadata nodes that contain this information. The +OpenCL FE uses metadata to pass information to the SPIR-V backend. One example +is the `spirv.Decorations` metadata nodes to adding decorations to values. We +chose not to use metadata because metadata is supposed to "convey extra +information about the code to the optimizers and code generator." However, these +attributes do not represent extra information. Instead, they are information +necessary for the code-generator to generate correct code. The information +cannot be dropped. + +Extensions and capabilities are module level information. It would be possible +to encode them as named metadata attached to the module, which cannot be +dropped. That could work, but we want to retain the connection between the +extensions and capabilities with the function or type so that the backend can +avoid generating them if the function or type is unused. + From 7b8e6146f4679f717f227c1f3a9bc9410371526f Mon Sep 17 00:00:00 2001 From: Steven Perron Date: Thu, 28 Nov 2024 13:08:11 -0500 Subject: [PATCH 3/3] Make vk::literal a target type. --- .../NNNN-inline-spirv-function-attributes.md | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/proposals/NNNN-inline-spirv-function-attributes.md b/proposals/NNNN-inline-spirv-function-attributes.md index 2f27c1f..9c3d144 100644 --- a/proposals/NNNN-inline-spirv-function-attributes.md +++ b/proposals/NNNN-inline-spirv-function-attributes.md @@ -48,8 +48,13 @@ The `vk::ext_instruction`, `vk:spvexecutionmode`, `vk::ext_capability`, and `vk::ext_extension` will become target attributes on the functions to which they apply. Then the backend can generate the appropriate SPIR-V. Note that `vk::ext_capability` and `vk::ext_extension` can apply to variables and type -aliases, but that will be part of another proposal. The `vk::literal` attribute -will be turned in to a target attribute on the function parameter. +aliases, but that will be part of another proposal. + +In Sema, paramters with the `vk::literal` attribute will be converted to a +parameter of type `target(spirv.inline.literal, )`, and the parameter passed +it is `zeroinitializer`. The SPIR-V backend will set the corresponding operand +in the `vk::ext_instruction` with the literal `N`. The value of the parameter is +ignored. The `vk::ext_reference` attribute can be handled in Clang but changing the type in the AST to a reference type. TODO: Need to figure out how address spaces work @@ -58,14 +63,14 @@ with this. The following table explains which target attribute each HLSL attribute will correspond to, and how it will be interpreted in the backend. -HLSL Attribute | Applicable to | llvm-ir target attribute | Attribute Description ---------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------ | --------------------- -`vk::ext_instruction(uint opcode, [string extended_instruction_set])` | Function declarations with no definition. | `"spv.ext_instruction"=","` | Calls to functions with this attribute are replaced by a single SPIR-V instruction.
If `` is the empty string, then it will generate the core SPIR-V instruction with the given opcode.
Otherwise, it will create an `OpExtInst` instruction, where the instruction is `` in the given instruction set. -`vk::spvexecutionmode(uint execution_mode, ...)` | Entry point functions | `"spv.executionmode"=":..."` | For each execution mode, a separate `OpExecuteMode` instruction is generated with the given operands. The operands are interpreted as literal integers. -`vk::ext_extension(string extension_name)` | Applicable to entry point functions and functions with `vk::ext_instruction`. | `"spv.extextension"=",,..."` | A separate `OpExtension` instruction is added for each extension name. The extension is added to the list of allowed extensions in the SPIR-V backend. -`vk::ext_capability(uint capability)` | Applicable to entry point functions and functions with `vk::ext_instruction`. | `"spv.extcapability"=": ..."` | A separate `OpCapability` instruction is added for each capability. The capability is added to the list of allowed capabilities in the SPIR-V backend. -`vk::ext_literal` | Parameters of functions with `vk::ext_instruction` | `"spv.literal"` | The parameter is encoded as a literal in the SPIR-V instruction instead of generating an `OpConstant`. -`vk::ext_reference` | Parameters of functions with `vk::ext_instruction` | N/A (handled in Clang) | The parameter's type is modified to a reference type in the Clang AST. (Address space handling needs further investigation.) +HLSL Attribute | Applicable to | llvm-ir | Attribute Description +--------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | --------------------- +`vk::ext_instruction(uint opcode, [string extended_instruction_set])` | Function declarations with no definition. | Target attribute `"spv.ext_instruction"=","` | Calls to functions with this attribute are replaced by a single SPIR-V instruction.
If `` is the empty string, then it will generate the core SPIR-V instruction with the given opcode.
Otherwise, it will create an `OpExtInst` instruction, where the instruction is `` in the given instruction set. +`vk::spvexecutionmode(uint execution_mode, ...)` | Entry point functions | Target attribute `"spv.executionmode"=":..."` | For each execution mode, a separate `OpExecuteMode` instruction is generated with the given operands. The operands are interpreted as literal integers. +`vk::ext_extension(string extension_name)` | Applicable to entry point functions and functions with `vk::ext_instruction`. | Target attribute `"spv.extextension"=",,..."` | A separate `OpExtension` instruction is added for each extension name. The extension is added to the list of allowed extensions in the SPIR-V backend. +`vk::ext_capability(uint capability)` | Applicable to entry point functions and functions with `vk::ext_instruction`. | Target attribute `"spv.extcapability"=": ..."` | A separate `OpCapability` instruction is added for each capability. The capability is added to the list of allowed capabilities in the SPIR-V backend. +`vk::ext_literal` | Parameters of functions with `vk::ext_instruction` | Target type `"spirv.inline.literal"` | The parameter's type becomes the `spirv.inline.literal` target type, and the operand of the target type is the value of the parameter. +`vk::ext_reference` | Parameters of functions with `vk::ext_instruction` | N/A (handled in Clang) | The parameter's type is modified to a reference type in the Clang AST. (Address space handling needs further investigation.) TODO: Discuss optimizations.