1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
// 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 CompilerOptionSet;
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
{
None = 0,
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;
}
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 setUseOriginalEntryPointName(bool value) { m_useOriginalEntryPointName = value; }
void setUseGLLayout(bool value) { m_useGLLayout = value; }
void setEmitSPIRVReflectionInfo(bool value) { m_emitSPIRVReflectionInfo = value; }
void loadFromOptionSet(CompilerOptionSet& optionSet);
/// 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;
/// 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
|