mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 09:15:29 +01:00 
			
		
		
		
	Keep stats on hw buffer uploads
This commit is contained in:
		@@ -114,6 +114,15 @@ const c8 *const FogTypeNames[] = {
 | 
			
		||||
		0,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
struct SFrameStats {
 | 
			
		||||
	//! Count of primitives drawn
 | 
			
		||||
	u32 PrimitivesDrawn = 0;
 | 
			
		||||
	//! Number of hardware buffers uploaded (new or updated)
 | 
			
		||||
	u32 HWBuffersUploaded = 0;
 | 
			
		||||
	//! Sum of uploaded hardware buffer size
 | 
			
		||||
	u32 HWBuffersUploadedSize = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Interface to driver which is able to perform 2d and 3d graphics functions.
 | 
			
		||||
/** This interface is one of the most important interfaces of
 | 
			
		||||
the Irrlicht Engine: All rendering and texture manipulation is done with
 | 
			
		||||
@@ -194,12 +203,6 @@ public:
 | 
			
		||||
	*/
 | 
			
		||||
	virtual const io::IAttributes &getDriverAttributes() const = 0;
 | 
			
		||||
 | 
			
		||||
	//! Check if the driver was recently reset.
 | 
			
		||||
	/** For d3d devices you will need to recreate the RTTs if the
 | 
			
		||||
	driver was reset. Should be queried right after beginScene().
 | 
			
		||||
	*/
 | 
			
		||||
	virtual bool checkDriverReset() = 0;
 | 
			
		||||
 | 
			
		||||
	//! Sets transformation matrices.
 | 
			
		||||
	/** \param state Transformation type to be set, e.g. view,
 | 
			
		||||
	world, or projection.
 | 
			
		||||
@@ -855,12 +858,8 @@ public:
 | 
			
		||||
	\return Approximate amount of frames per second drawn. */
 | 
			
		||||
	virtual s32 getFPS() const = 0;
 | 
			
		||||
 | 
			
		||||
	//! Returns amount of primitives (mostly triangles) which were drawn in the last frame.
 | 
			
		||||
	/** Together with getFPS() very useful method for statistics.
 | 
			
		||||
	\param mode Defines if the primitives drawn are accumulated or
 | 
			
		||||
	counted per frame.
 | 
			
		||||
	\return Amount of primitives drawn in the last frame. */
 | 
			
		||||
	virtual u32 getPrimitiveCountDrawn(u32 mode = 0) const = 0;
 | 
			
		||||
	//! Return some statistics about the last frame
 | 
			
		||||
	virtual SFrameStats getFrameStats() const = 0;
 | 
			
		||||
 | 
			
		||||
	//! Gets name of this video driver.
 | 
			
		||||
	/** \return Returns the name of the video driver, e.g. in case
 | 
			
		||||
 
 | 
			
		||||
@@ -11,53 +11,22 @@ namespace video
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
CFPSCounter::CFPSCounter() :
 | 
			
		||||
		FPS(60), Primitive(0), StartTime(0), FramesCounted(0),
 | 
			
		||||
		PrimitivesCounted(0), PrimitiveAverage(0), PrimitiveTotal(0)
 | 
			
		||||
		FPS(0), StartTime(0), FramesCounted(0)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! returns current fps
 | 
			
		||||
s32 CFPSCounter::getFPS() const
 | 
			
		||||
{
 | 
			
		||||
	return FPS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! returns current primitive count
 | 
			
		||||
u32 CFPSCounter::getPrimitive() const
 | 
			
		||||
{
 | 
			
		||||
	return Primitive;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! returns average primitive count of last period
 | 
			
		||||
u32 CFPSCounter::getPrimitiveAverage() const
 | 
			
		||||
{
 | 
			
		||||
	return PrimitiveAverage;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! returns accumulated primitive count since start
 | 
			
		||||
u32 CFPSCounter::getPrimitiveTotal() const
 | 
			
		||||
{
 | 
			
		||||
	return PrimitiveTotal;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! to be called every frame
 | 
			
		||||
void CFPSCounter::registerFrame(u32 now, u32 primitivesDrawn)
 | 
			
		||||
void CFPSCounter::registerFrame(u32 now)
 | 
			
		||||
{
 | 
			
		||||
	++FramesCounted;
 | 
			
		||||
	PrimitiveTotal += primitivesDrawn;
 | 
			
		||||
	PrimitivesCounted += primitivesDrawn;
 | 
			
		||||
	Primitive = primitivesDrawn;
 | 
			
		||||
 | 
			
		||||
	const u32 milliseconds = now - StartTime;
 | 
			
		||||
 | 
			
		||||
	if (milliseconds >= 1500) {
 | 
			
		||||
		const f32 invMilli = core::reciprocal((f32)milliseconds);
 | 
			
		||||
 | 
			
		||||
		FPS = core::ceil32((1000 * FramesCounted) * invMilli);
 | 
			
		||||
		PrimitiveAverage = core::ceil32((1000 * PrimitivesCounted) * invMilli);
 | 
			
		||||
 | 
			
		||||
		FramesCounted = 0;
 | 
			
		||||
		PrimitivesCounted = 0;
 | 
			
		||||
		StartTime = now;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,29 +17,15 @@ public:
 | 
			
		||||
	CFPSCounter();
 | 
			
		||||
 | 
			
		||||
	//! returns current fps
 | 
			
		||||
	s32 getFPS() const;
 | 
			
		||||
 | 
			
		||||
	//! returns primitive count
 | 
			
		||||
	u32 getPrimitive() const;
 | 
			
		||||
 | 
			
		||||
	//! returns average primitive count of last period
 | 
			
		||||
	u32 getPrimitiveAverage() const;
 | 
			
		||||
 | 
			
		||||
	//! returns accumulated primitive count since start
 | 
			
		||||
	u32 getPrimitiveTotal() const;
 | 
			
		||||
	s32 getFPS() const { return FPS; }
 | 
			
		||||
 | 
			
		||||
	//! to be called every frame
 | 
			
		||||
	void registerFrame(u32 now, u32 primitive);
 | 
			
		||||
	void registerFrame(u32 now);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	s32 FPS;
 | 
			
		||||
	u32 Primitive;
 | 
			
		||||
	u32 StartTime;
 | 
			
		||||
 | 
			
		||||
	u32 FramesCounted;
 | 
			
		||||
	u32 PrimitivesCounted;
 | 
			
		||||
	u32 PrimitiveAverage;
 | 
			
		||||
	u32 PrimitiveTotal;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // end namespace video
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,7 @@ public:
 | 
			
		||||
//! constructor
 | 
			
		||||
CNullDriver::CNullDriver(io::IFileSystem *io, const core::dimension2d<u32> &screenSize) :
 | 
			
		||||
		SharedRenderTarget(0), CurrentRenderTarget(0), CurrentRenderTargetSize(0, 0), FileSystem(io), MeshManipulator(0),
 | 
			
		||||
		ViewPort(0, 0, 0, 0), ScreenSize(screenSize), PrimitivesDrawn(0), MinVertexCountForVBO(500),
 | 
			
		||||
		ViewPort(0, 0, 0, 0), ScreenSize(screenSize), MinVertexCountForVBO(500),
 | 
			
		||||
		TextureCreationFlags(0), OverrideMaterial2DEnabled(false), AllowZWriteOnTransparent(false)
 | 
			
		||||
{
 | 
			
		||||
#ifdef _DEBUG
 | 
			
		||||
@@ -222,13 +222,13 @@ void CNullDriver::deleteAllTextures()
 | 
			
		||||
 | 
			
		||||
bool CNullDriver::beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil, const SExposedVideoData &videoData, core::rect<s32> *sourceRect)
 | 
			
		||||
{
 | 
			
		||||
	PrimitivesDrawn = 0;
 | 
			
		||||
	FrameStats = {};
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CNullDriver::endScene()
 | 
			
		||||
{
 | 
			
		||||
	FPSCounter.registerFrame(os::Timer::getRealTime(), PrimitivesDrawn);
 | 
			
		||||
	FPSCounter.registerFrame(os::Timer::getRealTime());
 | 
			
		||||
	updateAllHardwareBuffers();
 | 
			
		||||
	updateAllOcclusionQueries();
 | 
			
		||||
	return true;
 | 
			
		||||
@@ -605,7 +605,7 @@ void CNullDriver::drawVertexPrimitiveList(const void *vertices, u32 vertexCount,
 | 
			
		||||
{
 | 
			
		||||
	if ((iType == EIT_16BIT) && (vertexCount > 65536))
 | 
			
		||||
		os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur.");
 | 
			
		||||
	PrimitivesDrawn += primitiveCount;
 | 
			
		||||
	FrameStats.PrimitivesDrawn += primitiveCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! draws a vertex primitive list in 2d
 | 
			
		||||
@@ -613,7 +613,7 @@ void CNullDriver::draw2DVertexPrimitiveList(const void *vertices, u32 vertexCoun
 | 
			
		||||
{
 | 
			
		||||
	if ((iType == EIT_16BIT) && (vertexCount > 65536))
 | 
			
		||||
		os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur.");
 | 
			
		||||
	PrimitivesDrawn += primitiveCount;
 | 
			
		||||
	FrameStats.PrimitivesDrawn += primitiveCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Draws a 3d line.
 | 
			
		||||
@@ -743,12 +743,9 @@ s32 CNullDriver::getFPS() const
 | 
			
		||||
	return FPSCounter.getFPS();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! returns amount of primitives (mostly triangles) were drawn in the last frame.
 | 
			
		||||
//! very useful method for statistics.
 | 
			
		||||
u32 CNullDriver::getPrimitiveCountDrawn(u32 param) const
 | 
			
		||||
SFrameStats CNullDriver::getFrameStats() const
 | 
			
		||||
{
 | 
			
		||||
	return (0 == param) ? FPSCounter.getPrimitive() : (1 == param) ? FPSCounter.getPrimitiveAverage()
 | 
			
		||||
																   : FPSCounter.getPrimitiveTotal();
 | 
			
		||||
	return FrameStats;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Sets the dynamic ambient light color. The default color is
 | 
			
		||||
 
 | 
			
		||||
@@ -195,9 +195,7 @@ public:
 | 
			
		||||
	// get current frames per second value
 | 
			
		||||
	s32 getFPS() const override;
 | 
			
		||||
 | 
			
		||||
	//! returns amount of primitives (mostly triangles) were drawn in the last frame.
 | 
			
		||||
	//! very useful method for statistics.
 | 
			
		||||
	u32 getPrimitiveCountDrawn(u32 param = 0) const override;
 | 
			
		||||
	SFrameStats getFrameStats() const override;
 | 
			
		||||
 | 
			
		||||
	//! \return Returns the name of the video driver. Example: In case of the DIRECT3D8
 | 
			
		||||
	//! driver, it would return "Direct3D8.1".
 | 
			
		||||
@@ -538,8 +536,6 @@ public:
 | 
			
		||||
	virtual void convertColor(const void *sP, ECOLOR_FORMAT sF, s32 sN,
 | 
			
		||||
			void *dP, ECOLOR_FORMAT dF) const override;
 | 
			
		||||
 | 
			
		||||
	bool checkDriverReset() override { return false; }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	//! deletes all textures
 | 
			
		||||
	void deleteAllTextures();
 | 
			
		||||
@@ -570,6 +566,12 @@ protected:
 | 
			
		||||
	// prints renderer version
 | 
			
		||||
	void printVersion();
 | 
			
		||||
 | 
			
		||||
	inline void accountHWBufferUpload(u32 size)
 | 
			
		||||
	{
 | 
			
		||||
		FrameStats.HWBuffersUploaded++;
 | 
			
		||||
		FrameStats.HWBuffersUploadedSize += size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline bool getWriteZBuffer(const SMaterial &material) const
 | 
			
		||||
	{
 | 
			
		||||
		switch (material.ZWriteEnable) {
 | 
			
		||||
@@ -696,8 +698,8 @@ protected:
 | 
			
		||||
	core::matrix4 TransformationMatrix;
 | 
			
		||||
 | 
			
		||||
	CFPSCounter FPSCounter;
 | 
			
		||||
	SFrameStats FrameStats;
 | 
			
		||||
 | 
			
		||||
	u32 PrimitivesDrawn;
 | 
			
		||||
	u32 MinVertexCountForVBO;
 | 
			
		||||
 | 
			
		||||
	u32 TextureCreationFlags;
 | 
			
		||||
 
 | 
			
		||||
@@ -266,6 +266,8 @@ bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer)
 | 
			
		||||
	const E_VERTEX_TYPE vType = mb->getVertexType();
 | 
			
		||||
	const u32 vertexSize = getVertexPitchFromType(vType);
 | 
			
		||||
 | 
			
		||||
	accountHWBufferUpload(vertexSize * vertexCount);
 | 
			
		||||
 | 
			
		||||
	const c8 *vbuf = static_cast<const c8 *>(vertices);
 | 
			
		||||
	core::array<c8> buffer;
 | 
			
		||||
	if (!FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra]) {
 | 
			
		||||
@@ -367,6 +369,8 @@ bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer)
 | 
			
		||||
	}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	accountHWBufferUpload(indexCount * indexSize);
 | 
			
		||||
 | 
			
		||||
	// get or create buffer
 | 
			
		||||
	bool newBuffer = false;
 | 
			
		||||
	if (!HWBuffer->vbo_indicesID) {
 | 
			
		||||
 
 | 
			
		||||
@@ -255,10 +255,7 @@ bool COpenGL3DriverBase::genericDriverInit(const core::dimension2d<u32> &screenS
 | 
			
		||||
 | 
			
		||||
	DriverAttributes->setAttribute("MaxTextures", (s32)Feature.MaxTextureUnits);
 | 
			
		||||
	DriverAttributes->setAttribute("MaxSupportedTextures", (s32)Feature.MaxTextureUnits);
 | 
			
		||||
	//		DriverAttributes->setAttribute("MaxLights", MaxLights);
 | 
			
		||||
	DriverAttributes->setAttribute("MaxAnisotropy", MaxAnisotropy);
 | 
			
		||||
	//		DriverAttributes->setAttribute("MaxAuxBuffers", MaxAuxBuffers);
 | 
			
		||||
	//		DriverAttributes->setAttribute("MaxMultipleRenderTargets", MaxMultipleRenderTargets);
 | 
			
		||||
	DriverAttributes->setAttribute("MaxIndices", (s32)MaxIndices);
 | 
			
		||||
	DriverAttributes->setAttribute("MaxTextureSize", (s32)MaxTextureSize);
 | 
			
		||||
	DriverAttributes->setAttribute("MaxTextureLODBias", MaxTextureLODBias);
 | 
			
		||||
@@ -493,6 +490,7 @@ bool COpenGL3DriverBase::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuff
 | 
			
		||||
 | 
			
		||||
	const void *buffer = vertices;
 | 
			
		||||
	size_t bufferSize = vertexSize * vertexCount;
 | 
			
		||||
	accountHWBufferUpload(bufferSize);
 | 
			
		||||
 | 
			
		||||
	// get or create buffer
 | 
			
		||||
	bool newBuffer = false;
 | 
			
		||||
@@ -551,6 +549,9 @@ bool COpenGL3DriverBase::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffe
 | 
			
		||||
	}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const size_t bufferSize = indexCount * indexSize;
 | 
			
		||||
	accountHWBufferUpload(bufferSize);
 | 
			
		||||
 | 
			
		||||
	// get or create buffer
 | 
			
		||||
	bool newBuffer = false;
 | 
			
		||||
	if (!HWBuffer->vbo_indicesID) {
 | 
			
		||||
@@ -558,7 +559,7 @@ bool COpenGL3DriverBase::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffe
 | 
			
		||||
		if (!HWBuffer->vbo_indicesID)
 | 
			
		||||
			return false;
 | 
			
		||||
		newBuffer = true;
 | 
			
		||||
	} else if (HWBuffer->vbo_indicesSize < indexCount * indexSize) {
 | 
			
		||||
	} else if (HWBuffer->vbo_indicesSize < bufferSize) {
 | 
			
		||||
		newBuffer = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -566,16 +567,16 @@ bool COpenGL3DriverBase::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffe
 | 
			
		||||
 | 
			
		||||
	// copy data to graphics card
 | 
			
		||||
	if (!newBuffer)
 | 
			
		||||
		GL.BufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexCount * indexSize, indices);
 | 
			
		||||
		GL.BufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, bufferSize, indices);
 | 
			
		||||
	else {
 | 
			
		||||
		HWBuffer->vbo_indicesSize = indexCount * indexSize;
 | 
			
		||||
		HWBuffer->vbo_indicesSize = bufferSize;
 | 
			
		||||
 | 
			
		||||
		GLenum usage = GL_STATIC_DRAW;
 | 
			
		||||
		if (HWBuffer->Mapped_Index == scene::EHM_STREAM)
 | 
			
		||||
			usage = GL_STREAM_DRAW;
 | 
			
		||||
		else if (HWBuffer->Mapped_Index == scene::EHM_DYNAMIC)
 | 
			
		||||
			usage = GL_DYNAMIC_DRAW;
 | 
			
		||||
		GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, usage);
 | 
			
		||||
		GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, indices, usage);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 | 
			
		||||
@@ -589,22 +590,24 @@ bool COpenGL3DriverBase::updateHardwareBuffer(SHWBufferLink *HWBuffer)
 | 
			
		||||
	if (!HWBuffer)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	auto *b = static_cast<SHWBufferLink_opengl *>(HWBuffer);
 | 
			
		||||
 | 
			
		||||
	if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER) {
 | 
			
		||||
		if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex() || !static_cast<SHWBufferLink_opengl *>(HWBuffer)->vbo_verticesID) {
 | 
			
		||||
		if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex() || !b->vbo_verticesID) {
 | 
			
		||||
 | 
			
		||||
			HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex();
 | 
			
		||||
 | 
			
		||||
			if (!updateVertexHardwareBuffer(static_cast<SHWBufferLink_opengl *>(HWBuffer)))
 | 
			
		||||
			if (!updateVertexHardwareBuffer(b))
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (HWBuffer->Mapped_Index != scene::EHM_NEVER) {
 | 
			
		||||
		if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() || !static_cast<SHWBufferLink_opengl *>(HWBuffer)->vbo_indicesID) {
 | 
			
		||||
		if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() || !b->vbo_indicesID) {
 | 
			
		||||
 | 
			
		||||
			HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index();
 | 
			
		||||
 | 
			
		||||
			if (!updateIndexHardwareBuffer((SHWBufferLink_opengl *)HWBuffer))
 | 
			
		||||
			if (!updateIndexHardwareBuffer(b))
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -1953,6 +1953,11 @@ void Game::updateProfilers(const RunStats &stats, const FpsControl &draw_times,
 | 
			
		||||
	g_profiler->graphAdd("Sleep [us]", draw_times.sleep_time);
 | 
			
		||||
 | 
			
		||||
	g_profiler->graphSet("FPS", 1.0f / dtime);
 | 
			
		||||
 | 
			
		||||
	auto stats2 = driver->getFrameStats();
 | 
			
		||||
	g_profiler->avg("Irr: primitives drawn", stats2.PrimitivesDrawn);
 | 
			
		||||
	g_profiler->avg("Irr: buffers uploaded", stats2.HWBuffersUploaded);
 | 
			
		||||
	g_profiler->avg("Irr: buffers uploaded (bytes)", stats2.HWBuffersUploadedSize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Game::updateStats(RunStats *stats, const FpsControl &draw_times,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user