1 /**************************************************************************
2  *
3  * Copyright 2015 Alexander Trukhin
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25 
26 #pragma once
27 
28 #include <memory>
29 #include <vector>
30 #include <map>
31 #include <string>
32 #include <queue>
33 
34 #include "glproc.hpp"
35 #include "metric_backend.hpp"
36 #include "glretrace.hpp"
37 #include "mmap_allocator.hpp"
38 
39 #define INTEL_NAME_LENGTH 256 // metric name with max 256 chars
40 #define INTEL_DESC_LENGTH 1024 // description max 1024 chars
41 
42 class Metric_INTEL_perfquery : public Metric
43 {
44 private:
45     unsigned m_group, m_id;
46     unsigned m_offset;
47     std:: string m_name;
48     MetricNumType m_nType;
49     bool m_precached;
50 
51     void precache();
52 
53 public:
Metric_INTEL_perfquery(unsigned g,unsigned i)54     Metric_INTEL_perfquery(unsigned g, unsigned i) : m_group(g), m_id(i),
55                                                      m_offset(0),
56                                                      m_nType(CNT_NUM_UINT),
57                                                      m_precached(false) {}
58 
59     unsigned offset();
60 
61 
62     unsigned id() override;
63 
64     unsigned groupId() override;
65 
66     std::string name() override;
67 
68     std::string description() override;
69 
70     MetricNumType numType() override;
71 
72     MetricType type() override;
73 };
74 
75 
76 class MetricBackend_INTEL_perfquery : public MetricBackend
77 {
78 private:
79     class DataCollector
80     {
81         private:
82             MmapAllocator<unsigned char> alloc;
83             // deque with custom allocator
84             template <class T>
85             using mmapdeque = std::deque<T, MmapAllocator<T>>;
86             // data storage
87             mmapdeque<mmapdeque<unsigned char*>> data;
88             unsigned curPass;
89 
90         public:
DataCollector(MmapAllocator<char> & alloc)91             DataCollector(MmapAllocator<char> &alloc)
92                 : alloc(alloc), data(1, mmapdeque<unsigned char*>(alloc), alloc),
93                   curPass(0) {}
94 
95             ~DataCollector();
96 
97             unsigned char* newDataBuffer(unsigned event, size_t size);
98 
99             void endPass();
100 
101             unsigned char* getDataBuffer(unsigned pass, unsigned event);
102     };
103 
104 private:
105     // map from query id to its Metric list
106     std::map<unsigned, std::vector<Metric_INTEL_perfquery>> passes[2];
107     /* curQueryMetrics -- iterator through passes */
108     std::map<unsigned, std::vector<Metric_INTEL_perfquery>>::iterator curQueryMetrics;
109     unsigned curQuery;
110     bool supported;
111     bool perFrame;
112     bool queryInProgress;
113     int numPasses;
114     int numFramePasses;
115     int curPass;
116     unsigned curEvent; // Currently evaluated event
117     DataCollector collector;
118     /* nameLookup for querying metrics by name */
119     static std::map<std::string, std::pair<unsigned, unsigned>> nameLookup;
120 
121     MetricBackend_INTEL_perfquery(glretrace::Context* context, MmapAllocator<char> &alloc);
122 
123     MetricBackend_INTEL_perfquery(MetricBackend_INTEL_perfquery const&) = delete;
124 
125     void operator=(MetricBackend_INTEL_perfquery const&)            = delete;
126 
127     void freeQuery(unsigned event); // collect metrics data from the query
128 
129     static void populateLookupGroups(unsigned group, int error, void* userData);
130 
131     static void populateLookupMetrics(Metric* metric, int error, void* userData);
132 
133 public:
134     bool isSupported() override;
135 
136     void enumGroups(enumGroupsCallback callback, void* userData = nullptr) override;
137 
138     void enumMetrics(unsigned group, enumMetricsCallback callback,
139                      void* userData = nullptr) override;
140 
141     std::unique_ptr<Metric> getMetricById(unsigned groupId, unsigned metricId) override;
142 
143     std::unique_ptr<Metric> getMetricByName(std::string metricName) override;
144 
145     std::string getGroupName(unsigned group) override;
146 
147     int enableMetric(Metric* metric, QueryBoundary pollingRule = QUERY_BOUNDARY_DRAWCALL) override;
148 
149     unsigned generatePasses() override;
150 
151     void beginPass() override;
152 
153     void endPass() override;
154 
155     void pausePass() override;
156 
157     void continuePass() override;
158 
159     void beginQuery(QueryBoundary boundary = QUERY_BOUNDARY_DRAWCALL) override;
160 
161     void endQuery(QueryBoundary boundary = QUERY_BOUNDARY_DRAWCALL) override;
162 
163     void enumDataQueryId(unsigned id, enumDataCallback callback,
164                          QueryBoundary boundary,
165                          void* userData = nullptr) override;
166 
167     unsigned getNumPasses() override;
168 
169     static MetricBackend_INTEL_perfquery& getInstance(glretrace::Context* context,
170                                                       MmapAllocator<char> &alloc);
171 };
172 
173