1 | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | // Program.h: Defines the Program class. Implements GL program objects |
16 | // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. |
17 | |
18 | #ifndef LIBGLESV2_PROGRAM_H_ |
19 | #define LIBGLESV2_PROGRAM_H_ |
20 | |
21 | #include "Shader.h" |
22 | #include "Context.h" |
23 | #include "Shader/PixelShader.hpp" |
24 | #include "Shader/VertexShader.hpp" |
25 | |
26 | #include <string> |
27 | #include <vector> |
28 | #include <set> |
29 | #include <map> |
30 | |
31 | namespace es2 |
32 | { |
33 | class Device; |
34 | class ResourceManager; |
35 | class FragmentShader; |
36 | class VertexShader; |
37 | |
38 | // Helper struct representing a single shader uniform |
39 | struct Uniform |
40 | { |
41 | struct BlockInfo |
42 | { |
43 | BlockInfo(const glsl::Uniform& uniform, int blockIndex); |
44 | |
45 | int index = -1; |
46 | int offset = -1; |
47 | int arrayStride = -1; |
48 | int matrixStride = -1; |
49 | bool isRowMajorMatrix = false; |
50 | }; |
51 | |
52 | Uniform(const glsl::Uniform &uniform, const BlockInfo &blockInfo); |
53 | |
54 | ~Uniform(); |
55 | |
56 | bool isArray() const; |
57 | int size() const; |
58 | int registerCount() const; |
59 | |
60 | const GLenum type; |
61 | const GLenum precision; |
62 | const std::string name; |
63 | const unsigned int arraySize; |
64 | const BlockInfo blockInfo; |
65 | std::vector<glsl::ShaderVariable> fields; |
66 | |
67 | unsigned char *data = nullptr; |
68 | bool dirty = true; |
69 | |
70 | short psRegisterIndex = -1; |
71 | short vsRegisterIndex = -1; |
72 | }; |
73 | |
74 | // Helper struct representing a single shader uniform block |
75 | struct UniformBlock |
76 | { |
77 | // use GL_INVALID_INDEX for non-array elements |
78 | UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize, std::vector<unsigned int> memberUniformIndexes); |
79 | |
80 | void setRegisterIndex(GLenum shader, unsigned int registerIndex); |
81 | |
82 | bool isArrayElement() const; |
83 | bool isReferencedByVertexShader() const; |
84 | bool isReferencedByFragmentShader() const; |
85 | |
86 | const std::string name; |
87 | const unsigned int elementIndex; |
88 | const unsigned int dataSize; |
89 | |
90 | std::vector<unsigned int> memberUniformIndexes; |
91 | |
92 | unsigned int psRegisterIndex; |
93 | unsigned int vsRegisterIndex; |
94 | }; |
95 | |
96 | // Struct used for correlating uniforms/elements of uniform arrays to handles |
97 | struct UniformLocation |
98 | { |
99 | UniformLocation(const std::string &name, unsigned int element, unsigned int index); |
100 | |
101 | std::string name; |
102 | unsigned int element; |
103 | unsigned int index; |
104 | }; |
105 | |
106 | struct LinkedVarying |
107 | { |
108 | LinkedVarying(); |
109 | LinkedVarying(const std::string &name, GLenum type, GLsizei size, int reg, int col); |
110 | |
111 | // Original GL name |
112 | std::string name; |
113 | |
114 | GLenum type; |
115 | GLsizei size; |
116 | |
117 | int reg; // First varying register, assigned during link |
118 | int col; // First register element, assigned during link |
119 | }; |
120 | |
121 | class Program |
122 | { |
123 | public: |
124 | Program(ResourceManager *manager, GLuint handle); |
125 | |
126 | ~Program(); |
127 | |
128 | bool attachShader(Shader *shader); |
129 | bool detachShader(Shader *shader); |
130 | int getAttachedShadersCount() const; |
131 | |
132 | sw::PixelShader *getPixelShader(); |
133 | sw::VertexShader *getVertexShader(); |
134 | |
135 | void bindAttributeLocation(GLuint index, const char *name); |
136 | GLint getAttributeLocation(const char *name); |
137 | int getAttributeStream(int attributeIndex); |
138 | |
139 | GLint getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex); |
140 | TextureType getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex); |
141 | |
142 | GLuint getUniformIndex(const std::string &name) const; |
143 | GLuint getUniformBlockIndex(const std::string &name) const; |
144 | void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); |
145 | GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; |
146 | void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const; |
147 | |
148 | GLint getUniformLocation(const std::string &name) const; |
149 | bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v); |
150 | bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v); |
151 | bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v); |
152 | bool setUniform4fv(GLint location, GLsizei count, const GLfloat *v); |
153 | bool setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
154 | bool setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
155 | bool setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
156 | bool setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
157 | bool setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
158 | bool setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
159 | bool setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
160 | bool setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
161 | bool setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
162 | bool setUniform1iv(GLint location, GLsizei count, const GLint *v); |
163 | bool setUniform2iv(GLint location, GLsizei count, const GLint *v); |
164 | bool setUniform3iv(GLint location, GLsizei count, const GLint *v); |
165 | bool setUniform4iv(GLint location, GLsizei count, const GLint *v); |
166 | bool setUniform1uiv(GLint location, GLsizei count, const GLuint *v); |
167 | bool setUniform2uiv(GLint location, GLsizei count, const GLuint *v); |
168 | bool setUniform3uiv(GLint location, GLsizei count, const GLuint *v); |
169 | bool setUniform4uiv(GLint location, GLsizei count, const GLuint *v); |
170 | |
171 | bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params); |
172 | bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params); |
173 | bool getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params); |
174 | |
175 | void dirtyAllUniforms(); |
176 | void applyUniforms(Device *device); |
177 | void applyUniformBuffers(Device *device, BufferBinding* uniformBuffers); |
178 | void applyTransformFeedback(Device *device, TransformFeedback* transformFeedback); |
179 | |
180 | void link(); |
181 | bool isLinked() const; |
182 | size_t getInfoLogLength() const; |
183 | void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog); |
184 | void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); |
185 | |
186 | GLint getFragDataLocation(const GLchar *name); |
187 | |
188 | void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; |
189 | size_t getActiveAttributeCount() const; |
190 | GLint getActiveAttributeMaxLength() const; |
191 | |
192 | void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; |
193 | size_t getActiveUniformCount() const; |
194 | GLint getActiveUniformMaxLength() const; |
195 | GLint getActiveUniformi(GLuint index, GLenum pname) const; |
196 | |
197 | void getActiveUniformBlockName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const; |
198 | size_t getActiveUniformBlockCount() const; |
199 | GLint getActiveUniformBlockMaxLength() const; |
200 | |
201 | void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode); |
202 | void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const; |
203 | GLsizei getTransformFeedbackVaryingCount() const; |
204 | GLsizei getTransformFeedbackVaryingMaxLength() const; |
205 | GLenum getTransformFeedbackBufferMode() const; |
206 | |
207 | void addRef(); |
208 | void release(); |
209 | unsigned int getRefCount() const; |
210 | void flagForDeletion(); |
211 | bool isFlaggedForDeletion() const; |
212 | |
213 | void validate(Device* device); |
214 | bool validateSamplers(bool logErrors); |
215 | bool isValidated() const; |
216 | |
217 | unsigned int getSerial() const; |
218 | |
219 | bool getBinaryRetrievableHint() const { return retrievableBinary; } |
220 | void setBinaryRetrievable(bool retrievable) { retrievableBinary = retrievable; } |
221 | GLint getBinaryLength() const; |
222 | |
223 | private: |
224 | void unlink(); |
225 | void resetUniformBlockBindings(); |
226 | |
227 | bool linkVaryings(); |
228 | bool linkTransformFeedback(); |
229 | |
230 | bool linkAttributes(); |
231 | bool linkAttribute(const glsl::Attribute &attribute, int location, unsigned int &usedLocations); |
232 | int getAttributeLocation(const std::string &name); |
233 | |
234 | Uniform *getUniform(const std::string &name) const; |
235 | bool linkUniforms(const Shader *shader); |
236 | bool linkUniformBlocks(const Shader *vertexShader, const Shader *fragmentShader); |
237 | bool areMatchingUniformBlocks(const glsl::UniformBlock &block1, const glsl::UniformBlock &block2, const Shader *shader1, const Shader *shader2); |
238 | bool areMatchingFields(const std::vector<glsl::ShaderVariable>& fields1, const std::vector<glsl::ShaderVariable>& fields2, const std::string& name); |
239 | bool validateUniformStruct(GLenum shader, const glsl::Uniform &newUniformStruct); |
240 | bool defineUniform(GLenum shader, const glsl::Uniform &uniform, const Uniform::BlockInfo& blockInfo); |
241 | bool defineUniformBlock(const Shader *shader, const glsl::UniformBlock &block); |
242 | bool applyUniform(Device *device, GLint location, float* data); |
243 | bool applyUniform1bv(Device *device, GLint location, GLsizei count, const GLboolean *v); |
244 | bool applyUniform2bv(Device *device, GLint location, GLsizei count, const GLboolean *v); |
245 | bool applyUniform3bv(Device *device, GLint location, GLsizei count, const GLboolean *v); |
246 | bool applyUniform4bv(Device *device, GLint location, GLsizei count, const GLboolean *v); |
247 | bool applyUniform1fv(Device *device, GLint location, GLsizei count, const GLfloat *v); |
248 | bool applyUniform2fv(Device *device, GLint location, GLsizei count, const GLfloat *v); |
249 | bool applyUniform3fv(Device *device, GLint location, GLsizei count, const GLfloat *v); |
250 | bool applyUniform4fv(Device *device, GLint location, GLsizei count, const GLfloat *v); |
251 | bool applyUniformMatrix2fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
252 | bool applyUniformMatrix2x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
253 | bool applyUniformMatrix2x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
254 | bool applyUniformMatrix3fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
255 | bool applyUniformMatrix3x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
256 | bool applyUniformMatrix3x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
257 | bool applyUniformMatrix4fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
258 | bool applyUniformMatrix4x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
259 | bool applyUniformMatrix4x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
260 | bool applyUniform1iv(Device *device, GLint location, GLsizei count, const GLint *v); |
261 | bool applyUniform2iv(Device *device, GLint location, GLsizei count, const GLint *v); |
262 | bool applyUniform3iv(Device *device, GLint location, GLsizei count, const GLint *v); |
263 | bool applyUniform4iv(Device *device, GLint location, GLsizei count, const GLint *v); |
264 | bool applyUniform1uiv(Device *device, GLint location, GLsizei count, const GLuint *v); |
265 | bool applyUniform2uiv(Device *device, GLint location, GLsizei count, const GLuint *v); |
266 | bool applyUniform3uiv(Device *device, GLint location, GLsizei count, const GLuint *v); |
267 | bool applyUniform4uiv(Device *device, GLint location, GLsizei count, const GLuint *v); |
268 | |
269 | bool setUniformfv(GLint location, GLsizei count, const GLfloat *v, int numElements); |
270 | bool setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum type); |
271 | bool setUniformiv(GLint location, GLsizei count, const GLint *v, int numElements); |
272 | bool setUniformuiv(GLint location, GLsizei count, const GLuint *v, int numElements); |
273 | |
274 | void appendToInfoLog(const char *info, ...); |
275 | void resetInfoLog(); |
276 | |
277 | static unsigned int issueSerial(); |
278 | |
279 | FragmentShader *fragmentShader; |
280 | VertexShader *vertexShader; |
281 | |
282 | sw::PixelShader *pixelBinary; |
283 | sw::VertexShader *vertexBinary; |
284 | |
285 | std::map<std::string, GLuint> attributeBinding; |
286 | std::map<std::string, GLuint> linkedAttributeLocation; |
287 | std::vector<glsl::Attribute> linkedAttribute; |
288 | int attributeStream[MAX_VERTEX_ATTRIBS]; |
289 | |
290 | GLuint uniformBlockBindings[MAX_UNIFORM_BUFFER_BINDINGS]; |
291 | |
292 | std::vector<std::string> transformFeedbackVaryings; |
293 | GLenum transformFeedbackBufferMode; |
294 | size_t totalLinkedVaryingsComponents; |
295 | |
296 | struct Sampler |
297 | { |
298 | bool active; |
299 | GLint logicalTextureUnit; |
300 | TextureType textureType; |
301 | }; |
302 | |
303 | Sampler samplersPS[MAX_TEXTURE_IMAGE_UNITS]; |
304 | Sampler samplersVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS]; |
305 | |
306 | typedef std::vector<Uniform*> UniformArray; |
307 | UniformArray uniforms; |
308 | typedef std::vector<Uniform> UniformStructArray; |
309 | UniformStructArray uniformStructs; |
310 | typedef std::vector<UniformLocation> UniformIndex; |
311 | UniformIndex uniformIndex; |
312 | typedef std::vector<UniformBlock*> UniformBlockArray; |
313 | UniformBlockArray uniformBlocks; |
314 | typedef std::vector<LinkedVarying> LinkedVaryingArray; |
315 | LinkedVaryingArray transformFeedbackLinkedVaryings; |
316 | |
317 | bool linked; |
318 | bool orphaned; // Flag to indicate that the program can be deleted when no longer in use |
319 | char *infoLog; |
320 | bool validated; |
321 | bool retrievableBinary; |
322 | |
323 | unsigned int referenceCount; |
324 | const unsigned int serial; |
325 | |
326 | static unsigned int currentSerial; |
327 | |
328 | ResourceManager *resourceManager; |
329 | const GLuint handle; |
330 | }; |
331 | } |
332 | |
333 | #endif // LIBGLESV2_PROGRAM_H_ |
334 | |