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>& allPrograms();
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  static std::vector<std::string> getNames(const LocationMap& locations);
101 
102 private:
103 
104  bool validLocation(const ValidSet& locations, int32_t location) const {
105  return locations.count(location) != 0;
106  }
107 
108  void updateValid();
109 
110  ValidSet validInputs;
111  ValidSet validOutputs;
112  ValidSet validTextures;
113  ValidSet validUniformBuffers;
114  ValidSet validResourceBuffers;
115  ValidSet validUniforms;
116 };
117 
118 struct DialectVariantSource {
119  // The output of the scribe application with platforms specific headers
120  String scribe;
121  // Optimized SPIRV version of the shader
122  Binary spirv;
123  // Regenerated GLSL from the optimized SPIRV
124  String glsl;
125  // Shader reflection from the optimized SPIRV
126  Reflection reflection;
127 
128  bool valid() const { return !scribe.empty(); }
129 };
130 
131 struct DialectSource {
132  std::unordered_map<Variant, DialectVariantSource, EnumClassHash> variantSources;
133 };
134 
135 struct Source {
136  using Pointer = std::shared_ptr<Source>;
137  Source() = default;
138  Source& operator=(const Source& other);
139 
140  uint32_t id{ INVALID_SHADER };
141 
142  // The name of the shader file, with extension, i.e. DrawColor.frag
143  std::string name;
144 
145  // Map of platforms to their specific shaders
146  std::unordered_map<Dialect, DialectSource, EnumClassHash> dialectSources;
147 
148  // Support for swapping out code blocks for procedural and debugging shaders
149  std::unordered_map<std::string, std::string> replacements;
150 
151  String getSource(Dialect dialect, Variant variant) const;
152  const Reflection& getReflection(Dialect dialect, Variant variant) const;
153  bool valid() const { return !dialectSources.empty(); }
154  static Source generate(const std::string& glsl) { throw std::runtime_error("Implement me"); }
155  static const Source& get(uint32_t shaderId);
156 
157 private:
158  // Disallow copy construction
159  Source(const Source& other) = delete;
160 
161  static Source::Pointer loadSource(uint32_t shaderId) ;
162 
163  bool doReplacement(String& source) const;
164  const DialectVariantSource& getDialectVariantSource(Dialect dialect, Variant variant) const;
165 
166 };
167 
168 inline uint32_t getVertexId(uint32_t programId) {
169  return (programId >> 16) & UINT16_MAX;
170 }
171 
172 inline uint32_t getFragmentId(uint32_t programId) {
173  return programId & UINT16_MAX;
174 }
175 
176 } // namespace shader