PixelBullet  0.0.1
A C++ game engine
Loading...
Searching...
No Matches
Shader.hpp
1#pragma once
2
3#include "PixelBullet/Filesystem/VirtualPath.hpp"
4#include "PixelBullet/Serialization/Node.hpp"
5
6#include <volk.h>
7
8#include <array>
9#include <map>
10#include <optional>
11#include <string>
12#include <vector>
13
14typedef struct SpvReflectShaderModule SpvReflectShaderModule;
15
16namespace PixelBullet
17{
21 class Shader
22 {
23 public:
24 using Define = std::pair<std::string, std::string>;
25
27 {
28 public:
29 VertexInput(std::vector<VkVertexInputBindingDescription> bindingDescriptions = {},
30 std::vector<VkVertexInputAttributeDescription> attributeDescriptions = {})
31 : bindingDescriptions(std::move(bindingDescriptions))
32 , attributeDescriptions(std::move(attributeDescriptions))
33 {
34 }
35
36 const std::vector<VkVertexInputBindingDescription>& GetBindingDescriptions() const
37 {
38 return bindingDescriptions;
39 }
40 const std::vector<VkVertexInputAttributeDescription>& GetAttributeDescriptions() const
41 {
42 return attributeDescriptions;
43 }
44
45 bool operator<(const VertexInput& rhs) const
46 {
47 return bindingDescriptions.front().binding < rhs.bindingDescriptions.front().binding;
48 }
49
50 friend const Node& operator>>(const Node& node, VertexInput& vertexInput)
51 {
52 node["bindingDescriptions"] >> vertexInput.bindingDescriptions;
53 node["attributeDescriptions"] >> vertexInput.attributeDescriptions;
54 return node;
55 }
56
57 friend Node& operator<<(Node& node, const VertexInput& vertexInput)
58 {
59 node["bindingDescriptions"] << vertexInput.bindingDescriptions;
60 node["attributeDescriptions"] << vertexInput.attributeDescriptions;
61 return node;
62 }
63
64 private:
65 uint32_t binding = 0;
66 std::vector<VkVertexInputBindingDescription> bindingDescriptions;
67 std::vector<VkVertexInputAttributeDescription> attributeDescriptions;
68 };
69
70 class Uniform
71 {
72 friend class Shader;
73
74 public:
75 explicit Uniform(int32_t binding = -1, int32_t offset = -1, int32_t size = -1, int32_t glType = -1,
76 bool readOnly = false, bool writeOnly = false, VkShaderStageFlags stageFlags = 0)
77 : binding(binding)
78 , offset(offset)
79 , size(size)
80 , glType(glType)
81 , readOnly(readOnly)
82 , writeOnly(writeOnly)
83 , stageFlags(stageFlags)
84 {
85 }
86
87 int32_t GetBinding() const
88 {
89 return binding;
90 }
91 int32_t GetOffset() const
92 {
93 return offset;
94 }
95 int32_t GetSize() const
96 {
97 return size;
98 }
99 int32_t GetGlType() const
100 {
101 return glType;
102 }
103 bool IsReadOnly() const
104 {
105 return readOnly;
106 }
107 bool IsWriteOnly() const
108 {
109 return writeOnly;
110 }
111 VkShaderStageFlags GetStageFlags() const
112 {
113 return stageFlags;
114 }
115
116 bool operator==(const Uniform& rhs) const
117 {
118 return binding == rhs.binding && offset == rhs.offset && size == rhs.size && glType == rhs.glType &&
119 readOnly == rhs.readOnly && writeOnly == rhs.writeOnly && stageFlags == rhs.stageFlags;
120 }
121
122 bool operator!=(const Uniform& rhs) const
123 {
124 return !operator==(rhs);
125 }
126
127 friend const Node& operator>>(const Node& node, Uniform& uniform)
128 {
129 node["binding"] >> uniform.binding;
130 node["offset"] >> uniform.offset;
131 node["size"] >> uniform.size;
132 node["glType"] >> uniform.glType;
133 node["readOnly"] >> uniform.readOnly;
134 node["writeOnly"] >> uniform.writeOnly;
135 node["stageFlags"] >> uniform.stageFlags;
136 return node;
137 }
138
139 friend Node& operator<<(Node& node, const Uniform& uniform)
140 {
141 node["binding"].Set(uniform.binding);
142 node["offset"].Set(uniform.offset);
143 node["size"].Set(uniform.size);
144 node["glType"].Set(uniform.glType);
145 node["readOnly"].Set(uniform.readOnly);
146 node["writeOnly"].Set(uniform.writeOnly);
147 node["stageFlags"].Set(uniform.stageFlags);
148 return node;
149 }
150
151 private:
152 int32_t binding;
153 int32_t offset;
154 int32_t size;
155 int32_t glType;
156 bool readOnly;
157 bool writeOnly;
158 VkShaderStageFlags stageFlags;
159 };
160
162 {
163 friend class Shader;
164
165 public:
166 enum class Type
167 {
168 None,
169 Uniform,
170 Storage,
171 Push
172 };
173
174 explicit UniformBlock(int32_t binding = -1, int32_t size = -1, VkShaderStageFlags stageFlags = 0,
175 Type type = Type::Uniform)
176 : binding(binding)
177 , size(size)
178 , stageFlags(stageFlags)
179 , type(type)
180 {
181 }
182
183 int32_t GetBinding() const
184 {
185 return binding;
186 }
187 int32_t GetSize() const
188 {
189 return size;
190 }
191 VkShaderStageFlags GetStageFlags() const
192 {
193 return stageFlags;
194 }
195 Type GetType() const
196 {
197 return type;
198 }
199 const std::map<std::string, Uniform>& GetUniforms() const
200 {
201 return uniforms;
202 }
203
204 std::optional<Uniform> GetUniform(const std::string& name) const
205 {
206 auto it = uniforms.find(name);
207 return (it != uniforms.end()) ? std::optional<Uniform>(it->second) : std::nullopt;
208 }
209
210 bool operator==(const UniformBlock& rhs) const
211 {
212 return binding == rhs.binding && size == rhs.size && stageFlags == rhs.stageFlags && type == rhs.type &&
213 uniforms == rhs.uniforms;
214 }
215 bool operator!=(const UniformBlock& rhs) const
216 {
217 return !operator==(rhs);
218 }
219
220 friend const Node& operator>>(const Node& node, UniformBlock& uniformBlock)
221 {
222 node["binding"] >> uniformBlock.binding;
223 node["size"] >> uniformBlock.size;
224 node["stageFlags"] >> uniformBlock.stageFlags;
225 node["type"] >> uniformBlock.type;
226 node["uniforms"] >> uniformBlock.uniforms;
227 return node;
228 }
229 friend Node& operator<<(Node& node, const UniformBlock& uniformBlock)
230 {
231 node["binding"].Set(uniformBlock.binding);
232 node["size"].Set(uniformBlock.size);
233 node["stageFlags"].Set(uniformBlock.stageFlags);
234 node["type"].Set(uniformBlock.type);
235 node["uniforms"].Set(uniformBlock.uniforms);
236 return node;
237 }
238
239 private:
240 int32_t binding;
241 int32_t size;
242 VkShaderStageFlags stageFlags;
243 Type type;
244 std::map<std::string, Uniform> uniforms;
245 };
246
248 {
249 friend class Shader;
250
251 public:
252 explicit Attribute(int32_t set = -1, int32_t location = -1, int32_t size = -1, int32_t glType = -1)
253 : set(set)
254 , location(location)
255 , size(size)
256 , glType(glType)
257 {
258 }
259
260 int32_t GetSet() const
261 {
262 return set;
263 }
264 int32_t GetLocation() const
265 {
266 return location;
267 }
268 int32_t GetSize() const
269 {
270 return size;
271 }
272 int32_t GetGlType() const
273 {
274 return glType;
275 }
276
277 bool operator==(const Attribute& rhs) const
278 {
279 return set == rhs.set && location == rhs.location && size == rhs.size && glType == rhs.glType;
280 }
281 bool operator!=(const Attribute& rhs) const
282 {
283 return !operator==(rhs);
284 }
285
286 friend const Node& operator>>(const Node& node, Attribute& attribute)
287 {
288 node["set"] >> attribute.set;
289 node["location"] >> attribute.location;
290 node["size"] >> attribute.size;
291 node["glType"] >> attribute.glType;
292 return node;
293 }
294 friend Node& operator<<(Node& node, const Attribute& attribute)
295 {
296 node["set"] << attribute.set;
297 node["location"] << attribute.location;
298 node["size"] << attribute.size;
299 node["glType"] << attribute.glType;
300 return node;
301 }
302
303 private:
304 int32_t set;
305 int32_t location;
306 int32_t size;
307 int32_t glType;
308 };
309
311 {
312 friend class Shader;
313
314 public:
315 explicit Constant(int32_t binding = -1, int32_t size = -1, VkShaderStageFlags stageFlags = 0,
316 int32_t glType = -1)
317 : binding(binding)
318 , size(size)
319 , stageFlags(stageFlags)
320 , glType(glType)
321 {
322 }
323
324 int32_t GetBinding() const
325 {
326 return binding;
327 }
328 int32_t GetSize() const
329 {
330 return size;
331 }
332 VkShaderStageFlags GetStageFlags() const
333 {
334 return stageFlags;
335 }
336 int32_t GetGlType() const
337 {
338 return glType;
339 }
340
341 bool operator==(const Constant& rhs) const
342 {
343 return binding == rhs.binding && size == rhs.size && stageFlags == rhs.stageFlags &&
344 glType == rhs.glType;
345 }
346 bool operator!=(const Constant& rhs) const
347 {
348 return !operator==(rhs);
349 }
350
351 friend const Node& operator>>(const Node& node, Constant& constant)
352 {
353 node["binding"] >> constant.binding;
354 node["size"] >> constant.size;
355 node["stageFlags"] >> constant.stageFlags;
356 node["glType"] >> constant.glType;
357 return node;
358 }
359 friend Node& operator<<(Node& node, const Constant& constant)
360 {
361 node["binding"] << constant.binding;
362 node["size"] << constant.size;
363 node["stageFlags"] << constant.stageFlags;
364 node["glType"] << constant.glType;
365 return node;
366 }
367
368 private:
369 int32_t binding;
370 int32_t size;
371 VkShaderStageFlags stageFlags;
372 int32_t glType;
373 };
374
375 Shader();
376
377 bool ReportedNotFound(const std::string& name, bool reportIfFound) const;
378 static VkFormat GlTypeToVk(int32_t type);
379 std::optional<uint32_t> GetDescriptorLocation(const std::string& name) const;
380 std::optional<uint32_t> GetDescriptorSize(const std::string& name) const;
381 std::optional<Uniform> GetUniform(const std::string& name) const;
382 std::optional<UniformBlock> GetUniformBlock(const std::string& name) const;
383 std::optional<Attribute> GetAttribute(const std::string& name) const;
384 std::vector<VkPushConstantRange> GetPushConstantRanges() const;
385
386 std::optional<VkDescriptorType> GetDescriptorType(uint32_t location) const;
387 static VkShaderStageFlagBits GetShaderStage(const VirtualPath& filename);
388 VkShaderModule CreateShaderModule(const VirtualPath& moduleName, const std::string& moduleCode,
389 const std::string& preamble, VkShaderStageFlagBits moduleFlag);
390
391 const VirtualPath& GetName() const
392 {
393 return m_Stages.back();
394 }
395 uint32_t GetLastDescriptorBinding() const
396 {
397 return m_LastDescriptorBinding;
398 }
399 const std::map<std::string, Uniform>& GetUniforms() const
400 {
401 return m_Uniforms;
402 }
403 const std::map<std::string, UniformBlock>& GetUniformBlocks() const
404 {
405 return m_UniformBlocks;
406 }
407 const std::map<std::string, Attribute>& GetAttributes() const
408 {
409 return m_Attributes;
410 }
411 const std::map<std::string, Constant>& GetConstants() const
412 {
413 return m_Constants;
414 }
415 const std::array<std::optional<uint32_t>, 3>& GetLocalSizes() const
416 {
417 return m_LocalSizes;
418 }
419 const std::vector<VkDescriptorSetLayoutBinding>& GetDescriptorSetLayouts() const
420 {
421 return m_DescriptorSetLayouts;
422 }
423 const std::vector<VkDescriptorPoolSize>& GetDescriptorPools() const
424 {
425 return m_DescriptorPools;
426 }
427 const std::vector<VkVertexInputAttributeDescription>& GetAttributeDescriptions() const
428 {
429 return m_AttributeDescriptions;
430 }
431
432 friend const Node& operator>>(const Node& node, Shader& shader);
433 friend Node& operator<<(Node& node, const Shader& shader);
434
435 private:
436 void ReflectShader(const SpvReflectShaderModule& spvModule, VkShaderStageFlags stageFlag);
437
438 private:
439 std::vector<VirtualPath> m_Stages;
440 std::map<std::string, Uniform> m_Uniforms;
441 std::map<std::string, UniformBlock> m_UniformBlocks;
442 std::map<std::string, Attribute> m_Attributes;
443 std::map<std::string, Constant> m_Constants;
444 std::array<std::optional<uint32_t>, 3> m_LocalSizes;
445 std::map<std::string, uint32_t> m_DescriptorLocations;
446 std::map<std::string, uint32_t> m_DescriptorSizes;
447 std::vector<VkDescriptorSetLayoutBinding> m_DescriptorSetLayouts;
448 uint32_t m_LastDescriptorBinding = 0;
449 std::vector<VkDescriptorPoolSize> m_DescriptorPools;
450 std::map<uint32_t, VkDescriptorType> m_DescriptorTypes;
451 std::vector<VkVertexInputAttributeDescription> m_AttributeDescriptions;
452 mutable std::vector<std::string> m_NotFoundNames;
453 };
454
455 inline const Node& operator>>(const Node& node, VkVertexInputBindingDescription& bindingDescription)
456 {
457 node["binding"] >> bindingDescription.binding;
458 node["stride"] >> bindingDescription.stride;
459 node["inputRate"] >> bindingDescription.inputRate;
460 return node;
461 }
462
463 inline Node& operator<<(Node& node, const VkVertexInputBindingDescription& bindingDescription)
464 {
465 node["binding"] << bindingDescription.binding;
466 node["stride"] << bindingDescription.stride;
467 node["inputRate"] << bindingDescription.inputRate;
468 return node;
469 }
470
471 inline const Node& operator>>(const Node& node, VkVertexInputAttributeDescription& attributeDescription)
472 {
473 node["location"] >> attributeDescription.location;
474 node["binding"] >> attributeDescription.binding;
475 node["format"] >> attributeDescription.format;
476 node["offset"] >> attributeDescription.offset;
477 return node;
478 }
479
480 inline Node& operator<<(Node& node, const VkVertexInputAttributeDescription& attributeDescription)
481 {
482 node["location"] << attributeDescription.location;
483 node["binding"] << attributeDescription.binding;
484 node["format"] << attributeDescription.format;
485 node["offset"] << attributeDescription.offset;
486 return node;
487 }
488} // namespace PixelBullet
Represents a hierarchical node capable of storing various data types and supporting YAML serializatio...
Definition Node.hpp:51
Definition Shader.hpp:248
Definition Shader.hpp:311
Definition Shader.hpp:162
Definition Shader.hpp:71
Definition Shader.hpp:27
Class that loads and processes a shader, and provides reflection.
Definition Shader.hpp:22
Definition VirtualPath.hpp:11