https://github.com/shader-slang/slang
Raw File
Tip revision: 5902acdabc4445a65741a7a6a3a95f223e301059 authored by Yong He on 23 January 2024, 07:19:40 UTC
[LSP] Fetch configs directly from didConfigurationChanged message. (#3478)
Tip revision: 5902acd
slang-hlsl-to-vulkan-layout-options.h
// slang-hlsl-to-vulkan-layout-options.h
#ifndef SLANG_HLSL_TO_VULKAN_LAYOUT_OPTIONS_H
#define SLANG_HLSL_TO_VULKAN_LAYOUT_OPTIONS_H

#include "../core/slang-basic.h"
#include "../core/slang-name-value.h"

namespace Slang
{

/*
For support features similar to described here..

https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#descriptors

Options that allow for infering Vulkan bindings based on HLSL register bindings
  */
struct HLSLToVulkanLayoutOptions : public RefObject
{
public:

    static const Index kInvalidShift = Index(0x80000000);

        /// For holding combination of set and index for binding
    struct Binding
    {
        bool isSet() const { return set >= 0 && index >= 0;}
        void reset() { set = -1; index = -1; }
        bool isInvalid() const { return !isSet(); }

        Index set = -1;
        Index index = -1;
    };

    // https://github.com/KhronosGroup/glslang/wiki/HLSL-FAQ
    // {b|s|t|u} 
    enum class Kind
    {
        Invalid = -1,

            /// Unordered access view (u) 
            ///
            /// RWByteAddressBuffer/RWStructuredBuffer
            /// Append/ConsumeStructuredBuffer
            /// RWBuffer
            /// RWTextureXD/Array
        UnorderedAccess = 0,    

            /// Sampler (s)
            ///
            /// SamplerXD
            /// SamplerState/SamplerComparisonState
        Sampler,

            /// Shader Resource (t)
            ///
            /// TextureXD/Array
            /// ByteAddressBuffer/StructuredBuffer/Buffer/TBuffer
        ShaderResource,            

            /// Constant buffer (b)
            /// 
            /// ConstantBufferViews, CBuffer
        ConstantBuffer,     

        CountOf,
    };

    // A flag for each kind
    typedef uint32_t KindFlags;
    struct KindFlag
    {
        enum Enum : KindFlags
        {
            UnorderedAccess = KindFlags(1) << Index(Kind::UnorderedAccess),
            Sampler         = KindFlags(1) << Index(Kind::Sampler), 
            ShaderResource  = KindFlags(1) << Index(Kind::ShaderResource),
            ConstantBuffer  = KindFlags(1) << Index(Kind::ConstantBuffer),
        };
    };
       
        /// Get a kind flag from a kind
    SLANG_FORCE_INLINE static KindFlag::Enum getKindFlag(Kind kind) { SLANG_ASSERT(kind != Kind::Invalid); return KindFlag::Enum(KindFlags(1) << Index(kind)); }

    struct Key
    {
        typedef Key ThisType;

        bool operator==(const ThisType& rhs) const { return kind == rhs.kind && set == rhs.set; }
        bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }

        HashCode getHashCode() const { return combineHash(Slang::getHashCode(kind), Slang::getHashCode(set)); }

        Kind kind;          ///< The kind this entry is for
        Index set;          ///< The set this shift is associated with 
    };

        /// Set the the all option for the kind.
    void setAllShift(Kind kind, Index shift);

        /// Set the shift for kind/set
    void setShift(Kind kind, Index set, Index shift);

        /// Get the shift. Returns kInvalidShift if no shift is found
    Index getShift(Kind kind, Index set) const;

        /// True as global binds set
    bool hasGlobalsBinding() const { return m_globalsBinding.isSet(); }

        /// True if holds state such that vulkan bindings can be inferred from HLSL bindings
    bool canInferBindings() const { return m_kindShiftEnabledFlags != 0; }
        
        /// True if the kind/set can be inferred
    bool canInfer(Kind kind, Index set) const { return getShift(kind, set) != kInvalidShift; }

        /// True if can infer a binding for a kind
    bool canInferBindingForKind(Kind kind) const { return (m_kindShiftEnabledFlags & getKindFlag(kind)) != 0; }

        /// True if the compiler should invert the Y coordinate of any SV_Position output.
    bool shouldInvertY() const { return m_invertY; }

    bool shouldUseGLLayout() const { return m_useGLLayout; }

    bool shouldEmitSPIRVReflectionInfo() const { return m_emitSPIRVReflectionInfo; }

    bool getUseOriginalEntryPointName() const { return m_useOriginalEntryPointName; }

        /// Given an kind and a binding infer the vulkan binding.
        /// Will return an invalid binding if one is not found
    Binding inferBinding(Kind kind, const Binding& inBinding) const;

        /// Returns flags indicating for each kind if there is shift inference
    KindFlags getKindShiftEnabledFlags() const { return m_kindShiftEnabledFlags; }

        /// Reset state such that all options are set to their default. The same state as when 
        /// originally constructed
    void reset();

        /// Returns true if any state is set
    bool hasState() const;

        /// Returns true if contains default reset state. If so it can in effect be ignored
    bool isReset() const { return !hasState(); }

        /// Set the global binding
    void setGlobalsBinding(Index set, Index bindingIndex) { setGlobalsBinding(Binding{set, bindingIndex}); }
        /// Set the global bindings
    void setGlobalsBinding(const Binding& binding);
        /// Get the globals binding
    const Binding& getGlobalsBinding() const { return m_globalsBinding; }

    void setInvertY(bool value) { m_invertY = value; }

    void setUseOriginalEntryPointName(bool value) { m_useOriginalEntryPointName = value; }

    void setUseGLLayout(bool value) { m_useGLLayout = value; }

    void setEmitSPIRVReflectionInfo(bool value) { m_emitSPIRVReflectionInfo = value; }

        /// Ctor
    HLSLToVulkanLayoutOptions();
    
        /// Get information about the different kinds
    static ConstArrayView<NamesDescriptionValue> getKindInfos();

        /// Given a paramCategory get the kind. Returns Kind::Invalid if not an applicable category
    static Kind getKind(slang::ParameterCategory param);

protected:
        /// Marks that a shift is enabled for the kind
    void _enableShiftForKind(Kind kind) { m_kindShiftEnabledFlags |= getKindFlag(kind); }
    
    Binding m_globalsBinding;

        /// The `all` shifts
    Index m_allShifts[Count(Kind::CountOf)];

        /// Holds a bit for each kind that has a shift enabled
    KindFlags m_kindShiftEnabledFlags = 0;

        /// Maps a key to the amount of shift
    Dictionary<Key, Index> m_shifts;

        /// Whether to invert the Y coordinate of SV_Position output.
    bool m_invertY = false;

        /// If set, will use the original entry point name in the generated SPIRV instead of "main".
    bool m_useOriginalEntryPointName = false;

        /// If set, raw buffer load/stores will follow std430 layout.
    bool m_useGLLayout = false;

        /// If set, will emit SPIR-V reflection info.
    bool m_emitSPIRVReflectionInfo = false;
};

} // namespace Slang

#endif
back to top