]> git.cworth.org Git - vogl/blob - src/voglcommon/vogl_trace_stream_types.h
Initial vogl checkin
[vogl] / src / voglcommon / vogl_trace_stream_types.h
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
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 // File: vogl_trace_stream_types.h
27 #ifndef VOGL_TRACE_STREAM_TYPES_H
28 #define VOGL_TRACE_STREAM_TYPES_H
29 #include "vogl_miniz.h"
30
31 #define VOGL_TRACE_FILE_VERSION 0x0106
32 #define VOGL_TRACE_FILE_MINIMUM_COMPATIBLE_VERSION 0x0106
33
34 #define VOGL_TRACE_LINK_PROGRAM_UNIFORM_DESC_KEY_OFS 0xF0000
35
36 #pragma pack(push, 1)
37 enum vogl_trace_stream_packet_types_t
38 {
39     cTSPTSOF = 1,
40     cTSPTGLEntrypoint = 3,
41     cTSPTEOF = 4,
42     cTSPTTotalTypes
43 };
44
45 struct vogl_trace_stream_packet_base
46 {
47     enum
48     {
49         cTracePacketPrefix = 0xD1C71602
50     };
51     uint32 m_prefix;
52     uint32 m_size; // total size, including extra data, needed to get to next packet_base
53     uint32 m_crc;  // CRC32 of all packet data following this member
54
55     enum
56     {
57         cMinimumPossibleRnd = 1
58     };
59     uint16 m_rnd; // a random number, cannot be 0, must immediately follow m_crc!
60
61     uint64_t m_packet_begin_rdtsc;
62     uint64_t m_gl_begin_rdtsc;
63     uint64_t m_gl_end_rdtsc;
64     uint64_t m_packet_end_rdtsc;
65
66     uint8 m_type;     // trace_packet_types_t
67     uint16 m_inv_rnd; // not of m_rnd, for verification (and to purpusely increase the packet entropy - this is only for devel)
68
69     inline void init(uint8 type, uint32 size)
70     {
71         memset(this, 0, sizeof(*this));
72
73         m_prefix = cTracePacketPrefix;
74         m_type = type;
75         m_size = size;
76         m_rnd = cMinimumPossibleRnd;
77     }
78
79     // Sets the rnd field using g_thread_safe_random
80     inline void init_rnd()
81     {
82         uint32 rnd16 = static_cast<uint16>(g_thread_safe_random.urand32());
83         m_rnd = static_cast<uint16>(math::maximum<uint>(vogl_trace_stream_packet_base::cMinimumPossibleRnd, rnd16));
84         VOGL_ASSERT(m_rnd);
85     }
86
87     // Assumes the *entire* packet is sequential in memory (i.e. m_size bytes starting at this)
88     inline void finalize()
89     {
90         m_inv_rnd = ~m_rnd;
91
92         VOGL_ASSERT(m_size >= sizeof(vogl_trace_stream_packet_base));
93
94         m_crc = (uint32)mz_crc32(MZ_CRC32_INIT, reinterpret_cast<const uint8 *>(this) + (uint32)VOGL_OFFSETOF(vogl_trace_stream_packet_base, m_rnd), m_size - (uint32)VOGL_OFFSETOF(vogl_trace_stream_packet_base, m_rnd));
95     }
96
97     inline bool basic_validation() const
98     {
99         if (m_prefix != cTracePacketPrefix)
100             return false;
101
102         if (m_type >= cTSPTTotalTypes)
103             return false;
104
105         if (m_size < sizeof(vogl_trace_stream_packet_base))
106             return false;
107
108         VOGL_ASSUME(sizeof(m_rnd) == sizeof(uint16));
109         uint inv_rnd = (~m_rnd) & 0xFFFFU;
110
111         if ((m_rnd < static_cast<uint>(cMinimumPossibleRnd)) || (inv_rnd != static_cast<uint>(m_inv_rnd)))
112             return false;
113
114         return true;
115     }
116
117     // Assumes the *entire* packet is sequential in memory (i.e. m_size bytes starting at this)
118     inline bool check_crc(uint actual_buf_size) const
119     {
120         if (m_size < sizeof(vogl_trace_stream_packet_base))
121             return false;
122
123         if (m_size > actual_buf_size)
124             return false;
125
126         uint32 check_crc = (uint32)mz_crc32(MZ_CRC32_INIT, reinterpret_cast<const uint8 *>(this) + (uint32)VOGL_OFFSETOF(vogl_trace_stream_packet_base, m_rnd), m_size - (uint32)VOGL_OFFSETOF(vogl_trace_stream_packet_base, m_rnd));
127         if (check_crc != m_crc)
128             return false;
129
130         return true;
131     }
132
133     // Assumes the *entire* packet is sequential in memory (i.e. m_size bytes starting at this)
134     inline bool full_validation(uint actual_buf_size) const
135     {
136         if (!basic_validation())
137             return false;
138
139         return check_crc(actual_buf_size);
140     }
141 };
142
143 struct vogl_trace_stream_start_of_file_packet
144 {
145     enum
146     {
147         cSOFTracePacketPrefix = 0xD1C71601
148     };
149     uint32 m_prefix;
150     uint64_t m_size; // The size of this packet (NOT including the archive data)
151     uint32 m_crc;  // CRC32 of all packet data following this member
152
153     uint16 m_version; // must immediately follow m_crc!
154     uint8 m_pointer_sizes;
155     uint8 m_unused;
156
157     enum
158     {
159         cUUIDSize = 4
160     };
161     uint32 m_uuid[cUUIDSize];
162
163     uint64_t m_first_packet_offset;
164
165     // File offset and size of all ZIP archive data immediately following this packet, or 0 if there is no archive data.
166     uint64_t m_archive_offset;
167     uint64_t m_archive_size;
168
169     inline void init()
170     {
171         memset(this, 0, sizeof(*this));
172         m_size = sizeof(*this);
173         m_pointer_sizes = sizeof(void *);
174         m_version = VOGL_TRACE_FILE_VERSION;
175     }
176
177     uint32 compute_crc() const
178     {
179         return (uint32)mz_crc32(MZ_CRC32_INIT, reinterpret_cast<const uint8 *>(this) + (uint32)VOGL_OFFSETOF(vogl_trace_stream_start_of_file_packet, m_version), sizeof(*this) - (uint32)VOGL_OFFSETOF(vogl_trace_stream_start_of_file_packet, m_version));
180     }
181
182     inline void finalize()
183     {
184         m_prefix = cSOFTracePacketPrefix;
185         m_crc = compute_crc();
186     }
187
188     inline bool basic_validation() const
189     {
190         if (m_prefix != cSOFTracePacketPrefix)
191             return false;
192
193         if (m_size != sizeof(vogl_trace_stream_start_of_file_packet))
194             return false;
195
196         if (m_version < VOGL_TRACE_FILE_MINIMUM_COMPATIBLE_VERSION)
197             return false;
198
199         return true;
200     }
201
202     inline bool check_crc(uint actual_buf_size) const
203     {
204         if (m_size != sizeof(vogl_trace_stream_start_of_file_packet))
205             return false;
206         if (actual_buf_size < sizeof(vogl_trace_stream_start_of_file_packet))
207             return false;
208
209         uint32 check_crc = compute_crc();
210         if (check_crc != m_crc)
211             return false;
212
213         return true;
214     }
215
216     inline bool full_validation(uint actual_buf_size) const
217     {
218         if (!basic_validation())
219             return false;
220         return check_crc(actual_buf_size);
221     }
222 };
223
224 #define VOGL_RETURN_PARAM_INDEX 255
225
226 // GL entrypoint packets contain a fixed size struct vogl_trace_gl_entrypoint_packet, immediately
227 // followed by three variable sized data blobs:
228 //
229 // struct vogl_trace_gl_entrypoint_packet contains the base data in vogl_trace_stream_packet_base (total
230 // size of packet, crc of entire packet, various RDTSC's), and stuff like the entrypoint ID/context
231 // handle/kernel thread ID/call counter/etc.
232 //
233 // Immediately following this struct are up to three variable length blobs of data: The parameter
234 // data, any referenced client memory data, and an optional name value map.
235 struct vogl_trace_gl_entrypoint_packet : vogl_trace_stream_packet_base
236 {
237     uint16 m_entrypoint_id;
238
239     uint64_t m_context_handle;
240     uint64_t m_call_counter;
241     uint64_t m_thread_id;
242
243     uint16 m_param_size;
244     uint32 m_client_memory_size;
245
246     uint32 m_backtrace_hash_index;
247
248     // The code that handles serialization is written assuming most packets will *not* use a name value map.
249     // Maps are intended to be rare events that are only included on expensive GL/GLX calls.
250     uint32 m_name_value_map_size;
251
252     inline void init()
253     {
254         vogl_trace_stream_packet_base::init(cTSPTGLEntrypoint, sizeof(*this));
255     }
256 };
257 #pragma pack(pop)
258
259 enum vogl_internal_trace_command_rad_cmd_types_t
260 {
261     cITCRDemarcation = 0,
262     cITCRKeyValueMap = 1,
263     cITCRTotalTypes
264 };
265
266 // TODO: Is this the best location for this?
267 struct vogl_backtrace_addrs
268 {
269     enum
270     {
271         cMaxAddrs = 64
272     };
273     uint32 m_num_addrs;
274     uintptr_t m_addrs[cMaxAddrs];
275
276     void clear()
277     {
278         utils::zero_object(*this);
279     }
280
281     uint64_t get_hash() const
282     {
283         return vogl::calc_crc64(vogl::CRC64_INIT, reinterpret_cast<const uint8 *>(this), sizeof(uint32) + sizeof(m_addrs[0]) * m_num_addrs);
284     }
285
286     bool operator==(const vogl_backtrace_addrs &rhs) const
287     {
288         if (m_num_addrs != rhs.m_num_addrs)
289             return false;
290         return memcmp(m_addrs, rhs.m_addrs, m_num_addrs * sizeof(m_addrs[0])) == 0;
291     }
292
293     bool operator!=(const vogl_backtrace_addrs &rhs) const
294     {
295         return !(*this == rhs);
296     }
297
298     bool operator<(const vogl_backtrace_addrs &rhs) const
299     {
300         if (m_num_addrs < rhs.m_num_addrs)
301             return true;
302         else if (m_num_addrs == rhs.m_num_addrs)
303         {
304             for (uint i = 0; i < m_num_addrs; i++)
305             {
306                 if (m_addrs[i] < rhs.m_addrs[i])
307                     return true;
308                 else if (m_addrs[i] > rhs.m_addrs[i])
309                     return false;
310             }
311         }
312
313         return false;
314     }
315
316     uint32 hash() const
317     {
318         return fast_hash(this, sizeof(uint32) + (m_num_addrs * sizeof(m_addrs[0])));
319     }
320 };
321
322 typedef vogl::hash_map<vogl_backtrace_addrs, uint64_t, intrusive_hasher<vogl_backtrace_addrs> > vogl_backtrace_hashmap;
323
324 #define VOGL_TRACE_ARCHIVE_FRAME_FILE_OFFSETS_FILENAME   "frame_file_offsets"
325
326 #define VOGL_TRACE_ARCHIVE_COMPILER_INFO_FILENAME        "compiler_info.json"
327 #define VOGL_TRACE_ARCHIVE_MACHINE_INFO_FILENAME         "machine_info.json"
328 #define VOGL_TRACE_ARCHIVE_BACKTRACE_MAP_SYMS_FILENAME   "backtrace_map_syms.json"
329 #define VOGL_TRACE_ARCHIVE_BACKTRACE_MAP_ADDRS_FILENAME  "backtrace_map_addrs.json"
330
331 #endif // VOGL_TRACE_STREAM_TYPES_H