Contents
Sponsored Feature: Common Performance Issues in Game Programming
 
 
Printer-Friendly VersionPrinter-Friendly Version
 
Latest News
spacer View All spacer
 
November 22, 2009
 
Video Game Watchdog National Institute On Media And The Family Shutting Down [11]
 
Modern Warfare 2 Infinity Ward's 'Most Successful PC Version' Yet [12]
 
New Tech, Design Details Of Project Natal To Emerge At Gamefest In February
spacer
Latest Jobs
spacer View All     Post a Job     RSS spacer
 
November 22, 2009
 
Sucker Punch Productions
Texture Artist
 
Sucker Punch Productions
3D Environment Artist
 
Sucker Punch Productions
Network Programmer
 
Sucker Punch Productions
Character Artist
 
Sony Online Entertainment
Brand Manager
 
Monolith Productions
Sr. Software Engineer, Engine - Monolith Productions - #113767
 
Crystal Dynamics
Sr. Level Designer
 
Gargantuan Studios
Technical Art Director
spacer
Latest Features
spacer View All spacer
 
November 22, 2009
 
arrow Upping The Craft: Susan O'Connor On Games Writing [6]
 
arrow Small Developers: Minimizing Risks in Large Productions - Part II [7]
 
arrow iPhone Piracy: The Inside Story [48]
 
arrow And Yet It Grows: Analyzing the Size and Growth of the European Game Market [5]
 
arrow NPD: Behind the Numbers, October 2009 [13]
 
arrow Reflecting On Uncharted 2: How They Did It [5]
 
arrow Sponsored Feature: Rasterization on Larrabee -- Adaptive Rasterization Helps Boost Efficiency
 
arrow Postmortem: Wadjet Eye's The Blackwell Convergence [2]
spacer
Latest Blogs
spacer View All     Post     RSS spacer
 
November 22, 2009
 
Time Fcuk
 
Accepting the Inherent Value of Games
 
Planckogenesis, Part II: Song Structure & Gravy Train [1]
spacer
About
spacer News Director:
Leigh Alexander
Features Director:
Christian Nutt
Editor At Large:
Chris Remo
Advertising:
John 'Malik' Watson
Recruitment/Education:
Gina Gross
 
Features
  Sponsored Feature: Common Performance Issues in Game Programming
by Becky Heineman
2 comments
Share RSS
 
 
June 18, 2008 Article Start Previous Page 3 of 3
 

Eliminate int->float conversions

If the data being converted is semi-static, like a frame time quantum or the width of a screen, the data can be duplicated and functions that read the integer version or the floating-point version can fetch it without penalty.

Example:

typedef struct ScreenSize_t {
int m_iWidth;
int m_iHeight;
float m_fWidth;
float m_fHeight;

Advertisement
inline Void SetHeight(int iWidth) {
m_iWidth = iWidth;
m_fWidth = static_cast(iWidth);
};
} ScreenSize_t;

So functions that need an integer value for processing load from the "i" form of the members, while functions that require a floating-point input fetch from the "f" form. These values could be updated by an inline function that updates both the integer and floating-point versions at the same time.

Another form of integer to floating point conversion is where an iterator is used and converted. Since floating point compares have their own set of issues, they too need to be minimized. In this example, the angle is generated with each loop by converting it from an integer to a floating point number, causing a Load-Hit-Store

VOIDDebugDraw::DrawRing( const XMFLOAT3 &Origin,
const XMFLOAT3 &MajorAxis, const XMFLOAT3 &MinorAxis, D3DCOLOR Color )
{
static const DWORD dwRingSegments = 32;
MeshVertexP verts[ dwRingSegments + 1 ];

XMVECTOR vOrigin = XMLoadFloat3( &Origin );
XMVECTOR vMajor = XMLoadFloat3( &MajorAxis );
XMVECTOR vMinor = XMLoadFloat3( &MinorAxis );

FLOAT fAngleDelta = XM_2PI / (float)dwRingSegments;
for( DWORD i = 0; i<dwRingSegments; i++)
{
FLOAT fAngle = (FLOAT)i * fAngleDelta;
XMVECTOR Pos;
Pos = XMVectorAdd( vOrigin, XMVectorScale( vMajor, cosf( fAngle ) ) );
Pos = XMVectorAdd( Pos, XMVectorScale( vMinor, sinf( fAngle ) ) );
XMStoreFloat3( (XMFLOAT3*)&verts[i], Pos );
}

verts[ dwRingSegments ] = verts[0];

SimpleShaders::SetDeclPos();
SimpleShaders::BeginShader_Transformed_ConstantColor
( g_matViewProjection, Color );
g_pd3dDevice->DrawPrimitiveUP( D3DPT_LINESTRIP, dwRingSegments, (const
VOID*)verts, sizeof( MeshVertexP ) );
SimpleShaders::EndShader();
}

With three lines changed, the Load-Hit-Store is removed and the functionality is intact.

VOID DebugDraw::DrawRing( const XMFLOAT3 &Origin,
const XMFLOAT3 &MajorAxis, const XMFLOAT3 &MinorAxis, D3DCOLOR Color )
{
static const DWORD dwRingSegments = 32;
MeshVertexP verts[ dwRingSegments + 1 ];

XMVECTOR vOrigin = XMLoadFloat3( &Origin );
XMVECTOR vMajor = XMLoadFloat3( &MajorAxis );
XMVECTOR vMinor = XMLoadFloat3( &MinorAxis );

FLOAT fAngleDelta = XM_2PI / (float)dwRingSegments;
FLOAT fi = 0.0f; // Added a copy of i as a float
for( DWORD i = 0; i<dwRingSegments; i++, fi+=1.0f ) // Inc fi
{
FLOAT fAngle = fi * fAngleDelta; // NO int to float conversion
XMVECTOR Pos;
Pos = XMVectorAdd( vOrigin, XMVectorScale( vMajor, cosf( fAngle ) ) );
Pos = XMVectorAdd( Pos, XMVectorScale( vMinor, sinf( fAngle ) ) );
XMStoreFloat3( (XMFLOAT3*)&verts[i], Pos );
}

verts[ dwRingSegments ] = verts[0];

SimpleShaders::SetDeclPos();
SimpleShaders::BeginShader_Transformed_ConstantColor
( g_matViewProjection, Color );
g_pd3dDevice->DrawPrimitiveUP( D3DPT_LINESTRIP, dwRingSegments, (const
VOID*)verts, sizeof( MeshVertexP ) );
SimpleShaders::EndShader();
}

Faster, 360, Code! Code!

It takes only a little discipline to write clean code, but it's also easy to create code that can inadvertently introduce performance bottlenecks. Using Microsoft tools like PIX will help you track down some of these, but the best way to avoid bottlenecks, is to be aware of how they can exist so that they aren't written into the code in the first place.

A good understanding of the underlying hardware is not crucial to modern game programming from a high level. However, with a solid foundation of how CPUs work as well as how they interact with the memory subsystems, programmers can write software that maximizes performance.

 
Article Start Previous Page 3 of 3
 
Comments

Ben Garcia
profile image
FWIW, these are pretty common traits/behaviors with many RISC processor architectures (which is why they're also referred to as "load/store" architectures).

Carlos O'Donell
profile image
Note: In general GCC 4.2 and above, on most targets, will turn the example code into m_iData+=100. More complex statements may require tweaking.


none
 
Comment:
 


Submit Comment