mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-25 15:14:51 +01:00
439 lines
11 KiB
C++
439 lines
11 KiB
C++
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
the Free Software Foundation
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
|
|
|
#include "stdh.h"
|
|
|
|
#include <Engine/Base/Console.h>
|
|
#include <Engine/Base/Timer.h>
|
|
#include <Engine/Base/Priority.inl>
|
|
#include <Engine/Graphics/GfxLibrary.h>
|
|
|
|
#include <Engine/Graphics/ViewPort.h>
|
|
#include <Engine/Graphics/DrawPort.h>
|
|
|
|
#include <Engine/Templates/StaticArray.cpp>
|
|
#include <Engine/Templates/StaticStackArray.cpp>
|
|
|
|
|
|
static CViewPort *_pvp = NULL;
|
|
static CDrawPort *_pdp = NULL;
|
|
static PIX _pixSizeI;
|
|
static PIX _pixSizeJ;
|
|
static CTimerValue _tv;
|
|
static BOOL _bBlend = FALSE;
|
|
static BOOL _bVisible = FALSE;
|
|
static BOOL _bTexture = FALSE;
|
|
static BOOL _bDepth = FALSE;
|
|
static BOOL _bMultiTexture = FALSE;
|
|
static UBYTE *_pubTexture;
|
|
static ULONG _ulTexObject;
|
|
static ULONG _ulTexFormat;
|
|
static BOOL _bSubImage = FALSE;
|
|
static INDEX _ctR = 100;
|
|
static INDEX _ctC = 100;
|
|
static CTexParams _tpLocal;
|
|
|
|
static CStaticStackArray<GFXVertex> _avtx;
|
|
static CStaticStackArray<GFXTexCoord> _atex;
|
|
static CStaticStackArray<GFXColor> _acol;
|
|
static CStaticStackArray<INDEX> _aiElements;
|
|
|
|
|
|
|
|
BOOL _bStarted = FALSE;
|
|
static __forceinline void StartTimer(void)
|
|
{
|
|
ASSERT(!_bStarted);
|
|
_tv = _pTimer->GetHighPrecisionTimer();
|
|
_bStarted = TRUE;
|
|
}
|
|
|
|
|
|
static __forceinline DOUBLE StopTimer(void)
|
|
{
|
|
ASSERT(_bStarted);
|
|
_bStarted = FALSE;
|
|
return (_pTimer->GetHighPrecisionTimer()-_tv).GetSeconds();
|
|
}
|
|
|
|
|
|
// fill rate benchmark
|
|
static DOUBLE FillRatePass(INDEX ct)
|
|
{
|
|
if( !_pdp->Lock()) {
|
|
ASSERT(FALSE);
|
|
return 0;
|
|
}
|
|
|
|
StartTimer();
|
|
|
|
_pdp->Fill(C_GRAY|255);
|
|
_pdp->FillZBuffer(1.0f);
|
|
|
|
GFXVertex avtx[4];
|
|
avtx[0].x = 0; avtx[0].y = 0; avtx[0].z = 0.5f;
|
|
avtx[1].x = 0; avtx[1].y = _pixSizeJ; avtx[1].z = 0.5f;
|
|
avtx[2].x = _pixSizeI; avtx[2].y = _pixSizeJ; avtx[2].z = 0.5f;
|
|
avtx[3].x = _pixSizeI; avtx[3].y = 0; avtx[3].z = 0.5f;
|
|
GFXTexCoord atex[4] = { {0,0}, {0,1}, {1,1}, {1,0} };
|
|
GFXColor acol[4] = { 0xFF0000FF, 0xFF00FF00, 0xFFFF0000, 0xFFFF00FF };
|
|
INDEX aidx[6] = { 0,1,2, 0,2,3};
|
|
gfxSetVertexArray( &avtx[0], 4);
|
|
gfxSetTexCoordArray( &atex[0], FALSE);
|
|
gfxSetColorArray( &acol[0]);
|
|
|
|
if(_bTexture) {
|
|
gfxEnableTexture();
|
|
if(_bMultiTexture) {
|
|
gfxSetTextureUnit(1);
|
|
gfxEnableTexture();
|
|
gfxSetTexture( _ulTexObject, _tpLocal);
|
|
gfxSetTexCoordArray(atex, FALSE);
|
|
gfxSetTextureUnit(0);
|
|
}
|
|
} else {
|
|
gfxDisableTexture();
|
|
}
|
|
|
|
if(_bBlend) {
|
|
gfxEnableBlend();
|
|
if(_bTexture) {
|
|
gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA);
|
|
} else {
|
|
gfxBlendFunc( GFX_ONE, GFX_ONE);
|
|
}
|
|
} else {
|
|
gfxDisableBlend();
|
|
}
|
|
|
|
if(_bDepth) {
|
|
gfxEnableDepthTest();
|
|
gfxEnableDepthWrite();
|
|
} else {
|
|
gfxDisableDepthTest();
|
|
gfxDisableDepthWrite();
|
|
}
|
|
gfxDisableAlphaTest();
|
|
|
|
for( INDEX i=0; i<ct; i++) gfxDrawElements( 6, &aidx[0]);
|
|
|
|
if(_bMultiTexture) {
|
|
gfxSetTextureUnit(1);
|
|
gfxDisableTexture();
|
|
gfxSetTextureUnit(0);
|
|
}
|
|
_pdp->Unlock();
|
|
|
|
gfxFinish();
|
|
_pvp->SwapBuffers();
|
|
|
|
return StopTimer();
|
|
}
|
|
|
|
|
|
CTString FillRateString(void)
|
|
{
|
|
CTString str;
|
|
str.PrintF( "%s, %s, %s ",
|
|
_bTexture ? (_bMultiTexture ? "multitexture" : "texture") : "no texture",
|
|
_bBlend ? "blending" : "no blending",
|
|
_bDepth ? "z-buffer:" : "no z-buffer:");
|
|
return str;
|
|
}
|
|
|
|
|
|
static DOUBLE FillRate(void)
|
|
{
|
|
DOUBLE dDelta = 0;
|
|
for( INDEX i=0; i<10; i++) {
|
|
dDelta += FillRatePass(3) - FillRatePass(2);
|
|
}
|
|
dDelta /= 10.0;
|
|
return (_pixSizeI*_pixSizeJ)/dDelta;
|
|
}
|
|
|
|
|
|
static void InitTexture(void)
|
|
{
|
|
const SLONG slSize = 256*256 *4 *4/3 +16;
|
|
_pubTexture = (UBYTE*)AllocMemory(slSize);
|
|
for( INDEX i=0; i<256; i++) {
|
|
for( INDEX j=0; j<256; j++) {
|
|
_pubTexture[(j*256+i)*4+0] = i;
|
|
_pubTexture[(j*256+i)*4+1] = j;
|
|
_pubTexture[(j*256+i)*4+2] = i+j;
|
|
_pubTexture[(j*256+i)*4+3] = i-j;
|
|
}
|
|
}
|
|
MakeMipmaps( 15, (ULONG*)_pubTexture, 256,256);
|
|
_tpLocal.tp_bSingleMipmap = FALSE;
|
|
gfxGenerateTexture( _ulTexObject);
|
|
gfxSetTexture( _ulTexObject, _tpLocal);
|
|
}
|
|
|
|
|
|
static void EndTexture(void)
|
|
{
|
|
gfxDeleteTexture( _ulTexObject);
|
|
FreeMemory(_pubTexture);
|
|
_pubTexture = NULL;
|
|
}
|
|
|
|
|
|
static void InitTris(void)
|
|
{
|
|
INDEX iR, iC;
|
|
INDEX ctVx = _ctR*_ctC;
|
|
_avtx.Push(ctVx);
|
|
_atex.Push(ctVx);
|
|
_acol.Push(ctVx);
|
|
for( iR=0; iR<_ctR; iR++) {
|
|
for( iC=0; iC<_ctC; iC++) {
|
|
INDEX ivx = iR*_ctC+iC;
|
|
_avtx[ivx].x = FLOAT(iC) / _ctC*4 -2.0f;
|
|
_avtx[ivx].y = -FLOAT(iR) / _ctR*4 +2.0f;
|
|
_avtx[ivx].z = -1.0f;
|
|
_atex[ivx].s = (iC+iR) % 2;
|
|
_atex[ivx].t = (iR) % 2;
|
|
_acol[ivx].abgr = 0xFFFFFFFF;
|
|
}
|
|
}
|
|
INDEX ctTri = (_ctR-1)*(_ctC-1)*2;
|
|
_aiElements.Push(ctTri*3);
|
|
for( iR=0; iR<_ctR-1; iR++) {
|
|
for( iC=0; iC<_ctC-1; iC++) {
|
|
INDEX iq = iR*(_ctC-1)+iC;
|
|
_aiElements[iq*6+0] = (iR+1) * _ctC + (iC+0);
|
|
_aiElements[iq*6+1] = (iR+1) * _ctC + (iC+1);
|
|
_aiElements[iq*6+2] = (iR+0) * _ctC + (iC+0);
|
|
_aiElements[iq*6+3] = (iR+0) * _ctC + (iC+0);
|
|
_aiElements[iq*6+4] = (iR+1) * _ctC + (iC+1);
|
|
_aiElements[iq*6+5] = (iR+0) * _ctC + (iC+1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void EndTris(void)
|
|
{
|
|
_avtx.Clear();
|
|
_atex.Clear();
|
|
_acol.Clear();
|
|
_aiElements.Clear();
|
|
}
|
|
|
|
|
|
static DOUBLE TrisTroughputPass(INDEX ct)
|
|
{
|
|
if( !_pdp->Lock()) {
|
|
ASSERT(FALSE);
|
|
return 0;
|
|
}
|
|
|
|
StartTimer();
|
|
|
|
gfxSetFrustum( -0.5f, +0.5f, -0.5f, +0.5f, 0.5f, 2.0f);
|
|
gfxSetViewMatrix(NULL);
|
|
gfxCullFace(GFX_NONE);
|
|
|
|
_pdp->Fill(C_GRAY|255);
|
|
_pdp->FillZBuffer(1.0f);
|
|
|
|
if(_bTexture) {
|
|
gfxEnableTexture();
|
|
} else {
|
|
gfxDisableTexture();
|
|
}
|
|
|
|
if(_bBlend) {
|
|
gfxEnableBlend();
|
|
gfxBlendFunc( GFX_ONE, GFX_ONE);
|
|
} else {
|
|
gfxDisableBlend();
|
|
}
|
|
|
|
if(_bDepth) {
|
|
gfxEnableDepthTest();
|
|
gfxEnableDepthWrite();
|
|
} else {
|
|
gfxDisableDepthTest();
|
|
gfxDisableDepthWrite();
|
|
}
|
|
gfxDisableAlphaTest();
|
|
|
|
gfxSetVertexArray( &_avtx[0], _avtx.Count());
|
|
gfxLockArrays();
|
|
gfxSetTexCoordArray( &_atex[0], FALSE);
|
|
gfxSetColorArray( &_acol[0]);
|
|
|
|
if(_bMultiTexture) {
|
|
gfxSetTextureUnit(1);
|
|
gfxEnableTexture();
|
|
gfxSetTexture( _ulTexObject, _tpLocal);
|
|
gfxSetTexCoordArray( &_atex[0], FALSE);
|
|
gfxSetTextureUnit(0);
|
|
}
|
|
for( INDEX i=0; i<ct; i++) gfxDrawElements( _aiElements.Count(), &_aiElements[0]);
|
|
gfxUnlockArrays();
|
|
|
|
if(_bMultiTexture) {
|
|
gfxSetTextureUnit(1);
|
|
gfxDisableTexture();
|
|
gfxSetTextureUnit(0);
|
|
}
|
|
_pdp->Unlock();
|
|
|
|
gfxFinish();
|
|
_pvp->SwapBuffers();
|
|
|
|
return StopTimer();
|
|
}
|
|
|
|
|
|
static DOUBLE TrisTroughput(void)
|
|
{
|
|
DOUBLE dDelta = 0;
|
|
for( INDEX i=0; i<10; i++) {
|
|
dDelta += TrisTroughputPass(3) - TrisTroughputPass(2);
|
|
}
|
|
dDelta /= 10.0;
|
|
return ((_ctR-1)*(_ctC-1)*2)/dDelta;
|
|
}
|
|
|
|
|
|
|
|
static DOUBLE TextureUpload(void)
|
|
{
|
|
StartTimer();
|
|
gfxUploadTexture( (ULONG*)_pubTexture, 256, 256, _ulTexFormat, _bSubImage);
|
|
const SLONG slTotal = 256*256*4 *4/3;
|
|
return slTotal/StopTimer();
|
|
}
|
|
|
|
|
|
|
|
static DOUBLE _dX;
|
|
static DOUBLE _dD;
|
|
static void RunTest(DOUBLE (*pTest)(void), INDEX ct)
|
|
{
|
|
CSetPriority sp(REALTIME_PRIORITY_CLASS, THREAD_PRIORITY_TIME_CRITICAL);
|
|
|
|
DOUBLE dSum = 0;
|
|
DOUBLE dSum2 = 0;
|
|
for(INDEX i=0; i<(ct+5); i++) {
|
|
DOUBLE d = pTest();
|
|
// must ignore 1st couple of passes due to API queue
|
|
if( i>4) dSum += d;
|
|
if( i>4) dSum2 += d*d;
|
|
}
|
|
_dX = dSum/ct;
|
|
_dD = Sqrt((dSum2-2*dSum*_dX+ct*_dX*_dX)/(ct-1));
|
|
}
|
|
|
|
|
|
/* Benchmark current driver. */
|
|
void CGfxLibrary::Benchmark(CViewPort *pvp, CDrawPort *pdp)
|
|
{
|
|
// remember drawport/viewport
|
|
_pdp = pdp;
|
|
_pvp = pvp;
|
|
_pixSizeI = pdp->GetWidth();
|
|
_pixSizeJ = pdp->GetHeight();
|
|
|
|
CTString strAPI = "";
|
|
if( _pGfx->gl_eCurrentAPI==GAT_OGL) strAPI = "OpenGL";
|
|
#ifdef SE1_D3D
|
|
else if( _pGfx->gl_eCurrentAPI==GAT_D3D) strAPI = "Direct3D";
|
|
#endif // SE1_D3D
|
|
CPrintF("=====================================\n");
|
|
CPrintF("%s performance testing ...\n", strAPI);
|
|
|
|
InitTexture();
|
|
InitTris();
|
|
|
|
CPrintF("\n--- Texture upload\n");
|
|
|
|
_ulTexFormat = TS.ts_tfRGBA8;
|
|
_bSubImage = FALSE;
|
|
RunTest(TextureUpload, 10);
|
|
CPrintF("RGBA8 full: %6.02f +- %5.02f Mtex/s;" , _dX/1000/1000, _dD/1000/1000);
|
|
_bSubImage = TRUE;
|
|
RunTest(TextureUpload, 10);
|
|
CPrintF( " sub: %6.02f +- %5.02f Mtex/s\n", _dX/1000/1000, _dD/1000/1000);
|
|
|
|
_ulTexFormat = TS.ts_tfRGB8;
|
|
_bSubImage = FALSE;
|
|
RunTest(TextureUpload, 10);
|
|
CPrintF("RGB8 full: %6.02f +- %5.02f Mtex/s;" , _dX/1000/1000, _dD/1000/1000);
|
|
_bSubImage = TRUE;
|
|
RunTest(TextureUpload, 10);
|
|
CPrintF( " sub: %6.02f +- %5.02f Mtex/s\n", _dX/1000/1000, _dD/1000/1000);
|
|
|
|
_ulTexFormat = TS.ts_tfRGBA4;
|
|
_bSubImage = FALSE;
|
|
RunTest(TextureUpload, 10);
|
|
CPrintF("RGBA4 full: %6.02f +- %5.02f Mtex/s;" , _dX/1000/1000, _dD/1000/1000);
|
|
_bSubImage = TRUE;
|
|
RunTest(TextureUpload, 10);
|
|
CPrintF( " sub: %6.02f +- %5.02f Mtex/s\n", _dX/1000/1000, _dD/1000/1000);
|
|
|
|
_ulTexFormat = TS.ts_tfRGB5;
|
|
_bSubImage = FALSE;
|
|
RunTest(TextureUpload, 10);
|
|
CPrintF("RGB5 full: %6.02f +- %5.02f Mtex/s;" , _dX/1000/1000, _dD/1000/1000);
|
|
_bSubImage = TRUE;
|
|
RunTest(TextureUpload, 10);
|
|
CPrintF( " sub: %6.02f +- %5.02f Mtex/s\n", _dX/1000/1000, _dD/1000/1000);
|
|
|
|
CPrintF("\n--- Fill rate\n");
|
|
_bMultiTexture = 0;
|
|
_bBlend = 0; _bDepth = 0; _bTexture = 0;
|
|
RunTest(FillRate, 10);
|
|
CPrintF("%-38s %6.02f +- %5.02f Mpix/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000);
|
|
_bBlend = 0; _bDepth = 0; _bTexture = 1;
|
|
RunTest(FillRate, 10);
|
|
CPrintF("%-38s %6.02f +- %5.02f Mpix/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000);
|
|
_bBlend = 0; _bDepth = 1; _bTexture = 1;
|
|
RunTest(FillRate, 10);
|
|
CPrintF("%-38s %6.02f +- %5.02f Mpix/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000);
|
|
_bBlend = 1; _bDepth = 1; _bTexture = 1;
|
|
RunTest(FillRate, 10);
|
|
CPrintF("%-38s %6.02f +- %5.02f Mpix/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000);
|
|
|
|
if( _pGfx->gl_ctTextureUnits>1) {
|
|
_bMultiTexture = 1;
|
|
RunTest(FillRate, 10);
|
|
CPrintF("%-38s %6.02f +- %5.02f Mpix/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000);
|
|
}
|
|
|
|
CPrintF("\n--- Geometry speed (%dpix tris)\n", (_pixSizeI/_ctR)*(_pixSizeI/_ctC)/2);
|
|
_bMultiTexture = 0;
|
|
_bBlend = 0; _bDepth = 1; _bTexture = 1;
|
|
RunTest(TrisTroughput, 10);
|
|
CPrintF("%-34s %6.02f +- %5.02f Mtri/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000);
|
|
_bBlend = 1; _bDepth = 1; _bTexture = 1;
|
|
RunTest(TrisTroughput, 10);
|
|
CPrintF("%-34s %6.02f +- %5.02f Mtri/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000);
|
|
|
|
if( _pGfx->gl_ctTextureUnits>1) {
|
|
_bMultiTexture = 1;
|
|
RunTest(TrisTroughput, 10);
|
|
CPrintF("%-34s %6.02f +- %5.02f Mtri/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000);
|
|
}
|
|
|
|
EndTris();
|
|
EndTexture();
|
|
}
|