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  glsl450,
32  glsl410,
33  glsl310es,
34 };
35 
36 const std::vector<Dialect>& allDialects();
37 const std::string& dialectPath(Dialect dialect);
38 
39 enum class Variant {
40  Mono,
41  Stereo,
42 };
43 
44 const std::vector<Variant>& allVariants();
45 
46 static const uint32_t NUM_VARIANTS = 2;
47 
48 using Binary = std::vector<uint8_t>;
49 using String = std::string;
50 
51 struct EnumClassHash
52 {
53  template <typename T>
54  std::size_t operator()(T t) const
55  {
56  return static_cast<std::size_t>(t);
57  }
58 };
59 
60 struct Reflection {
61  using LocationMap = std::unordered_map<std::string, int32_t>;
62  using ValidSet = std::unordered_set<int32_t>;
63 
64  void parse(const std::string& json);
65  void merge(const Reflection& reflection);
66 
67  bool validInput(int32_t location) const { return validLocation(validInputs, location); }
68  bool validOutput(int32_t location) const { return validLocation(validOutputs, location); }
69  bool validTexture(int32_t location) const { return validLocation(validTextures, location); }
70  bool validUniform(int32_t location) const { return validLocation(validUniforms, location); }
71  bool validUniformBuffer(int32_t location) const { return validLocation(validUniformBuffers, location); }
72  bool validResourceBuffer(int32_t location) const { return validLocation(validResourceBuffers, location); }
73 
74 
75  LocationMap inputs;
76 
77  LocationMap outputs;
78 
79  LocationMap textures;
80 
81  LocationMap uniformBuffers;
82 
83  // Either SSBOs or Textures with the type samplerBuffer, depending on dialect
84  LocationMap resourceBuffers;
85 
86  // Needed for procedural code, will map to push constants for Vulkan
87  LocationMap uniforms;
88 
89  size_t descriptorCount() const {
90  return textures.size() + uniformBuffers.size() + resourceBuffers.size();
91  }
92 
93  static std::vector<std::string> getNames(const LocationMap& locations);
94 
95 private:
96 
97  bool validLocation(const ValidSet& locations, int32_t location) const {
98  return locations.contains(location);
99  }
100 
101  void updateValid();
102 
103  ValidSet validInputs;
104  ValidSet validOutputs;
105  ValidSet validTextures;
106  ValidSet validUniformBuffers;
107  ValidSet validResourceBuffers;
108  ValidSet validUniforms;
109 };
110 
111 struct DialectVariantSource {
112  // The output of the scribe application with platforms specific headers
113  String scribe;
114  // Optimized SPIRV version of the shader
115  Binary spirv;
116  // Regenerated GLSL from the optimized SPIRV
117  String glsl;
118  // Shader reflection from the optimized SPIRV
119  Reflection reflection;
120 
121  bool valid() const { return !scribe.empty(); }
122 };
123 
124 struct DialectSource {
125  std::unordered_map<Variant, DialectVariantSource, EnumClassHash> variantSources;
126 };
127 
128 struct Source {
129  using Pointer = std::shared_ptr<Source>;
130  Source() = default;
131  Source& operator=(const Source& other);
132 
133  uint32_t id{ INVALID_SHADER };
134 
135  // The name of the shader file, with extension, i.e. DrawColor.frag
136  std::string name;
137 
138  // Generic reflection, copied from the 450 dialect / mono variant
139  Reflection reflection;
140 
141  // Map of platforms to their specific shaders
142  std::unordered_map<Dialect, DialectSource, EnumClassHash> dialectSources;
143 
144  // Support for swapping out code blocks for procedural and debugging shaders
145  std::unordered_map<std::string, std::string> replacements;
146 
147  String getSource(Dialect dialect, Variant variant) const;
148  const Reflection& getReflection(Dialect dialect, Variant variant) const;
149  bool valid() const { return !dialectSources.empty(); }
150  static Source generate(const std::string& glsl) { throw std::runtime_error("Implement me"); }
151  static const Source& get(uint32_t shaderId);
152 
153 private:
154  // Disallow copy construction
155  Source(const Source& other) = delete;
156 
157  static Source::Pointer loadSource(uint32_t shaderId) ;
158 
159  bool doReplacement(String& source) const;
160  const DialectVariantSource& getDialectVariantSource(Dialect dialect, Variant variant) const;
161 
162 };
163 
164 inline uint32_t getVertexId(uint32_t programId) {
165  return (programId >> 16) & UINT16_MAX;
166 }
167 
168 inline uint32_t getFragmentId(uint32_t programId) {
169  return programId & UINT16_MAX;
170 }
171 
172 inline uint32_t makeProgramId(uint32_t vertexId, uint32_t fragmentId) {
173  return (vertexId << 16) | fragmentId;
174 }
175 
176 } // namespace shader