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
31namespace 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