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;
46			int offset;
47			int arrayStride;
48			int matrixStride;
49			bool isRowMajorMatrix;
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;
68		bool dirty;
69
70		short psRegisterIndex;
71		short vsRegisterIndex;
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		bool isUniformDefined(const std::string &name) const;
149		GLint getUniformLocation(const std::string &name) const;
150		bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
151		bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
152		bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
153		bool setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
154		bool setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
155		bool setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
156		bool setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
157		bool setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
158		bool setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
159		bool setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
160		bool setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
161		bool setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
162		bool setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
163		bool setUniform1iv(GLint location, GLsizei count, const GLint *v);
164		bool setUniform2iv(GLint location, GLsizei count, const GLint *v);
165		bool setUniform3iv(GLint location, GLsizei count, const GLint *v);
166		bool setUniform4iv(GLint location, GLsizei count, const GLint *v);
167		bool setUniform1uiv(GLint location, GLsizei count, const GLuint *v);
168		bool setUniform2uiv(GLint location, GLsizei count, const GLuint *v);
169		bool setUniform3uiv(GLint location, GLsizei count, const GLuint *v);
170		bool setUniform4uiv(GLint location, GLsizei count, const GLuint *v);
171
172		bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params);
173		bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params);
174		bool getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params);
175
176		void dirtyAllUniforms();
177		void applyUniforms(Device *device);
178		void applyUniformBuffers(Device *device, BufferBinding* uniformBuffers);
179		void applyTransformFeedback(Device *device, TransformFeedback* transformFeedback);
180
181		void link();
182		bool isLinked() const;
183		size_t getInfoLogLength() const;
184		void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
185		void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
186
187		GLint getFragDataLocation(const GLchar *name);
188
189		void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
190		size_t getActiveAttributeCount() const;
191		GLint getActiveAttributeMaxLength() const;
192
193		void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
194		size_t getActiveUniformCount() const;
195		GLint getActiveUniformMaxLength() const;
196		GLint getActiveUniformi(GLuint index, GLenum pname) const;
197
198		void getActiveUniformBlockName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
199		size_t getActiveUniformBlockCount() const;
200		GLint getActiveUniformBlockMaxLength() const;
201
202		void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode);
203		void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
204		GLsizei getTransformFeedbackVaryingCount() const;
205		GLsizei getTransformFeedbackVaryingMaxLength() const;
206		GLenum getTransformFeedbackBufferMode() const;
207
208		void addRef();
209		void release();
210		unsigned int getRefCount() const;
211		void flagForDeletion();
212		bool isFlaggedForDeletion() const;
213
214		void validate(Device* device);
215		bool validateSamplers(bool logErrors);
216		bool isValidated() const;
217
218		unsigned int getSerial() const;
219
220		bool getBinaryRetrievableHint() const { return retrievableBinary; }
221		void setBinaryRetrievable(bool retrievable) { retrievableBinary = retrievable; }
222		GLint getBinaryLength() const;
223
224	private:
225		void unlink();
226		void resetUniformBlockBindings();
227
228		bool linkVaryings();
229		bool linkTransformFeedback();
230
231		bool linkAttributes();
232		int getAttributeBinding(const glsl::Attribute &attribute);
233
234		bool linkUniforms(const Shader *shader);
235		bool linkUniformBlocks(const Shader *vertexShader, const Shader *fragmentShader);
236		bool areMatchingUniformBlocks(const glsl::UniformBlock &block1, const glsl::UniformBlock &block2, const Shader *shader1, const Shader *shader2);
237		bool areMatchingFields(const std::vector<glsl::ShaderVariable>& fields1, const std::vector<glsl::ShaderVariable>& fields2, const std::string& name);
238		bool validateUniformStruct(GLenum shader, const glsl::Uniform &newUniformStruct);
239		bool defineUniform(GLenum shader, const glsl::Uniform &uniform, const Uniform::BlockInfo& blockInfo);
240		bool defineUniformBlock(const Shader *shader, const glsl::UniformBlock &block);
241		bool applyUniform(Device *device, GLint location, float* data);
242		bool applyUniform1bv(Device *device, GLint location, GLsizei count, const GLboolean *v);
243		bool applyUniform2bv(Device *device, GLint location, GLsizei count, const GLboolean *v);
244		bool applyUniform3bv(Device *device, GLint location, GLsizei count, const GLboolean *v);
245		bool applyUniform4bv(Device *device, GLint location, GLsizei count, const GLboolean *v);
246		bool applyUniform1fv(Device *device, GLint location, GLsizei count, const GLfloat *v);
247		bool applyUniform2fv(Device *device, GLint location, GLsizei count, const GLfloat *v);
248		bool applyUniform3fv(Device *device, GLint location, GLsizei count, const GLfloat *v);
249		bool applyUniform4fv(Device *device, GLint location, GLsizei count, const GLfloat *v);
250		bool applyUniformMatrix2fv(Device *device, GLint location, GLsizei count, const GLfloat *value);
251		bool applyUniformMatrix2x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value);
252		bool applyUniformMatrix2x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value);
253		bool applyUniformMatrix3fv(Device *device, GLint location, GLsizei count, const GLfloat *value);
254		bool applyUniformMatrix3x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value);
255		bool applyUniformMatrix3x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value);
256		bool applyUniformMatrix4fv(Device *device, GLint location, GLsizei count, const GLfloat *value);
257		bool applyUniformMatrix4x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value);
258		bool applyUniformMatrix4x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value);
259		bool applyUniform1iv(Device *device, GLint location, GLsizei count, const GLint *v);
260		bool applyUniform2iv(Device *device, GLint location, GLsizei count, const GLint *v);
261		bool applyUniform3iv(Device *device, GLint location, GLsizei count, const GLint *v);
262		bool applyUniform4iv(Device *device, GLint location, GLsizei count, const GLint *v);
263		bool applyUniform1uiv(Device *device, GLint location, GLsizei count, const GLuint *v);
264		bool applyUniform2uiv(Device *device, GLint location, GLsizei count, const GLuint *v);
265		bool applyUniform3uiv(Device *device, GLint location, GLsizei count, const GLuint *v);
266		bool applyUniform4uiv(Device *device, GLint location, GLsizei count, const GLuint *v);
267
268		bool setUniformfv(GLint location, GLsizei count, const GLfloat *v, int numElements);
269		bool setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum type);
270		bool setUniformiv(GLint location, GLsizei count, const GLint *v, int numElements);
271		bool setUniformuiv(GLint location, GLsizei count, const GLuint *v, int numElements);
272
273		void appendToInfoLog(const char *info, ...);
274		void resetInfoLog();
275
276		static unsigned int issueSerial();
277
278	private:
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