1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
24 **************************************************************************/
26 // File: vogl_trace_packet.cpp
27 #include "vogl_common.h"
28 #include "vogl_trace_packet.h"
29 #include "vogl_console.h"
30 #include "vogl_file_utils.h"
31 #include "vogl_bigint128.h"
32 #include "vogl_dynamic_stream.h"
36 //----------------------------------------------------------------------------------------------------------------------
37 // vogl_trace_packet::compare
38 //----------------------------------------------------------------------------------------------------------------------
39 bool vogl_trace_packet::compare(const vogl_trace_packet &other, bool deep) const
43 if ((!m_is_valid) || (!other.m_is_valid))
46 if (other.get_ctypes() != get_ctypes())
49 if (m_total_params != other.m_total_params)
51 if (m_has_return_value != other.m_has_return_value)
55 if (m_packet.x != other.m_packet.x) \
59 CMP(m_context_handle);
67 CMP(m_packet_begin_rdtsc);
68 CMP(m_gl_begin_rdtsc);
70 CMP(m_backtrace_hash_index);
71 CMP(m_packet_end_rdtsc);
74 CMP(m_client_memory_size);
75 CMP(m_name_value_map_size);
79 const uint total_params_to_check = m_total_params + m_has_return_value;
80 for (uint i = 0; i < total_params_to_check; i++)
82 if (m_param_ctype[i] != other.m_param_ctype[i])
84 if (m_param_size[i] != other.m_param_size[i])
88 if ((!deep) && ((*m_pCTypes)[m_param_ctype[i]].m_is_pointer))
90 bool lhs_null = (m_param_data[i] != 0);
91 bool rhs_null = (other.m_param_data[i] != 0);
92 if (lhs_null != rhs_null)
98 if (m_param_data[i] != other.m_param_data[i])
102 const client_memory_desc_t &desc_lhs = m_client_memory_descs[i];
103 const client_memory_desc_t &desc_rhs = other.m_client_memory_descs[i];
105 if (desc_lhs.m_vec_ofs >= 0)
107 if (desc_rhs.m_vec_ofs < 0)
109 if ((deep) && (desc_lhs.m_vec_ofs != desc_rhs.m_vec_ofs))
111 if (desc_lhs.m_data_size != desc_rhs.m_data_size)
113 if (desc_lhs.m_pointee_ctype != desc_rhs.m_pointee_ctype)
115 if (memcmp(m_client_memory.get_ptr() + desc_lhs.m_vec_ofs, other.m_client_memory.get_ptr() + desc_rhs.m_vec_ofs, desc_lhs.m_data_size) != 0)
118 else if (desc_rhs.m_vec_ofs >= 0)
124 if (m_key_value_map != other.m_key_value_map)
130 //----------------------------------------------------------------------------------------------------------------------
131 // vogl_trace_packet::check
132 //----------------------------------------------------------------------------------------------------------------------
133 bool vogl_trace_packet::check() const
137 VOGL_ASSUME(VOGL_NUM_CTYPES < cUINT8_MAX);
142 if (m_packet.m_prefix != vogl_trace_stream_packet_base::cTracePacketPrefix)
144 if (m_packet.m_type != cTSPTGLEntrypoint)
147 const gl_entrypoint_desc_t &entrypoint_desc = g_vogl_entrypoint_descs[m_packet.m_entrypoint_id];
149 if (m_total_params != entrypoint_desc.m_num_params)
152 if (entrypoint_desc.m_return_ctype == VOGL_VOID)
154 if (m_has_return_value)
156 if (m_param_ctype[entrypoint_desc.m_num_params] != VOGL_INVALID_CTYPE)
161 if (!m_has_return_value)
163 if (m_param_ctype[entrypoint_desc.m_num_params] != entrypoint_desc.m_return_ctype)
165 if (m_param_size[entrypoint_desc.m_num_params] != (*m_pCTypes)[entrypoint_desc.m_return_ctype].m_size)
169 for (uint param_iter = 0; param_iter < entrypoint_desc.m_num_params; param_iter++)
171 if (m_param_ctype[param_iter] == VOGL_INVALID_CTYPE)
174 const gl_entrypoint_param_desc_t ¶m_desc = g_vogl_entrypoint_param_descs[m_packet.m_entrypoint_id][param_iter];
176 if (m_param_ctype[param_iter] != param_desc.m_ctype)
178 if (m_param_size[param_iter] != (*m_pCTypes)[param_desc.m_ctype].m_size)
182 uint total_params = entrypoint_desc.m_num_params + m_has_return_value;
183 for (uint param_iter = 0; param_iter < total_params; param_iter++)
185 const client_memory_desc_t &mem_desc = m_client_memory_descs[param_iter];
186 if (mem_desc.m_vec_ofs >= 0)
188 if ((!mem_desc.m_data_size) || (mem_desc.m_data_size >= static_cast<uint32>(cINT32_MAX)))
191 if ((mem_desc.m_vec_ofs + mem_desc.m_data_size) > m_client_memory.size())
194 uint pointee_ctype_size = 0;
195 bool pointee_is_opaque = false;
196 bool is_opaque_ptr = false;
197 if (param_iter < entrypoint_desc.m_num_params)
199 const gl_entrypoint_param_desc_t ¶m_desc = g_vogl_entrypoint_param_descs[m_packet.m_entrypoint_id][param_iter];
201 is_opaque_ptr = (*m_pCTypes)[param_desc.m_ctype].m_is_opaque_pointer;
203 if (!(*m_pCTypes)[param_desc.m_ctype].m_is_pointer)
206 if ((*m_pCTypes)[param_desc.m_ctype].m_pointee_ctype != VOGL_VOID)
208 pointee_ctype_size = (*m_pCTypes)[(*m_pCTypes)[param_desc.m_ctype].m_pointee_ctype].m_size;
209 pointee_is_opaque = (*m_pCTypes)[(*m_pCTypes)[param_desc.m_ctype].m_pointee_ctype].m_is_opaque_type;
214 is_opaque_ptr = (*m_pCTypes)[entrypoint_desc.m_return_ctype].m_is_opaque_pointer;
216 if (!(*m_pCTypes)[entrypoint_desc.m_return_ctype].m_is_pointer)
219 if ((*m_pCTypes)[entrypoint_desc.m_return_ctype].m_pointee_ctype != VOGL_VOID)
221 pointee_ctype_size = (*m_pCTypes)[(*m_pCTypes)[entrypoint_desc.m_return_ctype].m_pointee_ctype].m_size;
222 pointee_is_opaque = (*m_pCTypes)[(*m_pCTypes)[entrypoint_desc.m_return_ctype].m_pointee_ctype].m_is_opaque_type;
226 if ((pointee_ctype_size > 1) && (!is_opaque_ptr) && (!pointee_is_opaque))
228 if (mem_desc.m_data_size % pointee_ctype_size)
234 if (mem_desc.m_vec_ofs != -1)
236 if (mem_desc.m_data_size)
238 if (mem_desc.m_pointee_ctype != VOGL_VOID)
246 //----------------------------------------------------------------------------------------------------------------------
247 // vogl_trace_packet::deserialize
248 //----------------------------------------------------------------------------------------------------------------------
249 bool vogl_trace_packet::deserialize(const uint8 *pPacket_data, uint packet_data_buf_size, bool check_crc)
255 const vogl_trace_gl_entrypoint_packet *pTrace_gl_entrypoint_packet = reinterpret_cast<const vogl_trace_gl_entrypoint_packet *>(pPacket_data);
259 if (!pTrace_gl_entrypoint_packet->full_validation(packet_data_buf_size))
261 vogl_error_printf("%s: Trace packet failed basic validation!\n", VOGL_METHOD_NAME);
267 if (!pTrace_gl_entrypoint_packet->basic_validation())
269 vogl_error_printf("%s: Trace packet failed basic validation!\n", VOGL_METHOD_NAME);
274 m_packet = *reinterpret_cast<const vogl_trace_gl_entrypoint_packet *>(pTrace_gl_entrypoint_packet);
276 VOGL_ASSERT(m_packet.m_type == cTSPTGLEntrypoint);
278 if (m_packet.m_size < sizeof(vogl_trace_gl_entrypoint_packet))
281 if (m_packet.m_entrypoint_id >= VOGL_NUM_ENTRYPOINTS)
284 uint entrypoint_index = m_packet.m_entrypoint_id;
285 const gl_entrypoint_desc_t &entrypoint_desc = g_vogl_entrypoint_descs[entrypoint_index];
286 const gl_entrypoint_param_desc_t *pParam_desc = &g_vogl_entrypoint_param_descs[entrypoint_index][0];
288 m_total_params = entrypoint_desc.m_num_params;
289 m_has_return_value = (entrypoint_desc.m_return_ctype != VOGL_VOID);
291 const uint total_params_to_deserialize = m_total_params + m_has_return_value;
293 const uint8 *pExtra_packet_data = pPacket_data + sizeof(vogl_trace_gl_entrypoint_packet);
294 uint num_bytes_remaining = m_packet.m_size - sizeof(vogl_trace_gl_entrypoint_packet);
296 if (m_packet.m_param_size)
298 if (m_packet.m_param_size > num_bytes_remaining)
301 for (uint param_index = 0; param_index < total_params_to_deserialize; ++param_index, ++pParam_desc)
303 vogl_ctype_t param_ctype = (param_index >= m_total_params) ? entrypoint_desc.m_return_ctype : pParam_desc->m_ctype;
304 uint param_size = (*m_pCTypes)[param_ctype].m_size;
306 if (num_bytes_remaining < param_size)
309 m_param_ctype[param_index] = param_ctype;
310 VOGL_ASSERT(param_size <= cUINT8_MAX);
311 m_param_size[param_index] = param_size;
313 m_param_data[param_index] = 0;
314 memcpy(&m_param_data[param_index], pExtra_packet_data, param_size);
316 pExtra_packet_data += param_size;
317 num_bytes_remaining -= param_size;
321 if (m_packet.m_client_memory_size)
323 if (m_packet.m_client_memory_size > num_bytes_remaining)
326 uint client_memory_descs_size = (total_params_to_deserialize * sizeof(client_memory_desc_t));
327 if (num_bytes_remaining < client_memory_descs_size)
330 memcpy(m_client_memory_descs, pExtra_packet_data, client_memory_descs_size);
331 pExtra_packet_data += client_memory_descs_size;
332 num_bytes_remaining -= client_memory_descs_size;
334 if (client_memory_descs_size > m_packet.m_client_memory_size)
337 uint client_memory_vec_size = m_packet.m_client_memory_size - client_memory_descs_size;
339 m_client_memory.append(pExtra_packet_data, client_memory_vec_size);
340 pExtra_packet_data += client_memory_vec_size;
341 num_bytes_remaining -= client_memory_vec_size;
344 if (m_packet.m_name_value_map_size)
346 if (m_packet.m_name_value_map_size > num_bytes_remaining)
349 if (!m_key_value_map.deserialize_from_buffer(pExtra_packet_data, num_bytes_remaining, true, false))
352 pExtra_packet_data += m_packet.m_name_value_map_size;
353 num_bytes_remaining -= m_packet.m_name_value_map_size;
356 if (num_bytes_remaining)
361 VOGL_ASSERT(check());
366 //----------------------------------------------------------------------------------------------------------------------
367 // vogl_trace_packet::deserialize
368 //----------------------------------------------------------------------------------------------------------------------
369 bool vogl_trace_packet::deserialize(const uint8_vec &packet_buf, bool check_crc)
373 return deserialize(packet_buf.get_ptr(), packet_buf.size(), check_crc);
376 //----------------------------------------------------------------------------------------------------------------------
377 // vogl_trace_packet::serialize
378 //----------------------------------------------------------------------------------------------------------------------
379 bool vogl_trace_packet::serialize(data_stream &stream) const
386 VOGL_ASSERT(m_packet.m_gl_begin_rdtsc <= m_packet.m_gl_end_rdtsc);
387 VOGL_ASSERT(m_packet.m_packet_begin_rdtsc <= m_packet.m_packet_end_rdtsc);
389 vogl_trace_gl_entrypoint_packet packet(m_packet);
391 uint8 param_data[512];
393 uint total_params_to_serialize = m_total_params + m_has_return_value;
394 uint8 *pDst_param_data = param_data;
395 for (uint i = 0; i < total_params_to_serialize; i++)
397 uint size = m_param_size[i];
399 memcpy(pDst_param_data, &m_param_data[i], size);
400 pDst_param_data += size;
401 VOGL_ASSERT((pDst_param_data - param_data) <= static_cast<long>(sizeof(param_data)));
404 VOGL_VERIFY((pDst_param_data - param_data) <= cUINT8_MAX);
405 packet.m_param_size = static_cast<uint8>(pDst_param_data - param_data);
407 uint client_memory_descs_size = (total_params_to_serialize * sizeof(client_memory_desc_t));
408 packet.m_client_memory_size = client_memory_descs_size + m_client_memory.size();
410 uint64_t kvm_serialize_size = m_key_value_map.get_num_key_values() ? m_key_value_map.get_serialize_size(false) : 0;
411 if (kvm_serialize_size > cUINT32_MAX)
413 packet.m_name_value_map_size = static_cast<uint32>(kvm_serialize_size);
415 uint64_t total_packet_size = sizeof(vogl_trace_gl_entrypoint_packet) + packet.m_param_size + packet.m_client_memory_size + packet.m_name_value_map_size;
416 if (total_packet_size > static_cast<uint64_t>(cINT32_MAX))
419 packet.m_size = static_cast<uint32_t>(total_packet_size);
421 if (!m_packet_buf.try_resize(static_cast<uint32>(total_packet_size)))
424 uint8 *pDst_buf = m_packet_buf.get_ptr();
426 #define APPEND_TO_DST_BUF(pSrc, n) \
429 VOGL_ASSERT((int64_t)n <= (int64_t)(m_packet_buf.end() - pDst_buf)); \
430 memcpy(pDst_buf, pSrc, n); \
434 APPEND_TO_DST_BUF(&packet, sizeof(packet));
436 if (packet.m_param_size)
438 APPEND_TO_DST_BUF(param_data, packet.m_param_size);
441 if (packet.m_client_memory_size)
443 APPEND_TO_DST_BUF(m_client_memory_descs, client_memory_descs_size);
444 APPEND_TO_DST_BUF(m_client_memory.get_ptr(), m_client_memory.size());
447 if (m_key_value_map.get_num_key_values())
449 if (pDst_buf >= m_packet_buf.end())
455 uint buf_remaining = static_cast<uint>(m_packet_buf.end() - pDst_buf);
456 int result = m_key_value_map.serialize_to_buffer(pDst_buf, buf_remaining, true, false);
457 if (result != static_cast<int>(packet.m_name_value_map_size))
463 if (pDst_buf != m_packet_buf.end())
466 #undef APPEND_TO_DST_BUF
468 vogl_trace_gl_entrypoint_packet *pBuf_packet = reinterpret_cast<vogl_trace_gl_entrypoint_packet *>(m_packet_buf.get_ptr());
469 pBuf_packet->finalize();
471 VOGL_ASSERT(pBuf_packet->full_validation(m_packet_buf.size()));
473 uint n = stream.write(pBuf_packet, m_packet_buf.size());
474 if (n != m_packet_buf.size())
480 //----------------------------------------------------------------------------------------------------------------------
481 // vogl_trace_packet::serialize
482 //----------------------------------------------------------------------------------------------------------------------
483 bool vogl_trace_packet::serialize(uint8_vec &buf) const
487 dynamic_stream dyn_stream;
488 if (!dyn_stream.open(128))
490 if (!serialize(dyn_stream))
492 buf.swap(dyn_stream.get_buf());
496 //----------------------------------------------------------------------------------------------------------------------
497 // vogl_trace_packet::json_serialize
498 //----------------------------------------------------------------------------------------------------------------------
499 bool vogl_trace_packet::json_serialize(json_node &node, const json_serialize_params ¶ms) const
503 const char *pFunc_name = g_vogl_entrypoint_descs[m_packet.m_entrypoint_id].m_pName;
505 node.add_key_value("func", pFunc_name);
507 node.add_key_value("thread_id", dynamic_string(cVarArg, "0x%" PRIX64, m_packet.m_thread_id));
508 node.add_key_value("context", dynamic_string(cVarArg, "0x%" PRIX64, m_packet.m_context_handle));
509 node.add_key_value("call_counter", static_cast<int64_t>(m_packet.m_call_counter));
510 node.add_key_value("crc32", m_packet.m_crc);
511 node.add_key_value("begin_rdtsc", m_packet.m_packet_begin_rdtsc);
512 node.add_key_value("end_rdtsc", m_packet.m_packet_end_rdtsc);
513 node.add_key_value("gl_begin_rdtsc", m_packet.m_gl_begin_rdtsc);
514 node.add_key_value("gl_end_rdtsc", m_packet.m_gl_end_rdtsc);
515 node.add_key_value("backtrace_hash_index", m_packet.m_backtrace_hash_index);
516 node.add_key_value("rnd_check", m_packet.m_rnd);
517 node.add_key_value("inv_rnd_check", m_packet.m_inv_rnd);
519 json_node &gl_params_node = node.add_object("params");
520 for (uint param_index = 0; param_index < total_params(); param_index++)
522 if (!json_serialize_param(pFunc_name, gl_params_node, param_index, get_param_desc(param_index).m_pName,
523 get_param_data(param_index), get_param_size(param_index), get_param_ctype(param_index),
524 get_param_client_memory_ptr(param_index),
525 get_param_client_memory_data_size(param_index),
526 get_param_client_memory_ctype(param_index),
533 if (has_return_value())
535 if (!json_serialize_param(pFunc_name, node, -1, "return",
536 get_return_value_data(), get_return_value_size(), get_return_value_ctype(),
537 get_return_client_memory_ptr(),
538 get_return_client_memory_data_size(),
539 get_return_client_memory_ctype(),
546 if (m_packet.m_name_value_map_size)
548 json_node &gl_name_value_array = node.add_array("name_value_map");
550 dynamic_string key_str, value_str;
552 for (key_value_map::const_iterator it = m_key_value_map.begin(); it != m_key_value_map.end(); ++it)
554 const value &key = it->first;
555 const value &val = it->second;
557 json_node &entry_node = gl_name_value_array.add_object();
559 entry_node.add_key_value("key_type", g_value_data_type_strings[key.get_data_type()]);
560 entry_node.add_key_value("val_type", g_value_data_type_strings[val.get_data_type()]);
562 key.get_string(key_str, false);
564 if (key.get_data_type() == cDTStringHash)
566 string_hash hash(key.get_string_hash());
568 const char *pStr = find_well_known_string_hash(hash);
573 entry_node.add_key_value("key", key_str);
575 bool handle_as_blob_file = false;
579 if (val.get_blob()->size() >= params.m_blob_file_size_threshold)
580 handle_as_blob_file = true;
581 else if (should_always_write_as_blob_file(pFunc_name))
582 handle_as_blob_file = true;
585 if (handle_as_blob_file)
589 uint64_t blob_crc64 = calc_crc64(CRC64_INIT, reinterpret_cast<const uint8 *>(val.get_blob()->get_ptr()), val.get_blob()->size());
591 if (params.m_pBlob_manager)
593 //dynamic_string prefix(cVarArg, "%s_%s", params.m_output_basename.get_ptr(), pFunc_name);
594 dynamic_string prefix(cVarArg, "%s", pFunc_name);
596 id = params.m_pBlob_manager->add_buf_compute_unique_id(val.get_blob()->get_ptr(), val.get_blob()->size(), prefix, "blob", &blob_crc64);
599 vogl_error_printf("%s: Failed adding blob %s to blob manager\n", VOGL_METHOD_NAME, prefix.get_ptr());
603 vogl_message_printf("%s: Wrote blob id %s\n", VOGL_METHOD_NAME, id.get_ptr());
607 id = "<blob_writing_disabled>";
610 json_node &blob_node = entry_node.add_object("data");
611 blob_node.add_key_value("blob_id", id);
612 blob_node.add_key_value("crc64", dynamic_string(cVarArg, "0x%016" PRIX64, blob_crc64));
613 blob_node.add_key_value("size", val.get_blob()->size());
617 switch (val.get_data_type())
624 entry_node.add_key_value("data", val.get_int64());
631 entry_node.add_key_value("data", val.get_uint());
636 string_hash hash(val.get_string_hash());
638 const char *pStr = find_well_known_string_hash(hash);
640 entry_node.add_key_value("data", hash.get_hash());
642 entry_node.add_key_value("data", pStr);
647 float flt_val = val.get_float();
648 json_value &new_val = entry_node.add_key_value("data", flt_val);
650 dynamic_string new_val_as_str;
651 new_val.serialize(new_val_as_str, false);
654 if ((!test_val.deserialize(new_val_as_str)) || (test_val.as_float() != flt_val))
656 new_val.set_value(dynamic_string(cVarArg, "0x%08X", *reinterpret_cast<const uint32 *>(&flt_val)).get_ptr());
663 double dbl_val = val.get_double();
664 json_value &new_val = entry_node.add_key_value("data", dbl_val);
666 dynamic_string new_val_as_str;
667 new_val.serialize(new_val_as_str, false);
670 if ((!test_val.deserialize(new_val_as_str)) || (test_val.as_double() != dbl_val))
672 new_val.set_value(dynamic_string(cVarArg, "0x%" PRIX64, static_cast<uint64_t>(*reinterpret_cast<const uint64_t *>(&dbl_val))).get_ptr());
679 entry_node.add_key_value("data", dynamic_string(cVarArg, "0x%" PRIX64, val.get_uint64()).get_ptr());
684 entry_node.add_key_value("data", *val.get_json_document());
689 val.get_string(value_str, false);
690 entry_node.add_key_value("data", value_str);
699 if (params.m_write_debug_info)
701 json_node &gl_dbg_node = node.add_object("dbg");
702 gl_dbg_node.add_key_value("entrypoint_id", m_packet.m_entrypoint_id);
703 gl_dbg_node.add_key_value("total_params", total_params());
704 gl_dbg_node.add_key_value("has_return_value", has_return_value());
705 gl_dbg_node.add_key_value("is_whitelisted", get_entrypoint_desc().m_is_whitelisted);
706 gl_dbg_node.add_key_value("packet_size", m_packet.m_size);
707 gl_dbg_node.add_key_value("param_size", m_packet.m_param_size);
708 gl_dbg_node.add_key_value("client_mem_size", m_packet.m_client_memory_size);
709 gl_dbg_node.add_key_value("name_value_map_size", m_packet.m_name_value_map_size);
715 //----------------------------------------------------------------------------------------------------------------------
716 // print_json_context
717 //----------------------------------------------------------------------------------------------------------------------
718 static void print_json_context(const char *pDocument_filename, const json_node &node, eConsoleMessageType msg_category = cErrorConsoleMessage)
722 console::printf(msg_category, "Context: JSON filename %s, on or near line %u, node path: %s\n", pDocument_filename, node.get_line(), node.get_path_to_node().get_ptr());
725 //----------------------------------------------------------------------------------------------------------------------
726 // print_json_context
727 //----------------------------------------------------------------------------------------------------------------------
728 static void print_json_context(const char *pDocument_filename, const json_node &node, uint node_index, eConsoleMessageType msg_category = cErrorConsoleMessage)
732 console::printf(msg_category, "Context: JSON filename %s, on or near line %u, node item path: %s\n", pDocument_filename, node.get_line(), node.get_path_to_item(node_index).get_ptr());
735 //----------------------------------------------------------------------------------------------------------------------
736 // print_json_context
737 //----------------------------------------------------------------------------------------------------------------------
738 static void print_json_context(const char *pDocument_filename, const json_value &val, const json_node &node, eConsoleMessageType msg_category = cErrorConsoleMessage)
742 console::printf(msg_category, "Context: JSON filename %s, on or near the node at line %u, on or near the value at line %u, node path: %s\n", pDocument_filename, node.get_line(), val.get_line(), node.get_path_to_node().get_ptr());
745 //----------------------------------------------------------------------------------------------------------------------
746 // print_json_context
747 //----------------------------------------------------------------------------------------------------------------------
748 static void print_json_context(const char *pDocument_filename, const json_value &val, const json_node &node, uint node_index, eConsoleMessageType msg_category = cErrorConsoleMessage)
752 console::printf(msg_category, "Context: JSON filename %s, on or near the node at line %u, on or near the value at line %u, item path: %s\n", pDocument_filename, node.get_line(), val.get_line(), node.get_path_to_item(node_index).get_ptr());
755 //----------------------------------------------------------------------------------------------------------------------
756 // vogl_trace_packet::json_deserialize
757 //----------------------------------------------------------------------------------------------------------------------
758 bool vogl_trace_packet::json_deserialize(const json_node &node, const char *pDocument_filename, const vogl_blob_manager *pBlob_manager)
764 const dynamic_string gl_func_name(node.value_as_string("func"));
765 if (gl_func_name.is_empty())
767 vogl_error_printf("%s: Missing \"func\" node\n", VOGL_METHOD_NAME);
768 print_json_context(pDocument_filename, node);
772 entrypoint_name_hash_map_t::const_iterator it = g_vogl_entrypoint_hashmap.find(gl_func_name);
773 if (it == g_vogl_entrypoint_hashmap.end())
775 vogl_error_printf("%s: Unknown GL function name: \"%s\"\n", VOGL_METHOD_NAME, gl_func_name.get_ptr());
776 print_json_context(pDocument_filename, node);
780 gl_entrypoint_id_t gl_entrypoint_id = it->second;
782 const gl_entrypoint_desc_t &entrypoint_desc = g_vogl_entrypoint_descs[gl_entrypoint_id];
783 const gl_entrypoint_param_desc_t *pEntrypoint_params = &g_vogl_entrypoint_param_descs[gl_entrypoint_id][0];
785 uint64_t thread_id = 0;
786 get_uint64_from_json_node(node, "thread_id", thread_id);
788 uint64_t context = 0;
789 if (!get_uint64_from_json_node(node, "context", context))
792 uint64_t call_counter = 0;
793 get_uint64_from_json_node(node, "call_counter", call_counter);
795 const json_node *pParams_node = node.find_child("params");
796 json_node dummy_node;
799 if (entrypoint_desc.m_num_params)
801 vogl_error_printf("%s: Failed finding params key!\n", VOGL_METHOD_NAME);
802 print_json_context(pDocument_filename, node);
807 vogl_warning_printf("%s: Failed finding params key! Substituting a dummy empty node and trying to deserialize anyway.\n", VOGL_METHOD_NAME);
809 dummy_node.init_object();
810 pParams_node = &dummy_node;
813 if (!pParams_node->is_object())
815 vogl_error_printf("%s: Failed finding params key!\n", VOGL_METHOD_NAME);
816 print_json_context(pDocument_filename, *pParams_node);
820 uint num_params = pParams_node->size();
821 if (num_params != entrypoint_desc.m_num_params)
823 vogl_error_printf("%s: Unexpected number of param keys (expected %u, found %u)\n", VOGL_METHOD_NAME, entrypoint_desc.m_num_params, num_params);
824 print_json_context(pDocument_filename, *pParams_node);
828 const bool has_return_key = node.has_key("return");
829 if (entrypoint_desc.m_return_ctype == VOGL_VOID)
833 vogl_error_printf("%s: Unexpected return key\n", VOGL_METHOD_NAME);
834 print_json_context(pDocument_filename, node);
838 else if (!has_return_key)
840 vogl_error_printf("%s: Missing return key\n", VOGL_METHOD_NAME);
841 print_json_context(pDocument_filename, node);
845 m_packet.m_entrypoint_id = gl_entrypoint_id;
846 m_packet.m_call_counter = call_counter;
847 m_packet.m_context_handle = context;
848 m_packet.m_thread_id = thread_id;
850 // All of this is optional stuff
851 m_packet.m_packet_begin_rdtsc = node.value_as_uint64("begin_rdtsc");
852 m_packet.m_packet_end_rdtsc = node.value_as_uint64("end_rdtsc");
853 m_packet.m_gl_begin_rdtsc = node.value_as_uint64("gl_begin_rdtsc");
854 m_packet.m_gl_end_rdtsc = node.value_as_uint64("gl_end_rdtsc");
855 m_packet.m_backtrace_hash_index = node.value_as_uint32("backtrace_hash_index");
857 m_packet.m_rnd = node.value_as_uint32("rnd_check", 1);
859 // The rnd value can't be 0,
860 if (m_packet.m_rnd < vogl_trace_stream_packet_base::cMinimumPossibleRnd)
862 vogl_warning_printf("%s: rnd_check value cannot be 0\n", VOGL_METHOD_NAME);
863 print_json_context(pDocument_filename, node, cWarningConsoleMessage);
864 m_packet.m_rnd = vogl_trace_stream_packet_base::cMinimumPossibleRnd;
866 m_packet.m_inv_rnd = ~m_packet.m_inv_rnd;
868 m_total_params = num_params;
869 m_has_return_value = has_return_key;
871 for (uint param_iter = 0; param_iter < num_params; param_iter++)
873 const gl_entrypoint_param_desc_t ¶m_desc = pEntrypoint_params[param_iter];
875 if (!json_deserialize_param(
876 call_counter, gl_func_name.get_ptr(),
878 param_iter, param_desc.m_pName, param_desc.m_class, (*m_pCTypes)[param_desc.m_ctype], pDocument_filename, pBlob_manager))
884 if (m_has_return_value)
886 if (!json_deserialize_param(
887 call_counter, gl_func_name.get_ptr(),
889 num_params, "return", VOGL_VALUE_PARAM, (*m_pCTypes)[entrypoint_desc.m_return_ctype], pDocument_filename, pBlob_manager))
895 const json_node *pName_value_array = node.find_child("name_value_map");
896 if (pName_value_array)
898 if (!pName_value_array->is_array())
900 vogl_error_printf("%s: name_value_map is not an array\n", VOGL_METHOD_NAME);
901 print_json_context(pDocument_filename, *pName_value_array);
905 uint64_t size = pName_value_array->size();
906 VOGL_NOTE_UNUSED(size);
908 uint name_value_index = 0;
910 for (uint name_value_node_iter = 0; name_value_node_iter < pName_value_array->size(); name_value_node_iter++)
912 const json_node *pItem_node = pName_value_array->get_value_as_object(name_value_node_iter);
915 vogl_error_printf("%s: Expected object in name_value_map array\n", VOGL_METHOD_NAME);
916 print_json_context(pDocument_filename, *pName_value_array, name_value_node_iter);
919 const json_node &item_node = *pItem_node;
921 dynamic_string key_str(item_node.value_as_string("key"));
922 if (key_str.is_empty())
924 vogl_error_printf("%s: Expected key in name_value_map array\n", VOGL_METHOD_NAME);
925 print_json_context(pDocument_filename, *pName_value_array, name_value_node_iter);
929 const char *pKey_type_str = item_node.value_as_string_ptr("key_type");
930 const char *pValue_type_str = item_node.value_as_string_ptr("val_type");
932 if ((!pKey_type_str) || (!pValue_type_str))
934 vogl_error_printf("%s: Invalid data_types array in name_value_map object\n", VOGL_METHOD_NAME);
935 print_json_context(pDocument_filename, *pName_value_array, name_value_node_iter);
939 value_data_type key_type = string_to_value_data_type(pKey_type_str);
940 value_data_type value_type = string_to_value_data_type(pValue_type_str);
941 if ((key_type == cDTInvalid) || (value_type == cDTInvalid))
943 vogl_error_printf("%s: Invalid data_types array in name_value_map object\n", VOGL_METHOD_NAME);
944 print_json_context(pDocument_filename, *pName_value_array, name_value_node_iter);
949 if (!key.parse(key_str.get_ptr()))
951 vogl_error_printf("%s: Failed parsing name_value_map key string %s\n", VOGL_METHOD_NAME, key_str.get_ptr());
952 print_json_context(pDocument_filename, *pName_value_array, name_value_node_iter);
956 if (!force_value_to_type(key, key_type))
958 vogl_error_printf("%s: Failed parsing name_value_map key %s\n", VOGL_METHOD_NAME, key_str.get_ptr());
959 print_json_context(pDocument_filename, *pName_value_array, name_value_node_iter);
963 const json_value &json_val = item_node.find_value("data");
965 if ((value_type == cDTBlob) && (json_val.is_object()))
967 //vogl_error_printf("%s: Expected JSON object for name_value_map node key %s\n", VOGL_METHOD_NAME, key_str.get_ptr());
968 //print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter);
971 const json_node &blob_node = *json_val.get_node_ptr();
973 dynamic_string blob_id;
974 if (!blob_node.get_value_as_string("blob_id", blob_id))
976 vogl_error_printf("%s: Failed parsing blob_file key in name_value_map node key %s\n", VOGL_METHOD_NAME, key_str.get_ptr());
977 print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter);
981 uint64_t blob_crc64 = 0;
982 if (!get_uint64_from_json_node(blob_node, "crc64", blob_crc64))
984 vogl_error_printf("%s: Failed parsing crc64 key in name_value_map node key %s\n", VOGL_METHOD_NAME, key_str.get_ptr());
985 print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter);
989 uint64_t blob_size = 0;
990 if (!get_uint64_from_json_node(blob_node, "size", blob_size))
992 vogl_error_printf("%s: Failed parsing size key in name_value_map node key %s\n", VOGL_METHOD_NAME, key_str.get_ptr());
993 print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter);
997 if (blob_size > cUINT32_MAX)
999 vogl_error_printf("%s: Blob size is too large (%" PRIu64 "), blob id %s key %s\n", VOGL_METHOD_NAME, blob_size, blob_id.get_ptr(), key_str.get_ptr());
1000 print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter);
1006 vogl_error_printf("%s: Encountered data blob in packet but no blob manager was specified, blob size %" PRIu64 " blob id %s key %s\n", VOGL_METHOD_NAME, blob_size, blob_id.get_ptr(), key_str.get_ptr());
1007 print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter);
1012 if (!pBlob_manager->get(blob_id, blob))
1014 vogl_error_printf("%s: Failed retrieving data blob, blob size %" PRIu64 " blob id %s key %s CRC64 0x%" PRIX64 "\n", VOGL_METHOD_NAME, blob_size, blob_id.get_ptr(), key_str.get_ptr(), blob_crc64);
1015 print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter);
1019 uint64_t actual_blob_size = blob.size();
1021 // TODO: We'll eventually support enormous blob files
1022 if (actual_blob_size > cUINT32_MAX)
1024 vogl_error_printf("%s: Blob size is too large (%" PRIu64 "), blob id %s key %s\n", VOGL_METHOD_NAME, actual_blob_size, blob_id.get_ptr(), key_str.get_ptr());
1025 print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter);
1029 if (actual_blob_size != blob_size)
1031 vogl_warning_printf("%s: Unexpected size of blob id %s (should be %" PRIu64 " bytes, but is %" PRIu64 " bytes), reading all of file and hoping for the best\n", VOGL_METHOD_NAME, blob_id.get_ptr(), blob_size, actual_blob_size);
1032 print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter, cWarningConsoleMessage);
1035 uint64_t check_crc64 = calc_crc64(CRC64_INIT, blob.get_ptr(), blob.size());
1036 if (check_crc64 != blob_crc64)
1038 vogl_warning_printf("%s: name_value_map blob file %s's CRC64 is bad (expected 0x%016" PRIX64 " got 0x%016" PRIX64 ")\n", VOGL_METHOD_NAME, blob_id.get_ptr(), blob_crc64, check_crc64);
1039 print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter, cWarningConsoleMessage);
1042 val.set_blob_take_ownership(blob);
1044 else if (value_type == cDTJSONDoc)
1046 *val.init_json_document() = json_val;
1050 switch (json_val.get_type())
1052 case cJSONValueTypeBool:
1053 case cJSONValueTypeInt:
1055 val.set_int64(json_val.as_int64());
1058 case cJSONValueTypeDouble:
1060 val.set_int64(json_val.as_double());
1063 case cJSONValueTypeString:
1065 const char *pStr = json_val.as_string_ptr();
1066 if (!pStr || !val.parse(pStr))
1068 vogl_error_printf("%s: Failed parsing name_value_map value type for key %s\n", VOGL_METHOD_NAME, key_str.get_ptr());
1069 print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter);
1077 vogl_error_printf("%s: Unexpected name_value_map value type for key %s\n", VOGL_METHOD_NAME, key_str.get_ptr());
1078 print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter);
1084 if (!force_value_to_type(val, value_type))
1086 vogl_error_printf("%s: Failed parsing value for name_value_map key %s\n", VOGL_METHOD_NAME, key_str.get_ptr());
1087 print_json_context(pDocument_filename, json_val, *pName_value_array, name_value_node_iter);
1090 m_key_value_map.insert(key, val);
1094 } // name_value_node_iter
1097 if (!fixup_manually_edited_params(gl_entrypoint_id, gl_func_name.get_ptr(), call_counter))
1102 VOGL_ASSERT(check());
1107 //----------------------------------------------------------------------------------------------------------------------
1108 // vogl_trace_packet::validate_value_conversion
1109 // Returns true if the dest type is at least large enough to hold the parameter (or the same size in bytes for floats).
1110 //----------------------------------------------------------------------------------------------------------------------
1111 bool vogl_trace_packet::validate_value_conversion(uint dest_type_size, uint dest_type_loki_type_flags, int param_index) const
1115 VOGL_ASSERT((dest_type_size >= 1) && (dest_type_size <= 8));
1117 const vogl_ctype_desc_t ¶m_ctype_desc = (param_index < 0) ? get_return_value_ctype_desc() : get_param_ctype_desc(param_index);
1118 uint64_t param_data = (param_index < 0) ? get_return_value_data() : get_param_data(param_index);
1119 uint param_size = param_ctype_desc.m_size;
1121 if (param_ctype_desc.m_is_pointer)
1123 // This func is not really intended to be used with pointer types, but try to do something.
1124 return (dest_type_size >= m_pCTypes->get_pointer_size());
1127 if (param_ctype_desc.m_loki_type_flags & LOKI_TYPE_BITMASK(LOKI_IS_FLOAT))
1129 return dest_type_size == static_cast<uint>(param_ctype_desc.m_size);
1132 // unsigned ints = unsigned char, unsigned short int,unsigned int, unsigned long int, unsigned long long int
1133 // signed ints = signed char, short int,int, long int, long long int
1134 // integral = bool, char, wchar_t, or signed/unsigned ints
1135 bool param_is_signed = (param_ctype_desc.m_loki_type_flags & (LOKI_TYPE_BITMASK(LOKI_IS_SIGNED_INT) | LOKI_TYPE_BITMASK(LOKI_IS_SIGNED_LONG))) != 0;
1136 bool param_is_unsigned = (param_ctype_desc.m_loki_type_flags & (LOKI_TYPE_BITMASK(LOKI_IS_UNSIGNED_INT) | LOKI_TYPE_BITMASK(LOKI_IS_UNSIGNED_LONG))) != 0;
1137 VOGL_NOTE_UNUSED(param_is_unsigned);
1138 bool param_is_integral = (param_ctype_desc.m_loki_type_flags & LOKI_TYPE_BITMASK(LOKI_IS_INTEGRAL)) != 0;
1140 bool dest_is_signed = (dest_type_loki_type_flags & (LOKI_TYPE_BITMASK(LOKI_IS_SIGNED_INT) | LOKI_TYPE_BITMASK(LOKI_IS_SIGNED_LONG))) != 0;
1141 bool dest_is_unsigned = (dest_type_loki_type_flags & (LOKI_TYPE_BITMASK(LOKI_IS_UNSIGNED_INT) | LOKI_TYPE_BITMASK(LOKI_IS_UNSIGNED_LONG))) != 0;
1142 VOGL_NOTE_UNUSED(dest_is_unsigned);
1143 bool dest_is_integral = (dest_type_loki_type_flags & LOKI_TYPE_BITMASK(LOKI_IS_INTEGRAL)) != 0;
1145 if (param_is_integral != dest_is_integral)
1148 bigint128 dest_min_val, dest_max_val;
1149 bigint128::get_type_range(dest_type_size, dest_is_signed, dest_min_val, dest_max_val);
1152 bigint128 param_val(¶m_data, param_size, param_is_signed);
1156 return (param_val >= dest_min_val) && (param_val <= dest_max_val);
1160 return param_val.unsigned_less_equal(dest_max_val);
1164 //----------------------------------------------------------------------------------------------------------------------
1165 // vogl_trace_packet::should_always_write_as_blob_file
1166 //----------------------------------------------------------------------------------------------------------------------
1167 bool vogl_trace_packet::should_always_write_as_blob_file(const char *pFunc_name)
1171 if ((strstr(pFunc_name, "ShaderSource") != NULL) ||
1172 (strstr(pFunc_name, "TexSubImage") != NULL) ||
1173 (strstr(pFunc_name, "TexImage") != NULL))
1178 //----------------------------------------------------------------------------------------------------------------------
1179 // vogl_trace_packet::ctype_to_json_string
1180 // returns false if the returned string is a valid JSON numeric (otherwise it's a string)
1181 //----------------------------------------------------------------------------------------------------------------------
1182 void vogl_trace_packet::ctype_to_json_value(json_value &val, gl_entrypoint_id_t entrypoint_id, int param_index, uint64_t data, vogl_ctype_t ctype) const
1189 case VOGL_GLBOOLEAN:
1193 val.set_value(false);
1198 val.set_value(true);
1206 const gl_entrypoint_desc_t &entrypoint_desc = g_vogl_entrypoint_descs[entrypoint_id];
1207 VOGL_NOTE_UNUSED(entrypoint_desc);
1208 VOGL_ASSERT((param_index == -1) || (static_cast<uint>(param_index) < entrypoint_desc.m_num_params));
1210 const char *pName = g_gl_enums.find_name(data, entrypoint_id, param_index);
1214 VOGL_ASSERT(g_gl_enums.find_enum(pName) == data);
1216 val.set_value(pName);
1226 float flt_val = *reinterpret_cast<const float *>(&data);
1227 val.set_value(flt_val);
1229 dynamic_string val_as_str;
1230 val.serialize(val_as_str, false);
1232 json_value test_val;
1233 if ((!test_val.deserialize(val_as_str)) || (test_val.as_float() != flt_val))
1241 double dbl_val = *reinterpret_cast<const double *>(&data);
1242 val.set_value(dbl_val);
1244 dynamic_string val_as_str;
1245 val.serialize(val_as_str, false);
1247 json_value test_val;
1248 if ((!test_val.deserialize(val_as_str)) || (test_val.as_double() != dbl_val))
1259 val.set_value(static_cast<int32>(data));
1264 val.set_value(static_cast<int16>(data));
1269 val.set_value(static_cast<int8>(data));
1273 case VOGL_GLINT64EXT:
1275 val.set_value(static_cast<int64_t>(data));
1284 val.set_value(dynamic_string(cVarArg, "0x%" PRIX64, data).get_ptr());
1287 //----------------------------------------------------------------------------------------------------------------------
1288 // vogl_trace_packet::json_serialize_param
1289 //----------------------------------------------------------------------------------------------------------------------
1290 bool vogl_trace_packet::json_serialize_param(
1291 const char *pFunc_name,
1292 json_node &gl_params_node, int param_index, const char *pName, const uint64_t param_data, const uint param_size, vogl_ctype_t param_ctype,
1293 const void *pClient_mem, uint client_mem_size, vogl_ctype_t client_mem_ctype,
1294 const json_serialize_params ¶ms) const
1298 VOGL_NOTE_UNUSED(param_size);
1299 VOGL_NOTE_UNUSED(client_mem_ctype);
1301 const vogl_ctype_desc_t ¶m_ctype_desc = (*m_pCTypes)[param_ctype];
1303 const bool has_client_memory = (pClient_mem != NULL);
1305 if ((param_ctype_desc.m_is_pointer) && (param_data) && (has_client_memory))
1307 const vogl_ctype_t pointee_ctype = param_ctype_desc.m_pointee_ctype;
1308 const uint pointee_size = (*m_pCTypes)[pointee_ctype].m_size;
1309 const bool pointee_is_ptr = (*m_pCTypes)[pointee_ctype].m_is_pointer;
1311 bool print_as_cstring = false;
1312 switch (param_ctype)
1314 case VOGL_CONST_GLUBYTE_PTR:
1315 case VOGL_CONST_GLCHAR_PTR:
1316 case VOGL_GLCHARARB_PTR:
1317 case VOGL_CONST_GLBYTE_PTR:
1318 case VOGL_GLUBYTE_PTR:
1319 case VOGL_GLCHAR_PTR:
1320 case VOGL_CONST_GLCHARARB_PTR:
1322 if ((client_mem_size <= 8192) && (utils::is_buffer_printable(pClient_mem, client_mem_size, true, true)))
1324 print_as_cstring = true;
1333 if (print_as_cstring)
1335 if ((client_mem_size >= 2) && (static_cast<const char *>(pClient_mem)[0] == '0') && (static_cast<const char *>(pClient_mem)[1] == 'x'))
1336 print_as_cstring = false;
1337 //else if (g_vogl_entrypoint_hashmap.find(static_cast<const char *>(pClient_mem)) != g_vogl_entrypoint_hashmap.end())
1338 // print_as_cstring = false;
1341 json_node ¶m_node = gl_params_node.add_object(pName);
1343 if (print_as_cstring)
1345 const char *pStr = reinterpret_cast<const char *>(pClient_mem);
1347 // this was causing a crash and as far as I could tell it was a clang optimizer bug?
1348 //dynamic_string str(cVarArg, "%s", pStr);
1349 dynamic_string str(pStr);
1350 param_node.add_key_value("string", str);
1352 param_node.add_key_value("ptr", dynamic_string(cVarArg, "0x%016" PRIX64, param_data));
1356 param_node.add_key_value("ptr", dynamic_string(cVarArg, "0x%016" PRIX64, param_data));
1357 param_node.add_key_value("mem_size", client_mem_size);
1359 uint64_t client_mem_crc64 = calc_crc64(CRC64_INIT, reinterpret_cast<const uint8 *>(pClient_mem), client_mem_size);
1360 param_node.add_key_value("crc64", dynamic_string(cVarArg, "0x%016" PRIX64, client_mem_crc64));
1362 if ((pointee_size >= 1) && (pointee_size <= 8) && (math::is_power_of_2(pointee_size)) && (!(client_mem_size % pointee_size)))
1364 json_node ¶m_data_values_node = param_node.add_array("values");
1366 const uint client_mem_array_size = client_mem_size / pointee_size;
1368 for (uint i = 0; i < client_mem_array_size; i++)
1370 const void *p = reinterpret_cast<const uint8 *>(pClient_mem) + i * pointee_size;
1373 if (pointee_size == sizeof(uint8))
1374 data = *reinterpret_cast<const uint8 *>(p);
1375 else if (pointee_size == sizeof(uint16))
1376 data = *reinterpret_cast<const uint16 *>(p);
1377 else if (pointee_size == sizeof(uint32))
1378 data = *reinterpret_cast<const uint32 *>(p);
1379 else if (pointee_size == sizeof(uint64_t))
1380 data = *reinterpret_cast<const uint64_t *>(p);
1383 ctype_to_json_value(val, static_cast<gl_entrypoint_id_t>(m_packet.m_entrypoint_id), param_index, data, pointee_ctype);
1385 param_data_values_node.add_value(val);
1390 if ((!should_always_write_as_blob_file(pFunc_name)) && (client_mem_size < params.m_blob_file_size_threshold))
1394 buf.set_len(2 + client_mem_size * 2);
1395 buf.set_char(0, '0');
1396 buf.set_char(1, 'x');
1398 for (uint i = 0; i < client_mem_size; i++)
1400 const uint8 c = reinterpret_cast<const uint8 *>(pClient_mem)[(client_mem_size - 1) - i];
1401 buf.set_char(2 + i * 2 + 0, utils::to_hex((c >> 4) & 0xF));
1402 buf.set_char(2 + i * 2 + 1, utils::to_hex(c & 0xF));
1405 param_node.add_key_value("bytes", buf);
1411 if (params.m_pBlob_manager)
1413 //dynamic_string prefix(cVarArg, "%s_%s_param_%i", params.m_output_basename.get_ptr(), pFunc_name, param_index);
1414 dynamic_string prefix(cVarArg, "%s_%s", pFunc_name, g_vogl_entrypoint_param_descs[m_packet.m_entrypoint_id][param_index].m_pName);
1416 id = params.m_pBlob_manager->add_buf_compute_unique_id(pClient_mem, client_mem_size, prefix, "blob", &client_mem_crc64);
1419 vogl_error_printf("%s: Failed adding blob %s to blob manager\n", VOGL_METHOD_NAME, prefix.get_ptr());
1423 vogl_message_printf("%s: Wrote blob id %s\n", VOGL_METHOD_NAME, id.get_ptr());
1427 id = "<blob_writing_disabled>";
1430 param_node.add_key_value("blob_id", id);
1434 if (params.m_write_debug_info)
1436 json_node ¶m_dbg_node = param_node.add_object("dbg");
1437 param_dbg_node.add_key_value("ctype", (*m_pCTypes)[param_ctype].m_pCType);
1438 param_dbg_node.add_key_value("pointee_ctype", (*m_pCTypes)[pointee_ctype].m_pCType);
1439 param_dbg_node.add_key_value("pointee_ctype_size", (*m_pCTypes)[pointee_ctype].m_size);
1440 param_dbg_node.add_key_value("pointee_ctype_is_opaque", (*m_pCTypes)[pointee_ctype].m_is_opaque_pointer);
1441 param_dbg_node.add_key_value("pointee_is_ptr", pointee_is_ptr);
1442 param_dbg_node.add_key_value("pointee_size", pointee_size);
1448 json_value param_value;
1449 // This helper can return a hex string (beginning with 0x chars) for values that can't be losslessly converted to a JSON numeric
1450 ctype_to_json_value(param_value, static_cast<gl_entrypoint_id_t>(m_packet.m_entrypoint_id), param_index, param_data, param_ctype);
1451 gl_params_node.add_key_value(pName, param_value);
1457 //----------------------------------------------------------------------------------------------------------------------
1458 // vogl_trace_packet::convert_json_value_to_ctype_data
1459 //----------------------------------------------------------------------------------------------------------------------
1460 bool vogl_trace_packet::convert_json_value_to_ctype_data(uint64_t &data, const json_value &val, vogl_ctype_t ctype, const char *pName, int param_iter, gl_entrypoint_param_class_t param_class, bool permit_client_strings, const json_node &node, const char *pDocument_filename)
1464 VOGL_NOTE_UNUSED(param_class);
1466 const bool is_pointer = (*m_pCTypes)[ctype].m_is_pointer;
1468 // could either be a pointer to a string, or pointer value with no associated client memory, or a param value
1471 double dbl_data = 0;
1472 uint parsed_size = 0;
1473 VOGL_NOTE_UNUSED(parsed_size);
1474 bool parsed_double = false;
1475 bool parsed_hex = false;
1477 if (val.is_string())
1479 dynamic_string str(val.as_string());
1481 if ((str.get_len() >= 3) && (str[0] == '0') && (str[1] == 'x'))
1483 // hex parameter data - should be <= sizeof(uint64_t)
1484 // could be a pointer to unspecified client memory, or a non-ptr param value that couldn't be serialized to a regular json type
1486 const char *pBuf = str.get_ptr();
1487 if (!string_ptr_to_uint64(pBuf, data))
1489 vogl_error_printf("Failed parsing hex numeric value of parameter %s\n", pName);
1490 print_json_context(pDocument_filename, val, node);
1493 parsed_size = sizeof(uint64_t);
1496 else if (is_pointer)
1498 if (!permit_client_strings)
1500 vogl_error_printf("Unexpected string for parameter %s\n", pName);
1501 print_json_context(pDocument_filename, val, node);
1505 // must be a zero terminated string originally from client memory
1507 parsed_size = sizeof(uint32);
1511 vogl_error_printf("Encountered string for non-pointer parameter %s\n", pName);
1512 print_json_context(pDocument_filename, val, node);
1516 client_memory_desc_t &mem_desc = m_client_memory_descs[param_iter];
1517 mem_desc.m_vec_ofs = m_client_memory.size();
1518 mem_desc.m_data_size = str.get_len() + 1;
1519 mem_desc.m_pointee_ctype = (*m_pCTypes)[ctype].m_pointee_ctype;
1521 m_client_memory.append(reinterpret_cast<const uint8 *>(str.get_ptr()), str.get_len() + 1);
1525 uint64_t gl_enum = g_gl_enums.find_enum(str);
1526 if (gl_enum == gl_enums::cUnknownEnum)
1528 vogl_error_printf("Unexpected string for parameter %s\n", pName);
1529 print_json_context(pDocument_filename, val, node);
1533 // TODO - Fix this so it doesn't downcast to uint (can it safely return uint64_t?)
1534 VOGL_ASSERT(gl_enum <= cUINT32_MAX);
1537 data = static_cast<uint>(gl_enum);
1538 parsed_size = sizeof(uint);
1546 bool b = val.as_bool();
1547 memcpy(&data, &b, 1);
1550 else if (val.is_double())
1552 dbl_data = val.as_double();
1553 memcpy(&data, &dbl_data, sizeof(dbl_data));
1554 parsed_size = sizeof(dbl_data);
1555 parsed_double = true;
1557 else if (val.is_int())
1559 int64_t v = val.as_int64();
1560 memcpy(&data, &v, sizeof(data));
1561 parsed_size = sizeof(int64_t);
1565 vogl_error_printf("Invalid JSON node type for parameter %s\n", pName);
1566 print_json_context(pDocument_filename, val, node);
1571 int64_t idata = static_cast<int64_t>(data);
1581 v = static_cast<float>(dbl_data);
1582 else if (parsed_hex)
1583 v = *reinterpret_cast<const float *>(&data);
1586 v = static_cast<float>(idata);
1587 vogl_debug_printf("Parameter %s should be a float, but a non-float value was specified in the JSON file\n", pName);
1588 print_json_context(pDocument_filename, val, node, cDebugConsoleMessage);
1592 memcpy(&data, &v, sizeof(v));
1601 else if (parsed_hex)
1602 v = *reinterpret_cast<const double *>(&data);
1605 v = static_cast<double>(idata);
1606 vogl_debug_printf("Parameter %s should be a double, but a non-double value was specified in the JSON file\n", pName);
1607 print_json_context(pDocument_filename, val, node, cDebugConsoleMessage);
1609 memcpy(&data, &v, sizeof(v));
1616 vogl_warning_printf("Float point value specified for non-float parameter %s, casting to integer\n", pName);
1617 print_json_context(pDocument_filename, val, node, cWarningConsoleMessage);
1618 data = idata = static_cast<int64_t>(dbl_data);
1627 case VOGL_GLBOOLEAN:
1629 //if ((data != 0) && (data != 1))
1630 // vogl_warning_printf("Expected bool value for parameter %s\n", pName);
1633 case VOGL_GLBITFIELD:
1635 case VOGL_UNSIGNED_INT:
1637 case VOGL_GLHANDLEARB:
1639 if (data > cUINT32_MAX)
1641 vogl_warning_printf("Value out of range for parameter %s\n", pName);
1642 print_json_context(pDocument_filename, val, node, cWarningConsoleMessage);
1652 if ((idata < cINT32_MIN) || (idata > cINT32_MAX))
1654 vogl_warning_printf("Value out of range for parameter %s\n", pName);
1655 print_json_context(pDocument_filename, val, node, cWarningConsoleMessage);
1660 case VOGL_GLCHARARB:
1662 if ((idata < -cINT8_MAX) || (idata > cINT8_MAX))
1664 vogl_warning_printf("Value out of range for parameter %s\n", pName);
1665 print_json_context(pDocument_filename, val, node, cWarningConsoleMessage);
1672 if (data > cUINT8_MAX)
1674 vogl_warning_printf("Value out of range for parameter %s\n", pName);
1675 print_json_context(pDocument_filename, val, node, cWarningConsoleMessage);
1682 if (data > cUINT16_MAX)
1684 vogl_warning_printf("Value out of range for parameter %s\n", pName);
1685 print_json_context(pDocument_filename, val, node, cWarningConsoleMessage);
1691 if ((idata < cINT16_MIN) || (idata > cINT16_MAX))
1693 vogl_warning_printf("Value out of range for parameter %s\n", pName);
1694 print_json_context(pDocument_filename, val, node, cWarningConsoleMessage);
1705 //----------------------------------------------------------------------------------------------------------------------
1706 // vogl_trace_packet::json_deserialize_param
1707 //----------------------------------------------------------------------------------------------------------------------
1708 bool vogl_trace_packet::json_deserialize_param(
1709 uint64_t cur_call_counter, const char *pFunc_name,
1710 const json_node ¶ms_node, uint param_iter, const char *pParam_name, gl_entrypoint_param_class_t param_class, const vogl_ctype_desc_t ¶m_ctype_desc,
1711 const char *pDocument_filename, const vogl_blob_manager *pBlob_manager)
1715 VOGL_NOTE_UNUSED(cur_call_counter);
1717 int param_index = params_node.find_key(pParam_name);
1718 if (param_index < 0)
1720 vogl_error_printf("Failed finding function parameter \"%s\"\n", pParam_name);
1721 print_json_context(pDocument_filename, params_node);
1725 const json_value &val = params_node.get_value(param_index);
1726 if ((val.is_null()) || (val.is_array()))
1728 vogl_error_printf("Invalid JSON node type for parameter %s\n", pParam_name);
1729 print_json_context(pDocument_filename, params_node);
1733 if (val.is_object())
1735 // must be pointer to client memory of some sort
1736 if (!param_ctype_desc.m_is_pointer)
1738 vogl_error_printf("A memory object was specified for parameter %s, but parameter is not a pointer to client memory\n", pParam_name);
1739 print_json_context(pDocument_filename, val, params_node);
1743 vogl_ctype_t pointee_ctype = param_ctype_desc.m_pointee_ctype;
1744 VOGL_ASSERT(pointee_ctype != VOGL_INVALID_CTYPE);
1746 uint pointee_ctype_size = (*m_pCTypes)[pointee_ctype].m_size;
1748 const json_node *pParam_obj = val.get_node_ptr();
1751 if (!get_uint64_from_json_node(*pParam_obj, "ptr", ptr, 0))
1753 vogl_warning_printf("Failed parsing ptr field of parameter %s (the pointer is only for debugging, not replay, so this is not a hard failure)\n", pParam_name);
1754 print_json_context(pDocument_filename, *pParam_obj, cWarningConsoleMessage);
1757 if (pParam_obj->has_key("string"))
1759 const char *pStr = pParam_obj->find_value("string").as_string_ptr();
1760 uint str_len = vogl_strlen(pStr);
1762 client_memory_desc_t &mem_desc = m_client_memory_descs[param_iter];
1763 mem_desc.m_vec_ofs = m_client_memory.size();
1764 mem_desc.m_data_size = str_len + 1;
1765 mem_desc.m_pointee_ctype = pointee_ctype;
1767 m_client_memory.append(reinterpret_cast<const uint8 *>(pStr), str_len + 1);
1769 m_param_data[param_iter] = ptr;
1771 VOGL_ASSERT(param_ctype_desc.m_size <= cUINT8_MAX);
1772 m_param_size[param_iter] = param_ctype_desc.m_size;
1773 m_param_ctype[param_iter] = param_ctype_desc.m_ctype;
1777 uint64_t mem_size = 0;
1778 if (!get_uint64_from_json_node(*pParam_obj, "mem_size", mem_size, 0))
1780 vogl_error_printf("Failed parsing mem_size field of parameter %s\n", pParam_name);
1781 print_json_context(pDocument_filename, *pParam_obj);
1785 if (mem_size > 0x7FFF0000)
1787 vogl_error_printf("Client memory blob size is too large for parameter %s\n", pParam_name);
1788 print_json_context(pDocument_filename, *pParam_obj);
1792 uint64_t blob_crc64 = 0;
1793 bool has_blob_crc64 = get_uint64_from_json_node(*pParam_obj, "crc64", blob_crc64, 0);
1795 vogl::vector<uint8> blob(static_cast<uint32>(mem_size));
1797 if (pParam_obj->find_child("values"))
1799 if (pointee_ctype_size <= 0)
1801 vogl_error_printf("Can't specify a values array for void* parameter %s\n", pParam_name);
1802 print_json_context(pDocument_filename, *pParam_obj);
1806 const json_node *pValues = pParam_obj->find_child("values");
1808 if (!pValues->is_array())
1810 vogl_error_printf("Expected array for values field of parameter %s\n", pParam_name);
1811 print_json_context(pDocument_filename, *pValues);
1815 uint num_vals = pValues->size();
1816 if (num_vals != (mem_size / pointee_ctype_size))
1818 vogl_error_printf("Array size is invalid for parameter %s\n", pParam_name);
1819 print_json_context(pDocument_filename, *pValues);
1823 if ((mem_size % pointee_ctype_size) != 0)
1825 vogl_error_printf("Mem size is invalid for parameter %s\n", pParam_name);
1826 print_json_context(pDocument_filename, *pValues);
1830 for (uint val_iter = 0; val_iter < num_vals; val_iter++)
1832 const json_value &val = pValues->get_value(val_iter);
1834 uint64_t param_data;
1835 if (!convert_json_value_to_ctype_data(param_data, val, pointee_ctype, "values", -1, VOGL_VALUE_PARAM, false, *pValues, pDocument_filename))
1838 memcpy(blob.get_ptr() + val_iter * pointee_ctype_size, ¶m_data, pointee_ctype_size);
1841 else if (pParam_obj->has_key("blob_id"))
1843 dynamic_string blob_id;
1844 pParam_obj->get_value_as_string("blob_id", blob_id);
1848 vogl_error_printf("%s: No blob manager specified, blob id %s\n", VOGL_METHOD_NAME, blob_id.get_ptr());
1849 print_json_context(pDocument_filename, *pParam_obj);
1853 uint8_vec data_blob;
1854 if (!pBlob_manager->get(blob_id, data_blob))
1856 vogl_error_printf("%s: Failed retrieving data blob, blob size %" PRIu64 " blob id %s CRC64 0x%" PRIX64 "\n", VOGL_METHOD_NAME, mem_size, blob_id.get_ptr(), blob_crc64);
1857 print_json_context(pDocument_filename, *pParam_obj);
1861 // TODO: We'll support uint64_t blob sizes eventually
1862 uint64_t file_size = data_blob.size();
1863 if (file_size > cUINT32_MAX)
1865 vogl_error_printf("%s: Blob file %s is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, blob_id.get_ptr(), file_size);
1866 print_json_context(pDocument_filename, *pParam_obj);
1870 blob.swap(data_blob);
1872 if (file_size != mem_size)
1874 vogl_warning_printf("Unexpected size of blob file %s (should be %" PRIu64 " bytes, but is %" PRIu64 " bytes), reading all of file and hoping for the best\n", blob_id.get_ptr(), mem_size, file_size);
1875 print_json_context(pDocument_filename, *pParam_obj, cWarningConsoleMessage);
1878 else if (pParam_obj->has_key("bytes"))
1880 const json_value &bytes_val = pParam_obj->find_value("bytes");
1881 const char *pByte_str = bytes_val.as_string_ptr();
1884 vogl_error_printf("Expected bytes value string for parameter %s\n", pFunc_name);
1885 print_json_context(pDocument_filename, *pParam_obj);
1889 uint bytes_len = vogl_strlen(pByte_str);
1890 if ((bytes_len != 2 + 2 * mem_size) || (pByte_str[0] != '0') || (pByte_str[1] != 'x'))
1892 vogl_error_printf("Can't parse bytes value string for parameter %s (either size is bad, or string doesn't start with 0x)\n", pFunc_name);
1893 print_json_context(pDocument_filename, *pParam_obj);
1897 for (uint i = 0; i < mem_size; i++)
1899 char c0 = pByte_str[2 + i * 2 + 0];
1900 char c1 = pByte_str[2 + i * 2 + 1];
1902 int val_c0 = utils::from_hex(c0);
1903 int val_c1 = utils::from_hex(c1);
1905 if ((val_c0 < 0) || (val_c1 < 0))
1907 vogl_error_printf("Non-hex char in bytes value at byte index %u for parameter %s\n", i, pFunc_name);
1908 print_json_context(pDocument_filename, *pParam_obj);
1912 blob[(static_cast<uint>(mem_size) - 1) - i] = (val_c0 << 4) | (val_c1);
1917 vogl_error_printf("Failed parsing array parameter %s\n", pParam_name);
1918 print_json_context(pDocument_filename, *pParam_obj);
1924 uint64_t check_crc64 = calc_crc64(CRC64_INIT, blob.get_ptr(), static_cast<size_t>(mem_size));
1925 if (check_crc64 != blob_crc64)
1927 vogl_warning_printf("Blob CRC64 check failed for parameter %s (expected 0x%016" PRIX64 " got 0x%016" PRIX64 ")\n", pParam_name, blob_crc64, check_crc64);
1928 print_json_context(pDocument_filename, *pParam_obj, cWarningConsoleMessage);
1932 m_param_data[param_iter] = ptr;
1934 VOGL_ASSERT(param_ctype_desc.m_size <= cUINT8_MAX);
1935 m_param_size[param_iter] = param_ctype_desc.m_size;
1936 m_param_ctype[param_iter] = param_ctype_desc.m_ctype;
1938 client_memory_desc_t &mem_desc = m_client_memory_descs[param_iter];
1939 mem_desc.m_vec_ofs = m_client_memory.size();
1940 mem_desc.m_data_size = blob.size();
1941 mem_desc.m_pointee_ctype = pointee_ctype;
1943 m_client_memory.append(blob.get_ptr(), blob.size());
1948 uint64_t param_data;
1949 if (!convert_json_value_to_ctype_data(param_data, val, param_ctype_desc.m_ctype, pParam_name, param_iter, param_class, true, params_node, pDocument_filename))
1952 m_param_data[param_iter] = 0;
1953 memcpy(&m_param_data[param_iter], ¶m_data, param_ctype_desc.m_size);
1955 VOGL_ASSERT(param_ctype_desc.m_size <= cUINT8_MAX);
1956 m_param_size[param_iter] = param_ctype_desc.m_size;
1957 m_param_ctype[param_iter] = param_ctype_desc.m_ctype;
1959 } // val.is_object()
1964 //----------------------------------------------------------------------------------------------------------------------
1965 // vogl_trace_packet::get_uint64_from_json_node
1966 // TODO: This is now outdated, we can retrieve uint64_t's directly using members in the json_node class
1967 //----------------------------------------------------------------------------------------------------------------------
1968 bool vogl_trace_packet::get_uint64_from_json_node(const json_node &node, const char *pKey, uint64_t &val, uint64_t def)
1972 int key_index = node.find_key(pKey);
1979 const json_value &json_val = node.get_value(key_index);
1981 if (json_val.is_string())
1983 const char *pBuf = json_val.as_string_ptr();
1984 if (!string_ptr_to_uint64(pBuf, val))
1993 if (!json_val.get_numeric(ival, static_cast<int64_t>(def)))
1998 VOGL_ASSERT(ival >= 0);
1999 val = static_cast<uint64_t>(ival);
2005 //----------------------------------------------------------------------------------------------------------------------
2006 // vogl_trace_packet::force_value_to_type
2007 //----------------------------------------------------------------------------------------------------------------------
2008 bool vogl_trace_packet::force_value_to_type(value &val, value_data_type type)
2016 val.set_bool(val.get_bool());
2021 val.set_int8(val.get_int8());
2026 val.set_uint8(val.get_uint8());
2031 val.set_int16(val.get_int16());
2036 val.set_uint16(val.get_uint16());
2041 val.set_int(val.get_int());
2046 val.set_uint(val.get_uint());
2051 val.set_int64(val.get_int64());
2056 val.set_uint64(val.get_uint64());
2061 val.set_float(val.get_float());
2066 val.set_double(val.get_double());
2071 val.set_void_ptr((void *)val.get_uint64());
2076 if (val.get_data_type() != cDTString)
2082 val.set_string_hash(val.get_string_hash());
2087 if (val.get_data_type() != cDTBlob)
2093 if (val.get_data_type() != cDTJSONDoc)
2104 //----------------------------------------------------------------------------------------------------------------------
2105 // vogl_trace_packet::fixup_manually_edited_params
2106 //----------------------------------------------------------------------------------------------------------------------
2107 bool vogl_trace_packet::fixup_manually_edited_params(gl_entrypoint_id_t gl_entrypoint_id, const char *pGL_func_name, uint64_t cur_call_counter)
2111 if ((gl_entrypoint_id == VOGL_ENTRYPOINT_glShaderSource) || (gl_entrypoint_id == VOGL_ENTRYPOINT_glShaderSourceARB))
2113 //int count = get_param_data(1);
2114 GLsizei count = get_param_value<GLsizei>(1);
2117 int32 *pLengths = get_param_client_memory<int32>(3);
2118 if ((pLengths) && (get_param_client_memory_data_size(3) == count * sizeof(int32)))
2120 for (GLsizei i = 0; i < count; i++)
2122 key_value_map::const_iterator it = m_key_value_map.find(i);
2123 if (it == m_key_value_map.end())
2125 vogl_error_printf("GL func %s call counter %" PRIu64 ": Failed finding shader source blob string in GL key value map\n", pGL_func_name, cur_call_counter);
2129 const uint8_vec *pBlob = it->second.get_blob();
2132 vogl_error_printf("GL func %s call counter %" PRIu64 ": Failed finding shader source blob string in GL key value map\n", pGL_func_name, cur_call_counter);
2136 uint l = pLengths[i];
2138 if (pBlob->size() != l)
2140 vogl_warning_printf("GL func %s call counter %" PRIu64 ": Shader source code line %u: blob size is %u bytes, but length field is %u bytes: Fixing up length field to match blob's size\n",
2141 pGL_func_name, cur_call_counter, static_cast<uint>(i), pBlob->size(), l);
2142 pLengths[i] = pBlob->size();
2152 //----------------------------------------------------------------------------------------------------------------------
2153 // vogl_trace_packet::pretty_print_param
2154 //----------------------------------------------------------------------------------------------------------------------
2155 bool vogl_trace_packet::pretty_print(dynamic_string &str, bool type_info) const
2165 dynamic_string return_val;
2166 if (!pretty_print_return_value(return_val, type_info))
2172 str.format("%s %s(", return_val.get_ptr(), get_entrypoint_desc().m_pName);
2174 dynamic_string param_val;
2175 for (uint i = 0; i < m_total_params; i++)
2177 if (!pretty_print_param(param_val, i, type_info))
2185 if (i != (m_total_params - 1))
2194 //----------------------------------------------------------------------------------------------------------------------
2195 // vogl_trace_packet::pretty_print_param
2196 //----------------------------------------------------------------------------------------------------------------------
2197 bool vogl_trace_packet::pretty_print_param(dynamic_string &str, uint param_index, bool type_info) const
2206 const bool is_return_param = has_return_value() && (param_index == m_total_params);
2208 VOGL_ASSERT((param_index < m_total_params) || is_return_param);
2210 uint64_t val_data = m_param_data[param_index];
2211 //uint val_size = m_param_size[param_index];
2213 const vogl_ctype_desc_t &ctype_desc = trace_ctypes()[m_param_ctype[param_index]];
2216 str.format("(%s) ", ctype_desc.m_pCType);
2218 bool handled = false;
2220 if (ctype_desc.m_is_pointer)
2222 const void *pClient_mem = NULL;
2223 uint client_mem_size = 0;
2225 if (m_client_memory_descs[param_index].m_vec_ofs >= 0)
2227 pClient_mem = &m_client_memory[m_client_memory_descs[param_index].m_vec_ofs];
2228 client_mem_size = m_client_memory_descs[param_index].m_data_size;
2231 if ((pClient_mem) && (client_mem_size))
2233 //const vogl_ctype_t pointee_ctype = ctype_desc.m_pointee_ctype;
2234 //const uint pointee_size = (*m_pCTypes)[pointee_ctype].m_size;
2235 //const bool pointee_is_ptr = (*m_pCTypes)[pointee_ctype].m_is_pointer;
2237 bool print_as_cstring = false;
2238 switch (ctype_desc.m_ctype)
2240 case VOGL_CONST_GLUBYTE_PTR:
2241 case VOGL_CONST_GLCHAR_PTR:
2242 case VOGL_GLCHARARB_PTR:
2243 case VOGL_CONST_GLBYTE_PTR:
2244 case VOGL_GLUBYTE_PTR:
2245 case VOGL_GLCHAR_PTR:
2246 case VOGL_CONST_GLCHARARB_PTR:
2248 if ((client_mem_size <= 64) && (utils::is_buffer_printable(pClient_mem, client_mem_size, true, true)))
2250 print_as_cstring = true;
2259 if (print_as_cstring)
2261 const char *pStr = reinterpret_cast<const char *>(pClient_mem);
2262 str.format_append("\"%s\"", pStr);
2270 switch (ctype_desc.m_ctype)
2273 case VOGL_GLBOOLEAN:
2280 else if (val_data == 1)
2290 const char *pName = g_gl_enums.find_name(val_data, get_entrypoint_id(), is_return_param ? -1 : param_index);
2294 VOGL_ASSERT(g_gl_enums.find_enum(pName) == val_data);
2306 str.format_append("%f", *reinterpret_cast<const float *>(&val_data));
2313 str.format_append("%f", *reinterpret_cast<const double *>(&val_data));
2323 str.format_append("%i", *reinterpret_cast<const int32 *>(&val_data));
2329 str.format_append("%i", *reinterpret_cast<const int16 *>(&val_data));
2335 str.format_append("%i", *reinterpret_cast<const int8 *>(&val_data));
2340 case VOGL_GLINT64EXT:
2342 str.format_append("%" PRIi64, val_data);
2353 if ((ctype_desc.m_is_pointer) && (!type_info))
2354 str.format_append("(%s) 0x%" PRIX64, ctype_desc.m_pCType, val_data);
2356 str.format_append("0x%" PRIX64, val_data);
2362 //----------------------------------------------------------------------------------------------------------------------
2363 // vogl_trace_packet::pretty_print_return_value
2364 //----------------------------------------------------------------------------------------------------------------------
2365 bool vogl_trace_packet::pretty_print_return_value(dynamic_string &str, bool type_info) const
2374 if (!has_return_value())
2380 pretty_print_param(str, m_total_params, type_info);
2384 //----------------------------------------------------------------------------------------------------------------------
2385 // vogl_does_packet_refer_to_program
2386 // This conservatively determines if a trace packet refers to a GL program or ARB program object (there may be some
2387 // false positives in here because ARB program and shader objects live in the same namespace).
2388 //----------------------------------------------------------------------------------------------------------------------
2389 bool vogl_does_packet_refer_to_program(const vogl_trace_packet &gl_packet, GLuint &program)
2395 gl_entrypoint_id_t entrypoint_id = gl_packet.get_entrypoint_id();
2396 const gl_entrypoint_desc_t &entrypoint_desc = gl_packet.get_entrypoint_desc();
2398 if ((entrypoint_desc.m_return_namespace == VOGL_NAMESPACE_PROGRAMS) || (entrypoint_id == VOGL_ENTRYPOINT_glCreateProgramObjectARB))
2400 program = gl_packet.get_return_value<GLuint>();
2404 for (uint i = 0; i < entrypoint_desc.m_num_params; i++)
2406 vogl_namespace_t param_namespace = g_vogl_entrypoint_param_descs[entrypoint_id][i].m_namespace;
2408 if (param_namespace == VOGL_NAMESPACE_PROGRAMS)
2410 // TODO: Make sure this never can be a ptr to an array of handles
2411 VOGL_VERIFY(!gl_packet.get_param_ctype_desc(i).m_is_pointer);
2412 program = gl_packet.get_param_value<GLuint>(i);
2416 // Special case the GL_ARB_shader_objects/GL_ARB_vertex_shader GLhandleARB, which alias programs.
2417 // We want to reject handles that are clearly shader objects, and accept everything else.
2418 if ((!i) && (param_namespace == VOGL_NAMESPACE_GLHANDLEARB))
2422 switch (entrypoint_id)
2424 case VOGL_ENTRYPOINT_glShaderSourceARB:
2425 case VOGL_ENTRYPOINT_glCompileShaderARB:
2436 // TODO: Make sure this never can be a ptr to an array of handles
2437 VOGL_VERIFY(!gl_packet.get_param_ctype_desc(i).m_is_pointer);
2438 program = gl_packet.get_param_value<GLuint>(i);
2447 //----------------------------------------------------------------------------------------------------------------------
2448 // vogl_write_glInternalTraceCommandRAD
2449 //----------------------------------------------------------------------------------------------------------------------
2450 bool vogl_write_glInternalTraceCommandRAD(data_stream &stream, const vogl_ctypes *pCTypes, GLuint cmd, GLuint size, const GLubyte *data)
2454 vogl_trace_packet packet(pCTypes);
2456 packet.begin_construction(VOGL_ENTRYPOINT_glInternalTraceCommandRAD, 0, 0, 0, utils::RDTSC());
2458 uint64_t cur_rdtsc = utils::RDTSC();
2459 packet.set_gl_begin_rdtsc(cur_rdtsc);
2460 packet.set_gl_end_rdtsc(cur_rdtsc + 1);
2462 packet.set_param(0, VOGL_GLUINT, &cmd, sizeof(cmd));
2463 packet.set_param(1, VOGL_GLUINT, &size, sizeof(size));
2465 vogl_trace_ptr_value ptr_val = reinterpret_cast<vogl_trace_ptr_value>(data);
2466 packet.set_param(2, VOGL_CONST_GLUBYTE_PTR, &ptr_val, packet.get_ctypes()->get_pointer_size());
2470 case cITCRDemarcation:
2474 case cITCRKeyValueMap:
2476 if ((size == sizeof(key_value_map)) && (data))
2478 // Directly jam in the key value map, so it properly serializes as readable JSON.
2479 packet.get_key_value_map() = *reinterpret_cast<const key_value_map *>(data);
2490 vogl_error_printf("%s: Unknown trace command type %u\n", VOGL_FUNCTION_NAME, cmd);
2496 packet.end_construction(utils::RDTSC());
2498 return packet.serialize(stream);