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