mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
372 lines
12 KiB
C++
372 lines
12 KiB
C++
/*
|
|
* Descent 3
|
|
* Copyright (C) 2024 Parallax Software
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
|
|
--- HISTORICAL COMMENTS FOLLOW ---
|
|
|
|
* $Logfile: /DescentIII/Main/rtperformance/rtperformance.cpp $
|
|
* $Revision: 9 $
|
|
* $Date: 10/21/99 3:21p $
|
|
* $Author: Kevin $
|
|
*
|
|
* Run time performance lib
|
|
*
|
|
* $Log: /DescentIII/Main/rtperformance/rtperformance.cpp $
|
|
*
|
|
* 9 10/21/99 3:21p Kevin
|
|
* Mac merge
|
|
*
|
|
* 8 5/07/99 6:21p Jeff
|
|
* hooked up fvi to rtperformance
|
|
*
|
|
* 7 4/16/99 4:04a Jeff
|
|
* fixed up for non-window's builds
|
|
*
|
|
* 6 4/16/99 1:59a Jeff
|
|
* ifdef out windows.h for now windows builds
|
|
*
|
|
* 5 10/19/98 7:51p Kevin
|
|
* performance testing
|
|
*
|
|
* 4 10/19/98 2:48p Jeff
|
|
* changed define for rtp performance...just define USE_RTP in
|
|
* rtperformance.h in order to enable it
|
|
*
|
|
* 3 10/17/98 6:05p Jeff
|
|
* it helps to write the heading to file
|
|
*
|
|
* 2 10/17/98 5:58p Jeff
|
|
* put in heading
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
|
|
#if defined(WIN32)
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include "cfile.h"
|
|
#include "ddio.h"
|
|
#include "manage.h"
|
|
#include "log.h"
|
|
#include "rtperformance.h"
|
|
|
|
float rtp_startlog_time;
|
|
|
|
// maximum number of samples before we stop and autoflush
|
|
#define MAX_RTP_SAMPLES 3800 // this is a little more than whats needed for 2 minutes at 30fps
|
|
|
|
// Internal Global Vars
|
|
// ------------------------------
|
|
INT64 Runtime_performance_flags = RTI_FRAMETIME;
|
|
INT64 Runtime_performance_clockfreq = 0;
|
|
INT64 Runtime_performance_frame_counter = 0;
|
|
uint32_t Runtime_performance_counter = 0;
|
|
uint8_t Runtime_performance_enabled = 0;
|
|
|
|
tRTFrameInfo RTP_SingleFrame;
|
|
#ifdef USE_RTP
|
|
tRTFrameInfo RTP_FrameBuffer[MAX_RTP_SAMPLES];
|
|
#endif
|
|
|
|
void rtp_Close();
|
|
|
|
/*
|
|
void rtp_WriteBufferLog
|
|
Writes the buffer of frames to file...
|
|
*/
|
|
void rtp_WriteBufferLog() {
|
|
#ifdef USE_RTP
|
|
Runtime_performance_enabled = 1; // make sure it's enabled for the macros
|
|
// determine how many frames to write out
|
|
uint32_t Num_frames;
|
|
uint32_t counter;
|
|
char buffer[4096];
|
|
|
|
Num_frames = std::min<unsigned>(Runtime_performance_counter, MAX_RTP_SAMPLES);
|
|
|
|
// Open the log file for writing
|
|
CFILE *file = cfopen(std::filesystem::path(LocalD3Dir) / "D3Performance.txt", "wt");
|
|
|
|
if (file) {
|
|
LOG_DEBUG << "RTP: Recording Log";
|
|
|
|
strcpy(buffer, "FrameNum,FrameTime,RenderFrameTime,MultiFrameTime,MusicFrameTime,AmbientSoundTime,WeatherFrameTime,"
|
|
"PlayerFrameTime,DoorwayFrameTime,LevelGoalFrameTime,MatCenFrameTime,ObjectFrameTime,AIFrameAllTime,"
|
|
"ProcessKeysTime,REN:NumTexturesUploaded,REN:PolysDrawn,OBJ:CT_FlyingTime,OBJ:CT_AIDoFrameTime,OBJ:"
|
|
"CT_WeaponFrameTime,OBJ:CT_ExplosionFrameTime,OBJ:CT_DebrisFrameTime,OBJ:CT_SplinterFrameTime,OBJ:"
|
|
"MT_PhsyicsFrameTime,OBJ:MT_WalkingFrame,OBJ:MT_ShockWaveTime,OBJ:DoEffectTime,OBJ:MovePlayerTime,"
|
|
"OBJ:D3XIntervalTime,OBJ:ObjLightTime,FRAME:NormalEventTime,AnimCycle,VisEffectMoveAll,"
|
|
"DoPhysLinkedFrame,ObjDoFrame,NumFVICalls,FVITime");
|
|
cf_WriteString(file, buffer);
|
|
|
|
// Loop through all the frames, and write out the data for each frame
|
|
for (counter = 0; counter < Num_frames; counter++) {
|
|
tRTFrameInfo *fi = &RTP_FrameBuffer[counter];
|
|
double renderframe_time;
|
|
double multiframe_time;
|
|
double musicframe_time;
|
|
double ambsound_frame_time;
|
|
double weatherframe_time;
|
|
double playerframe_time;
|
|
double doorframe_time;
|
|
double levelgoal_time;
|
|
double matcenframe_time;
|
|
double objframe_time;
|
|
double aiframeall_time;
|
|
double processkeys_time;
|
|
double ct_flying_time;
|
|
double ct_aidoframe_time;
|
|
double ct_weaponframe_time;
|
|
double ct_explosionframe_time;
|
|
double ct_debrisframe_time;
|
|
double ct_splinterframe_time;
|
|
double mt_physicsframe_time;
|
|
double mt_walkingframe_time;
|
|
double mt_shockwave_time;
|
|
double obj_doeffect_time;
|
|
double obj_move_player_time;
|
|
double obj_d3xint_time;
|
|
double obj_objlight_time;
|
|
double normalevent_time;
|
|
double cycle_anim;
|
|
double vis_eff_move;
|
|
double phys_link;
|
|
double obj_do_frm;
|
|
double fvi_time;
|
|
|
|
RTP_CLOCKSECONDS(fi->renderframe_time, renderframe_time);
|
|
RTP_CLOCKSECONDS(fi->multiframe_time, multiframe_time);
|
|
RTP_CLOCKSECONDS(fi->musicframe_time, musicframe_time);
|
|
RTP_CLOCKSECONDS(fi->ambsound_frame_time, ambsound_frame_time);
|
|
RTP_CLOCKSECONDS(fi->weatherframe_time, weatherframe_time);
|
|
RTP_CLOCKSECONDS(fi->playerframe_time, playerframe_time);
|
|
RTP_CLOCKSECONDS(fi->doorframe_time, doorframe_time);
|
|
RTP_CLOCKSECONDS(fi->levelgoal_time, levelgoal_time);
|
|
RTP_CLOCKSECONDS(fi->matcenframe_time, matcenframe_time);
|
|
RTP_CLOCKSECONDS(fi->objframe_time, objframe_time);
|
|
RTP_CLOCKSECONDS(fi->aiframeall_time, aiframeall_time);
|
|
RTP_CLOCKSECONDS(fi->processkeys_time, processkeys_time);
|
|
RTP_CLOCKSECONDS(fi->ct_flying_time, ct_flying_time);
|
|
RTP_CLOCKSECONDS(fi->ct_aidoframe_time, ct_aidoframe_time);
|
|
RTP_CLOCKSECONDS(fi->ct_weaponframe_time, ct_weaponframe_time);
|
|
RTP_CLOCKSECONDS(fi->ct_explosionframe_time, ct_explosionframe_time);
|
|
RTP_CLOCKSECONDS(fi->ct_debrisframe_time, ct_debrisframe_time);
|
|
RTP_CLOCKSECONDS(fi->ct_splinterframe_time, ct_splinterframe_time);
|
|
RTP_CLOCKSECONDS(fi->mt_physicsframe_time, mt_physicsframe_time);
|
|
RTP_CLOCKSECONDS(fi->mt_walkingframe_time, mt_walkingframe_time);
|
|
RTP_CLOCKSECONDS(fi->mt_shockwave_time, mt_shockwave_time);
|
|
RTP_CLOCKSECONDS(fi->obj_doeffect_time, obj_doeffect_time);
|
|
RTP_CLOCKSECONDS(fi->obj_move_player_time, obj_move_player_time);
|
|
RTP_CLOCKSECONDS(fi->obj_d3xint_time, obj_d3xint_time);
|
|
RTP_CLOCKSECONDS(fi->obj_objlight_time, obj_objlight_time);
|
|
RTP_CLOCKSECONDS(fi->normalevent_time, normalevent_time);
|
|
RTP_CLOCKSECONDS(fi->cycle_anim, cycle_anim);
|
|
RTP_CLOCKSECONDS(fi->vis_eff_move, vis_eff_move);
|
|
RTP_CLOCKSECONDS(fi->phys_link, phys_link);
|
|
RTP_CLOCKSECONDS(fi->obj_do_frm, obj_do_frm);
|
|
RTP_CLOCKSECONDS(fi->fvi_time, fvi_time);
|
|
|
|
snprintf(buffer, sizeof(buffer),
|
|
"%d,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%d,%d,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f "
|
|
"%d %lld",
|
|
(int)fi->frame_num, fi->frame_time, renderframe_time, multiframe_time, musicframe_time,
|
|
ambsound_frame_time, weatherframe_time, playerframe_time, doorframe_time, levelgoal_time,
|
|
matcenframe_time, objframe_time, aiframeall_time, processkeys_time, fi->texture_uploads, fi->polys_drawn,
|
|
ct_flying_time, ct_aidoframe_time, ct_weaponframe_time, ct_explosionframe_time, ct_debrisframe_time,
|
|
ct_splinterframe_time, mt_physicsframe_time, mt_walkingframe_time, mt_shockwave_time, obj_doeffect_time,
|
|
obj_move_player_time, obj_d3xint_time, obj_objlight_time, normalevent_time, cycle_anim, vis_eff_move,
|
|
phys_link, obj_do_frm, fi->fvi_calls, fi->fvi_time);
|
|
|
|
cf_WriteString(file, buffer);
|
|
}
|
|
|
|
// Close the log file
|
|
cfclose(file);
|
|
} else
|
|
LOG_DEBUG << "RTP: Unable to open log for writing";
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
void rtp_RecordFrame
|
|
Calling this will record the data of the frame into the internal log, and prepare for
|
|
the next frame
|
|
*/
|
|
void rtp_RecordFrame() {
|
|
#ifdef USE_RTP
|
|
if (Runtime_performance_enabled) {
|
|
// do our saving of information
|
|
// --------------------------------
|
|
|
|
RTP_SingleFrame.frame_num = Runtime_performance_frame_counter; // save the frame num
|
|
|
|
// Copy everything into the buffer, and advance the buffer
|
|
memcpy(&RTP_FrameBuffer[Runtime_performance_counter], &RTP_SingleFrame, sizeof(tRTFrameInfo));
|
|
|
|
Runtime_performance_counter++;
|
|
|
|
if (Runtime_performance_counter >= MAX_RTP_SAMPLES) {
|
|
// uh oh, we hit the end of our samples, flush the buffer and stop
|
|
rtp_StopLog();
|
|
}
|
|
|
|
// reset our global struct to zero everything out
|
|
// ------------------------------------------------
|
|
memset(&RTP_SingleFrame, 0, sizeof(tRTFrameInfo));
|
|
}
|
|
|
|
// Update the frame counter to the next frame, always
|
|
Runtime_performance_frame_counter++;
|
|
#endif
|
|
}
|
|
|
|
// External Functions
|
|
// -----------------------------
|
|
/*
|
|
void rtp_Init
|
|
This function initilizes the runtime performance system so it's ready to be used
|
|
*/
|
|
void rtp_Init() {
|
|
#ifdef USE_RTP
|
|
Runtime_performance_flags = 0;
|
|
Runtime_performance_clockfreq = 0;
|
|
Runtime_performance_frame_counter = 0;
|
|
Runtime_performance_counter = 0;
|
|
Runtime_performance_enabled = 0;
|
|
|
|
LARGE_INTEGER freq;
|
|
if (!QueryPerformanceFrequency(&freq)) {
|
|
// there is no hi-res clock available....ummmm
|
|
LOG_DEBUG << "RTP: No Hi-Resolution clock available on this system!!!!!!";
|
|
// well, this isn't good...what to do, what to do?
|
|
}
|
|
|
|
// Setup the clock freq....we'll need this info later I guess when converting to seconds
|
|
Runtime_performance_clockfreq = freq.QuadPart;
|
|
rtp_EnableFlags(RTI_FRAMETIME);
|
|
|
|
atexit(rtp_Close);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
void rtp_Close
|
|
This function shuts down the runtime performance system when the game is done
|
|
*/
|
|
void rtp_Close() {
|
|
#ifdef USE_RTP
|
|
if (Runtime_performance_enabled) {
|
|
// Save the log out, since it was currently logging
|
|
rtp_StopLog();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
void rtp_EnableFlags
|
|
This function enables the performance profiling of whatever flags you pass in
|
|
*/
|
|
void rtp_EnableFlags(INT64 flags) {
|
|
#ifdef USE_RTP
|
|
Runtime_performance_flags |= flags;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
void rtp_DisableFlags
|
|
This function disables the performance profiling of whatever flags you pass in
|
|
*/
|
|
void rtp_DisableFlags(INT64 flags) {
|
|
#ifdef USE_RTP
|
|
Runtime_performance_flags &= ~flags;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
void rtp_StartLog
|
|
Calling this function will reset the log and start a new log, recording immediatly
|
|
*/
|
|
void rtp_StartLog() {
|
|
#ifdef USE_RTP
|
|
LOG_DEBUG << "RTP: Starting Log";
|
|
Runtime_performance_counter = 0;
|
|
Runtime_performance_enabled = 1;
|
|
memset(&RTP_SingleFrame, 0, sizeof(tRTFrameInfo));
|
|
rtp_startlog_time = timer_GetTime();
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
void rtp_StopLog
|
|
Calling this function will stop the currently processing log and write it out to
|
|
file.
|
|
*/
|
|
void rtp_StopLog() {
|
|
#ifdef USE_RTP
|
|
LOG_DEBUG.printf("Recorded performance for %f seconds", timer_GetTime() - rtp_startlog_time);
|
|
LOG_DEBUG << "RTP: Stopping Log";
|
|
|
|
// Save out the log now
|
|
rtp_WriteBufferLog();
|
|
|
|
Runtime_performance_enabled = 0;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
void rtp_PauseLog
|
|
Calling this function will pause the log recording until rtp_ResumeLog is called
|
|
*/
|
|
void rtp_PauseLog() {
|
|
#ifdef USE_RTP
|
|
LOG_DEBUG << "RTP: Pausing Log";
|
|
Runtime_performance_enabled = 0;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
void rtp_ResumeLog
|
|
Calling this will resume a paused log, starting at where it left off
|
|
*/
|
|
void rtp_ResumeLog() {
|
|
#ifdef USE_RTP
|
|
LOG_DEBUG << "RTP: Resuming Log";
|
|
Runtime_performance_enabled = 1;
|
|
#endif
|
|
}
|
|
|
|
// Internal Functions
|
|
// -------------------------------
|
|
/*
|
|
INT64 rtp_GetClock
|
|
Returns the current hi-resolution clock value...no checking for overflow
|
|
*/
|
|
INT64 rtp_GetClock() {
|
|
#ifdef USE_RTP
|
|
LARGE_INTEGER t;
|
|
QueryPerformanceCounter(&t);
|
|
return (INT64)t.QuadPart;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|