• 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.OES_EGL_image_external_essl3 = 1;
184 	resources.EXT_draw_buffers = 1;
185 	resources.ARB_texture_rectangle = 1;
186 	resources.MaxCallStackDepth = 64;
187 	assembler->Init(resources);
188 
189 	return assembler;
190 }
191 
clear()192 void Shader::clear()
193 {
194 	infoLog.clear();
195 
196 	varyings.clear();
197 	activeUniforms.clear();
198 	activeAttributes.clear();
199 }
200 
compile()201 void Shader::compile()
202 {
203 	clear();
204 
205 	createShader();
206 	TranslatorASM *compiler = createCompiler(getType());
207 
208 	// Ensure we don't pass a nullptr source to the compiler
209 	const char *source = "\0";
210 	if(mSource)
211 	{
212 		source = mSource;
213 	}
214 
215 	bool success = compiler->compile(&source, 1, SH_OBJECT_CODE);
216 
217 	if(false)
218 	{
219 		static int serial = 1;
220 
221 		if(false)
222 		{
223 			char buffer[256];
224 			sprintf(buffer, "shader-input-%d-%d.txt", getName(), serial);
225 			FILE *file = fopen(buffer, "wt");
226 			fprintf(file, "%s", mSource);
227 			fclose(file);
228 		}
229 
230 		getShader()->print("shader-output-%d-%d.txt", getName(), serial);
231 
232 		serial++;
233 	}
234 
235 	shaderVersion = compiler->getShaderVersion();
236 	infoLog += compiler->getInfoSink().info.c_str();
237 
238 	if(!success)
239 	{
240 		deleteShader();
241 
242 		TRACE("\n%s", infoLog.c_str());
243 	}
244 
245 	delete compiler;
246 }
247 
isCompiled()248 bool Shader::isCompiled()
249 {
250 	return getShader() != 0;
251 }
252 
addRef()253 void Shader::addRef()
254 {
255 	mRefCount++;
256 }
257 
release()258 void Shader::release()
259 {
260 	mRefCount--;
261 
262 	if(mRefCount == 0 && mDeleteStatus)
263 	{
264 		mResourceManager->deleteShader(mHandle);
265 	}
266 }
267 
getRefCount() const268 unsigned int Shader::getRefCount() const
269 {
270 	return mRefCount;
271 }
272 
isFlaggedForDeletion() const273 bool Shader::isFlaggedForDeletion() const
274 {
275 	return mDeleteStatus;
276 }
277 
flagForDeletion()278 void Shader::flagForDeletion()
279 {
280 	mDeleteStatus = true;
281 }
282 
releaseCompiler()283 void Shader::releaseCompiler()
284 {
285 	FreeCompilerGlobals();
286 	compilerInitialized = false;
287 }
288 
289 // true if varying x has a higher priority in packing than y
compareVarying(const glsl::Varying & x,const glsl::Varying & y)290 bool Shader::compareVarying(const glsl::Varying &x, const glsl::Varying &y)
291 {
292 	if(x.type == y.type)
293 	{
294 		return x.size() > y.size();
295 	}
296 
297 	switch(x.type)
298 	{
299 	case GL_FLOAT_MAT4: return true;
300 	case GL_FLOAT_MAT2:
301 		switch(y.type)
302 		{
303 		case GL_FLOAT_MAT4: return false;
304 		case GL_FLOAT_MAT2: return true;
305 		case GL_FLOAT_VEC4: return true;
306 		case GL_FLOAT_MAT3: return true;
307 		case GL_FLOAT_VEC3: return true;
308 		case GL_FLOAT_VEC2: return true;
309 		case GL_FLOAT:      return true;
310 		default: UNREACHABLE(y.type);
311 		}
312 		break;
313 	case GL_FLOAT_VEC4:
314 		switch(y.type)
315 		{
316 		case GL_FLOAT_MAT4: return false;
317 		case GL_FLOAT_MAT2: return false;
318 		case GL_FLOAT_VEC4: return true;
319 		case GL_FLOAT_MAT3: return true;
320 		case GL_FLOAT_VEC3: return true;
321 		case GL_FLOAT_VEC2: return true;
322 		case GL_FLOAT:      return true;
323 		default: UNREACHABLE(y.type);
324 		}
325 		break;
326 	case GL_FLOAT_MAT3:
327 		switch(y.type)
328 		{
329 		case GL_FLOAT_MAT4: return false;
330 		case GL_FLOAT_MAT2: return false;
331 		case GL_FLOAT_VEC4: return false;
332 		case GL_FLOAT_MAT3: return true;
333 		case GL_FLOAT_VEC3: return true;
334 		case GL_FLOAT_VEC2: return true;
335 		case GL_FLOAT:      return true;
336 		default: UNREACHABLE(y.type);
337 		}
338 		break;
339 	case GL_FLOAT_VEC3:
340 		switch(y.type)
341 		{
342 		case GL_FLOAT_MAT4: return false;
343 		case GL_FLOAT_MAT2: return false;
344 		case GL_FLOAT_VEC4: return false;
345 		case GL_FLOAT_MAT3: return false;
346 		case GL_FLOAT_VEC3: return true;
347 		case GL_FLOAT_VEC2: return true;
348 		case GL_FLOAT:      return true;
349 		default: UNREACHABLE(y.type);
350 		}
351 		break;
352 	case GL_FLOAT_VEC2:
353 		switch(y.type)
354 		{
355 		case GL_FLOAT_MAT4: return false;
356 		case GL_FLOAT_MAT2: return false;
357 		case GL_FLOAT_VEC4: return false;
358 		case GL_FLOAT_MAT3: return false;
359 		case GL_FLOAT_VEC3: return false;
360 		case GL_FLOAT_VEC2: return true;
361 		case GL_FLOAT:      return true;
362 		default: UNREACHABLE(y.type);
363 		}
364 		break;
365 	case GL_FLOAT: return false;
366 	default: UNREACHABLE(x.type);
367 	}
368 
369 	return false;
370 }
371 
VertexShader(ResourceManager * manager,GLuint handle)372 VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
373 {
374 	vertexShader = 0;
375 }
376 
~VertexShader()377 VertexShader::~VertexShader()
378 {
379 	delete vertexShader;
380 }
381 
getType() const382 GLenum VertexShader::getType() const
383 {
384 	return GL_VERTEX_SHADER;
385 }
386 
getSemanticIndex(const std::string & attributeName) const387 int VertexShader::getSemanticIndex(const std::string &attributeName) const
388 {
389 	if(!attributeName.empty())
390 	{
391 		for(const auto &attribute : activeAttributes)
392 		{
393 			if(attribute.name == attributeName)
394 			{
395 				return attribute.registerIndex;
396 			}
397 		}
398 	}
399 
400 	return -1;
401 }
402 
getShader() const403 sw::Shader *VertexShader::getShader() const
404 {
405 	return vertexShader;
406 }
407 
getVertexShader() const408 sw::VertexShader *VertexShader::getVertexShader() const
409 {
410 	return vertexShader;
411 }
412 
createShader()413 void VertexShader::createShader()
414 {
415 	delete vertexShader;
416 	vertexShader = new sw::VertexShader();
417 }
418 
deleteShader()419 void VertexShader::deleteShader()
420 {
421 	delete vertexShader;
422 	vertexShader = nullptr;
423 }
424 
FragmentShader(ResourceManager * manager,GLuint handle)425 FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
426 {
427 	pixelShader = 0;
428 }
429 
~FragmentShader()430 FragmentShader::~FragmentShader()
431 {
432 	delete pixelShader;
433 }
434 
getType() const435 GLenum FragmentShader::getType() const
436 {
437 	return GL_FRAGMENT_SHADER;
438 }
439 
getShader() const440 sw::Shader *FragmentShader::getShader() const
441 {
442 	return pixelShader;
443 }
444 
getPixelShader() const445 sw::PixelShader *FragmentShader::getPixelShader() const
446 {
447 	return pixelShader;
448 }
449 
createShader()450 void FragmentShader::createShader()
451 {
452 	delete pixelShader;
453 	pixelShader = new sw::PixelShader();
454 }
455 
deleteShader()456 void FragmentShader::deleteShader()
457 {
458 	delete pixelShader;
459 	pixelShader = nullptr;
460 }
461 
462 }
463