aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/swr/rasterizer/common/rdtsc_buckets.h
diff options
context:
space:
mode:
authorTim Rowley <[email protected]>2016-02-16 17:28:09 -0600
committerTim Rowley <[email protected]>2016-03-02 18:38:41 -0600
commitc6e67f5a9373e916a8d2333585cb5787aa5f7bb7 (patch)
tree5b5c60bea784f16736c394c989fdd5df3ebae233 /src/gallium/drivers/swr/rasterizer/common/rdtsc_buckets.h
parent2b2d3680bf164ec4f8b50436b96c3fc195318ea5 (diff)
gallium/swr: add OpenSWR rasterizer
Acked-by: Roland Scheidegger <[email protected]> Acked-by: Jose Fonseca <[email protected]>
Diffstat (limited to 'src/gallium/drivers/swr/rasterizer/common/rdtsc_buckets.h')
-rw-r--r--src/gallium/drivers/swr/rasterizer/common/rdtsc_buckets.h229
1 files changed, 229 insertions, 0 deletions
diff --git a/src/gallium/drivers/swr/rasterizer/common/rdtsc_buckets.h b/src/gallium/drivers/swr/rasterizer/common/rdtsc_buckets.h
new file mode 100644
index 00000000000..99cb10ec6e8
--- /dev/null
+++ b/src/gallium/drivers/swr/rasterizer/common/rdtsc_buckets.h
@@ -0,0 +1,229 @@
+/****************************************************************************
+* Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice (including the next
+* paragraph) shall be included in all copies or substantial portions of the
+* Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+* IN THE SOFTWARE.
+*
+* @file rdtsc_buckets.h
+*
+* @brief declaration for rdtsc buckets.
+*
+* Notes:
+*
+******************************************************************************/
+#pragma once
+
+#include "os.h"
+#include <vector>
+#include <mutex>
+#include <sstream>
+
+#include "rdtsc_buckets_shared.h"
+
+// unique thread id stored in thread local storage
+extern THREAD UINT tlsThreadId;
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief BucketManager encapsulates a single instance of the buckets
+/// functionality. There can be one or many bucket managers active
+/// at any time. The manager owns all the threads and
+/// bucket information that have been registered to it.
+class BucketManager
+{
+public:
+ BucketManager(bool enableThreadViz) : mThreadViz(enableThreadViz)
+ {
+ if (mThreadViz)
+ {
+ uint32_t pid = GetCurrentProcessId();
+ std::stringstream str;
+ str << "threadviz." << pid;
+ mThreadVizDir = str.str();
+ CreateDirectory(mThreadVizDir.c_str(), NULL);
+ }
+ }
+
+ // removes all registered thread data
+ void ClearThreads()
+ {
+ mThreadMutex.lock();
+ mThreads.clear();
+ mThreadMutex.unlock();
+ }
+
+ // removes all registered buckets
+ void ClearBuckets()
+ {
+ mBuckets.clear();
+ }
+
+ /// Registers a new thread with the manager.
+ /// @param name - name of thread, used for labels in reports and threadviz
+ void RegisterThread(const std::string& name);
+
+ /// Registers a new bucket type with the manager. Returns a unique
+ /// id which should be used in subsequent calls to start/stop the bucket
+ /// @param desc - description of the bucket
+ /// @return unique id
+ UINT RegisterBucket(const BUCKET_DESC& desc);
+
+ // dump threadviz data
+ void DumpThreadViz();
+
+ // print report
+ void PrintReport(const std::string& filename);
+
+ // start capturing
+ INLINE void StartCapture()
+ {
+ mCapturing = true;
+ }
+
+ // stop capturing
+ INLINE void StopCapture()
+ {
+ mCapturing = false;
+
+ // wait for all threads to pop back to root bucket
+ bool stillCapturing = true;
+ while (stillCapturing)
+ {
+ stillCapturing = false;
+ for (const BUCKET_THREAD& t : mThreads)
+ {
+ if (t.pCurrent != &t.root)
+ {
+ stillCapturing = true;
+ continue;
+ }
+ }
+ }
+ }
+
+ // start a bucket
+ // @param id generated by RegisterBucket
+ INLINE void StartBucket(UINT id)
+ {
+ if (!mCapturing) return;
+
+ SWR_ASSERT(tlsThreadId < mThreads.size());
+
+ BUCKET_THREAD& bt = mThreads[tlsThreadId];
+
+ // if threadviz is enabled, only need to dump start info to threads viz file
+ if (mThreadViz)
+ {
+ SWR_ASSERT(bt.vizFile != nullptr);
+ if (mBuckets[id].enableThreadViz)
+ {
+ VIZ_START_DATA data{ VIZ_START, id, __rdtsc() };
+ Serialize(bt.vizFile, data);
+ }
+ }
+ else
+ {
+ if (bt.pCurrent->children.size() < mBuckets.size())
+ {
+ bt.pCurrent->children.resize(mBuckets.size());
+ }
+ BUCKET &child = bt.pCurrent->children[id];
+ child.pParent = bt.pCurrent;
+ child.id = id;
+ child.start = __rdtsc();
+
+ // update thread's currently executing bucket
+ bt.pCurrent = &child;
+ }
+
+ bt.level++;
+ }
+
+ // stop the currently executing bucket
+ INLINE void StopBucket(UINT id)
+ {
+ SWR_ASSERT(tlsThreadId < mThreads.size());
+ BUCKET_THREAD &bt = mThreads[tlsThreadId];
+
+ if (bt.level == 0) return;
+
+ if (mThreadViz)
+ {
+ SWR_ASSERT(bt.vizFile != nullptr);
+ if (mBuckets[id].enableThreadViz)
+ {
+ VIZ_STOP_DATA data{ VIZ_STOP, __rdtsc() };
+ Serialize(bt.vizFile, data);
+ }
+ }
+ else
+ {
+ if (bt.pCurrent->start == 0) return;
+ SWR_ASSERT(bt.pCurrent->id == id, "Mismatched buckets detected");
+
+ bt.pCurrent->elapsed += (__rdtsc() - bt.pCurrent->start);
+ bt.pCurrent->count++;
+
+ // pop to parent
+ bt.pCurrent = bt.pCurrent->pParent;
+ }
+
+ bt.level--;
+ }
+
+ INLINE void AddEvent(uint32_t id, uint32_t count)
+ {
+ if (!mCapturing) return;
+
+ SWR_ASSERT(tlsThreadId < mThreads.size());
+
+ BUCKET_THREAD& bt = mThreads[tlsThreadId];
+
+ // don't record events for threadviz
+ if (!mThreadViz)
+ {
+ if (bt.pCurrent->children.size() < mBuckets.size())
+ {
+ bt.pCurrent->children.resize(mBuckets.size());
+ }
+ BUCKET &child = bt.pCurrent->children[id];
+ child.pParent = bt.pCurrent;
+ child.id = id;
+ child.count += count;
+ }
+ }
+
+private:
+ void PrintBucket(FILE* f, UINT level, UINT64 threadCycles, UINT64 parentCycles, const BUCKET& bucket);
+ void PrintThread(FILE* f, const BUCKET_THREAD& thread);
+
+ // list of active threads that have registered with this manager
+ std::vector<BUCKET_THREAD> mThreads;
+
+ // list of buckets registered with this manager
+ std::vector<BUCKET_DESC> mBuckets;
+
+ // is capturing currently enabled
+ volatile bool mCapturing{ false };
+
+ std::mutex mThreadMutex;
+
+ // enable threadviz
+ bool mThreadViz{ false };
+ std::string mThreadVizDir;
+};