diff --git a/clang/docs/HLSL/ResourceTypes.rst b/clang/docs/HLSL/ResourceTypes.rst index 4309435cf14f0..e2a2d86f1346a 100644 --- a/clang/docs/HLSL/ResourceTypes.rst +++ b/clang/docs/HLSL/ResourceTypes.rst @@ -9,23 +9,50 @@ Introduction ============ HLSL Resources are runtime-bound data that is provided as input, output or both -to shader programs written in HLSL. Resource Types in HLSL provide key user -abstractions for reading and writing resource data. +to shader programs written in HLSL. These appear in HLSL source as instances of +special classes like `RWByteAddressBuffer`_, `ConstantBuffer`_, `Texture3D`_, +and `RasterizerOrderedTexture2D`_. They provide key user abstractions for +reading and writing resource data. + +.. _RWByteAddressBuffer: https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-rwbyteaddressbuffer +.. _ConstantBuffer: https://learn.microsoft.com/en-us/windows/win32/direct3d12/resource-binding-in-hlsl#constant-buffers +.. _Texture3D: https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-texture3d +.. _RasterizerOrderedTexture2D: https://learn.microsoft.com/en-us/windows/win32/direct3d11/rasterizer-order-views Implementation Details ====================== -In Clang resource types are forward declared by the ``HLSLExternalSemaSource`` -on initialization. They are then lazily completed when ``requiresCompleteType`` -is called later in Sema. - -Resource types are classes that have the "intangible" resource handle type, -`__hlsl_resource_t`, as a member. These are generally templated class -declarations that specify the type of data that can be loaded from or stored -into the resource. The handle is annotated with hlsl-specific attributes -describing properties of the resource. Member functions of a resource type are -generally fairly simple wrappers around builtins that operate on the handle -member. +Clang's implementation of the HLSL resource types is designed to allow for a +future version where the individual classes are implemented directly as HLSL in +a library. However, this isn't possible today as they rely on some features, +such as constructors, that are explicitly disallowed in HLSL user code. Because +of this, these types are forward declared by the ``HLSLExternalSemaSource`` on +initialization. They are then lazily completed when ``requiresCompleteType`` is +called later in Sema. + +A class is a resource if it contains a member of the ``__hlsl_resource_t`` +type, which represents a "intangible resource handle". This resource handle +type is annotated with various attributes to describe what type of resource it +is and what can be done with it. + +- ``hlsl::resource_class(C)``: Given ``C`` in ``"SRV"``, ``"UAV"``, + ``"CBuffer"``, or ``"Sampler"``, mark the resource as a shader resource view, + unordered access view, constant buffer, or sampler, respectively. +- ``hlsl::contained_type(T)``: Given a type ``T``, specify the type of objects + contained in the resource. +- ``hlsl::dimension(K)``: Given ``K`` in ``"Unknown"``, ``"1D"``, ``"2D"``, + ``"3D"``, or ``"Cube"``, mark the resource as having the given dimensions. +- ``hlsl::is_array``: Specify that the resource is an array of objects of the + given dimensions. +- ``hlsl::raw_buffer``: Specify that the resource is accessed as a raw buffer, + rather than following the typed buffer alignment and offset rules. +- ``hlsl::is_ms``: Specify that the resource is multisampled. +- ``hlsl::is_rov``: Specify that the resource is a rasterizer ordered view. +- ``hlsl::is_counter``: Specify that this is a counter associated with another + resource. + +Member functions of a resource class are generally fairly simple wrappers +around builtins that operate on the handle member. During code generation resource types are lowered to target extension types in IR. These types are target specific and differ between DXIL and SPIR-V diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 39c672322d515..6baacd294f9bd 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4709,7 +4709,7 @@ def HLSLControlFlowHint: StmtAttr { let Subjects = SubjectList<[IfStmt, SwitchStmt], ErrorDiag, "'if' and 'switch' statements">; let LangOpts = [HLSL]; - let Documentation = [InternalOnly]; + let Documentation = [HLSLControlFlowHintDocs]; } def CapturedRecord : InheritableAttr { @@ -5200,24 +5200,6 @@ def HLSLShader : InheritableAttr { }]; } -def HLSLIsArray : TypeAttr { - let Spellings = [CXX11<"hlsl", "is_array">]; - let LangOpts = [HLSL]; - let Documentation = [InternalOnly]; -} - -def HLSLIsMultiSampled : TypeAttr { - let Spellings = [CXX11<"hlsl", "is_ms">]; - let LangOpts = [HLSL]; - let Documentation = [InternalOnly]; -} - -def HLSLROV : TypeAttr { - let Spellings = [CXX11<"hlsl", "is_rov">]; - let LangOpts = [HLSL]; - let Documentation = [InternalOnly]; -} - def HLSLResourceClass : TypeAttr { let Spellings = [CXX11<"hlsl", "resource_class">]; let LangOpts = [HLSL]; @@ -5226,7 +5208,7 @@ def HLSLResourceClass : TypeAttr { /*is_string=*/true, ["SRV", "UAV", "CBuffer", "Sampler"], ["SRV", "UAV", "CBuffer", "Sampler"], /*opt=*/0, /*fake=*/0, /*isExternalType=*/1>]; - let Documentation = [InternalOnly]; + let Documentation = [HLSLResourceClassDocs]; } def HLSLResourceDimension : TypeAttr { @@ -5237,26 +5219,44 @@ def HLSLResourceDimension : TypeAttr { /*is_string=*/true, ["Unknown", "1D", "2D", "3D", "Cube"], ["Unknown", "Dim1D", "Dim2D", "Dim3D", "Cube"], /*opt=*/0, /*fake=*/0, /*isExternalType=*/1>]; - let Documentation = [InternalOnly]; + let Documentation = [HLSLResourceDimensionDocs]; } def HLSLContainedType : TypeAttr { let Spellings = [CXX11<"hlsl", "contained_type">]; let LangOpts = [HLSL]; let Args = [TypeArgument<"Type", /*opt=*/0>]; - let Documentation = [InternalOnly]; + let Documentation = [HLSLContainedTypeDocs]; } def HLSLRawBuffer : TypeAttr { let Spellings = [CXX11<"hlsl", "raw_buffer">]; let LangOpts = [HLSL]; - let Documentation = [InternalOnly]; + let Documentation = [HLSLRawBufferDocs]; +} + +def HLSLIsArray : TypeAttr { + let Spellings = [CXX11<"hlsl", "is_array">]; + let LangOpts = [HLSL]; + let Documentation = [HLSLIsArrayDocs]; +} + +def HLSLIsMultiSampled : TypeAttr { + let Spellings = [CXX11<"hlsl", "is_ms">]; + let LangOpts = [HLSL]; + let Documentation = [HLSLIsMultiSampledDocs]; +} + +def HLSLIsROV : TypeAttr { + let Spellings = [CXX11<"hlsl", "is_rov">]; + let LangOpts = [HLSL]; + let Documentation = [HLSLIsROVDocs]; } def HLSLIsCounter : TypeAttr { let Spellings = [CXX11<"hlsl", "is_counter">]; let LangOpts = [HLSL]; - let Documentation = [InternalOnly]; + let Documentation = [HLSLIsCounterDocs]; } def HLSLGroupSharedAddressSpace : TypeAttr { diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 05e4cb0870652..8e38705ef561c 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -8995,6 +8995,31 @@ for details. }]; } +def HLSLControlFlowHintDocs : Documentation { + let Category = DocCatStmt; + let Heading = "branch, flatten"; + let Content = [{ + +The ``branch`` and ``flatten`` attributes can be applied to *if* and *switch* +statements in the HLSL language mode to provide hints for how the backend +should execute them. + +- ``branch`` means that control flow is preferred. The condition should be + evaluated first and we should only execute the block guarded by it. + +- ``flatten`` means that control flow should be avoided. All blocks should be + executed and variables that are modified should be conditionally assigned. + +These control flow hints are preserved through the compilation and emitted in a +backend-specific way. + +For details, see the Direct3D documentation for `if Statement`_ and `switch Statement`_. + +.. _`if Statement`: https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-if +.. _`switch Statement`: https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-switchhttps://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-switch + }]; +} + def AtomicDocs : Documentation { let Category = DocCatStmt; let Content = [{ @@ -9088,6 +9113,120 @@ The full documentation is available here: https://learn.microsoft.com/en-us/wind }]; } +def HLSLResourceClassDocs : Documentation { + let Category = DocCatType; + let Content = [{ +The ``hlsl::resource_class`` attribute specifies the resource class of the HLSL +resource represented by a member variable of type ``__hlsl_resource_t``, +declaring it to be an SRV, UAV, CBuffer, or Sampler resource. + +This attribute is only valid for resource handles, and is an implementation +detail of clang's HLSL implementation. For more information see `HLSL Resource +Types`_ + +.. _`HLSL Resource Types`: https://clang.llvm.org/docs/HLSL/ResourceTypes.html> + }]; +} + +def HLSLResourceDimensionDocs : Documentation { + let Category = DocCatType; + let Content = [{ +The ``hlsl::dimension`` attribute specifies the dimensions of the HLSL resource +represented by a member variable of type ``__hlsl_resource_t``, declaring the +resource to have Unknown, 1D, 2D, 3D, or Cube dimension. + +This attribute is only valid for resource handles, and is an implementation +detail of clang's HLSL implementation. For more information see `HLSL Resource +Types`_ + +.. _`HLSL Resource Types`: https://clang.llvm.org/docs/HLSL/ResourceTypes.html> + }]; +} + +def HLSLContainedTypeDocs : Documentation { + let Category = DocCatType; + let Content = [{ +The ``hlsl::contained_type`` attribute specifies the type of the HLSL resource +represented by a member variable of type ``__hlsl_resource_t``. + +This attribute is only valid for resource handles, and is an implementation +detail of clang's HLSL implementation. For more information see `HLSL Resource +Types`_ + +.. _`HLSL Resource Types`: https://clang.llvm.org/docs/HLSL/ResourceTypes.html> + }]; +} + +def HLSLRawBufferDocs : Documentation { + let Category = DocCatType; + let Content = [{ +The ``hlsl::raw_buffer`` attribute specifies that the HLSL resource represented +by a member variable of type ``__hlsl_resource_t`` has raw buffer semantics. + +This attribute is only valid for resource handles, and is an implementation +detail of clang's HLSL implementation. For more information see `HLSL Resource +Types`_ + +.. _`HLSL Resource Types`: https://clang.llvm.org/docs/HLSL/ResourceTypes.html> + }]; +} + +def HLSLIsArrayDocs : Documentation { + let Category = DocCatType; + let Content = [{ +The ``hlsl::is_array`` attribute specifies that the HLSL resource represented +by a member variable of type ``__hlsl_resource_t`` has array dimensions. + +This attribute is only valid for resource handles, and is an implementation +detail of clang's HLSL implementation. For more information see `HLSL Resource +Types`_ + +.. _`HLSL Resource Types`: https://clang.llvm.org/docs/HLSL/ResourceTypes.html> + }]; +} + +def HLSLIsMultiSampledDocs : Documentation { + let Category = DocCatType; + let Content = [{ +The ``hlsl::is_array`` attribute specifies that the HLSL resource represented +by a member variable of type ``__hlsl_resource_t`` is multisampled. + +This attribute is only valid for resource handles, and is an implementation +detail of clang's HLSL implementation. For more information see `HLSL Resource +Types`_ + +.. _`HLSL Resource Types`: https://clang.llvm.org/docs/HLSL/ResourceTypes.html> + }]; +} + +def HLSLIsROVDocs : Documentation { + let Category = DocCatType; + let Content = [{ +The ``hlsl::is_rov`` attribute specifies that the HLSL resource represented by +a member variable of type ``__hlsl_resource_t`` is a rasterizer ordered view. + +This attribute is only valid for resource handles, and is an implementation +detail of clang's HLSL implementation. For more information see `HLSL Resource +Types`_ + +.. _`HLSL Resource Types`: https://clang.llvm.org/docs/HLSL/ResourceTypes.html> + }]; +} + +def HLSLIsCounterDocs : Documentation { + let Category = DocCatType; + let Content = [{ +The ``hlsl::is_counter`` attribute specifies that the HLSL resource represented +by a member variable of type ``__hlsl_resource_t`` is a counter buffer. + +This attribute is only valid for resource handles, and is an implementation +detail of clang's HLSL implementation. For more information see `HLSL Resource +Types`_ + +.. _`HLSL Resource Types`: https://clang.llvm.org/docs/HLSL/ResourceTypes.html> + }]; +} + def HLSLGroupSharedAddressSpaceDocs : Documentation { let Category = DocCatVariable; let Content = [{ diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 60964d2859790..4b1346a62975f 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -2025,7 +2025,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, llvm_unreachable("BTFTypeTag attribute handled separately"); case attr::HLSLResourceClass: - case attr::HLSLROV: + case attr::HLSLIsROV: case attr::HLSLRawBuffer: case attr::HLSLContainedType: case attr::HLSLIsCounter: diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index 929e8bc824afa..5c17f0ebf6fdc 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -1168,7 +1168,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addResourceMember( QualType AttributedResTy = QualType(); SmallVector Attrs = { HLSLResourceClassAttr::CreateImplicit(Ctx, RC), - IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr, + IsROV ? HLSLIsROVAttr::CreateImplicit(Ctx) : nullptr, RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr, RD != ResourceDimension::Unknown ? HLSLResourceDimensionAttr::CreateImplicit(Ctx, RD) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index c353c3fec3f62..760b3dcd718a2 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -2140,7 +2140,7 @@ bool clang::CreateHLSLAttributedResourceType( HasResourceDimension = true; break; } - case attr::HLSLROV: + case attr::HLSLIsROV: if (ResAttrs.IsROV) { S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A; return false; @@ -2277,8 +2277,8 @@ bool SemaHLSL::handleResourceTypeAttr(QualType T, const ParsedAttr &AL) { break; } - case ParsedAttr::AT_HLSLROV: - A = HLSLROVAttr::Create(getASTContext(), ACI); + case ParsedAttr::AT_HLSLIsROV: + A = HLSLIsROVAttr::Create(getASTContext(), ACI); break; case ParsedAttr::AT_HLSLRawBuffer: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index dc3564c8b17fd..133e8234a247e 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -9353,7 +9353,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, } case ParsedAttr::AT_HLSLResourceClass: case ParsedAttr::AT_HLSLResourceDimension: - case ParsedAttr::AT_HLSLROV: + case ParsedAttr::AT_HLSLIsROV: case ParsedAttr::AT_HLSLRawBuffer: case ParsedAttr::AT_HLSLIsArray: case ParsedAttr::AT_HLSLIsMultiSampled: