Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

753 lines
19 KiB

//========= Copyright © 1996-2004, Valve LLC, All rights reserved. ============
//
// This is the common include file to be included in SPU jobs.
// It takes care to remap/emulate some SPU-specific functinality on PPU
//
#ifndef PS3_SPU_JOB_SHARED_HDR
#define PS3_SPU_JOB_SHARED_HDR
#ifdef _PS3
#include <ps3/ps3_platform.h>
#include <cell/spurs/job_chain.h>
#include <cell/spurs/job_queue.h>
#include <cell/spurs/job_queue_port2.h>
#include <cell/dma/types.h>
//
// NOTE: Enable the following block for debugging GCM on SPU; works as of SDK 350
//
#if 0 && defined( __SPU__ )
#include <cell/gcm/gcm_macros.h>
#undef CELL_GCM_ASSERT
#undef CELL_GCM_ASSERTS
#define CELL_GCM_ASSERT(condition) Assert( condition )
#define CELL_GCM_ASSERTS(condition, description) AssertSpuMsg( condition, description )
#define CELL_GCM_ASSERT_ENABLE
#endif
enum DmaTagEnum_t
{
DMATAG_SYNC = 2, // used for synchronous transfers, where we need the transfer to finish very soon/immediately after issuing
DMATAG_TEXTURES = 3,
DMATAG_SHADERS = 4,
DMATAG_SCRATCH = 5, // used for DMA PUTs from Scratch memory, so we need to wait for this to finish before job finishes
// each jobchain needs 2 dma tags, up to tag 30
// DMATAG_EDGE_JOBCHAIN = 8,
// DMATAG_FPCP_JOBCHAIN = 10,
// DMATAG_GCM_JOBCHAIN = 12,
DMATAG_ANIM = 8, // non immediate dma's
DMATAG_BUILDINDICES = 8,
DMATAG_BUILDRENDERABLES = 8,
}; // shouldn't overlap with the tags used by the workload
// Enable this define to disable assert. This may be necessary to detect timing issues in DEBUG and RELEASE,
// or incorrectly generated code from compiler. When LSGUARD is enabled, we disable asserts to force potential issues.
#ifdef USE_LSGUARD
# define DISABLE_ASSERT
#endif
template <typename T>
inline T* AddBytes( T* p, int nBytes )
{
return ( T* )( int( p ) + nBytes );
}
template <typename T>
inline T Min( T a, T b )
{
return a < b ? a : b;
}
template <typename T>
inline T Max( T a, T b )
{
return a > b ? a : b;
}
template <typename T>
inline void Swap( T& a , T & b )
{
T c = a; a = b; b = c;
}
// <sergiy> should I port platform.h to SPU?
#ifdef SPU
#include <cell/spurs/job_context.h>
#include "cell/spurs/common.h"
#include <cell/atomic.h>
#include <spu_intrinsics.h>
#include <vmx2spu.h>
#define PPU_ONLY(X)
#define SPU_ONLY(X) X
#define vector __vector
void CheckBufferOverflow_Impl();
void CheckDmaGet_Impl( const void * pBuffer, size_t nSize );
#if defined(_CERT) || defined(DISABLE_ASSERT)
# define VjobSpuLog(...)
# define DebuggerBreak()
# define Warning(...)
# define CheckBufferOverflow()
# define CheckDmaGet(p, size)
#else
# include <spu_printf.h>
# define VjobSpuLog( MSG, ... ) spu_printf( "[%d]" MSG, cellSpursGetCurrentSpuId(), ##__VA_ARGS__ )
# define Msg( MSG, ... ) spu_printf( "[%d]" MSG, cellSpursGetCurrentSpuId(), ##__VA_ARGS__ )
#ifndef BASETYPES_H
#define DebuggerBreak() __asm volatile ("stopd $0,$0,$0")
#endif
# define Warning( MSG, ... ) spu_printf( "[%d] Warning: " MSG, cellSpursGetCurrentSpuId(), ##__VA_ARGS__ )
# define CELL_DMA_ASSERT_VERBOSE
# define CheckBufferOverflow() CheckBufferOverflow_Impl()
# define CheckDmaGet(p, size) CheckDmaGet_Impl( p, size )
#endif
#define LWSYNC_PPU_ONLY()
#define VJOB_IOBUFFER_DMATAG g_stInfo->dmaTag // fake DMA tag
#include <cell/spurs/common.h>
#define VjobDmaPut cellDmaPut
#define VjobDmaGet cellDmaGet
#define VjobDmaGetf cellDmaGetf
#define VjobDmaListGet cellDmaListGet
#define VjobDmaLargePut cellDmaLargePut
#define VjobDmaLargePutf cellDmaLargePutf
//#define VjobDmaLargePutb cellDmaLargePutb
#define VjobDmaPutf cellDmaPutf
#define VjobDmaSmallPut cellDmaSmallPut
#define VjobDmaSmallPutf cellDmaSmallPutf
//#define VjobDmaSmallPutb cellDmaSmallPutb
#define VjobDmaSmallGet cellDmaSmallGet
#define VjobWaitTagStatusAll cellDmaWaitTagStatusAll
#define VjobWaitTagStatusImmediate cellDmaWaitTagStatusImmediate
#define VjobDmaGetUint32 cellDmaGetUint32
#define VjobDmaPutUint32 cellDmaPutUint32
#define VjobDmaGetUint64 cellDmaGetUint64
#define VjobDmaPutUint64 cellDmaPutUint64
#define VjobDmaUnalignedPutf cellDmaUnalignedPutf
#define VjobDmaUnalignedPut cellDmaUnalignedPut
#define VjobDmaPutfUintTemplate(SIZE, value, ea, tag, tid, rid) \
do { \
uint64_t __cellDma_ea = ea; \
uint32_t __cellDma_tag = tag; \
qword _buf = (qword)spu_splats(value); \
cellDmaDataAssert(__cellDma_ea,sizeof(uint##SIZE##_t),__cellDma_tag); \
cellDmaAndWait(cellDmaEa2Ls(__cellDma_ea,&_buf),__cellDma_ea,sizeof(uint##SIZE##_t),__cellDma_tag,MFC_CMD_WORD(tid,rid,MFC_PUTF_CMD)); \
} while(0)
#define VjobDmaPutfUint8(value, ea, tag) cellDmaPutUintTemplate(8, ((uint8_t)value), ea, tag, 0, 0)
#define VjobDmaPutfUint16(value, ea, tag) cellDmaPutUintTemplate(16, ((uint16_t)value), ea, tag, 0, 0)
#define VjobDmaPutfUint32(value, ea, tag) cellDmaPutUintTemplate(32, ((uint32_t)value), ea, tag, 0, 0)
#define VjobDmaPutfUint64(value, ea, tag) cellDmaPutUintTemplate(64, ((uint64_t)value), ea, tag, 0, 0)
#define VjobSpuId() int( cellSpursGetCurrentSpuId() )
#define V_memset __builtin_memset
#define V_memcpy __builtin_memcpy
#if !defined ARRAYSIZE
#define ARRAYSIZE( ARRAY ) ( sizeof( ARRAY ) / sizeof( ( ARRAY )[0] ) )
#endif
typedef signed int int32;
typedef unsigned int uint;
typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef signed int int32;
typedef unsigned int uint32;
typedef signed long long int64;
typedef unsigned long long uint64;
typedef unsigned int uintp;
typedef vector float fltx4 ;
#define INT_MAX 0x7fffffff
#define DECL_ALIGN(x) __attribute__( ( aligned( x ) ) )
#ifndef BASETYPES_H
#define ALIGN16 DECL_ALIGN(16)
#define ALIGN16_POST
#define ALIGN128 DECL_ALIGN(128)
#define ALIGN128_POST
template <typename T>
inline T AlignValue( T val, uintp alignment )
{
return ( T )( ( ( uintp )val + alignment - 1 ) & ~( alignment - 1 ) );
}
#define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) )
inline bool IsPowerOfTwo( uint x )
{
return ( x & ( x - 1 ) ) == 0;
}
#endif
#define FORCEINLINE inline /* __attribute__ ((always_inline)) */
#define IsPlatformPS3() 1
#define IsPlatformPS3_PPU() 0
#define IsPlatformPS3_SPU() 1
#define IsPlatformX360() 0
#define IsPlatformOSX() 0
#if !defined RESTRICT
#define RESTRICT
#endif
#define V_memset __builtin_memset
#define V_memcpy __builtin_memcpy
inline void VjobPpuRereadEA( uintp ea ){}
#if defined(_CERT) || defined(DISABLE_ASSERT)
#define Assert(x) ((void)(0))
#define AssertSpuMsg(x,MSG,...)((void)0)
#ifndef DBG_H
#define COMPILE_TIME_ASSERT( pred ) // to avoid any unpredictable affects in the optimizer
#endif
#else
#define DBGFLAG_ASSERT
#ifndef DBG_H
#define Assert(x) do{if( !( x ) ) { spu_printf( "Assert on SPU[%d](" #x ")\n", cellSpursGetCurrentSpuId() ); DebuggerBreak(); } }while(0)
#endif
#define AssertSpuMsg(x,MSG,...) do{if( !( x ) ) { spu_printf( "Assert on SPU[%d](" #x "), " MSG, cellSpursGetCurrentSpuId(), ## __VA_ARGS__ ); DebuggerBreak(); } }while(0)
#ifndef DBG_H
#define COMPILE_TIME_ASSERT( pred ) switch(0){case 0:case pred:;}
#endif
#endif
// mimic the PPU class on SPU
// template< int bytesAlignment, class T >
// class CAlignedNewDelete : public T
// {public:
// }
// WARNING: SLOWNESS. DO NOT USE IN PRODUCTION.
inline void DebugMemcpyEa( uint eaDest, uint eaSrc, uint nSize, void *lsScratch )
{
Assert( ! ( 0xF & ( eaSrc | eaDest | nSize ) ) );
uint nBytesLeft = nSize, nOffset = 0;
while( nBytesLeft )
{
uint nChunk = Min<uint>( 16 * 1024, nBytesLeft );
VjobDmaGet( lsScratch, eaSrc + nOffset, nChunk, DMATAG_SYNC, 0, 0 );
VjobWaitTagStatusAll( 1 << DMATAG_SYNC );
VjobDmaPut( lsScratch, eaDest + nOffset, nChunk, DMATAG_SYNC, 0, 0 );
VjobWaitTagStatusAll( 1 << DMATAG_SYNC );
nBytesLeft -= nChunk;
nOffset += nChunk;
}
}
#define vec_to_uint32(X) si_to_uint( ( qword )( X ) )
#define VjobQueuePort2PushJob( eaPort, eaJob, sizeDesc, tag, dmaTag, flag ) cellSpursJobQueuePort2PushJob( (uintp)( eaPort ), (uintp)( eaJob ), ( sizeDesc ), ( tag ), ( dmaTag ), ( flag ) )
#define VjobQueuePort2PushSync( eaPort2, tagMask, dmaTag, flag ) cellSpursJobQueuePort2PushSync( ( uintp ) ( eaPort2), ( tagMask ), ( dmaTag ), ( flag ) )
inline void VjobQueuePort2PushJobBlocking( CellSpursJobQueuePort2 *eaPort2, CellSpursJobHeader *eaJob, size_t sizeDesc, uint nQueueTag, uint nDmaTag )
{
int nError;
for(;;)
{
nError = cellSpursJobQueuePort2PushJob( uintp( eaPort2 ), uintp( eaJob ) , sizeDesc, nQueueTag, nDmaTag, CELL_SPURS_JOBQUEUE_FLAG_NON_BLOCKING );
if( nError != CELL_SPURS_JOB_ERROR_AGAIN )
{
break;
}
}
if ( nError != CELL_OK )
{
VjobSpuLog( "Cannot push job, error %d. RSX is going to hang, then SPUs, then PPU.\n", nError );
DebuggerBreak();
}
}
inline void VjobQueuePort2PushSyncBlocking( CellSpursJobQueuePort2 *eaPort2, unsigned tagMask, uint nDmaTag )
{
int nError;
for(;;)
{
nError = cellSpursJobQueuePort2PushSync( uintp( eaPort2 ), tagMask, nDmaTag, CELL_SPURS_JOBQUEUE_FLAG_NON_BLOCKING );
if( nError != CELL_SPURS_JOB_ERROR_AGAIN )
{
break;
}
}
if ( nError != CELL_OK )
{
VjobSpuLog( "Cannot push job, error %d. RSX is going to hang, then SPUs, then PPU.\n", nError );
DebuggerBreak();
}
}
#else
#include "tier0/platform.h"
#include "tier1/strtools.h"
#include "mathlib/ssemath.h"
#include <altivec.h>
#include <cell/spurs/job_context_types.h>
inline uint32_t GetCurrentSpuId()
{
return 0xFFFFFFFF;
}
using namespace ::cell::Spurs;
extern void VjobSpuLog( const char * p, ... );
#define VJOB_IOBUFFER_DMATAG 0 // fake DMA tag
#define PPU_ONLY(X) X
#define SPU_ONLY(X)
#ifdef _DEBUG
#define AssertSpuMsg(x,MSG,...) do { if( !( x ) ) { Warning( "Assert(" #x "), " MSG, ## __VA_ARGS__ ); DebuggerBreak(); } }while( 0 )
#else
#define AssertSpuMsg(x,MSG,...)
#endif
#define VjobQueuePort2PushJob( eaPort, eaJob, sizeDesc, tag, dmaTag, flag ) cellSpursJobQueuePort2PushJob( (CellSpursJobQueuePort2 *)( eaPort ), (CellSpursJobHeader *)( eaJob ), ( sizeDesc ), ( tag ), ( flag ) )
#define VjobQueuePort2PushSync( eaPort2, tagMask, dmaTag, flag ) cellSpursJobQueuePort2PushSync( (CellSpursJobQueuePort2 *) ( eaPort2), ( tagMask ), ( flag ) )
inline void VjobQueuePort2PushJobBlocking( CellSpursJobQueuePort2 *eaPort2, CellSpursJobHeader *eaJob, size_t sizeDesc, uint nQueueTag, uint nDmaTag )
{
int nError = cellSpursJobQueuePort2PushJob( eaPort2, eaJob, sizeDesc, nQueueTag, 0 );// synchronous call
(void) nError;
Assert( nError == CELL_OK );
}
inline void VjobQueuePort2PushSyncBlocking( CellSpursJobQueuePort2 *eaPort2, unsigned tagMask, uint nDmaTag )
{
int nError = cellSpursJobQueuePort2PushSync( eaPort2, tagMask, 0 ); // synchronous call
(void) nError;
Assert( nError == CELL_OK );
}
#define VjobSpuId() -1
#define LWSYNC_PPU_ONLY() __lwsync()
extern void VjobDmaPut(
const void * ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
extern void VjobDmaGet(
void * ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
extern void VjobDmaGetf(
void * ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
extern void VjobDmaListGet(
void *ls,
uint64_t ea,
const CellDmaListElement *list,
uint32_t listSize,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
extern void VjobDmaLargePut(
const void * ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
extern void VjobDmaLargePutf(
const void * ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
extern void VjobDmaLargePutb(
const void * ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
extern void VjobDmaPutf(
const void * ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
extern void VjobDmaSmallPut(
const void * ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
extern void VjobDmaSmallGet(
void * ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
extern void VjobDmaSmallPutb(
const void * ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
extern void VjobDmaSmallPutf(
const void * ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
// NOTE: implementation must wait for tag
uint32_t VjobDmaGetUint32(
uint64_t ea,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
void VjobDmaPutUint32(
uint32_t value,
uint64_t ea,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
uint64_t VjobDmaGetUint64(
uint64_t ea,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
void VjobDmaPutUint64(
uint64_t value,
uint64_t ea,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
void VjobDmaUnalignedPutf(
const void *ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
void VjobDmaUnalignedPut(
const void *ls,
uint64_t ea,
uint32_t size,
uint32_t tag,
uint32_t tid,
uint32_t rid
);
// These functions are empty because I'm too lazy to implement deferred DMA emulation ...
inline uint VjobWaitTagStatusAll( uint nTagMask ){ return nTagMask;}
inline uint VjobWaitTagStatusImmediate( uint nTagMask ) { return nTagMask ; }
#define VjobDmaPutfUint8(value, ea, tag) *(uint8*)ea = (uint8)value
#define VjobDmaPutfUint16(value, ea, tag) *(uint16*)ea = (uint16)value
#define VjobDmaPutfUint32(value, ea, tag) *(uint32*)ea = (uint32)value
#define VjobDmaPutfUint64(value, ea, tag) *(uint64*)ea = (uint64)value
void VjobPushJob( void ( *pfnMain )( CellSpursJobContext2 * stInfo, CellSpursJob256 * job ), CellSpursJob128 * job );
extern void VjobSpuLog( const char * p, ... );
extern void VjobPpuRereadEA( uintp ea );
inline void DebugMemcpyEa( uint eaDest, uint eaSrc, uint nSize, void *lsScratch )
{
Assert( ! ( 0xF & ( eaSrc | eaDest | nSize ) ) );
memcpy( (void*)eaDest, (void*)eaSrc, nSize );
}
extern void TestAlignBuffer();
#define vec_to_uint32(X) (*(uint32*)&(X))
#endif // SPU
#define VjobDmaEa2Ls16(ea, ls) ((uintptr_t)(ls)+((uint32_t)(ea)&15))
#define VjobDmaEa2Ls128(ea, ls) ((uintptr_t)(ls)+((uint32_t)(ea)&127))
inline uint32* PrepareSmallPut32( vector unsigned int * lsAligned, volatile uint32 * eaUnaligned, uint32 nInitialValue )
{
Assert( !( 3 & uint( lsAligned ) ) );
uint32 * ls = ( uint32* )VjobDmaEa2Ls16( eaUnaligned, lsAligned );
*ls = nInitialValue;
return ls;
}
inline uint64* PrepareSmallPut64( vector unsigned int * lsAligned, volatile uint64 * eaUnaligned, uint64 nInitialValue )
{
Assert( !( 7 & uint( lsAligned ) ) );
uint64 * ls = ( uint64* )VjobDmaEa2Ls16( eaUnaligned, lsAligned );
*ls = nInitialValue;
return ls;
}
extern CellSpursJobContext2* g_stInfo;
#ifndef IsDebug
# ifdef _DEBUG
# define IsDebug() true
# else
# define IsDebug() false
# endif
#endif
#ifndef IsCert
# ifdef _CERT
# define IsCert() true
# else
# define IsCert() false
# endif
#endif
extern uint g_nBreakMask ;
#ifdef _CERT
# define BreakOn( nId )
#else
# define BreakOn( nId ) do \
{ \
if( g_nBreakMask & ( 1 << nId ) ) \
DebuggerBreak(); \
}while( 0 )
#endif
inline void VjobDebugSpinCycles( uint nCycles )
{
if( !IsCert() )
{
#ifdef SPU
uint nStart = spu_read_decrementer();
while( nStart - spu_read_decrementer() < nCycles / 40 )
continue;
#else
sys_timer_usleep( nCycles / 3200 );
/*
uint nStart = __mftb();
while( __mftb() - nStart() < nCycles / 40 )
continue;
*/
#endif
}
}
// this is the DMA list element without notify or reserved fields, so that it's easy to fill it in
// and be sure there is no garbage left (in notify and reserved fields) and there are no bit field operations (to store size, which is effectively only 14-bit value)
struct BasicDmaListElement_t
{
uint32 size;
uint32 eal;
};
// shifts unaligned pBuffer of given size left by 0..15 bytes to make it aligned
// returns the aligned pointer, pBuffer & -16
extern void* AlignBuffer( void * pBuffer, uint nBytes);
//
// Adds constant nAdd to the given unaligned buffer of uint16's
//
extern void UnalignedBufferAddU16( uint16 * pBuffer, uint nCount, uint16 nAdd );
// SpursJob_t must be one of CellSpursJob64, CellSpursJob128, CellSpursJob256,...
// JobParam_t is the parameter structure passed to the job
template < typename JobParam_t , typename SpursJob_t >
inline JobParam_t * VjobGetJobParams( void * pJob )
{
Assert( sizeof( JobParam_t ) + sizeof( CellSpursJobHeader ) <= sizeof( SpursJob_t ) );
JobParam_t * pJobParams = ( JobParam_t* ) ( uintp( pJob ) + ( sizeof( SpursJob_t ) - sizeof( JobParam_t ) ) );
Assert( uintp( pJobParams + 1 ) == uintp( pJob ) + sizeof( SpursJob_t ) );
return pJobParams;
}
extern void UnalignedBufferAddU16( );
template <uint n> struct Log2{};
template<>struct Log2<8> {enum{VALUE=3};};
template<>struct Log2<16>{enum{VALUE=4};};
template<>struct Log2<32>{enum{VALUE=5};};
template<>struct Log2<256>{enum{VALUE=8};};
#define COMPILE_TIME_LOG2(VAL) ( Log2<VAL>::VALUE )
inline void ZeroMemAligned( void * p, uint nSize )
{
Assert( !( ( uintp( p ) | nSize ) & 15 ) );
for( uint i = 0; i < nSize; i += 16 )
{
*( vec_uint4* )( uintp( p ) + i ) = (vec_uint4){0,0,0,0};
}
}
inline void CopyMemAligned( void * pDst, const void * pSrc, uint nSize )
{
Assert( !( ( uintp( pDst ) | uintp( pSrc ) | nSize ) & 15 ) );
for( uint i = 0; i < nSize; i += 16 )
{
*( vec_uint4* )( uintp( pDst ) + i ) = *( vec_uint4* )( uintp( pSrc ) + i );
}
}
///////////////////////////////////////////////////////////////////////////
//
// Reference implementation
//
template <uint nBitCount>
class CBitArray
{
public:
void Clear()
{
for( uint i = 0; i < ( nBitCount >> 7 ); ++i )
{
m_qword[i] = ( vec_uint4 ){0,0,0,0};
}
//m_nSetCount = 0;
}
void SetRange( uint nStart, uint nEnd )
{
nEnd = Min( nEnd, nBitCount );
if( nStart > nEnd )
return;
//m_nSetCount = Max( nEnd, m_nSetCount );
uint nMask = uint( -1 ) >> ( nStart & 0x1F );
for( uint i = ( nStart >> 5 ); i < ( nEnd >> 5); ++i )
{
m_u32[i] |= nMask;
nMask = uint( -1 );
}
nMask &= ~( uint( -1 ) >> ( nEnd & 0x1F ) );
m_u32[ nEnd >> 5 ] |= nMask;
}
//uint GetSetCount()const{return m_nSetCount;}
uint GetFirst1( uint nFrom )const
{
for( uint i = nFrom; i < nBitCount; ++i )
if( GetBit( i ) )
return i;
return nBitCount;
}
uint GetFirst0( uint nFrom )const
{
for( uint i = nFrom; i < nBitCount; ++i )
if( !GetBit( i ) )
return i;
return nBitCount;
}
uint GetBit( uint n )const
{
return m_u32[ n >> 5 ] & ( 0x80000000 >> ( n & 0x1F ) );
}
protected:
union
{
vec_uint4 m_qword[ ( nBitCount + 127 ) / 128 ];
uint32 m_u32[ ( nBitCount + 31 ) / 32 ];
};
//uint m_nSetCount;
};
#endif // _PS3
#endif