2009 • 41:58
OpenGL ES provides access to the stunning graphics power of iPhone and iPod touch. Learn how your application can create incredible visuals while maintaining high frame rates using the programmable pipeline enabled by OpenGL ES 2.0. Get specific recommendations for maximizing OpenGL ES performance and understand the best practices to keep your application on the fast path. This two-part session is essential for developers utilizing interactive graphics for games and other mobile 3D applications.
Speaker: Allan Schaffer
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Hello, I'm Allan Schaffe, the Graphics and Media Technology Evangelist at Apple. This presentation is the first in a two-part series on mastering OpenGL ES for iPhone. There's a lot to learn. Part 1 focuses on the environment that OpenGL ES operates in on the iPhone OS. I cover OpenGL ES versions and the devices where they're supported. And I explain the iPhone OS display system and walk you through optimizing the interaction between OpenGL ES and Core Animation.
Then I introduce CA DisplayLink, which can replace your use of NS Timer to drive your rendering loop. And finally, conclude with details about how OpenGL ES applications should take advantage of the ARM architecture. And whereas Part 1 focuses on the environment around OpenGL ES, Part 2 shines a spotlight onto mastering OpenGL ES itself. I explain the common architecture and the capabilities of the graphics processors, and then dive into specific performance recommendations for optimizing texture and geometry. So I hope you'll learn a lot from both parts. Now let's get started with Part 1.
So OpenGL ES is the interface for high-performance 3D graphics on the iPhone. And it goes beyond 3D. It is also the dominant API for hardware-accelerated 2D sprite-based rendering as well. Now, OpenGL ES is the mobile variant of the OpenGL standard from the desktop. It's defined by an industry consortium called the Kronos Group, of which Apple is an active participant. Allan Schaffer And OpenGL ES really provides a distillation of the scope of the desktop version of OpenGL and is a subset of the API. It's been pared down to an interface that's appropriate to the capabilities and feature set of embedded devices.
Now, the OpenGL ES API itself is really easy to learn, but mastering OpenGL ES can be more difficult. There's a lot to absorb. Of course, the first things you need to learn are the principles of 3D graphics, things like 3D transformations and linear algebra, and the concepts of defining vertices, normals, and colors, and then how those ideas are expressed in the OpenGL API and OpenGL shading language.
Then you need to also understand the architecture of the rendering system and the stages of the graphics pipeline. Because OpenGL is a state machine, but it's implemented in a pipelined architecture, so understanding the purpose of the various pipeline stages becomes critical to understanding the API itself. So that's just the beginning, but this represents just the basics of what's necessary to become proficient with OpenGL ES.
Then there's always platform-specific behavior that you have to master as well. How OpenGL fits into the display system, the render loop, and any CPU-specific behaviors for the devices that your app might be running on. And the attributes of the graphic processor as well. Its capabilities, its limits, and any device-specific extensions or best practices. And mastering this complexity is achieved by coding defensively, testing for the presence of capabilities you need, and querying the extensions and limits of the device you're running on. And either providing the full functionality in your app if the capability is there, or providing fallbacks if it's not.
And finally, in this category, there's a variety of optimization techniques that become critical to mastering OpenGL ES. It's specific to each stage of the graphics pipeline. And finally, there's many topics from the supporting technologies, such as any software you use for 3D modeling or texture painting or creating shaders.
There's a variety of more advanced techniques from the world of scene graphs and game engines to provide higher-level decisions about what needs to be drawn and how to draw it. Things like making the simple observation that certain objects in your scene might be off-screen at the moment and don't need to be submitted to the 3D graphics hardware at all, saving the hardware from having to do all that extra processing. And then more expert 3D rendering techniques themselves, such as multi-pass effects and more advanced shaders. So as you can see, this is a really long list, but it begins to explain the background and information you'll want to learn more about as you learn about using OpenGL ES.
Now, in this presentation, I focus on this middle section having to do with many of the iPhone-specific optimizations and best practices you'll need to know about. In Part 1, I focus on OpenGL versions and OpenGL's interaction with the display system, the render loop, and the ARM architecture. In Part 2, the focus is on platform capabilities, extensions, and limits, and optimizations for texture and geometry.
Now back in June this year at WWDC, we introduced the first iPhone devices that supported OpenGL ES version 2.0 and the ability to use a fully programmable graphics pipeline. So I'd like to describe some of what this change really means. OpenGL ES 1.1 is the API that we had been using since the beginning of iPhone OS devices.
This targets what's called a fixed function graphics pipeline. And what that means is that the various stages of the pipeline, the command processing, 3D transformations, the lighting calculations, and rasterization, fog, depth test, and other stages, all have fixed or predefined functionality. And you, the developer, have the ability to enable or disable various parts of the pipeline. And you can configure various parameters for each stage, but the calculations done are predefined and fundamentally cannot be changed.
Whereas OpenGL ES version 2.0 replaces many of these fixed pipeline stages with fully programmable stages, where you, the developer, write the code that will perform the calculations for each stage. So if you want higher quality lighting calculations, for example, you simply implement that yourself in a C-like shading language.
And either have your algorithm run on a per vertex or per pixel basis as commands are submitted to the graphics hardware. This enables an entirely new realm of capabilities for developers to create interactive 3D experiences and at a performance level that's never been seen before on a mobile platform.
These are some examples of the kinds of algorithms that can now be expressed in the GPU with a programmable pipeline. Unique lighting models, as I've just mentioned, the ability to have bump maps and environment maps for reflection and refraction performed by the GPU, various operations on the frame buffer for image processing, and a lot more.
So I'd like to start by actually showing you a demo that we developed at WWDC that really shows off some of the capabilities of the iPhone 3GS with OpenGL ES 2.0. So this demo is from a familiar genre. The ball moves from side to side, bouncing off my bat and off the walls as I try to score against the AI.
And you can see a smoke texture being laid down in the scene at the location of the ball each frame and then becoming part of the background. And as you can see, there's a fluid dynamic simulation actually running in a number of shaders, computing the density and velocity of the smoke particles. And you can see as I move my bat up and down that it affects the smoke in the region around it.
But the key is that all of the simulation is happening on the GPU. This leaves the CPU free to do everything else, the AI, the game dynamics, any networking, playing audio, and so on. Now, since all of this is implemented using shaders in the programmable pipeline, if I want to change modes, I can actually just change shaders.
So here is a bump map shader. Nine lines of GLSL, it takes a normal map and attenuates the light based on the normal and does the correct falloff for that light. And I hope this gives you the inspiration to learn more about OpenGL ES 2.0 and use it within your apps.
So for those of you who are beginners, I'd like to point out a few resources to help you learn OpenGL ES. The first is the OpenGL ES Programming Guide for iPhone from Apple. This has a lot of platform-specific information and tuning advice that you'll want to take advantage of.
The next is the OpenGL ES 2.0 Programming Guide called the Gold Book. This book was actually written prior to the introduction of the iPhone, but now this author has developed a number of iPhone-compatible code samples on their companion website. So it's highly recommended, especially to help you learn about shader programming and the capabilities of the OpenGL ES 2.0 API.
Then there's a number of books that originated from the desktop version of OpenGL. And the first of these is the OpenGL Shading Language book called the Orange Book and now in its third edition. This is a great resource for learning how to write shaders in GLSL. And once you've learned that, it's easy to carry that understanding over into learning GLSL ES. The next is the OpenGL programming guide itself, the Redbook, now in the 7th edition. This is the definitive treatment for OpenGL from the desktop and will teach you a lot of the concepts of OpenGL that carry over into OpenGL ES.
The OpenGL Super Bible, currently in its fourth edition, another book originally written for the desktop, but in this edition, there's a chapter detailing the changes you make for OpenGL ES. And finally, there are a number of resources online, such as the OpenGL.org website, where you'll find the OpenGL ES specification and some developer forms.
And finally, for beginners, the ideal place for you to get started is with the OpenGL ES application template in Xcode. This will show you how to get an OpenGL ES application up and running with an animation loop and an OpenGL ES context and frame buffer all set up for you.
Now, for those of you who are already familiar with OpenGL ES on the iPhone, there are three key changes that we've made in the template in the 3.1 version of the SDK that you really should go take a look at. The first is that the template now supports both OpenGL ES 1.1 and 2.0. It makes a runtime decision of the renderer based on whether the context creation is successful or not.
The second is that the render loop of the template is now being driven by something new we've added in iPhone OS 3.1 called CA Display Link. Or if you're not running 3.1, then it will fall back to an older method of using NS Timer. Now, I'll have a lot more to say about CA Display Link in just a minute.
And the third change to note is that the OpenGL ES 2.0 path is now using a simple vertex and fragment program for rendering. And this is really useful for developers who are accustomed to OpenGL ES 1.1. and could use a simple example of just how to set up a shader.
So now let's dive deeper into the specifics of OpenGL ES 1.1 and 2.0 on iPhone OS. So here's a chart outlining the platform support for OpenGL ES 1.1 and 2.0. And I'll be referring back to this several times during the presentation. But the first thing to notice is that OpenGL ES 1.1 is supported across all devices.
So an application you wrote using 1.1 in the early days of the iPhone SDK will continue to function, even on the latest hardware. Now, certain devices also support the programmable pipeline of OpenGL ES 2.0. And specifically, this is the iPhone 3GS and the 32 and 64 gigabyte versions of the third generation iPod touch.
That support correlates to the graphics processor used in each device. So the iPhone 3GS and third generation iPod touch both use the PowerVR SGX processor from Imagination Technologies. And all the other devices, the iPhone, iPhone 3G, and first and second generation iPod touch use the PowerVR MBX Lite processor as their GPU.
Now in Part 2 of the presentation, I'll be going into a lot of detail about the common architecture and the differences between the SGX and MBX Lite. But one more point to simply note is that both versions of OpenGL ES can coexist on the same device if the GPU supports that. And applications simply make a runtime decision of the renderer and API.
So here's how you configure which version of OpenGL ES you'll use in your application. The code for actually choosing the API is nothing new. It's configured by your OpenGL context, which on iPhone OS is handled by an Eagle context object. And when you initialize that object, you'll indicate which API version to use. In the case here, we're configuring our Eagle context to use the OpenGL ES 1.1 API. And assuming that's successful, we'll go on to use the fixed function pipeline normally.
Now, as I said, it's possible for one application to be written to support both of these API versions and make a runtime decision of which one to use, essentially based on the hardware you're running on. In such a case, you'd first attempt to create an OpenGL ES 2.0 context. And if that's successful, then it means you're running on a device which supports OpenGL ES 2.0. You can load shaders and go on to use the 2.0 API and the capabilities of a programmable pipeline.
However, in the same app, if it happens to be running on a device that only supports OpenGL ES 1.1, then the attempt to create a 2.0 context will fail. And we'll fall into this second bit of code where we're attempting to create a 1.1 context. Presumably, that will succeed and the app will go on to use the 1.1 API and fixed function pipeline.
So this is a very important capability. You're able to write a single application that takes advantage of the programmable pipeline when running on a device with that capability, while simultaneously supporting the fixed function GPUs in the rest of the product line to get the broadest possible device coverage.
Now, there's a final example to take note of. You can develop your application to only support OpenGL ES 2.0 and use that API in the programmable pipeline without providing any fallback to OpenGL ES 1.1, as shown here. However, if you do this, then you should also indicate that requirement in your InfoP list. In iPhone OS 3.0 and above, you're able to specify a list of required device capabilities.
OpenGL ES 2.0 is one of the requirements that you can set up. And actually, this is just one from a whole list that you can choose from. If your application required, let's say, the accelerometer and the magnetometer and OpenGL ES 2.0, you can list these under the UI required device capabilities token. Then those requirements would be reflected in the on-device version of the App Store when a user goes to purchase your app.
So next, I want to dive deeper into some of the specific information about using OpenGL ES on the iPhone OS. And I'll be covering these three topics. First, the interaction between OpenGL ES and the compositing and animation system provided by Core Animation. Then, some of the new functionality that's been added in iPhone OS 3.1 to drive your rendering loop. And finally, a brief mention at the end regarding optimizing for the ARM processor architecture. So, let's start with the display system.
The interaction between OpenGL ES and the display system on iPhone is handled by Core Animation. Core Animation really acts as the display manager on the iPhone, much in the same way that a window manager on your desktop handles multiple applications, each with its own window. On the iPhone, Core Animation handles typically a single application, but with a hierarchy of views that might be animated and composited together.
Now, layers are the fundamental building blocks used by core animation. We say that views are backed by a layer. This means that UIView contents get cached into a layer. And likewise, OpenGL ES content is rendered into a layer subclass called CA Eagle Layer. And all that's special about a CA Eagle Layer is that it knows how to reference the color render buffer attachment of a frame buffer object in OpenGL. Layers may be animated and composited as your application manipulates its view hierarchy, and any CA Eagle layers just become another participant in all of this.
So, let's look at this more conceptually. Your application has some data in a vertex array, which it will render with OpenGL ES, and the resulting pixels end up in the Color Render Buffer attachment to an FBO. The Eagle layer object knows how to reference the contents of that FBO. So at this point, we're just dealing with pixels and OpenGL can fall out of the picture.
And the UI view is backed by a layer that just happened to have its contents generated by OpenGL. That view and layer just become another participant with other views you might also have in a view hierarchy. For example, in this case, compositing with the UI label and UI slider.
So, the task for OpenGL developers is to optimize this interaction. And doing so means minimizing the compositing work to be done. And it turns out there's five things that can slow this down, listed here, and I'll go through them in more detail in just a moment. But it involves such things as the properties you set on your CA Eagle layer, the color format, retained backing, any transformations and its opacity, and any other activity that might be taking place in the rest of the view hierarchy. And it's worth noting that some of these have more of a performance impact than the others.
The first is the color format. So this is a property of the CA Eagle layer, and it can be set either to RGBA8, the default, for a 32-bit deep color render buffer format with alpha, or RGB 565, which is 16 bits deep. Now, RGB 565 provides half the color precision of RGBA8, but it uses half the memory bandwidth each frame.
The reason why this is important, potentially, is because, in particular, the devices that have the PowerVR MBX Lite are also very sensitive to memory bandwidth. And the performance of your application, in many cases, might be bottlenecked by the system memory bandwidth. So anything you can do to reduce the pressure on memory bandwidth could have a big performance benefit.
The second property to mention is retained backing, or sometimes this is referred to as backing store. This determines whether the contents of your color render buffer will be preserved after it's been presented. That's somewhat unusual in OpenGL applications, so it's off by default. But turning it on means that a copy of your render buffer will be made each frame, with a performance cost associated with making that copy.
The third on our list was transformations. Your CA Eagle layer. This is where your OpenGL content is being rendered. It will be composited fastest if no scaling transformation is applied to the layer, no subpixel translations are applied to the layer, and with a few limited exceptions, if no rotation is applied to the layer.
The only exception that applies is that on the iPhone 3GS and both the second and third generation iPod touch, rotations that are a multiple of 90 degrees can be done without any compositing performance penalty. But any other rotation, 1 degree, 45 degrees, and so on, or any other devices, namely the iPhone, the iPhone 3G, and the original iPod touch, will cause extra compositing work if any rotation is applied.
So the advice we've given to date has been to generally avoid setting any layer.transform. And instead, for example, to rotate your OpenGL content into landscape orientation, you'd simply use a 3D transformation on the model view matrix in OpenGL. And also swap your viewport width and height to handle the change in orientation.
But you should also watch out for any view controller above you in the hierarchy that may be putting a 90-degree rotation on you. In that case, you may need to put an inverse rotation on your CA Eagle there so they cancel out. Unless, as I had mentioned, your app happens to be running on one of the devices that can do a rotation without penalty.
The fourth topic is blended content. And so there's several scenarios. Other views might be composited on top of your CA Eagle layer or your CA Eagle layer might be composited on top of other views. And in either of these two cases, whatever's on top might be opaque or might have alpha.
The first case, where you have other views composited on top of a CA Eagle layer. This is actually okay. This is, for example, an OpenGL scene that has some buttons or a slider or some text overlaid on top of it. You'll see some loss of performance if the overlaid views aren't opaque. And anytime they change their content or are animated, there will be a performance penalty.
But the other case, where you have a semi-transparent CA Eagle layer being composited on top of another view, this is very expensive and has a serious performance impact. And I'll note, if you do this, you must use pre-multiplied alpha for proper compositing results. And I've seen a number of scenarios where developers have done this. Sometimes it's intentional, but many other times it doesn't seem like it's being done for the right reasons.
The scenario where I think it is for the right reason is in, for example, augmented reality types of applications, where a CA Eagle layer is being overlaid atop the UI image picker controller. In iPhone OS 3.1, there's a new property on the image picker called Camera Overlay View that's made for this very purpose. So in that case, you'll take the compositing hit for blending your CA Eagle layer, but at least what you're doing is intentional.
But the scenario where I've seen this compositing has been unnecessary has been in applications that were actually creating multiple CA Eagle layers and stacking them up on top of each other. And just to explain this, the one on the bottom had the background drawn in it, the one in the middle had various sprites being drawn and updated each frame, and then a third one on top had an overlay.
And this setup is very inefficient and is not necessary. Instead, it would be much more preferable to collapse all three into a single opaque CA Eagle layer. So the takeaway is to make sure your CA Eagle layer is opaque. Set the opaque property of the layer to yes and make sure also your view opacity is 1.0.
And the final optimization relates to other views which may be updating or being animated at the same time that you're rendering with OpenGL ES. As I mentioned earlier, you'll get faster performance if any views overlaid atop your CA Eagle layer are static. Or the inverse, you'll see best performance animating your views if the CA Eagle layer isn't being redrawn at the same time.
So the situation you should try to avoid is when both are updating or rendering or animating simultaneously. And I've especially seen this, for example, in OpenGL-based applications that overlay the main CA Eagle layer with a UI label for the current score of a game or current time or current speed. Some other value that's being updated every frame. You have to minimize or eliminate those updates to get the best OpenGL ES performance. Perhaps by rendering. your times and scores and so on directly in OpenGL.
Now, here's some great news, actually. In Instruments, you can bring up the Core Animation Instrument, and this has a number of diagnostics that you can enable from its debug options to monitor the compositor workload. And if you click these checkboxes while your device is attached, it'll show you any blending that's going on, any updates, and whether your OpenGL rendering is on the fast path, and so on.
So I'd like to show you how to do this yourself. Okay, I'm going to bring up instruments and go into the core animation instrument. I have my iPhone attached. Great. And now I'll bring up the debug options. And you can see a number of checkboxes here. Now I'm going to switch over to the phone and show you what's happening on device as I make various selections.
All right, so here we are on the iPhone. I'd like to show you first from the core animation instrument color blended layers. You can see that even here in the springboard. That'll show you the different layers on the device. Now, green means that these pixels are basically going through without any extra compositing work.
And red is extra compositing for layers that are being shown here. Now, this is really visible in one of the examples that we've put up on the iPhone Dev Center called GL image processing. This is an OpenGL example that has down at the bottom you can see a tab bar and then in the middle a slider. And also you can see up at the top the menu bar.
Now, there's a number of hotspots here as you can tell. So, for example, with the slider on the bottom, you can see that that is being composited directly over the OpenGL scene. And it's colored red for that reason. Now, I'm going to turn on flash updated regions. Great. So, now what this is showing is as I move.
As I select different items in the tab bar or as I move the slider around. You can see the parts of the screen that are actually being recomposited every frame. And so these would be a performance hit in OpenGL if you were doing OpenGL rendering at the same time. And then finally, let me turn these off and then I'll go to show color the OpenGL FastPath blue.
Now, here you see actually most of the pixels are coming through blue. And so that's very good. The only ones that aren't. Are for the tab bar at the bottom. And also, of course, the slider that's been put on top. So, those would be some hotspots. So, you might want to look at in this application if you were really trying to optimize core animation and the interaction with OpenGL ES.
So that's a quick look at using the Core Animation Instrument to see if your rendering is optimal or if it's requiring the display system to do a lot of extra work. It's a great resource and I'd actually recommend pausing this video right now and trying it out with your app.
So, to summarize, the CA Eagle layer is a layer subclass that OpenGL ES uses to participate in the normal view hierarchy. But OpenGL developers should try to optimize this interaction between OpenGL ES and core animation. And the things to look at are the color format, retain backing, and transform properties of the CA Eagle layer.
And to eliminate any cases where the layer itself is being alpha blended over other UIKit content. And minimize any other drawing being done at the same time. And you can use the debug options in the core animation instrument to check out what's actually happening in your app. All right, that was a big topic.
[Transcript missing]
Next, I have a few pieces of general guidance about managing your rendering loop. The first is that it's frequently a good idea to limit your frame rate to what you can normally achieve based on your average rendering load, rather than just running as fast as you can.
It's because an erratic frame rate, meaning one that changes every few frames as your rendering load changes, can be really jarring to the user and give them the impression of a very choppy and unsteady motion in your application. It's usually a better idea to set your frame rate to, say, 30 and always hit it than to set it to 60 and miss it every few frames, if that's the situation your app would be in.
A second bit of guidance is that many kinds of applications don't necessarily need to be blasting the graphics pipeline at 30 or 60 frames per second all the time. Particularly if your frame isn't changing at the moment, you could slow down or even pause your rendering. Certain casual games, for example, like a chess game, might be waiting for the user to make a move and could pull back on the workload given to the CPU and the graphics processor. and that can have a big savings on battery usage. Both CA DisplayLink and NSTimers have a facility for handling this.
And then a quick note about the behavior of present render buffer. This is what you call at the end of every frame in OpenGL ES, and the contents of the render buffer actually become undefined after they're presented. Now, on devices with the PowerVR MBX Lite, it just happened that the contents would remain unchanged, even though that was technically an undefined result.
Now, that behavior is not what you'll see on devices with the PowerVR SGX. The contents actually are destroyed after the call to present render buffer on those. So you either need to redraw the entire render buffer every frame, or if you do need to retain the contents, then you can enable retain backing with a performance cost.
And a final note about the rendering loop, less significant than what I've covered in previous slides, but still worthwhile, has to do with the OpenGL ES template itself. The template was written very defensively, assuming that developers will extend it in many ways. So it's built to handle the possibility that you are managing multiple OpenGL contexts or have multiple render buffer attachments and so on. But if you're not doing those things, then those calls are being made every frame to set the context and bind the frame buffer and render buffer. Those become redundant. They're already set before you get into the rendering loop and you don't need to reset them every frame.
So you could just take them out and save a small amount of overhead. The render or draw frame method in the template typically set up the context, then it would bind the default frame buffer, then issue a bunch of OpenGL commands to draw something, then binds the color render buffer, and finally calls present render buffer. But for the most basic applications, all you really need to be calling each frame are your drawing commands and present render buffer.
All right, so that's coverage of the render loop. So just remember, make a runtime decision of how you drive your render loop based on the OS version. If you're running on 3.1 or above, you can use CA Display Link, and otherwise you'll use timers or another method you've developed.
You should limit your frame rate so it will remain steady as your rendering load changes, and pause your rendering if nothing is changing. And finally, note that a few of these calls in the template are redundant and can be removed if you're not using multiple contexts or multiple framebuffer object attachments.
And the final topic for this video has to do with a bit of optimization that you can do for the ARM processor. So let me start with devices that support the ARMv6 processor architecture. This is the original iPhone, the iPhone 3G, and first and second generation iPod touch.
And when the compiler is generating code for these devices, it will use either the thumb instruction set or ARM instruction set. And thumb is the default. Thumb instructions are 16-bit wide instead of 32-bit wide for ARM, which means that you can pack twice as many thumb instructions into the same code space as a given number of ARM instructions. That reduces your overall code size for your binary by a fair amount, potentially, and it allows twice as many instructions to be present in the cache at any particular moment.
But the thumb instruction set does not support floating point. So when the compiler needs to generate instructions to handle some floating point code, it actually briefly switches over to the native ARM instruction set, executes those instructions, and then switches back. And that switch comes with a slight performance cost. Now, many applications never notice this because they don't do enough floating point calculations for it to really be an issue. And they more than make up for it by having more instructions take advantage of the instruction cache.
But many graphical applications, and in particular many OpenGL ES-based applications, are more floating-point heavy than average. And the overhead of this switching back and forth becomes noticeable. So in those instances, and only on the devices that use the ARMv6 processor architecture, we recommend telling the compiler to generate ARM instructions all the time.
You lose the advantages of the smaller code size and the gains you would have from having more instructions in cache, but now floating-point calculations can be handled without the extra switching overhead, which for floating-point heavy applications can be a significant net performance win. Now, as I said, this optimization is specific to devices supporting the ARMv6 architecture. And again, those are the original iPhone, iPhone 3G, and first and second generation iPod touch.
Now, if on the other hand, your application is running on a device that supports the ARMv7 architecture, and this is specifically the iPhone 3GS and the third generation iPod touch, then in this case, we recommend sticking with Thumb. Or for this architecture, it's actually called Thumb 2. And Thumb 2 has a hybrid instruction set, mostly consisting of 16-bit instructions, but also containing 32-bit extensions for floating point.
So with Thumb 2, you get all the advantages of regular Thumb, the smaller code size, more instructions in the cache, while also natively supporting floating point without needing to switch to ARM mode. And in fact, on these devices supporting the ARMv7 architecture, using the ARM instruction set doesn't buy you anything. You just get less advantage from the instruction cache and a larger executable.
So as a practical matter, this means that we need to set up our build so that we create both an ARMv7. So we'll create an ARMv6 and an ARMv7 version of our binary. Then we'll turn Thumb off for the ARMv6 binary and leave Thumb 2 turned on for the ARMv7 binary.
That's a lot to keep straight, so I'll walk you through how it's done. And some of this is actually already baked into the OpenGL ES application template in Xcode. So in this case, I'm going to use the view template of a view-based application, just to have a clean start. And I start by opening up my target info. Going to the build settings.
And first I'm going to go into the architecture setting and set this to optimized, both ARMv6 and v7. So this will instruct the compiler to generate both an ARMv6 and ARMv7 version of my binary, and will put both of them into my application bundle. This idea is very similar to that of a universal binary on the Mac desktop systems. Next I'll find my thumb settings.
And there it is, compile for thumb. Right now it's turned on. And if I highlight this, see if I turn it off, it'll be off for both ARMv6 and ARMv7. And instead what I want is to set up a conditional build setting. So I'll do that here, add build setting condition.
And if I select Arm 6, Arm v6, I'll create another one, somewhat redundant, but just for completeness, Arm v7. So I want thumb to be turned on for Arm v7 and turned off for Arm v6. That's what I have. And that's it. Now my project is set up to build with the ARM instruction set on ARMv6 and with the Thumb2 instruction set for ARMv7.
All right, so that concludes Part 1 of Mastering OpenGL ES for iPhone. I've covered OpenGL ES versions, had a long discussion about optimizing compositing, introduced CA DisplayLink, and ended with details about thumb and arm. In Part 2, I dive much deeper within OpenGL ES itself. I cover the common architecture, the capabilities, and the differences between the PowerVR MBX Lite and the PowerVR SGX.
Then dive deep into texture optimization and geometry optimization. So I hope you'll stay tuned for that. In the meantime, here's my contact information and a link to the iPhone Dev Center, where you'll find a variety of OpenGL ES-based sample code projects and the OpenGL ES programming guide for iPhone. And you can also find me online in the developer forums. Thank you for watching.