diff options
author | Tim Rowley <[email protected]> | 2016-02-16 17:28:09 -0600 |
---|---|---|
committer | Tim Rowley <[email protected]> | 2016-03-02 18:38:41 -0600 |
commit | c6e67f5a9373e916a8d2333585cb5787aa5f7bb7 (patch) | |
tree | 5b5c60bea784f16736c394c989fdd5df3ebae233 /src/gallium/drivers/swr/rasterizer/common/rdtsc_buckets.h | |
parent | 2b2d3680bf164ec4f8b50436b96c3fc195318ea5 (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.h | 229 |
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; +}; |