Przeglądaj źródła

Merge pull request #87 from MarcoROG/master

Fixed several memory leaks and bugfixes
Marko Pintera 8 lat temu
rodzic
commit
8e81a20cf0

+ 1 - 1
Source/BansheeCore/Include/BsCommonTypes.h

@@ -166,7 +166,7 @@ namespace bs
 		 * However it is hard to guarantee when GPU has finished using a buffer.
 		 */
 		GBL_WRITE_ONLY_NO_OVERWRITE,
-		/** Allows you to both read and write to a buffer. */
+		/** Allows you to write to a buffer. */
 		GBL_WRITE_ONLY	
 	};
 

+ 19 - 13
Source/BansheeCore/Include/BsProfilerGPU.h

@@ -9,8 +9,8 @@
 namespace bs
 {
 	/** @addtogroup Profiling
-	 *  @{
-	 */
+	*  @{
+	*/
 
 	/** Contains various profiler statistics about a single GPU profiling sample. */
 	struct GPUProfileSample
@@ -72,6 +72,7 @@ namespace bs
 
 	public:
 		ProfilerGPU();
+		~ProfilerGPU();
 
 		/**
 		 * Signals a start of a new frame. Every frame will generate a separate profiling report. This call must be followed
@@ -80,8 +81,8 @@ namespace bs
 		void beginFrame();
 
 		/**
-		 * Signals an end of the currently sampled frame. Results of the sampling will be available once 
-		 * getNumAvailableReports increments. This may take a while as the sampling is scheduled on the core thread and 
+		 * Signals an end of the currently sampled frame. Results of the sampling will be available once
+		 * getNumAvailableReports increments. This may take a while as the sampling is scheduled on the core thread and
 		 * on the GPU.
 		 */
 		void endFrame();
@@ -100,17 +101,17 @@ namespace bs
 		 *
 		 * @param[in]	name	Unique name for the sample.
 		 *
-		 * @note	
-		 * Unique name is primarily needed to more easily identify mismatched begin/end sample pairs. Otherwise the name in 
+		 * @note
+		 * Unique name is primarily needed to more easily identify mismatched begin/end sample pairs. Otherwise the name in
 		 * beginSample() would be enough. Must be called between beginFrame()/endFrame() calls.
 		 */
 		void endSample(const ProfilerString& name);
 
 		/**
-		 * Returns number of profiling reports that are ready but haven't been retrieved yet. 
+		 * Returns number of profiling reports that are ready but haven't been retrieved yet.
 		 *
-		 * @note	
-		 * There is an internal limit of maximum number of available reports, where oldest ones will get deleted so make 
+		 * @note
+		 * There is an internal limit of maximum number of available reports, where oldest ones will get deleted so make
 		 * sure to call this often if you don't want to miss some.
 		 * @note
 		 * Thread safe.
@@ -118,14 +119,15 @@ namespace bs
 		UINT32 getNumAvailableReports();
 
 		/**
-		 * Gets the oldest report available and removes it from the internal list. Throws an exception if no reports are 
+		 * Gets the oldest report available and removes it from the internal list. Throws an exception if no reports are
 		 * available.
 		 *
 		 * @note	Thread safe.
 		 */
 		GPUProfilerReport getNextReport();
 
-	public: // ***** INTERNAL ******
+	public: 
+		// ***** INTERNAL ******
 		/** @name Internal
 		 *  @{
 		 */
@@ -151,7 +153,7 @@ namespace bs
 		SPtr<ct::OcclusionQuery> getOcclusionQuery() const;
 
 		/**
-		 * Interprets the active frame results and generates a profiler report for the frame. Provided frame queries must 
+		 * Interprets the active frame results and generates a profiler report for the frame. Provided frame queries must
 		 * have finished before calling this.
 		 */
 		GPUProfilerReport resolveFrame(ActiveFrame& frame);
@@ -165,7 +167,11 @@ namespace bs
 		Stack<UINT32> mActiveSampleIndexes;
 
 		Queue<ActiveFrame> mUnresolvedFrames;
-		Queue<GPUProfilerReport> mReadyReports;
+		GPUProfilerReport* mReadyReports;
+
+		static const UINT32 MAX_QUEUE_ELEMENTS;
+		UINT32 mReportHeadPos;
+		UINT32 mReportCount;
 
 		mutable Stack<SPtr<ct::TimerQuery>> mFreeTimerQueries;
 		mutable Stack<SPtr<ct::OcclusionQuery>> mFreeOcclusionQueries;

+ 34 - 9
Source/BansheeCore/Source/BsHString.cpp

@@ -11,7 +11,7 @@ namespace bs
 	{
 		mStringData = StringTableManager::instance().getTable(stringTableId)->getStringData(L"");
 
-		if(mStringData->numParameters > 0)
+		if (mStringData->numParameters > 0)
 			mParameters = bs_newN<WString>(mStringData->numParameters);
 	}
 
@@ -20,7 +20,7 @@ namespace bs
 	{
 		mStringData = StringTableManager::instance().getTable(stringTableId)->getStringData(identifierString);
 
-		if(mStringData->numParameters > 0)
+		if (mStringData->numParameters > 0)
 			mParameters = bs_newN<WString>(mStringData->numParameters);
 	}
 
@@ -38,7 +38,26 @@ namespace bs
 
 	HString::HString(const HString& copy)
 	{
-		*this = copy;
+		mStringData = copy.mStringData;
+		mIsDirty = copy.mIsDirty;
+		mCachedString = copy.mCachedString;
+
+		if (copy.mStringData->numParameters > 0)
+		{
+			mParameters = bs_newN<WString>(mStringData->numParameters);
+			if (copy.mParameters != nullptr)
+			{
+				for (UINT32 i = 0; i < mStringData->numParameters; i++)
+					mParameters[i] = copy.mParameters[i];
+			}
+
+			mStringPtr = &mCachedString;
+		}
+		else
+		{
+			mParameters = nullptr;
+			mStringPtr = &mStringData->string;
+		}
 	}
 
 	HString::~HString()
@@ -47,13 +66,19 @@ namespace bs
 			bs_deleteN(mParameters, mStringData->numParameters);
 	}
 
-	HString::operator const WString& () const 
-	{ 
-		return getValue(); 
+	HString::operator const WString& () const
+	{
+		return getValue();
 	}
 
 	HString& HString::operator=(const HString& rhs)
 	{
+		if (mParameters != nullptr)
+		{
+			bs_deleteN(mParameters, mStringData->numParameters);
+			mParameters = nullptr;
+		}
+
 		mStringData = rhs.mStringData;
 		mIsDirty = rhs.mIsDirty;
 		mCachedString = rhs.mCachedString;
@@ -80,9 +105,9 @@ namespace bs
 
 	const WString& HString::getValue() const
 	{
-		if(mIsDirty)
+		if (mIsDirty)
 		{
-			if(mParameters != nullptr)
+			if (mParameters != nullptr)
 			{
 				mStringData->concatenateString(mCachedString, mParameters, mStringData->numParameters);
 				mStringPtr = &mCachedString;
@@ -95,7 +120,7 @@ namespace bs
 			mIsDirty = false;
 		}
 
-		return *mStringPtr; 
+		return *mStringPtr;
 	}
 
 	void HString::setParameter(UINT32 idx, const WString& value)

+ 25 - 10
Source/BansheeCore/Source/BsProfilerGPU.cpp

@@ -8,9 +8,18 @@
 
 namespace bs
 {
+	const UINT32 ProfilerGPU::MAX_QUEUE_ELEMENTS = 5;
+
 	ProfilerGPU::ProfilerGPU()
-		:mIsFrameActive(false)
-	{ }
+		:mIsFrameActive(false), mReadyReports(nullptr), mReportHeadPos(0), mReportCount(0)
+	{
+		mReadyReports = bs_newN<GPUProfilerReport>(MAX_QUEUE_ELEMENTS);
+	}
+
+	ProfilerGPU::~ProfilerGPU()
+	{
+		bs_deleteN(mReadyReports, MAX_QUEUE_ELEMENTS);
+	}
 
 	void ProfilerGPU::beginFrame()
 	{
@@ -62,7 +71,7 @@ namespace bs
 		ActiveSample& sample = mActiveFrame.samples[lastSampleIdx];
 		if (sample.sampleName != name)
 		{
-			String errorStr = "Attempting to end a sample that doesn't match. Got: " + 
+			String errorStr = "Attempting to end a sample that doesn't match. Got: " +
 				String(name.c_str()) + ". Expected: " + String(sample.sampleName.c_str());
 
 			BS_EXCEPT(InvalidStateException, errorStr);
@@ -76,18 +85,20 @@ namespace bs
 	{
 		Lock lock(mMutex);
 
-		return (UINT32)mReadyReports.size();
+		return mReportCount;
 	}
 
 	GPUProfilerReport ProfilerGPU::getNextReport()
 	{
 		Lock lock(mMutex);
 
-		if (mReadyReports.empty())
+		if (mReportCount == 0)
 			BS_EXCEPT(InvalidStateException, "No reports are available.")
 
-		GPUProfilerReport report = mReadyReports.front();
-		mReadyReports.pop();
+			GPUProfilerReport report = mReadyReports[mReportHeadPos];
+
+		mReportHeadPos = (mReportHeadPos + 1) % MAX_QUEUE_ELEMENTS;
+		mReportCount--;
 
 		return report;
 	}
@@ -107,7 +118,11 @@ namespace bs
 
 				{
 					Lock lock(mMutex);
-					mReadyReports.push(report);
+					mReadyReports[(mReportHeadPos + mReportCount) % MAX_QUEUE_ELEMENTS] = report;
+					if (mReportCount == MAX_QUEUE_ELEMENTS)
+						mReportHeadPos = (mReportHeadPos + 1) % MAX_QUEUE_ELEMENTS;
+					else
+						mReportCount++;
 				}
 			}
 			else
@@ -118,7 +133,7 @@ namespace bs
 	GPUProfilerReport ProfilerGPU::resolveFrame(ActiveFrame& frame)
 	{
 		GPUProfilerReport report;
-		
+
 		resolveSample(frame.frameSample, report.frameSample);
 
 		for (auto& sample : frame.samples)
@@ -145,7 +160,7 @@ namespace bs
 
 		reportSample.numVertices = (UINT32)(sample.endStats.numVertices - sample.startStats.numVertices);
 		reportSample.numPrimitives = (UINT32)(sample.endStats.numPrimitives - sample.startStats.numPrimitives);
-		
+
 		reportSample.numPipelineStateChanges = (UINT32)(sample.endStats.numPipelineStateChanges - sample.startStats.numPipelineStateChanges);
 
 		reportSample.numGpuParamBinds = (UINT32)(sample.endStats.numGpuParamBinds - sample.startStats.numGpuParamBinds);

+ 2 - 0
Source/BansheeUtility/Source/BsFrameAlloc.cpp

@@ -235,6 +235,8 @@ namespace bs
 
 				allocBlock(totalBytes);
 			}
+			else
+				mBlocks[0]->mFreePtr = 0;
 		}
 	}
 

+ 4 - 1
Source/BansheeUtility/Source/BsThreadPool.cpp

@@ -261,8 +261,11 @@ namespace bs
 
 		for(auto& thread : idleThreads)
 		{
-			if(i < limit)
+			if (i < limit)
+			{
 				mThreads.push_back(thread);
+				i++;
+			}
 			else
 				destroyThread(thread);
 		}