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 // Shader.cpp: Implements the Shader class and its  derived classes
16 // VertexShader and FragmentShader. Implements GL shader objects and related
17 // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
18 
19 #include "Shader.h"
20 
21 #include "main.h"
22 #include "utilities.h"
23 
24 #include <string>
25 #include <algorithm>
26 
27 namespace es2
28 {
29 std::mutex Shader::mutex;
30 bool Shader::compilerInitialized = false;
31 
Shader(ResourceManager * manager,GLuint handle)32 Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
33 {
34 	mSource = nullptr;
35 
36 	clear();
37 
38 	mRefCount = 0;
39 	mDeleteStatus = false;
40 }
41 
~Shader()42 Shader::~Shader()
43 {
44 	delete[] mSource;
45 }
46 
getName() const47 GLuint Shader::getName() const
48 {
49 	return mHandle;
50 }
51 
setSource(GLsizei count,const char * const * string,const GLint * length)52 void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
53 {
54 	delete[] mSource;
55 	int totalLength = 0;
56 
57 	for(int i = 0; i < count; i++)
58 	{
59 		if(length && length[i] >= 0)
60 		{
61 			totalLength += length[i];
62 		}
63 		else
64 		{
65 			totalLength += (int)strlen(string[i]);
66 		}
67 	}
68 
69 	mSource = new char[totalLength + 1];
70 	char *code = mSource;
71 
72 	for(int i = 0; i < count; i++)
73 	{
74 		int stringLength;
75 
76 		if(length && length[i] >= 0)
77 		{
78 			stringLength = length[i];
79 		}
80 		else
81 		{
82 			stringLength = (int)strlen(string[i]);
83 		}
84 
85 		strncpy(code, string[i], stringLength);
86 		code += stringLength;
87 	}
88 
89 	mSource[totalLength] = '\0';
90 }
91 
getInfoLogLength() const92 size_t Shader::getInfoLogLength() const
93 {
94 	if(infoLog.empty())
95 	{
96 		return 0;
97 	}
98 	else
99 	{
100 	   return infoLog.size() + 1;
101 	}
102 }
103 
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLogOut)104 void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLogOut)
105 {
106 	int index = 0;
107 
108 	if(bufSize > 0)
109 	{
110 		if(!infoLog.empty())
111 		{
112 			index = std::min(bufSize - 1, (GLsizei)infoLog.size());
113 			memcpy(infoLogOut, infoLog.c_str(), index);
114 		}
115 
116 		infoLogOut[index] = '\0';
117 	}
118 
119 	if(length)
120 	{
121 		*length = index;
122 	}
123 }
124 
getSourceLength() const125 size_t Shader::getSourceLength() const
126 {
127 	if(!mSource)
128 	{
129 		return 0;
130 	}
131 	else
132 	{
133 	   return strlen(mSource) + 1;
134 	}
135 }
136 
getSource(GLsizei bufSize,GLsizei * length,char * source)137 void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
138 {
139 	int index = 0;
140 
141 	if(bufSize > 0)
142 	{
143 		if(mSource)
144 		{
145 			index = std::min(bufSize - 1, (int)strlen(mSource));
146 			memcpy(source, mSource, index);
147 		}
148 
149 		source[index] = '\0';
150 	}
151 
152 	if(length)
153 	{
154 		*length = index;
155 	}
156 }
157 
createCompiler(GLenum shaderType)158 TranslatorASM *Shader::createCompiler(GLenum shaderType)
159 {
160 	if(!compilerInitialized)
161 	{
162 		compilerInitialized = InitCompilerGlobals();
163 
164 		if(!compilerInitialized)
165 		{
166 			infoLog += "GLSL compiler failed to initialize.\n";
167 
168 			return nullptr;
169 		}
170 	}
171 
172 	TranslatorASM *assembler = new TranslatorASM(this, shaderType);
173 
174 	ShBuiltInResources resources;
175 	resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
176 	resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
177 	resources.MaxVaryingVectors = MAX_VARYING_VECTORS;
178 	resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
179 	resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
180 	resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
181 	resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
182 	resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
183 	resources.MaxVertexOutputVectors = MAX_VERTEX_OUTPUT_VECTORS;
184 	resources.MaxFragmentInputVectors = MAX_FRAGMENT_INPUT_VECTORS;
185 	resources.MinProgramTexelOffset = MIN_PROGRAM_TEXEL_OFFSET;
186 	resources.MaxProgramTexelOffset = MAX_PROGRAM_TEXEL_OFFSET;
187 	resources.OES_standard_derivatives = 1;
188 	resources.OES_fragment_precision_high = 1;
189 	resources.OES_EGL_image_external = 1;
190 	resources.OES_EGL_image_external_essl3 = 1;
191 	resources.EXT_draw_buffers = 1;
192 	resources.ARB_texture_rectangle = 1;
193 	resources.MaxCallStackDepth = MAX_SHADER_CALL_STACK_SIZE;
194 	assembler->Init(resources);
195 
196 	return assembler;
197 }
198 
clear()199 void Shader::clear()
200 {
201 	infoLog.clear();
202 
203 	varyings.clear();
204 	activeUniforms.clear();
205 	activeAttributes.clear();
206 }
207 
compile()208 void Shader::compile()
209 {
210 	// Our version of glslang is not thread safe.
211 	std::lock_guard<std::mutex> lock(mutex);
212 
213 	clear();
214 
215 	createShader();
216 	TranslatorASM *compiler = createCompiler(getType());
217 
218 	if(!compiler)
219 	{
220 		deleteShader();
221 
222 		return;
223 	}
224 
225 	// Ensure we don't pass a nullptr source to the compiler
226 	const char *source = "\0";
227 	if(mSource)
228 	{
229 		source = mSource;
230 	}
231 
232 	bool success = compiler->compile(&source, 1, SH_OBJECT_CODE);
233 
234 	if(false)
235 	{
236 		static int serial = 1;
237 
238 		if(false)
239 		{
240 			char buffer[256];
241 			sprintf(buffer, "shader-input-%d-%d.txt", getName(), serial);
242 			FILE *file = fopen(buffer, "wt");
243 			fprintf(file, "%s", mSource);
244 			fclose(file);
245 		}
246 
247 		getShader()->print("shader-output-%d-%d.txt", getName(), serial);
248 
249 		serial++;
250 	}
251 
252 	shaderVersion = compiler->getShaderVersion();
253 	infoLog += compiler->getInfoSink().info.c_str();
254 
255 	if(!success)
256 	{
257 		deleteShader();
258 
259 		TRACE("\n%s", infoLog.c_str());
260 	}
261 
262 	delete compiler;
263 }
264 
isCompiled()265 bool Shader::isCompiled()
266 {
267 	return getShader() != 0;
268 }
269 
addRef()270 void Shader::addRef()
271 {
272 	mRefCount++;
273 }
274 
release()275 void Shader::release()
276 {
277 	mRefCount--;
278 
279 	if(mRefCount == 0 && mDeleteStatus)
280 	{
281 		mResourceManager->deleteShader(mHandle);
282 	}
283 }
284 
getRefCount() const285 unsigned int Shader::getRefCount() const
286 {
287 	return mRefCount;
288 }
289 
isFlaggedForDeletion() const290 bool Shader::isFlaggedForDeletion() const
291 {
292 	return mDeleteStatus;
293 }
294 
flagForDeletion()295 void Shader::flagForDeletion()
296 {
297 	mDeleteStatus = true;
298 }
299 
releaseCompiler()300 void Shader::releaseCompiler()
301 {
302 	// Our version of glslang is not thread safe.
303 	std::lock_guard<std::mutex> lock(mutex);
304 
305 	FreeCompilerGlobals();
306 	compilerInitialized = false;
307 }
308 
309 // true if varying x has a higher priority in packing than y
compareVarying(const glsl::Varying & x,const glsl::Varying & y)310 bool Shader::compareVarying(const glsl::Varying &x, const glsl::Varying &y)
311 {
312 	if(x.type == y.type)
313 	{
314 		return x.size() > y.size();
315 	}
316 
317 	switch(x.type)
318 	{
319 	case GL_FLOAT_MAT4: return true;
320 	case GL_FLOAT_MAT2:
321 		switch(y.type)
322 		{
323 		case GL_FLOAT_MAT4: return false;
324 		case GL_FLOAT_MAT2: return true;
325 		case GL_FLOAT_VEC4: return true;
326 		case GL_FLOAT_MAT3: return true;
327 		case GL_FLOAT_VEC3: return true;
328 		case GL_FLOAT_VEC2: return true;
329 		case GL_FLOAT:      return true;
330 		default: UNREACHABLE(y.type);
331 		}
332 		break;
333 	case GL_FLOAT_VEC4:
334 		switch(y.type)
335 		{
336 		case GL_FLOAT_MAT4: return false;
337 		case GL_FLOAT_MAT2: return false;
338 		case GL_FLOAT_VEC4: return true;
339 		case GL_FLOAT_MAT3: return true;
340 		case GL_FLOAT_VEC3: return true;
341 		case GL_FLOAT_VEC2: return true;
342 		case GL_FLOAT:      return true;
343 		default: UNREACHABLE(y.type);
344 		}
345 		break;
346 	case GL_FLOAT_MAT3:
347 		switch(y.type)
348 		{
349 		case GL_FLOAT_MAT4: return false;
350 		case GL_FLOAT_MAT2: return false;
351 		case GL_FLOAT_VEC4: return false;
352 		case GL_FLOAT_MAT3: return true;
353 		case GL_FLOAT_VEC3: return true;
354 		case GL_FLOAT_VEC2: return true;
355 		case GL_FLOAT:      return true;
356 		default: UNREACHABLE(y.type);
357 		}
358 		break;
359 	case GL_FLOAT_VEC3:
360 		switch(y.type)
361 		{
362 		case GL_FLOAT_MAT4: return false;
363 		case GL_FLOAT_MAT2: return false;
364 		case GL_FLOAT_VEC4: return false;
365 		case GL_FLOAT_MAT3: return false;
366 		case GL_FLOAT_VEC3: return true;
367 		case GL_FLOAT_VEC2: return true;
368 		case GL_FLOAT:      return true;
369 		default: UNREACHABLE(y.type);
370 		}
371 		break;
372 	case GL_FLOAT_VEC2:
373 		switch(y.type)
374 		{
375 		case GL_FLOAT_MAT4: return false;
376 		case GL_FLOAT_MAT2: return false;
377 		case GL_FLOAT_VEC4: return false;
378 		case GL_FLOAT_MAT3: return false;
379 		case GL_FLOAT_VEC3: return false;
380 		case GL_FLOAT_VEC2: return true;
381 		case GL_FLOAT:      return true;
382 		default: UNREACHABLE(y.type);
383 		}
384 		break;
385 	case GL_FLOAT: return false;
386 	default: UNREACHABLE(x.type);
387 	}
388 
389 	return false;
390 }
391 
VertexShader(ResourceManager * manager,GLuint handle)392 VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
393 {
394 	vertexShader = 0;
395 }
396 
~VertexShader()397 VertexShader::~VertexShader()
398 {
399 	delete vertexShader;
400 }
401 
getType() const402 GLenum VertexShader::getType() const
403 {
404 	return GL_VERTEX_SHADER;
405 }
406 
getSemanticIndex(const std::string & attributeName) const407 int VertexShader::getSemanticIndex(const std::string &attributeName) const
408 {
409 	if(!attributeName.empty())
410 	{
411 		for(const auto &attribute : activeAttributes)
412 		{
413 			if(attribute.name == attributeName)
414 			{
415 				return attribute.registerIndex;
416 			}
417 		}
418 	}
419 
420 	return -1;
421 }
422 
getShader() const423 sw::Shader *VertexShader::getShader() const
424 {
425 	return vertexShader;
426 }
427 
getVertexShader() const428 sw::VertexShader *VertexShader::getVertexShader() const
429 {
430 	return vertexShader;
431 }
432 
createShader()433 void VertexShader::createShader()
434 {
435 	delete vertexShader;
436 	vertexShader = new sw::VertexShader();
437 }
438 
deleteShader()439 void VertexShader::deleteShader()
440 {
441 	delete vertexShader;
442 	vertexShader = nullptr;
443 }
444 
FragmentShader(ResourceManager * manager,GLuint handle)445 FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
446 {
447 	pixelShader = 0;
448 }
449 
~FragmentShader()450 FragmentShader::~FragmentShader()
451 {
452 	delete pixelShader;
453 }
454 
getType() const455 GLenum FragmentShader::getType() const
456 {
457 	return GL_FRAGMENT_SHADER;
458 }
459 
getShader() const460 sw::Shader *FragmentShader::getShader() const
461 {
462 	return pixelShader;
463 }
464 
getPixelShader() const465 sw::PixelShader *FragmentShader::getPixelShader() const
466 {
467 	return pixelShader;
468 }
469 
createShader()470 void FragmentShader::createShader()
471 {
472 	delete pixelShader;
473 	pixelShader = new sw::PixelShader();
474 }
475 
deleteShader()476 void FragmentShader::deleteShader()
477 {
478 	delete pixelShader;
479 	pixelShader = nullptr;
480 }
481 
482 }
483