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