Exemplo n.º 1
0
/*
 * Carga un programa a partir de un fichero binario (ya compilado), o, si este
 * no existe, compila y construye un programa a partir de un fichero con el
 * código fuente.
 * > ctx : Contexto en el cual crear el programa.
 * > ds  : Array con los dispostivos seleccionados.
 * > src : Ruta del código fuente.
 * > bin : Ruta del fichero binario.
 */
cl_program loadProgramFromArgs (cl_context ctx, cl_device_id *ds, 
								cl_uint ds_size, char *src, char *bin) {
	FILE *f;
	char *data;
	cl_program prg;
	size_t size;

	if ((f = fopen(bin, "rb")) != NULL)
		return loadBinaryProgram(ctx, ds, ds_size, bin);

	if ((f = fopen(src, "r")) != NULL) {
		printf("Compiling %s... ", src);
		fflush(stdout);
		data = (char*) malloc(PRG_BUFFER_SIZE * sizeof(char));
		size = fread(data, 1, PRG_BUFFER_SIZE, f);
		fclose(f);
		data[size] = '\0';
		prg = clCreateProgramWithSource(ctx, 1, (const char**)&data, NULL,
			NULL);

		if(clBuildProgram(prg, ds_size, ds, NULL, NULL, NULL) != CL_SUCCESS) {
			fprintf(stderr, "FAIL\n");
			showProgramBuildLog(ds, ds_size, prg);
			return NULL;
		}
		printf("OK\n");

		saveBinaryProgram(prg, ds, ds_size, bin);
		return prg;
	}

	return NULL;
}
/*!****************************************************************************
 @Function		InitView
 @Return		bool		true if no error occured
 @Description	Code in InitView() will be called by PVRShell upon
				initialization or after a change in the rendering context.
				Used to initialize variables that are dependant on the rendering
				context (e.g. textures, vertex buffers, etc.)
******************************************************************************/
bool OGLES2BinaryShader::InitView()
{
	// Initialise a colour to draw our triangle
	// (For this training course, binary loaded shaders use a different colour
	// To show which is being used. Red means it had to compile the shaders,
	// green shows that it retrieved the binary from memory.
	float afColour[]={0.0,0.0,0.0};

	// Filename and path strings.
	char* pWritePath = (char*)PVRShellGet(prefWritePath);
	char* shaderPath = new char[strlen(pWritePath) + 13];
	sprintf(shaderPath, "%sShaderBinary", pWritePath);

	//Checks if the program binary handling extension is supported.
	m_bBinaryShaderSupported=IsGLExtensionSupported("GL_OES_get_program_binary");

#if !defined (TARGET_OS_IPHONE)
	glGetProgramBinaryOES=0;
	glProgramBinaryOES=0;

	// Retrieves the functions needed to use the extension.
	if (m_bBinaryShaderSupported)
	{
		glGetProgramBinaryOES = (PFNGLGETPROGRAMBINARYOESPROC) PVRGetProcAddress(glGetProgramBinaryOES);
		glProgramBinaryOES = (PFNGLPROGRAMBINARYOESPROC) PVRGetProcAddress(glProgramBinaryOES);
	}
#endif

	// If binary shaders are not supported or there isn't a valid binary shader stored, recompile the shaders.
	if (!m_bBinaryShaderSupported || !loadBinaryProgram(shaderPath,m_uiProgramObject))
	{
		{
			// Fragment shader code
			const char* pszFragShader = "\
				uniform lowp vec3 myColour;\
				void main (void)\
				{\
					gl_FragColor = vec4(myColour, 1.0);\
				}";

			// Create the fragment shader object
			m_uiFragShader = glCreateShader(GL_FRAGMENT_SHADER);

			// Load the source code into it
			glShaderSource(m_uiFragShader, 1, (const char**)&pszFragShader, NULL);

			// Compile the source code
			glCompileShader(m_uiFragShader);

			// Check if compilation succeeded
			GLint bShaderCompiled;
			glGetShaderiv(m_uiFragShader, GL_COMPILE_STATUS, &bShaderCompiled);
			if (!bShaderCompiled)
			{
				// An error happened, first retrieve the length of the log message
				int i32InfoLogLength, i32CharsWritten;
				glGetShaderiv(m_uiFragShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);

				// Allocate enough space for the message and retrieve it
				char* pszInfoLog = new char[i32InfoLogLength];
				glGetShaderInfoLog(m_uiFragShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);

				/*
					Displays the message in a dialog box when the application quits
					using the shell PVRShellSet function with first parameter prefExitMessage.
				*/
				char* pszMsg = new char[i32InfoLogLength+256];
				strcpy(pszMsg, "Failed to compile fragment shader: ");
				strcat(pszMsg, pszInfoLog);
				PVRShellSet(prefExitMessage, pszMsg);

				delete [] pszMsg;
				delete [] pszInfoLog;
				delete [] shaderPath;
				return false;
			}
		}
/*!****************************************************************************
 @Function		InitView
 @Return		bool		true if no error occured
 @Description	Code in InitView() will be called by PVRShell upon
				initialization or after a change in the rendering context.
				Used to initialize variables that are dependant on the rendering
				context (e.g. textures, vertex buffers, etc.)
******************************************************************************/
bool OGLES3BinaryShader::InitView()
{
	// Initialise a colour to draw our triangle
	// (For this training course, binary loaded shaders use a different colour
	// To show which is being used. Red means it had to compile the shaders,
	// green shows that it retrieved the binary from memory.
	float afColour[]={0.0,0.0,0.0};

	// Filename and path strings.
	char* pWritePath = (char*)PVRShellGet(prefWritePath);
	char* shaderPath = new char[strlen(pWritePath) + 13];
	sprintf(shaderPath, "%sShaderBinary", pWritePath);

	// If binary shaders are not supported or there isn't a valid binary shader stored, recompile the shaders.
	if(!loadBinaryProgram(shaderPath,m_uiProgramObject))
	{
		{
			// Fragment shader code
			const char* pszFragShader = "\
				#version 300 es\n\
				uniform lowp vec3 myColour;\
				layout (location = 0) out lowp vec4 oColour;\
				void main (void)\
				{\
					oColour = vec4(myColour, 1.0);\
				}";

			// Create the fragment shader object
			m_uiFragShader = glCreateShader(GL_FRAGMENT_SHADER);

			// Load the source code into it
			glShaderSource(m_uiFragShader, 1, (const char**)&pszFragShader, NULL);

			// Compile the source code
			glCompileShader(m_uiFragShader);

			// Check if compilation succeeded
			GLint bShaderCompiled;
			glGetShaderiv(m_uiFragShader, GL_COMPILE_STATUS, &bShaderCompiled);
			if (!bShaderCompiled)
			{
				// An error happened, first retrieve the length of the log message
				int i32InfoLogLength, i32CharsWritten;
				glGetShaderiv(m_uiFragShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);

				// Allocate enough space for the message and retrieve it
				char* pszInfoLog = new char[i32InfoLogLength];
				glGetShaderInfoLog(m_uiFragShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);

				/*
					Displays the message in a dialog box when the application quits
					using the shell PVRShellSet function with first parameter prefExitMessage.
				*/
				char* pszMsg = new char[i32InfoLogLength+256];
				strcpy(pszMsg, "Failed to compile fragment shader: ");
				strcat(pszMsg, pszInfoLog);
				PVRShellSet(prefExitMessage, pszMsg);

				delete [] pszMsg;
				delete [] pszInfoLog;
				delete [] shaderPath;
				return false;
			}
		}

		{
			// Vertex shader code.
			const char* pszVertShader = "\
			#version 300 es\n\
			layout (location = 0) in highp vec4 myVertex;\
			uniform mediump mat4	myPMVMatrix;\
			void main(void)\
			{\
				gl_Position = myPMVMatrix * myVertex;\
			}";
			// Loads the vertex shader in the same way
			m_uiVertexShader = glCreateShader(GL_VERTEX_SHADER);
			glShaderSource(m_uiVertexShader, 1, (const char**)&pszVertShader, NULL);
			glCompileShader(m_uiVertexShader);

			// Checks if the shader has compiled.
			GLint bShaderCompiled;
			glGetShaderiv(m_uiVertexShader, GL_COMPILE_STATUS, &bShaderCompiled);
			if (!bShaderCompiled)
			{
				int i32InfoLogLength, i32CharsWritten;
				glGetShaderiv(m_uiVertexShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
				char* pszInfoLog = new char[i32InfoLogLength];
				glGetShaderInfoLog(m_uiVertexShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
				char* pszMsg = new char[i32InfoLogLength+256];
				strcpy(pszMsg, "Failed to compile vertex shader: ");
				strcat(pszMsg, pszInfoLog);
				PVRShellSet(prefExitMessage, pszMsg);

				delete [] pszMsg;
				delete [] pszInfoLog;
				delete [] shaderPath;
				return false;
			}
		}

		// Create the shader program
		m_uiProgramObject = glCreateProgram();

		// Attach the fragment and vertex shaders to the shader program.
		glAttachShader(m_uiProgramObject, m_uiFragShader);
		glAttachShader(m_uiProgramObject, m_uiVertexShader);

		// Bind the custom vertex attribute "myVertex" to location VERTEX_ARRAY
		glBindAttribLocation(m_uiProgramObject, VERTEX_ARRAY, "myVertex");

		// Link the program
		glLinkProgram(m_uiProgramObject);

		// Check if linking succeeded in the same way we checked for compilation success
		GLint bLinked;
		glGetProgramiv(m_uiProgramObject, GL_LINK_STATUS, &bLinked);
		if (!bLinked)
		{
			int i32InfoLogLength, i32CharsWritten;
			glGetProgramiv(m_uiProgramObject, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
			char* pszInfoLog = new char[i32InfoLogLength];
			glGetProgramInfoLog(m_uiProgramObject, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
			char* pszMsg = new char[i32InfoLogLength+256];
			strcpy(pszMsg, "Failed to link program: ");
			strcat(pszMsg, pszInfoLog);
			PVRShellSet(prefExitMessage, pszMsg);

			delete [] pszMsg;
			delete [] pszInfoLog;
			delete [] shaderPath;
			return false;
		}

		// As there is no stored binary, save the current binary out for use later.
		// Note that this is done after both binding attributes and linking -
		// none of these can be performed after
		saveBinaryProgram(shaderPath,m_uiProgramObject);

		//Set red channel of the colour to maximum - red shows that the shaders had to be compiled.
		afColour[0]=1.0f;
	}
	else
	{
		//Set green channel of the colour to maximum - green shows that the shaders were loaded from binary files.
		afColour[1]=1.0f;
	}

	delete[] shaderPath;

	// Uses the program.
	glUseProgram(m_uiProgramObject);

	// Bind the colour to the fragment shader.
	GLint i32ColourLocation = glGetUniformLocation(m_uiProgramObject, "myColour");

	// Then passes the colour to that variable
	glUniform3fv(i32ColourLocation, 1, afColour);

	// Sets the clear color
	glClearColor(0.6f, 0.8f, 1.0f, 1.0f);

	// Create VBO for the triangle from our data

	// Vertex data
	GLfloat afVertices[] = {-0.4f,-0.4f,0.0f,  0.4f,-0.4f,0.0f,   0.0f,0.4f,0.0f};

	// Gen VBO
	glGenBuffers(1, &m_ui32Vbo);

	// Bind the VBO
	glBindBuffer(GL_ARRAY_BUFFER, m_ui32Vbo);

	// Set the buffer's data
	glBufferData(GL_ARRAY_BUFFER, 3 * (3 * sizeof(GLfloat)) /* 3 Vertices of 3 floats in size */, afVertices, GL_STATIC_DRAW);

	// Unbind the VBO
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	// Enable culling
	glEnable(GL_CULL_FACE);
	return true;
}