写了个测试程序,方便个人在使用中查询,不当之处请指出(以下结论均为三角形数为20000,一个批次中完成渲染)
1 在三角形数量不超过20000时,DrawIndexedPrimitive和DrawIndexedPrimitiveUP效率没有明显差别,
前提是创建buffer时没有使用D3DUSAGE_DYNAMIC,否则DrawIndexedPrimitive的性能不如DrawIndexedPrimitiveUP
2 创建buffer时,如果D3DUSAGE使用的是0,DrawIndexedPrimitive的性能不如DrawIndexedPrimitiveUP,
而且0和D3DUSAGE_WRITEONLY在三角形数量为20000时,性能差别比较大(差不多有100帧的差距)
3 尽量不要使用DrawPrimitive和DrawPrimitiveUP,尤其是DrawPrimitiveUP,效率比起前面两个函数,差很多
4 使用DrawIndexedPrimitive和DrawIndexedPrimitiveUP两个函数测试D3DPOOL_DEFAULT,D3DPOOL_MANAGED,
D3DPOOL_SYSTEMMEM。发现D3DPOOL_DEFAULT,D3DPOOL_MANAGED的效率差不多,D3DPOOL_DEFAULT表现稍好。
当使用D3DPOOL_SYSTEMMEM时,效率相对前面两个参数,DrawIndexedPrimitive有明显下降。
而DrawIndexedPrimitiveUP的速度稍有下降,而且DrawIndexedPrimitiveUP比DrawIndexedPrimitive要快
以下是测试程序:
// -----------------------------------------------------------------------------
// Desc: 全局变量
// -----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL; // Direct3D对象
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Direct3D设备对象
LPDIRECT3DVERTEXBUFFER9 g_pVB_Index = NULL; // 顶点缓冲区对象
LPDIRECT3DINDEXBUFFER9 g_pIB_Index = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // 顶点缓冲区对象
LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;
// -----------------------------------------------------------------------------
// Desc: 顶点结构
// -----------------------------------------------------------------------------
struct CUSTOMVERTEX
{
FLOAT x, y, z; // 顶点位置
DWORD diffuse;
// public:
// CUSTOMVERTEX():diffuse(0xffffffff){}
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
const int g_edgeVertexCnts = 101 ; // 每边顶点数目
CUSTOMVERTEX * g_pVertex_Index; // 顶点
int * g_pIndexes_Index; // 索引
CUSTOMVERTEX * g_pVertex; // 顶点
// -----------------------------------------------------------------------------
// Desc: 渲染类型
// -----------------------------------------------------------------------------
enum Draw_Prim_Type
{
DPT_INDEX = 0 , // drawindexedprimitive
DPT_INDEX_UP, // drawindexedprimitiveup
DPT_PRIM, // drawprimitive
DPT_PRIM_UP, // drawprimitiveup
};
Draw_Prim_Type g_kDrawType = DPT_INDEX;
// -----------------------------------------------------------------------------
// Desc: 设置变换矩阵
// -----------------------------------------------------------------------------
VOID SetupMatrices()
{
D3DXMATRIX matWorld;
D3DXMatrixIdentity( & matWorld);
g_pd3dDevice -> SetTransform(D3DTS_WORLD, & matWorld);
D3DXMATRIX matView;
D3DXVECTOR3 vecEyeat( 0 , 100 , - 100 );
D3DXVECTOR3 vecLookat( 0 , 0 , 10 );
D3DXVECTOR3 vecUp( 0 , 1 , 0 );
D3DXMatrixLookAtLH( & matView, & vecEyeat, & vecLookat, & vecUp);
g_pd3dDevice -> SetTransform(D3DTS_VIEW, & matView);
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( & matProj, D3DX_PI / 2 , 4.0f / 3.0f , 1.0f , 1000.0f );
g_pd3dDevice -> SetTransform(D3DTS_PROJECTION, & matProj);
}
// -----------------------------------------------------------------------------
// Desc: 初始化Direct3D
// -----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
// 创建d3d对象
g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
// 初始化设置参数
D3DPRESENT_PARAMETERS parm;
ZeroMemory( & parm, sizeof (D3DPRESENT_PARAMETERS));
parm.BackBufferWidth = 800 ;
parm.BackBufferHeight = 600 ;
parm.BackBufferCount = 2 ;
parm.BackBufferFormat = D3DFMT_UNKNOWN;
parm.MultiSampleType = D3DMULTISAMPLE_NONE;
parm.SwapEffect = D3DSWAPEFFECT_DISCARD;
parm.Windowed = true ;
parm.hDeviceWindow = hWnd;
parm.EnableAutoDepthStencil = false ;
parm.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
// 创建设备
HRESULT hr = g_pD3D -> CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING, & parm, & g_pd3dDevice);
if (FAILED(hr))
{
return S_FALSE;
}
// 禁用light
g_pd3dDevice -> SetRenderState(D3DRS_LIGHTING, false );
g_pd3dDevice -> SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
SetupMatrices();
return S_OK;
}
// -----------------------------------------------------------------------------
// Desc: 创建场景图形
// -----------------------------------------------------------------------------
HRESULT InitGriphics()
{
// --------------vertex buffer for index
const float fGridLenth = 0.10f ;
g_pVertex_Index = new CUSTOMVERTEX[g_edgeVertexCnts * g_edgeVertexCnts];
for ( int j = 0 ; j < g_edgeVertexCnts; j += 1 )
{
for ( int i = 0 ; i < g_edgeVertexCnts; i += 1 )
{
g_pVertex_Index[j * g_edgeVertexCnts + i].x = fGridLenth * i;
g_pVertex_Index[j * g_edgeVertexCnts + i].y = 0 ;
g_pVertex_Index[j * g_edgeVertexCnts + i].z = 0.5f * fGridLenth * (g_edgeVertexCnts - 1 ) - fGridLenth * j;
}
}
HRESULT hr = g_pd3dDevice -> CreateVertexBuffer(
g_edgeVertexCnts * g_edgeVertexCnts * sizeof (CUSTOMVERTEX),
D3DUSAGE_WRITEONLY, // 非常影响新能
D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT,
& g_pVB_Index,
NULL);
if (FAILED(hr))
{
return S_FALSE;
}
// 写入数据
void * pData;
g_pVB_Index -> Lock( 0 , g_edgeVertexCnts * g_edgeVertexCnts * sizeof (CUSTOMVERTEX), ( void ** ) & pData, D3DLOCK_DISCARD);
memcpy(pData, g_pVertex_Index, g_edgeVertexCnts * g_edgeVertexCnts * sizeof (CUSTOMVERTEX));
g_pVB_Index -> Unlock();
// --------------index buffer for index
int iIndexCount = (g_edgeVertexCnts - 1 ) * (g_edgeVertexCnts - 1 ) * 6 ;
g_pIndexes_Index = new int [iIndexCount];
for ( int j = 0 ;j < g_edgeVertexCnts - 1 ;j += 1 )
{
for ( int i = 0 ;i < g_edgeVertexCnts - 1 ;i += 1 )
{
g_pIndexes_Index[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 0 ] = ( int )(j * g_edgeVertexCnts + i);
g_pIndexes_Index[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 1 ] = ( int )(j * g_edgeVertexCnts + i + g_edgeVertexCnts + 1 );
g_pIndexes_Index[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 2 ] = ( int )(j * g_edgeVertexCnts + i + g_edgeVertexCnts);
g_pIndexes_Index[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 3 ] = ( int )(j * g_edgeVertexCnts + i);
g_pIndexes_Index[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 4 ] = ( int )(j * g_edgeVertexCnts + i + 1 );
g_pIndexes_Index[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 5 ] = ( int )(j * g_edgeVertexCnts + i + g_edgeVertexCnts + 1 );
}
}
g_pd3dDevice -> CreateIndexBuffer(iIndexCount * sizeof ( int ),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX32,
D3DPOOL_DEFAULT,
& g_pIB_Index,
NULL);
void * pp;
if (FAILED(g_pIB_Index -> Lock( 0 , iIndexCount * sizeof ( int ), ( void ** ) & pp, 0 )))
{
// add code
return S_FALSE;
}
memcpy(pp, g_pIndexes_Index, iIndexCount * sizeof ( int ));
g_pIB_Index -> Unlock();
// --------------vertex buffer
int prim_list_vertex_cnts = (g_edgeVertexCnts - 1 ) * (g_edgeVertexCnts - 1 ) * 6 ;
g_pVertex = new CUSTOMVERTEX[prim_list_vertex_cnts];
for ( int j = 0 ; j < g_edgeVertexCnts - 1 ; j += 1 )
{
for ( int i = 0 ; i < g_edgeVertexCnts - 1 ; i += 1 )
{
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 0 ].x = i * fGridLenth;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 0 ].y = 0 ;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 0 ].z = 0.5f * fGridLenth * (g_edgeVertexCnts - 1 ) - j * fGridLenth;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 1 ].x = (i + 1 ) * fGridLenth;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 1 ].y = 0 ;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 1 ].z = 0.5f * fGridLenth * (g_edgeVertexCnts - 1 ) - j * fGridLenth;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 2 ].x = (i + 1 ) * fGridLenth;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 2 ].y = 0 ;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 2 ].z = 0.5f * fGridLenth * (g_edgeVertexCnts - 1 ) - (j + 1 ) * fGridLenth;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 3 ].x = i * fGridLenth;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 3 ].y = 0 ;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 3 ].z = 0.5f * fGridLenth * (g_edgeVertexCnts - 1 ) - j * fGridLenth;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 4 ].x = (i + 1 ) * fGridLenth;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 4 ].y = 0 ;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 4 ].z = 0.5f * fGridLenth * (g_edgeVertexCnts - 1 ) - (j + 1 ) * fGridLenth;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 5 ].x = i * fGridLenth;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 5 ].y = 0 ;
g_pVertex[j * (g_edgeVertexCnts - 1 ) * 6 + i * 6 + 5 ].z = 0.5f * fGridLenth * (g_edgeVertexCnts - 1 ) - (j + 1 ) * fGridLenth;
}
}
if ( FAILED( g_pd3dDevice -> CreateVertexBuffer(
prim_list_vertex_cnts * sizeof (CUSTOMVERTEX),
D3DUSAGE_WRITEONLY,
D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT,
& g_pVB,
NULL ) ) )
{
return E_FAIL;
}
VOID * pVertices;
if ( FAILED( g_pVB -> Lock( 0 , prim_list_vertex_cnts * sizeof (CUSTOMVERTEX), ( void ** ) & pVertices, 0 ) ) )
return E_FAIL;
memcpy( pVertices, g_pVertex, prim_list_vertex_cnts * sizeof (CUSTOMVERTEX) );
g_pVB -> Unlock();
return S_OK;
}
// -----------------------------------------------------------------------------
// Desc: 释放创建的对象
// -----------------------------------------------------------------------------
VOID Cleanup()
{
// 释放顶点缓冲区对象
if ( g_pVB_Index != NULL )
g_pVB_Index -> Release();
// 释放Direct3D设备对象
if ( g_pd3dDevice != NULL )
g_pd3dDevice -> Release();
// 释放Direct3D对象
if ( g_pD3D != NULL )
g_pD3D -> Release();
}
// -----------------------------------------------------------------------------
// Desc: 渲染图形
// -----------------------------------------------------------------------------
VOID Render()
{
g_pd3dDevice -> Clear( 0 , NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0 , 0 , 255 ), 1 , 0 );
g_pd3dDevice -> BeginScene();
g_pd3dDevice -> SetFVF(D3DFVF_CUSTOMVERTEX);
switch (g_kDrawType)
{
case DPT_INDEX:
g_pd3dDevice -> SetStreamSource( 0 ,g_pVB_Index, 0 , sizeof (CUSTOMVERTEX));
g_pd3dDevice -> SetIndices(g_pIB_Index);
g_pd3dDevice -> DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0 , 0 ,
g_edgeVertexCnts * g_edgeVertexCnts, 0 ,
(g_edgeVertexCnts - 1 ) * (g_edgeVertexCnts - 1 ) * 2 );
break ;
case DPT_INDEX_UP:
g_pd3dDevice -> SetStreamSource( 0 ,g_pVB_Index, 0 , sizeof (CUSTOMVERTEX));
g_pd3dDevice -> SetIndices(g_pIB_Index);
g_pd3dDevice -> DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0 , g_edgeVertexCnts * g_edgeVertexCnts,
(g_edgeVertexCnts - 1 ) * (g_edgeVertexCnts - 1 ) * 2 , g_pIndexes_Index,
D3DFMT_INDEX32, g_pVertex_Index, sizeof (CUSTOMVERTEX));
break ;
case DPT_PRIM:
g_pd3dDevice -> SetStreamSource( 0 ,g_pVB, 0 , sizeof (CUSTOMVERTEX));
g_pd3dDevice -> DrawPrimitive(D3DPT_TRIANGLELIST, 0 , (g_edgeVertexCnts - 1 ) * (g_edgeVertexCnts - 1 ) * 2 );
break ;
case DPT_PRIM_UP:
g_pd3dDevice -> SetStreamSource( 0 ,g_pVB, 0 , sizeof (CUSTOMVERTEX));
g_pd3dDevice -> DrawPrimitiveUP(D3DPT_TRIANGLELIST, (g_edgeVertexCnts - 1 ) * (g_edgeVertexCnts - 1 ) * 2 ,
g_pVertex, sizeof (CUSTOMVERTEX));
break ;
}
g_pd3dDevice -> EndScene();
g_pd3dDevice -> Present(NULL,NULL,NULL,NULL);
}
// -----------------------------------------------------------------------------
// Desc: 消息处理
// -----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch ( msg )
{
case WM_DESTROY:
Cleanup();
PostQuitMessage( 0 );
case WM_KEYDOWN:
{
switch ((WORD)wParam)
{
case ' W ' :
g_pd3dDevice -> SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
break ;
case ' S ' :
g_pd3dDevice -> SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
break ;
case ' 1 ' :
g_kDrawType = DPT_INDEX;
break ;
case ' 2 ' :
g_kDrawType = DPT_INDEX_UP;
break ;
case ' 3 ' :
g_kDrawType = DPT_PRIM;
break ;
case ' 4 ' :
g_kDrawType = DPT_PRIM_UP;
break ;
case ' Q ' :
exit( 0 );
break ;
}
}
return 0 ;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
// -----------------------------------------------------------------------------
// Desc: 入口函数
// -----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
// 注册窗口类
WNDCLASSEX wc = { sizeof (WNDCLASSEX), CS_CLASSDC, MsgProc, 0L , 0L ,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
L " ClassName " , NULL };
RegisterClassEx( & wc );
RECT rc;
rc.left = 0 ;
rc.top = 0 ;
rc.right = 800 ;
rc.bottom = 600 ;
AdjustWindowRect( & rc, WS_VISIBLE | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW, false );
// 创建窗口
HWND hWnd = CreateWindow( L " ClassName " , L " 纹理影射基础 " ,
WS_OVERLAPPEDWINDOW,
200 ,
100 ,
rc.right - rc.left,
rc.bottom - rc.top,
GetDesktopWindow(), NULL, wc.hInstance, NULL );
// 初始化Direct3D
if ( SUCCEEDED( InitD3D( hWnd ) ) )
{
// 创建场景图形
if ( SUCCEEDED( InitGriphics() ) )
{
// 显示窗口
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
// 进入消息循环
MSG msg;
ZeroMemory( & msg, sizeof (msg) );
while ( msg.message != WM_QUIT )
{
if ( PeekMessage( & msg, NULL, 0U , 0U , PM_REMOVE ) )
{
TranslateMessage( & msg );
DispatchMessage( & msg );
}
else
{
Render(); // 渲染图形
}
}
}
}
UnregisterClass( L " ClassName " , wc.hInstance );
return 0 ;
}