Skip to main content

PS1 Performance: Graphics, Animation, and Sound

· 5 min read
Unity developer and creator of Polygon Engine

As I brought graphics, scripts, collision, animation, and audio together in Polygon Engine, I needed to look at the work they perform as a whole. Counting a scene's polygons helps explain part of that workload, but leaves out many operations needed to run the game.

Even a small room can contain scripts running continuously, animated objects, lights, and several active sounds. Some surfaces may also overlap and cover much of the screen. To decide what to optimize, I needed to understand the cost of each system and how those costs add up.

Frame time and memory usage​

One of the first distinctions is between memory use and processing time. A scene can stay within every memory limit and still take too long to update or draw. Capacity validation checks the stored data; understanding performance also requires measuring CPU and GPU work.

At a nominal video rate of 60 Hz, the interval between screen refreshes is about 16.7 milliseconds; at 50 Hz, it is 20 milliseconds. The game may render at a lower rate. When reviewing a measurement, I therefore distinguish the video rate, simulation step, and frames the game actually completes.

I also need to know whether a measurement includes processing or waiting. Timing a section of code that includes graphics synchronization may capture time the CPU spends waiting for the GPU. Attributing all of it to gameplay could lead me to optimize the wrong system. Understanding the result requires knowing where the measurement starts and ends.

Overdraw and visibility​

Two scenes with the same triangle count can place very different demands on the GPU. Small objects in the distance cover few pixels. Several large overlapping surfaces require drawing the same screen area repeatedly, even if the number of triangles is identical.

Repeatedly drawing pixels that will later be covered is overdraw. Transparency and certain surface arrangements can make it harder to avoid. Reducing the number of submitted triangles helps only if those triangles were a meaningful part of the bottleneck.

Visibility tools help reduce that work. Rooms and Portals can limit which parts of a level are submitted for drawing based on the space being viewed from. They depend on correctly configured connections between rooms. Their role is visibility control; they do not automatically stream the world in and out of memory.

When adjusting a portal, I need to check that everything the player can see remains visible. Restricting visibility too much creates gaps or disappearing objects; allowing too much provides little reduction in work. Inspection tools help find that balance without introducing rendering errors.

Lighting calculations​

With lighting, I also had to connect the editor's controls to the calculations available on PS1. The work relies on vertex lighting and prepared colors, with different results and costs from the per-pixel shaders and shadow maps common in modern engines.

The GTE provides useful lighting-related operations, but the engine still decides which surfaces are affected, prepares the inputs, and handles its supported light types. More lights and more affected vertices can mean more work before drawing begins.

In a corridor with fixed lamps, for example, some colors can be prepared in advance to suggest illumination. A light that moves or changes during play needs updates. Separating those cases lets runtime calculations focus on changes the player will actually see.

Animation data and deformation​

An animation clip needs stored poses or other animation data, and the runtime needs to evaluate the current pose. Mesh deformation then adds work that a static object does not require.

Polygon Engine's skeletal animation uses hard skinning: one bone influence per vertex. This limits deformation work but also affects model preparation. It works well for rigid joints; an area that needs a soft bend, such as a shoulder, requires more care because weights cannot blend across several bones.

When reviewing an animation, I need to consider bone count, clip length, sampling rate, and visible animated vertices. Reducing the mesh's triangle count can help rendering, but does not reduce the clip's data on its own. The skeletal animation guide explains the import process and its constraints.

Sound memory and playback voices​

The SPU provides 24 ADPCM voices and 512 KiB of sound RAM. Voices play audio samples, while memory limits how many samples can remain loaded and how much space is available for reverb. The SPU reference explains how both resources are used.

The same short sample can play on several voices at once. Many samples can also remain loaded while only a few are playing. I need to check both occupied memory and simultaneous playback; counting audio files is not enough to assess those limits.

A sound's role also affects its preparation. A door effect needs to respond promptly, while a long background track requires planning for storage and continuous playback. Scripts should trigger an effect when its event occurs: requesting it every frame can occupy multiple voices and accidentally repeat the sound.

Comparing performance measurements​

To compare results, I try to keep the same camera, interaction, and execution settings. I can then vary one specific aspect: reduce the lights affecting a surface, limit the visible area, run a script operation less frequently, or simplify an animation. This lets me relate the change to the measurement.

Those comparisons also depend on where the game runs. The editor lets me review a scene while working, an emulator lets me test the PS1 build, and the console lets me measure its behavior on real hardware. Desktop performance and capacity reports provide useful information, but evaluating target performance requires measurements on that target.

That is why I want the engine's tools to show both resource usage and execution times. Looking at them together helps me decide whether to change an asset, adjust a scene, or review a system. Integrating these modules has encouraged me to approach performance through specific changes whose effects I can check.