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 
getBinaryRetrievableHint()219 		bool getBinaryRetrievableHint() const { return retrievableBinary; }
setBinaryRetrievable(bool retrievable)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