Overte C++ Documentation
Shader.h
1 //
2 // Shader.h
3 // libraries/gpu/src/gpu
4 //
5 // Created by Sam Gateau on 2/27/2015.
6 // Copyright 2014 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 #ifndef hifi_gpu_Shader_h
12 #define hifi_gpu_Shader_h
13 
14 #include "Resource.h"
15 #include <string>
16 #include <memory>
17 #include <set>
18 #include <unordered_set>
19 #include <unordered_map>
20 #include <map>
21 #include <functional>
22 #include <shaders/Shaders.h>
23 #include <QUrl>
24 
25 namespace gpu {
26 
27 class Shader {
28 public:
29  // unique identifier of a shader
30  using ID = uint32_t;
31 
32  enum Type
33  {
34  VERTEX = 0,
35  PIXEL,
36  FRAGMENT = PIXEL,
37  GEOMETRY,
38  NUM_DOMAINS,
39 
40  PROGRAM,
41  };
42 
43  typedef std::shared_ptr<Shader> Pointer;
44  typedef std::vector<Pointer> Shaders;
45 
46  using Source = shader::Source;
47  using Reflection = shader::Reflection;
48  using Dialect = shader::Dialect;
49  using Variant = shader::Variant;
50 
51  struct CompilationLog {
52  std::string message;
53  bool compiled{ false };
54 
55  CompilationLog() {}
56  CompilationLog(const CompilationLog& src) : message(src.message), compiled(src.compiled) {}
57  };
58  using CompilationLogs = std::vector<CompilationLog>;
59 
60  static const int32 INVALID_LOCATION = -1;
61 
62  template <typename T>
63  class Less {
64  public:
65  bool operator()(const T& x, const T& y) const { return x._name < y._name; }
66  };
67 
68  static const Source& getShaderSource(uint32_t id);
69  static const Source& getVertexShaderSource(uint32_t id) { return getShaderSource(id); }
70  static const Source& getFragmentShaderSource(uint32_t id) { return getShaderSource(id); }
71  static Pointer createVertex(const Source& source);
72  static Pointer createPixel(const Source& source);
73  static Pointer createGeometry(const Source& source);
74 
75  static Pointer createVertex(uint32_t shaderId);
76  static Pointer createPixel(uint32_t shaderId);
77  static Pointer createGeometry(uint32_t shaderId);
78 
79  static Pointer createProgram(uint32_t programId);
80  static Pointer createProgram(const Pointer& vertexShader, const Pointer& pixelShader);
81  static Pointer createProgram(const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader);
82 
83  ~Shader();
84 
85  ID getID() const;
86  Type getType() const { return _type; }
87  bool isProgram() const { return getType() > NUM_DOMAINS; }
88  bool isDomain() const { return getType() < NUM_DOMAINS; }
89 
90  const Source& getSource() const { return _source; }
91 
92  const Shaders& getShaders() const { return _shaders; }
93 
94  Reflection getReflection(shader::Dialect dialect, shader::Variant variant) const;
95  Reflection getReflection() const; // get the default version of the reflection
96 
97  // Compilation Handler can be passed while compiling a shader (in the makeProgram call) to be able to give the hand to
98  // the caller thread if the compilation fails and to provide a different version of the source for it
99  // @param0 the Shader object that just failed to compile
100  // @param1 the original source code as submitted to the compiler
101  // @param2 the compilation log containing the error message
102  // @param3 a new string ready to be filled with the new version of the source that could be proposed from the handler functor
103  // @return boolean true if the backend should keep trying to compile the shader with the new source returned or false to stop and fail that shader compilation
104  using CompilationHandler = std::function<bool(const Shader&, const std::string&, CompilationLog&, std::string&)>;
105 
106  // Check the compilation state
107  bool compilationHasFailed() const { return _compilationHasFailed; }
108  const CompilationLogs& getCompilationLogs() const { return _compilationLogs; }
109  uint32_t getNumCompilationAttempts() const { return _numCompilationAttempts; }
110 
111  // Set COmpilation logs can only be called by the Backend layers
112  void setCompilationHasFailed(bool compilationHasFailed) { _compilationHasFailed = compilationHasFailed; }
113  void setCompilationLogs(const CompilationLogs& logs) const;
114  void incrementCompilationAttempt() const;
115 
116  const GPUObjectPointer gpuObject{};
117 
118 protected:
119  Shader(Type type, const Source& source, bool dynamic);
120  Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel);
121 
122  // Source contains the actual source code or nothing if the shader is a program
123  const Source _source;
124 
125  // if shader is composed of sub shaders, here they are
126  const Shaders _shaders;
127 
128 
129  // The type of the shader, the master key
130  const Type _type;
131 
132  // Number of attempts to compile the shader
133  mutable uint32_t _numCompilationAttempts{ 0 };
134  // Compilation logs (one for each versions generated)
135  mutable CompilationLogs _compilationLogs;
136 
137  // Whether or not the shader compilation failed
138  bool _compilationHasFailed{ false };
139 
140  // Global maps of the shaders
141  // Unique shader ID
142  //static std::atomic<ID> _nextShaderID;
143 
144  static ShaderPointer createOrReuseDomainShader(Type type, uint32_t sourceId);
145 
146  using ProgramMapKey = glm::uvec3; // The IDs of the shaders in a program make its key
147  class ProgramKeyLess {
148  public:
149  bool operator()(const ProgramMapKey& l, const ProgramMapKey& r) const {
150  if (l.x == r.x) {
151  if (l.y == r.y) {
152  return (l.z < r.z);
153  } else {
154  return (l.y < r.y);
155  }
156  } else {
157  return (l.x < r.x);
158  }
159  }
160  };
161  using ProgramMap = std::map<ProgramMapKey, std::weak_ptr<Shader>, ProgramKeyLess>;
162  static ProgramMap _programMap;
163 
164  static ShaderPointer createOrReuseProgramShader(Type type,
165  const Pointer& vertexShader,
166  const Pointer& geometryShader,
167  const Pointer& pixelShader);
168  friend class Serializer;
169  friend class Deserializer;
170 };
171 
172 typedef Shader::Pointer ShaderPointer;
173 typedef std::vector<ShaderPointer> Shaders;
174 
175 }; // namespace gpu
176 
177 #endif