Home | History | Annotate | Download | only in libGLESv2
      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 
     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 
     41 Shader::~Shader()
     42 {
     43 	delete[] mSource;
     44 }
     45 
     46 GLuint Shader::getName() const
     47 {
     48 	return mHandle;
     49 }
     50 
     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 
     91 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 
    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 
    124 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 
    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 
    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 
    191 void Shader::clear()
    192 {
    193 	infoLog.clear();
    194 
    195 	varyings.clear();
    196 	activeUniforms.clear();
    197 	activeAttributes.clear();
    198 }
    199 
    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 
    254 bool Shader::isCompiled()
    255 {
    256 	return getShader() != 0;
    257 }
    258 
    259 void Shader::addRef()
    260 {
    261 	mRefCount++;
    262 }
    263 
    264 void Shader::release()
    265 {
    266 	mRefCount--;
    267 
    268 	if(mRefCount == 0 && mDeleteStatus)
    269 	{
    270 		mResourceManager->deleteShader(mHandle);
    271 	}
    272 }
    273 
    274 unsigned int Shader::getRefCount() const
    275 {
    276 	return mRefCount;
    277 }
    278 
    279 bool Shader::isFlaggedForDeletion() const
    280 {
    281 	return mDeleteStatus;
    282 }
    283 
    284 void Shader::flagForDeletion()
    285 {
    286 	mDeleteStatus = true;
    287 }
    288 
    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
    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 
    378 VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
    379 {
    380 	vertexShader = 0;
    381 }
    382 
    383 VertexShader::~VertexShader()
    384 {
    385 	delete vertexShader;
    386 }
    387 
    388 GLenum VertexShader::getType() const
    389 {
    390 	return GL_VERTEX_SHADER;
    391 }
    392 
    393 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 
    409 sw::Shader *VertexShader::getShader() const
    410 {
    411 	return vertexShader;
    412 }
    413 
    414 sw::VertexShader *VertexShader::getVertexShader() const
    415 {
    416 	return vertexShader;
    417 }
    418 
    419 void VertexShader::createShader()
    420 {
    421 	delete vertexShader;
    422 	vertexShader = new sw::VertexShader();
    423 }
    424 
    425 void VertexShader::deleteShader()
    426 {
    427 	delete vertexShader;
    428 	vertexShader = nullptr;
    429 }
    430 
    431 FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
    432 {
    433 	pixelShader = 0;
    434 }
    435 
    436 FragmentShader::~FragmentShader()
    437 {
    438 	delete pixelShader;
    439 }
    440 
    441 GLenum FragmentShader::getType() const
    442 {
    443 	return GL_FRAGMENT_SHADER;
    444 }
    445 
    446 sw::Shader *FragmentShader::getShader() const
    447 {
    448 	return pixelShader;
    449 }
    450 
    451 sw::PixelShader *FragmentShader::getPixelShader() const
    452 {
    453 	return pixelShader;
    454 }
    455 
    456 void FragmentShader::createShader()
    457 {
    458 	delete pixelShader;
    459 	pixelShader = new sw::PixelShader();
    460 }
    461 
    462 void FragmentShader::deleteShader()
    463 {
    464 	delete pixelShader;
    465 	pixelShader = nullptr;
    466 }
    467 
    468 }
    469