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