Home | History | Annotate | Download | only in libGL
      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 
     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 
     40 Shader::~Shader()
     41 {
     42 	delete[] mSource;
     43 }
     44 
     45 GLuint Shader::getName() const
     46 {
     47 	return mHandle;
     48 }
     49 
     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 
     90 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 
    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 
    123 int Shader::getSourceLength() const
    124 {
    125 	if(!mSource)
    126 	{
    127 		return 0;
    128 	}
    129 	else
    130 	{
    131 	   return strlen(mSource) + 1;
    132 	}
    133 }
    134 
    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 
    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 
    183 void Shader::clear()
    184 {
    185 	infoLog.clear();
    186 
    187 	varyings.clear();
    188 	activeUniforms.clear();
    189 	activeAttributes.clear();
    190 }
    191 
    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 	const 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 
    231 bool Shader::isCompiled()
    232 {
    233 	return getShader() != 0;
    234 }
    235 
    236 void Shader::addRef()
    237 {
    238 	mRefCount++;
    239 }
    240 
    241 void Shader::release()
    242 {
    243 	mRefCount--;
    244 
    245 	if(mRefCount == 0 && mDeleteStatus)
    246 	{
    247 		mResourceManager->deleteShader(mHandle);
    248 	}
    249 }
    250 
    251 unsigned int Shader::getRefCount() const
    252 {
    253 	return mRefCount;
    254 }
    255 
    256 bool Shader::isFlaggedForDeletion() const
    257 {
    258 	return mDeleteStatus;
    259 }
    260 
    261 void Shader::flagForDeletion()
    262 {
    263 	mDeleteStatus = true;
    264 }
    265 
    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
    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 
    355 VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
    356 {
    357 	vertexShader = 0;
    358 }
    359 
    360 VertexShader::~VertexShader()
    361 {
    362 	delete vertexShader;
    363 }
    364 
    365 GLenum VertexShader::getType()
    366 {
    367 	return GL_VERTEX_SHADER;
    368 }
    369 
    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 
    386 sw::Shader *VertexShader::getShader() const
    387 {
    388 	return vertexShader;
    389 }
    390 
    391 sw::VertexShader *VertexShader::getVertexShader() const
    392 {
    393 	return vertexShader;
    394 }
    395 
    396 void VertexShader::createShader()
    397 {
    398 	delete vertexShader;
    399 	vertexShader = new sw::VertexShader();
    400 }
    401 
    402 void VertexShader::deleteShader()
    403 {
    404 	delete vertexShader;
    405 	vertexShader = nullptr;
    406 }
    407 
    408 FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
    409 {
    410 	pixelShader = 0;
    411 }
    412 
    413 FragmentShader::~FragmentShader()
    414 {
    415 	delete pixelShader;
    416 }
    417 
    418 GLenum FragmentShader::getType()
    419 {
    420 	return GL_FRAGMENT_SHADER;
    421 }
    422 
    423 sw::Shader *FragmentShader::getShader() const
    424 {
    425 	return pixelShader;
    426 }
    427 
    428 sw::PixelShader *FragmentShader::getPixelShader() const
    429 {
    430 	return pixelShader;
    431 }
    432 
    433 void FragmentShader::createShader()
    434 {
    435 	delete pixelShader;
    436 	pixelShader = new sw::PixelShader();
    437 }
    438 
    439 void FragmentShader::deleteShader()
    440 {
    441 	delete pixelShader;
    442 	pixelShader = nullptr;
    443 }
    444 
    445 }
    446