Overte C++ Documentation
Shaders.h
1 //
2 // Created by Bradley Austin Davis on 2018/07/09
3 // Copyright 2013-2018 High Fidelity, Inc.
4 //
5 // Distributed under the Apache License, Version 2.0.
6 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
7 //
8 
9 #pragma once
10 #include <cstdint>
11 #include <memory>
12 #include <unordered_map>
13 #include <unordered_set>
14 #include <string>
15 #include <vector>
16 #include <stdexcept>
17 
18 #include <QtCore/QtGlobal>
19 
20 #include <ShaderEnums.h>
21 
22 namespace shader {
23 
24 static const uint32_t INVALID_SHADER = (uint32_t)-1;
25 static const uint32_t INVALID_PROGRAM = (uint32_t)-1;
26 
27 const std::vector<uint32_t>& startupPrograms();
28 const std::vector<uint32_t>& allShaders();
29 
30 enum class Dialect
31 {
32 #if defined(USE_GLES)
33  // GLES only support 3.1 es
34  glsl310es,
35 #elif defined(Q_OS_MAC)
36  // Mac only supports 4.1
37  glsl410,
38 #else
39  // Everything else supports 4.1 and 4.5
40  glsl450,
41  glsl410,
42 #endif
43 };
44 
45 extern const Dialect DEFAULT_DIALECT;
46 
47 const std::vector<Dialect>& allDialects();
48 const std::string& dialectPath(Dialect dialect);
49 
50 enum class Variant {
51  Mono,
52  Stereo,
53 };
54 
55 const std::vector<Variant>& allVariants();
56 
57 static const uint32_t NUM_VARIANTS = 2;
58 
59 using Binary = std::vector<uint8_t>;
60 using String = std::string;
61 
62 struct EnumClassHash
63 {
64  template <typename T>
65  std::size_t operator()(T t) const
66  {
67  return static_cast<std::size_t>(t);
68  }
69 };
70 
71 struct Reflection {
72  using LocationMap = std::unordered_map<std::string, int32_t>;
73  using ValidSet = std::unordered_set<int32_t>;
74 
75  void parse(const std::string& json);
76  void merge(const Reflection& reflection);
77 
78  bool validInput(int32_t location) const { return validLocation(validInputs, location); }
79  bool validOutput(int32_t location) const { return validLocation(validOutputs, location); }
80  bool validTexture(int32_t location) const { return validLocation(validTextures, location); }
81  bool validUniform(int32_t location) const { return validLocation(validUniforms, location); }
82  bool validUniformBuffer(int32_t location) const { return validLocation(validUniformBuffers, location); }
83  bool validResourceBuffer(int32_t location) const { return validLocation(validResourceBuffers, location); }
84 
85 
86  LocationMap inputs;
87 
88  LocationMap outputs;
89 
90  LocationMap textures;
91 
92  LocationMap uniformBuffers;
93 
94  // Either SSBOs or Textures with the type samplerBuffer, depending on dialect
95  LocationMap resourceBuffers;
96 
97  // Needed for procedural code, will map to push constants for Vulkan
98  LocationMap uniforms;
99 
100  size_t descriptorCount() const {
101  return textures.size() + uniformBuffers.size() + resourceBuffers.size();
102  }
103 
104  static std::vector<std::string> getNames(const LocationMap& locations);
105 
106 private:
107 
108  bool validLocation(const ValidSet& locations, int32_t location) const {
109  return locations.count(location) != 0;
110  }
111 
112  void updateValid();
113 
114  ValidSet validInputs;
115  ValidSet validOutputs;
116  ValidSet validTextures;
117  ValidSet validUniformBuffers;
118  ValidSet validResourceBuffers;
119  ValidSet validUniforms;
120 };
121 
122 struct DialectVariantSource {
123  // The output of the scribe application with platforms specific headers
124  String scribe;
125  // Optimized SPIRV version of the shader
126  Binary spirv;
127  // Regenerated GLSL from the optimized SPIRV
128  //String glsl;
129  // Shader reflection from the optimized SPIRV
130  Reflection reflection;
131 
132  bool valid() const { return !scribe.empty(); }
133 };
134 
135 struct DialectSource {
136  std::unordered_map<Variant, DialectVariantSource, EnumClassHash> variantSources;
137 };
138 
139 struct Source {
140  using Pointer = std::shared_ptr<Source>;
141  Source() = default;
142  Source& operator=(const Source& other);
143 
144  uint32_t id{ INVALID_SHADER };
145 
146  // The name of the shader file, with extension, i.e. DrawColor.frag
147  std::string name;
148 
149  // Generic reflection, copied from the 450 dialect / mono variant
150  Reflection reflection;
151 
152  // Map of platforms to their specific shaders
153  std::unordered_map<Dialect, DialectSource, EnumClassHash> dialectSources;
154 
155  // Support for swapping out code blocks for procedural and debugging shaders
156  std::unordered_map<std::string, std::string> replacements;
157 
158  String getSource(Dialect dialect, Variant variant) const;
159  const Reflection& getReflection(Dialect dialect, Variant variant) const;
160  bool valid() const { return !dialectSources.empty(); }
161  static Source generate(const std::string& glsl) { throw std::runtime_error("Implement me"); }
162  static const Source& get(uint32_t shaderId);
163 
164 private:
165  // Disallow copy construction
166  Source(const Source& other) = delete;
167 
168  static Source::Pointer loadSource(uint32_t shaderId) ;
169 
170  bool doReplacement(String& source) const;
171  const DialectVariantSource& getDialectVariantSource(Dialect dialect, Variant variant) const;
172 
173 };
174 
175 inline uint32_t getVertexId(uint32_t programId) {
176  return (programId >> 16) & UINT16_MAX;
177 }
178 
179 inline uint32_t getFragmentId(uint32_t programId) {
180  return programId & UINT16_MAX;
181 }
182 
183 inline uint32_t makeProgramId(uint32_t vertexId, uint32_t fragmentId) {
184  return (vertexId << 16) | fragmentId;
185 }
186 
187 } // namespace shader