XCode4 Build Rules for iOS

For a while now I have been manually compiling files since my asset conversion pipeline tool is not quite finished yet.

So I took at look into Build Rules in XCode. My main trouble within using them was finding the environment variables, even googling them doesn’t turn up much information.

I think the output files act as an error check, if the output file fails to appear then the tool failed.

One other thing I had an issue with was the source files list. I tried comma and semi colon delimiters, and spaces, but the TGA file kept giving the warning on Tree1.tga. I have yet t0 find the a way to do this without multiple entries. And I’m thinking a separate tool for building files may be easier.

 

iPhone Orientation

Earlier I wanted to test my engine with autorotation for when an iOS device’s orientation changes. I spent a fair bit of time trying to work out why, sure that I had written some code somewhere to stop it from triggering.

After creating another app and still haven’t the same problem, I was about to report it as a bug when the answer dawned on me, I had the orientation lock on.

It would be nice if you could do it on an application basis as well as a global one, since I only turn it on because photos get orientated incorrectly.

The contents of my “Useless” app folder: Stocks, Weather, Contacts, Calculator, Voice Memos, Compass, Reminders. If only you could turn off the default apps as well.

On another note, I’ve added a page next to website for iOS specific links.

iOS: Using Separate Shaders

One of the lovely additions to iOS5 is there is now the ability to use separate vertex and fragment shaders (GL_EXT_separate_shader_objects).

The first step in using separate shaders is to create an object to bind them onto that will be our overall shader program, known as a pipeline object.

GLuint gProgramPipeline = 0;
GLuint gVertexProgram = 0;
GLuint gFragmentProgram = 0;
 
//
//
int main()
{
	//
	CreatePipeline();
	CreateShaders();
 
	//
	BindShadersToPipeline();
 
	//
	do
	{
		//
		UpdateUniforms();
 
		//
		BindPipeline();
		DrawSomething();
		UnbindPipeline();
	}
	while( true );
 
	//
	DestroyShaders();
	DestroyPipeline();
}
 
//
//
void CreatePipeline()
{
	glGenProgramPipelinesEXT( 1, &gProgramPipeline );
}
 
//
//
void DestroyPipeline()
{
	if( gProgramPipeline )
	{
		glDeleteProgramPipelinesEXT( 1, &gProgramPipeline );
		gProgramPipeline = 0;
	}
}

This pipeline object acts similar to vertex array object (VAO) only with shader programs, however instead of using glUseProgram, a separate function glUseProgramStagesEXT() must be used to bind the shader program to the pipeline, specifying the role of the shader program.

//
//
void BindShadersToPipeline()
{
	glUseProgramStagesEXT( gProgramPipeline, GL_VERTEX_SHADER_BIT_EXT, gVertexProgram );
	glUseProgramStagesEXT( gProgramPipeline, GL_FRAGMENT_SHADER_BIT_EXT, gFragmentProgram );
}

Updating uniforms is slightly different as well.

//
//
void UpdateUniforms()
{
	//
	GLint uniformLoc = glGetUniformLocation( gVertexProgram, "myVertUniform" );
	glProgramUniform1fEXT( gVertexProgram,
			       uniformLoc,
			       1.248f );
 
	uniformLoc = glGetUniformLocation( gFragmentProgram, "myFragUniform" );
	glProgramUniform1fEXT( gFragmentProgram,
			       uniformLoc,
			       6.1218f );
 
	//
	uniformLoc = glGetUniformLocation( gVertexProgram, "myCommonUniform" );
	float commonValue = 2.0f;
 
	glProgramUniform1fEXT( gVertexProgram,
			       uniformLoc,
			       commonValue );
 
	uniformLoc = glGetUniformLocation( gFragmentProgram, "myCommonUniform" );
	glProgramUniform1fEXT( gVertexProgram,
			       uniformLoc,
			       commonValue );
}

Finally to use the program pipeline, we just need to bind it.

//
//
void BindPipeline()
{
	glBindProgramPipelineEXT( gProgramPipeline );
}
 
//
//
void UnbindPipeline()
{
	glBindProgramPipelineEXT( 0 );
}

fef

Bootstrap Server and thread yielding

PythonGodOne annoying this about iOS development is when the device crashes and you get the following message.

Couldn’t register com.yourcompany.youapp with the bootstrap server. Error: unknown error code.
This generally means that another instance of this process was already running or is hung in the debugger.

It usually means a restart of a few minutes. I kept getting these when using an iterative formula to calculate something. I have made a mistake of subtracting instead of adding, and I ended up getting into an infinite loop (I really should have put an attempt timeout in the while condition).

This happened about 5-6 times before I was able to track it down, and when working on the main thread, I couldn’t seem to put a breakpoint in to debug it.

However I found that calling sched_yield() on the main thread within my loop, did stop (or at least drastically reduce) the number of bootstrap failures.

“Internet Explorer, the Number One browser for downloading a better browser.”

LONG_MAX on 64bit OSX

hartnell-sensorites
Some Sensorites have been known to be dicks

I came by an annoying problem when I was adding some asserts to my FBX to Athena tool. I was basically adding a check to my vertex buffer size to make sure it was not larger than a GLsizeiptr (defined as a long in iOS5 SDK).

I’ve always assumed chars to be 8, shorts to be 16, longs to be 32 and ints to be whatever the system wants it to be (most likely the register size for an atomic copy). However, my tool is setup using 64bit OSX project, and the long comes out as 8 bytes, so the value given by LONG_MAX is huge, while the int remains at 4 bytes.

I wouldn’t have even noticed that my assert would have never been hit if it had not been for the warning the IDE gave after writing the statement, “Comparison is always true due to limited range of data type”.

In the end I just replaced LONG_MAX with INT32_MAX (stdint.h). And after a bit of googling, I found this on wikipedia.

The sizes of short, int, and long in C/C++ are dependent upon the implementation of the language:

  • On older, 16-bit operating systems, int was 16-bit and long was 32-bit.
  • On 32-bit Unix, DOS, and Windows, int and long are 32-bits, while long long is 64-bits. This is also true for 64-bit processors running 32-bit programs.
  • On 64-bit Unix, int is 32-bits, while long and long long are 64-bits.

While this does sound kinda familiar to me, I do not think I’ve ever had a situation where it has appeared to me until now.