DebugSurface: implement new texture streaming debug overlay

Implement a new imgui based texture streaming overlay. The old one typically clips out of the screen and cannot be explored.
This commit is contained in:
Kawe Mazidjatari 2025-01-08 21:44:14 +01:00
parent 74d8cdfb26
commit c2deaaf3e8
5 changed files with 258 additions and 23 deletions

View File

@ -162,6 +162,8 @@ add_sources( SOURCE_GROUP "GameUI"
"${ENGINE_SOURCE_DIR}/gameui/IBrowser.h"
"${ENGINE_SOURCE_DIR}/gameui/IConsole.cpp"
"${ENGINE_SOURCE_DIR}/gameui/IConsole.h"
"${ENGINE_SOURCE_DIR}/gameui/IStreamOverlay.cpp"
"${ENGINE_SOURCE_DIR}/gameui/IStreamOverlay.h"
"${ENGINE_SOURCE_DIR}/gameui/imgui_system.cpp"
"${ENGINE_SOURCE_DIR}/gameui/imgui_system.h"

View File

@ -0,0 +1,218 @@
/******************************************************************************
-------------------------------------------------------------------------------
File : IStreamOverlay.cpp
Date : 08:01:2025
Author : Kawe Mazidjatari
Purpose: Implements the in-game texture streaming debug overlay
-------------------------------------------------------------------------------
History:
- 08:01:2025 | 19:05 : Created by Kawe Mazidjatari
******************************************************************************/
#include "windows/id3dx.h"
#include "materialsystem/texturestreaming.h"
#include "IStreamOverlay.h"
//-----------------------------------------------------------------------------
// Console variables
//-----------------------------------------------------------------------------
static ConVar stream_overlay_memory("stream_overlay_memory", "524288", FCVAR_DEVELOPMENTONLY, "Total string memory to allocate for the texture streaming debug overlay.", true, 1.f, false, 0.0f);
//-----------------------------------------------------------------------------
// Console commands
//-----------------------------------------------------------------------------
static ConCommand stream_dumpinfo("stream_dumpinfo", CStreamOverlay::DumpStreamInfo_f, "Dump texture streaming debug info to the console", FCVAR_DEVELOPMENTONLY, nullptr, "tex mtl bsp short");
//-----------------------------------------------------------------------------
// Purpose: constructor/destructor
//-----------------------------------------------------------------------------
CStreamOverlay::CStreamOverlay(void)
{
m_surfaceLabel = "Stream Overlay";
m_scratchBuffer = nullptr;
m_scratchBufferSize = 0;
m_lastAvailability = false;
}
CStreamOverlay::~CStreamOverlay(void)
{
Shutdown();
}
//-----------------------------------------------------------------------------
// Purpose: stream overlay initialization
//-----------------------------------------------------------------------------
bool CStreamOverlay::Init(void)
{
SetStyleVar(1200, 524, -1000, 50);
m_initialized = true;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: stream overlay shutdown
//-----------------------------------------------------------------------------
void CStreamOverlay::Shutdown(void)
{
FreeScratchBuffer();
m_initialized = false;
}
//-----------------------------------------------------------------------------
// Purpose: check value of stream_overlay and determine availability of window
//-----------------------------------------------------------------------------
void CStreamOverlay::UpdateWindowAvailability(void)
{
const bool enabled = stream_overlay->GetBool();
if (enabled == m_lastAvailability)
return;
if (!enabled && m_activated)
{
m_activated = false;
ResetInput();
}
else if (enabled && !m_activated)
m_activated = true;
m_lastAvailability = enabled;
}
//-----------------------------------------------------------------------------
// Purpose: run stream overlay frame
//-----------------------------------------------------------------------------
void CStreamOverlay::RunFrame(void)
{
if (!m_initialized)
Init();
Animate();
int baseWindowStyleVars = 0;
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, m_fadeAlpha); baseWindowStyleVars++;
const bool drawn = DrawSurface();
ImGui::PopStyleVar(baseWindowStyleVars);
if (!drawn)
FreeScratchBuffer();
UpdateWindowAvailability();
}
//-----------------------------------------------------------------------------
// Purpose: syncs the cvar and updates the availability of mouse/key inputs
//-----------------------------------------------------------------------------
static void StreamOverlay_HandleClose(void)
{
stream_overlay->SetValue(false);
ResetInput();
}
//-----------------------------------------------------------------------------
// Purpose: draw stream overlay
//-----------------------------------------------------------------------------
bool CStreamOverlay::DrawSurface(void)
{
if (!IsVisible())
return false;
if (!ImGui::Begin(m_surfaceLabel, &m_activated, ImGuiWindowFlags_None, &StreamOverlay_HandleClose))
{
ImGui::End();
return false;
}
if (ImGui::BeginChild("##StreamReport", ImVec2(-1, -1), ImGuiChildFlags_Border, ImGuiWindowFlags_None))
{
ResizeScratchBuffer(stream_overlay_memory.GetInt());
TextureStreamMgr_GetStreamOverlay(stream_overlay_mode->GetString(), m_scratchBuffer, m_scratchBufferSize);
ImGui::TextUnformatted(m_scratchBuffer);
}
ImGui::EndChild();
ImGui::End();
return true;
}
//-----------------------------------------------------------------------------
// Purpose: dynamically scale the scratch buffer if it became smaller or larger
//-----------------------------------------------------------------------------
void CStreamOverlay::ResizeScratchBuffer(const size_t newSize)
{
Assert(newSize > 0);
if (newSize == m_scratchBufferSize)
return; // Same size.
if (m_scratchBuffer)
delete[] m_scratchBuffer;
m_scratchBuffer = new char[newSize];
m_scratchBufferSize = newSize;
}
//-----------------------------------------------------------------------------
// Purpose: free the scratch buffer if we have one
//-----------------------------------------------------------------------------
void CStreamOverlay::FreeScratchBuffer(void)
{
if (m_scratchBuffer)
{
delete[] m_scratchBuffer;
m_scratchBuffer = nullptr;
m_scratchBufferSize = 0;
}
else
Assert(m_scratchBufferSize == 0);
}
//-----------------------------------------------------------------------------
// Purpose: render current streaming data to console with given or default mode
//-----------------------------------------------------------------------------
void CStreamOverlay::RenderToConsole(const char* const mode)
{
const bool isTemp = m_scratchBuffer == nullptr;
// If we have a buffer already, use that to render the overlay report into
// it. Else create a temporary buffer and free it afterwards.
if (isTemp)
{
const size_t targetBufLen = stream_overlay_memory.GetInt();
m_scratchBuffer = new char[targetBufLen];
m_scratchBufferSize = targetBufLen;
}
TextureStreamMgr_GetStreamOverlay(mode ? mode : stream_overlay_mode->GetString(), m_scratchBuffer, m_scratchBufferSize);
Msg(eDLL_T::MS, "%s\n", m_scratchBuffer);
if (isTemp)
{
delete[] m_scratchBuffer;
m_scratchBuffer = nullptr;
m_scratchBufferSize = 0;
}
}
CStreamOverlay g_streamOverlay;
/*
=====================
DumpStreamInfo_f
Dumps the stream info to the console.
=====================
*/
void CStreamOverlay::DumpStreamInfo_f(const CCommand& args)
{
const char* const mode = args.ArgC() >= 2 ? args.Arg(1) : nullptr;
g_streamOverlay.RenderToConsole(mode);
}

View File

@ -0,0 +1,36 @@
#pragma once
#include "imgui/misc/imgui_logger.h"
#include "imgui/misc/imgui_utility.h"
#include "imgui_surface.h"
class CStreamOverlay : public CImguiSurface
{
public:
CStreamOverlay(void);
~CStreamOverlay(void);
virtual bool Init(void);
virtual void Shutdown(void);
virtual void RunFrame(void);
virtual bool DrawSurface(void);
void UpdateWindowAvailability(void);
void ResizeScratchBuffer(const size_t newSize);
void FreeScratchBuffer(void);
void RenderToConsole(const char* const mode);
// Command callbacks.
static void DumpStreamInfo_f(const CCommand& args);
private:
char* m_scratchBuffer;
size_t m_scratchBufferSize;
bool m_lastAvailability;
};
extern CStreamOverlay g_streamOverlay;

View File

@ -95,29 +95,6 @@ int CMaterialSystem::Shutdown(CMaterialSystem* thisptr)
}
#ifndef MATERIALSYSTEM_NODX
static ConVar stream_overlay_memory("stream_overlay_memory", "524288", FCVAR_DEVELOPMENTONLY, "Total string memory to allocate for the texture streaming debug overlay.");
/*
=====================
Mat_DumpStreamInfo_f
Prints the stream info to the console.
=====================
*/
static void Mat_DumpStreamInfo_f(const CCommand& args)
{
const int stringMem = stream_overlay_memory.GetInt();
std::unique_ptr<char[]> stringBuf(new char[stringMem]);
const char* const mode = args.ArgC() >= 2 ? args.Arg(1) : stream_overlay_mode->GetString();
char* const scratch = stringBuf.get();
TextureStreamMgr_GetStreamOverlay(mode, scratch, stringMem);
Msg(eDLL_T::MS, "%s\n", scratch);
}
static ConCommand stream_dumpinfo("stream_dumpinfo", Mat_DumpStreamInfo_f, "Dump texture streaming debug info to the console", FCVAR_DEVELOPMENTONLY, nullptr, "tex mtl bsp short");
//---------------------------------------------------------------------------------
// Purpose: draw frame
//---------------------------------------------------------------------------------

View File

@ -10,6 +10,7 @@
#include "geforce/reflex.h"
#include "gameui/IConsole.h"
#include "gameui/IBrowser.h"
#include "gameui/IStreamOverlay.h"
#include "gameui/imgui_system.h"
#include "engine/framelimit.h"
#include "engine/sys_mainwind.h"
@ -330,6 +331,7 @@ void DirectX_Init()
{
ImguiSystem()->AddSurface(&g_Console);
ImguiSystem()->AddSurface(&g_Browser);
ImguiSystem()->AddSurface(&g_streamOverlay);
}
else
{