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_gl_replayer.cpp
27 #include "vogl_gl_replayer.h"
28 #include "vogl_general_context_state.h"
29 #include "vogl_sync_object.h"
30 #include "vogl_trace_file_writer.h"
31 #include "vogl_texture_format.h"
32 #include "gl_glx_replay_helper_macros.inc"
33 #include "vogl_backtrace.h"
35 #define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
36 #include "vogl_miniz.h"
38 #include "vogl_timer.h"
39 #include "vogl_file_utils.h"
41 #include "vogl_vector.h"
43 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC 129
44 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC 0x12345678
45 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC -999999.0f
47 //----------------------------------------------------------------------------------------------------------------------
48 // glInterleavedArrays helper table
49 //----------------------------------------------------------------------------------------------------------------------
50 struct interleaved_array_desc_entry_t
66 #define _2f (sizeof(GLfloat) * 2)
67 #define _3f (sizeof(GLfloat) * 3)
68 #define _4f (sizeof(GLfloat) * 4)
69 #define _5f (sizeof(GLfloat) * 5)
70 #define _6f (sizeof(GLfloat) * 6)
71 #define _7f (sizeof(GLfloat) * 7)
72 #define _8f (sizeof(GLfloat) * 8)
73 #define _9f (sizeof(GLfloat) * 9)
74 #define _10f (sizeof(GLfloat) * 10)
75 #define _11f (sizeof(GLfloat) * 11)
76 #define _12f (sizeof(GLfloat) * 12)
77 #define _15f (sizeof(GLfloat) * 15)
78 #define _c (sizeof(GL_UNSIGNED_BYTE) * 4)
80 static const interleaved_array_desc_entry_t vogl_g_interleaved_array_descs[] =
82 // format et ec en st sc sv tc pc pn pv s
83 { GL_V2F, false, false, false, 0, 0, 2, 0, 0, 0, 0, _2f },
84 { GL_V3F, false, false, false, 0, 0, 3, 0, 0, 0, 0, _3f },
85 { GL_C4UB_V2F, false, true, false, 0, 4, 2, GL_UNSIGNED_BYTE, 0, 0, _c, _c + _2f },
86 { GL_C4UB_V3F, false, true, false, 0, 4, 3, GL_UNSIGNED_BYTE, 0, 0, _c, _c + _3f },
87 { GL_C3F_V3F, false, true, false, 0, 3, 3, GL_FLOAT, 0, 0, _3f, _6f },
88 { GL_N3F_V3F, false, false, true, 0, 0, 3, 0, 0, 0, _3f, _6f },
89 { GL_C4F_N3F_V3F, false, true, true, 0, 4, 3, GL_FLOAT, 0, _4f, _7f, _10f },
90 { GL_T2F_V3F, true, false, false, 2, 0, 3, 0, 0, 0, _2f, _5f },
91 { GL_T4F_V4F, true, false, false, 4, 0, 4, 0, 0, 0, _4f, _8f },
92 { GL_T2F_C4UB_V3F, true, true, false, 2, 4, 3, GL_UNSIGNED_BYTE, _2f, 0, _c + _2f, _c + _5f },
93 { GL_T2F_C3F_V3F, true, true, false, 2, 3, 3, GL_FLOAT, 0, _2f, _5f, _8f },
94 { GL_T2F_N3F_V3F, true, false, true, 2, 0, 3, 0, 0, _2f, _5f, _8f },
95 { GL_T2F_C4F_N3F_V3F, true, true, true, 2, 4, 3, GL_FLOAT, _2f, _6f, _9f, _12f },
96 { GL_T4F_C4F_N3F_V4F, true, true, true, 4, 4, 4, GL_FLOAT, _4f, _8f, _11f, _15f }
113 #define VOGL_INTERLEAVED_ARRAY_SIZE (sizeof(vogl_g_interleaved_array_descs) / sizeof(vogl_g_interleaved_array_descs[0]))
115 //----------------------------------------------------------------------------------------------------------------------
116 // vogl_replayer::vogl_replayer
117 //----------------------------------------------------------------------------------------------------------------------
118 vogl_gl_replayer::vogl_gl_replayer()
120 m_swap_sleep_time(0),
121 m_dump_framebuffer_on_draw_prefix("screenshot"),
122 m_screenshot_prefix("screenshot"),
123 m_dump_framebuffer_on_draw_frame_index(-1),
124 m_dump_framebuffer_on_draw_first_gl_call_index(-1),
125 m_dump_framebuffer_on_draw_last_gl_call_index(-1),
126 m_ctypes_packet(&m_trace_gl_ctypes),
127 m_trace_pointer_size_in_bytes(0),
128 m_trace_pointer_size_in_uints(0),
129 m_temp_gl_packet(&m_trace_gl_ctypes),
130 m_temp2_gl_packet(&m_trace_gl_ctypes),
131 m_pCur_gl_packet(NULL),
133 m_pending_make_current_packet(&m_trace_gl_ctypes),
134 m_pending_window_resize_width(0),
135 m_pending_window_resize_height(0),
136 m_pending_window_resize_attempt_counter(false),
139 m_last_parsed_call_counter(-1),
140 m_last_processed_call_counter(-1),
141 m_cur_trace_context(0),
142 m_cur_replay_context(NULL),
143 m_pCur_context_state(NULL),
144 m_frame_draw_counter(0),
145 m_frame_draw_counter_kill_threshold(cUINT64_MAX),
147 m_pBlob_manager(NULL),
148 m_pPending_snapshot(NULL),
149 m_delete_pending_snapshot_after_applying(false),
150 m_replay_to_trace_remapper(*this)
154 m_trace_gl_ctypes.init();
157 //----------------------------------------------------------------------------------------------------------------------
158 // vogl_replayer::~vogl_replayer
159 //----------------------------------------------------------------------------------------------------------------------
160 vogl_gl_replayer::~vogl_gl_replayer()
167 //----------------------------------------------------------------------------------------------------------------------
168 // vogl_replayer::init
169 //----------------------------------------------------------------------------------------------------------------------
170 bool vogl_gl_replayer::init(uint flags, vogl_replay_window *pWindow, const vogl_trace_stream_start_of_file_packet &sof_packet, const vogl_blob_manager &blob_manager)
177 if ((!pWindow) || (!pWindow->is_opened()))
183 if ((sof_packet.m_pointer_sizes != sizeof(uint32)) && (sof_packet.m_pointer_sizes != sizeof(uint64_t)))
185 vogl_error_printf("%s: Invalid trace pointer size (%u)\n", VOGL_METHOD_NAME, m_sof_packet.m_pointer_sizes);
189 m_pBlob_manager = &blob_manager;
193 m_sof_packet = sof_packet;
194 m_trace_pointer_size_in_bytes = m_sof_packet.m_pointer_sizes;
195 m_trace_pointer_size_in_uints = m_sof_packet.m_pointer_sizes / sizeof(uint);
197 m_trace_gl_ctypes.init();
198 m_trace_gl_ctypes.change_pointer_sizes(m_trace_pointer_size_in_bytes);
200 if (!m_pWindow->is_opened())
202 const uint initial_window_width = 1024;
203 const uint initial_window_height = 768;
204 if (!m_pWindow->open(initial_window_width, initial_window_height))
206 vogl_error_printf("%s: Failed opening window!\n", VOGL_METHOD_NAME);
211 m_pCur_gl_packet = NULL;
215 m_last_parsed_call_counter = 0;
216 m_last_processed_call_counter = 0;
218 m_pending_make_current_packet.clear();
219 m_pending_window_resize_width = 0;
220 m_pending_window_resize_height = 0;
221 m_pending_window_resize_attempt_counter = 0;
223 m_at_frame_boundary = true;
225 m_cur_trace_context = 0;
226 m_cur_replay_context = 0;
227 m_pCur_context_state = NULL;
231 m_frame_draw_counter = 0;
232 m_frame_draw_counter_kill_threshold = cUINT64_MAX;
239 //----------------------------------------------------------------------------------------------------------------------
240 // vogl_replayer::deinit
241 //----------------------------------------------------------------------------------------------------------------------
242 void vogl_gl_replayer::deinit()
246 destroy_pending_snapshot();
249 // TODO: Make a 1st class snapshot cache class
250 for (uint i = 0; i < m_snapshots.size(); i++)
251 vogl_delete(m_snapshots[i].m_pSnapshot);
254 m_ctypes_packet.reset();
256 m_pCur_gl_packet = NULL;
260 m_last_parsed_call_counter = 0;
261 m_last_processed_call_counter = 0;
263 m_pending_make_current_packet.clear();
264 m_pending_window_resize_width = 0;
265 m_pending_window_resize_height = 0;
266 m_pending_window_resize_attempt_counter = 0;
268 m_at_frame_boundary = true;
270 m_cur_trace_context = 0;
271 m_cur_replay_context = 0;
272 m_pCur_context_state = NULL;
274 m_frame_draw_counter = 0;
275 m_frame_draw_counter_kill_threshold = cUINT32_MAX;
277 m_pBlob_manager = NULL;
280 m_swap_sleep_time = 0;
281 m_dump_framebuffer_on_draw_prefix = "screenshot";
282 m_screenshot_prefix = "screenshot";
283 m_backbuffer_hash_filename.clear();
284 m_dump_framebuffer_on_draw_frame_index = -1;
285 m_dump_framebuffer_on_draw_first_gl_call_index = -1;
286 m_dump_framebuffer_on_draw_last_gl_call_index = -1;
288 m_dump_frontbuffer_filename.clear();
293 //----------------------------------------------------------------------------------------------------------------------
294 // vogl_gl_replayer::dump_trace_gl_packet_debug_info
295 //----------------------------------------------------------------------------------------------------------------------
296 void vogl_gl_replayer::dump_trace_gl_packet_debug_info(const vogl_trace_gl_entrypoint_packet &gl_packet)
300 vogl_debug_printf("Trace packet: Total size %u, Param size: %u, Client mem size %u, Name value size %u, call %" PRIu64 ", ID: %s (%u), Thread ID: 0x%" PRIX64 ", Trace Context: 0x%" PRIX64 "\n",
302 gl_packet.m_param_size,
303 gl_packet.m_client_memory_size,
304 gl_packet.m_name_value_map_size,
305 gl_packet.m_call_counter,
306 g_vogl_entrypoint_descs[gl_packet.m_entrypoint_id].m_pName,
307 gl_packet.m_entrypoint_id,
308 gl_packet.m_thread_id,
309 gl_packet.m_context_handle);
312 //----------------------------------------------------------------------------------------------------------------------
313 // vogl_gl_replayer::dump_packet_as_func_call
314 //----------------------------------------------------------------------------------------------------------------------
315 void vogl_gl_replayer::dump_packet_as_func_call(const vogl_trace_packet& trace_packet)
321 if (!trace_packet.pretty_print(str, false))
322 vogl_error_printf("%s: packet pretty print failed!\n", VOGL_METHOD_NAME);
324 vogl_debug_printf("%s\n", str.get_ptr());
327 //----------------------------------------------------------------------------------------------------------------------
328 // vogl_replayer::process_next_packet
329 //----------------------------------------------------------------------------------------------------------------------
330 vogl_gl_replayer::status_t vogl_gl_replayer::process_next_packet(const vogl_trace_packet &gl_packet)
332 // TODO: Fix const correctness
333 return process_gl_entrypoint_packet((vogl_trace_packet &)gl_packet);
336 //----------------------------------------------------------------------------------------------------------------------
337 // vogl_replayer::process_next_packet
338 //----------------------------------------------------------------------------------------------------------------------
339 vogl_gl_replayer::status_t vogl_gl_replayer::process_next_packet(vogl_trace_file_reader &trace_reader)
343 vogl_trace_file_reader::trace_file_reader_status_t read_status = trace_reader.read_next_packet();
344 if (read_status == vogl_trace_file_reader::cEOF)
346 vogl_message_printf("At trace file EOF\n");
349 else if (read_status != vogl_trace_file_reader::cOK)
351 vogl_error_printf("Failed reading from trace file\n");
352 return cStatusHardFailure;
355 status_t status = cStatusOK;
357 switch (trace_reader.get_packet_type())
364 case cTSPTGLEntrypoint:
366 if (!m_temp_gl_packet.deserialize(trace_reader.get_packet_buf().get_ptr(), trace_reader.get_packet_buf().size(), false))
368 vogl_error_printf("Failed deserializing GL entrypoint packet\n");
369 status = cStatusHardFailure;
373 status = process_next_packet(m_temp_gl_packet);
379 vogl_message_printf("Encountered EOF packet in trace file\n");
380 status = cStatusAtEOF;
385 vogl_error_printf("Encountered unknown packet type in trace file\n");
386 status = cStatusSoftFailure;
393 vogl_error_printf("%s: %s failure processing GL entrypoint packet\n", VOGL_METHOD_NAME, (status == cStatusHardFailure) ? "Hard" : "Soft");
399 //----------------------------------------------------------------------------------------------------------------------
400 // vogl_replayer::process_pending_window_resize
401 //----------------------------------------------------------------------------------------------------------------------
402 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_window_resize(bool *pApplied_snapshot)
406 if (pApplied_snapshot)
407 *pApplied_snapshot = false;
409 status_t status = cStatusOK;
411 if (get_has_pending_window_resize())
413 status = process_frame_check_for_pending_window_resize();
414 if (status != cStatusOK)
418 if (m_pPending_snapshot)
420 if (pApplied_snapshot)
421 *pApplied_snapshot = true;
423 status_t status = process_applying_pending_snapshot();
424 if (status != cStatusOK)
431 //----------------------------------------------------------------------------------------------------------------------
432 // vogl_replayer::process_frame
433 //----------------------------------------------------------------------------------------------------------------------
434 vogl_gl_replayer::status_t vogl_gl_replayer::process_frame(vogl_trace_file_reader &trace_reader)
438 status_t status = cStatusOK;
442 status = process_next_packet(trace_reader);
443 if ((status == cStatusNextFrame) || (status == cStatusResizeWindow) || (status == cStatusAtEOF) || (status == cStatusHardFailure))
450 //----------------------------------------------------------------------------------------------------------------------
451 // vogl_replayer::process_event
452 //----------------------------------------------------------------------------------------------------------------------
453 bool vogl_gl_replayer::update_window_dimensions()
457 m_pWindow->update_dimensions();
462 //----------------------------------------------------------------------------------------------------------------------
463 // vogl_gl_replayer::dump_frontbuffer_screenshot_before_next_swap
464 //----------------------------------------------------------------------------------------------------------------------
465 bool vogl_gl_replayer::dump_frontbuffer_screenshot_before_next_swap(const dynamic_string &filename)
467 m_dump_frontbuffer_filename = filename;
472 //----------------------------------------------------------------------------------------------------------------------
473 // vogl_gl_replayer::dump_frontbuffer_to_file
474 //----------------------------------------------------------------------------------------------------------------------
475 bool vogl_gl_replayer::dump_frontbuffer_to_file(const dynamic_string &filename)
477 if ((!m_is_valid) || (!m_pWindow))
483 uint width = 0, height = 0;
484 m_pWindow->get_actual_dimensions(width, height);
486 m_screenshot_buffer.resize(width * height * 3);
488 bool success = vogl_copy_buffer_to_image(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size(), width, height, GL_RGB, GL_UNSIGNED_BYTE, false, 0, GL_FRONT);
491 vogl_error_printf("%s: Failed calling glReadPixels() to take frontbuffer screenshot!\n", VOGL_METHOD_NAME);
496 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
498 success = file_utils::write_buf_to_file(filename.get_ptr(), pPNG_data, png_size);
501 vogl_error_printf("%s: Failed writing PNG screenshot to file \"%s\"\n", filename.get_ptr(), VOGL_METHOD_NAME);
505 vogl_message_printf("Wrote PNG screenshot to file \"%s\"\n", filename.get_ptr());
513 //----------------------------------------------------------------------------------------------------------------------
514 // vogl_replayer::trigger_pending_window_resize
515 //----------------------------------------------------------------------------------------------------------------------
516 vogl_gl_replayer::status_t vogl_gl_replayer::trigger_pending_window_resize(uint win_width, uint win_height)
520 m_pending_window_resize_width = win_width;
521 m_pending_window_resize_height = win_height;
522 m_pending_window_resize_attempt_counter = 0;
523 m_time_since_pending_window_resize.start();
525 m_pWindow->resize(win_width, win_height);
527 if (m_flags & cGLReplayerVerboseMode)
528 vogl_debug_printf("%s: Waiting for window to resize to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
530 return cStatusResizeWindow;
533 //----------------------------------------------------------------------------------------------------------------------
534 // vogl_replayer::clear_pending_window_resize
535 //----------------------------------------------------------------------------------------------------------------------
536 void vogl_gl_replayer::clear_pending_window_resize()
540 m_pending_window_resize_width = 0;
541 m_pending_window_resize_height = 0;
542 m_pending_window_resize_attempt_counter = 0;
545 //----------------------------------------------------------------------------------------------------------------------
546 // vogl_replayer::process_frame_check_for_pending_window_resize
547 //----------------------------------------------------------------------------------------------------------------------
548 vogl_gl_replayer::status_t vogl_gl_replayer::process_frame_check_for_pending_window_resize()
552 const uint cMaxSecsToWait = 5;
554 if (!get_has_pending_window_resize())
557 if (m_pending_window_resize_attempt_counter >= cMaxSecsToWait)
559 vogl_warning_printf("Waited too long for window to resize to %ux%u, giving up and continuing replay\n", get_pending_window_resize_width(), get_pending_winow_resize_height());
561 clear_pending_window_resize();
566 uint win_width = 0, win_height = 0;
567 m_pWindow->get_actual_dimensions(win_width, win_height);
569 if ((win_width != get_pending_window_resize_width()) ||
570 (win_height != get_pending_winow_resize_height()))
572 if (m_time_since_pending_window_resize.get_elapsed_secs() < 1.0f)
574 // sleep 1ms, then retry
576 return cStatusResizeWindow;
579 // What could possibly go wrong?
580 m_pending_window_resize_attempt_counter++;
581 if (m_pending_window_resize_attempt_counter < cMaxSecsToWait)
583 m_pWindow->resize(get_pending_window_resize_width(), get_pending_winow_resize_height());
585 m_time_since_pending_window_resize.start();
587 vogl_warning_printf("Waiting up to 5 secs for window to resize to %ux%u\n", get_pending_window_resize_width(), get_pending_winow_resize_height());
588 return cStatusResizeWindow;
592 clear_pending_window_resize();
593 m_pWindow->update_dimensions();
598 //----------------------------------------------------------------------------------------------------------------------
599 // vogl_replayer::destroy_pending_snapshot
600 //----------------------------------------------------------------------------------------------------------------------
601 void vogl_gl_replayer::destroy_pending_snapshot()
605 if (m_pPending_snapshot)
607 if (m_delete_pending_snapshot_after_applying)
609 // Ensure the snapshot cache can't be pointing to the snapshot, just to be safe.
610 // TODO: Make this a real class damn it.
611 for (uint i = 0; i < m_snapshots.size(); i++)
613 if (m_snapshots[i].m_pSnapshot == m_pPending_snapshot)
615 m_snapshots.erase(i);
620 vogl_delete(const_cast<vogl_gl_state_snapshot *>(m_pPending_snapshot));
623 m_pPending_snapshot = NULL;
626 m_delete_pending_snapshot_after_applying = false;
629 //----------------------------------------------------------------------------------------------------------------------
630 // vogl_replayer::check_gl_error
631 // Returns *true* on error, just like vogl_check_gl_error()
632 //----------------------------------------------------------------------------------------------------------------------
633 bool vogl_gl_replayer::check_gl_error_internal(bool quietly, const char *pFile, uint line, const char *pFunc)
640 // http://www.opengl.org/sdk/docs/man/xhtml/glGetError.xml
641 // "Thus, glGetError should always be called in a loop, until it returns GL_NO_ERROR, if all error flags are to be reset."
642 GLenum gl_err = GL_ENTRYPOINT(glGetError)();
643 if (gl_err == GL_NO_ERROR)
648 process_entrypoint_warning("%s: GL error: 0x%08X (%u): %s (Called from File: %s Line: %u Func: %s)\n", VOGL_METHOD_NAME, gl_err, gl_err, g_gl_enums.find_name("ErrorCode", gl_err), pFile ? pFile : "?", line, pFunc ? pFunc : "?");
657 //----------------------------------------------------------------------------------------------------------------------
658 // vogl_replayer::clear_contexts
659 //----------------------------------------------------------------------------------------------------------------------
660 void vogl_gl_replayer::clear_contexts()
664 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
666 context_state *pContext_state = it->second;
668 vogl_delete(pContext_state);
673 m_cur_trace_context = 0;
674 m_cur_replay_context = NULL;
675 m_pCur_context_state = NULL;
678 //----------------------------------------------------------------------------------------------------------------------
679 // vogl_replayer::destroy_contexts
680 //----------------------------------------------------------------------------------------------------------------------
681 void vogl_gl_replayer::destroy_contexts()
685 if ((m_contexts.size()) && (m_pWindow->get_display()) && (GL_ENTRYPOINT(glXMakeCurrent)) && (GL_ENTRYPOINT(glXDestroyContext)))
687 GL_ENTRYPOINT(glXMakeCurrent)(m_pWindow->get_display(), (GLXDrawable)NULL, NULL);
689 vogl::vector<context_state *> contexts_to_destroy;
690 for (context_hash_map::const_iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
691 contexts_to_destroy.push_back(it->second);
693 // Delete "tail" contexts (ones that are not referenced by any other context) in sharegroups first.
694 while (contexts_to_destroy.size())
696 for (int i = 0; i < static_cast<int>(contexts_to_destroy.size()); i++)
698 context_state *pContext_state = contexts_to_destroy[i];
700 vogl_trace_ptr_value trace_context = pContext_state->m_context_desc.get_trace_context();
702 bool skip_context = false;
703 for (int j = 0; j < static_cast<int>(contexts_to_destroy.size()); j++)
708 if (contexts_to_destroy[j]->m_context_desc.get_trace_share_context() == trace_context)
718 // This context may have been the sharegroup's root and could have been already deleted.
719 if (!pContext_state->m_deleted)
721 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), pContext_state->m_replay_context);
724 contexts_to_destroy.erase(i);
733 //----------------------------------------------------------------------------------------------------------------------
734 // vogl_replayer::define_new_context
735 //----------------------------------------------------------------------------------------------------------------------
736 vogl_gl_replayer::context_state *vogl_gl_replayer::define_new_context(
737 vogl_trace_context_ptr_value trace_context, GLXContext replay_context, vogl_trace_context_ptr_value trace_share_context, GLboolean direct, gl_entrypoint_id_t creation_func, const int *pAttrib_list, uint attrib_list_size)
741 if ((!trace_context) || (!replay_context))
747 context_state *pContext_state = vogl_new(context_state, *this);
749 pContext_state->m_trace_context = trace_context;
750 pContext_state->m_replay_context = replay_context;
752 pContext_state->m_context_desc.init(creation_func, direct, trace_context, trace_share_context, vogl_context_attribs(pAttrib_list, attrib_list_size));
754 if (trace_share_context)
756 for (context_hash_map::const_iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
758 if (trace_share_context == it->first)
760 context_state *pShare_context = it->second;
761 while (!pShare_context->is_root_context())
762 pShare_context = pShare_context->m_pShared_state;
764 pContext_state->m_pShared_state = pShare_context;
765 pContext_state->m_pShared_state->m_ref_count++;
771 if (!pContext_state->m_pShared_state)
773 process_entrypoint_error("%s: Unable to find trace share context handle 0x%" PRIX64 "!\n", VOGL_METHOD_NAME, trace_share_context);
777 m_contexts.insert(trace_context, pContext_state);
779 return pContext_state;
782 //----------------------------------------------------------------------------------------------------------------------
783 // vogl_replayer::remap_context
784 //----------------------------------------------------------------------------------------------------------------------
785 GLXContext vogl_gl_replayer::remap_context(vogl_trace_context_ptr_value trace_context)
792 context_hash_map::iterator it = m_contexts.find(trace_context);
793 return (it == m_contexts.end()) ? NULL : it->second->m_replay_context;
796 //----------------------------------------------------------------------------------------------------------------------
797 // vogl_replayer::destroy_context
798 //----------------------------------------------------------------------------------------------------------------------
799 bool vogl_gl_replayer::destroy_context(vogl_trace_context_ptr_value trace_context)
803 VOGL_ASSERT(trace_context);
805 context_hash_map::iterator it = m_contexts.find(trace_context);
806 if (it == m_contexts.end())
809 context_state *pContext_state = it->second;
810 VOGL_ASSERT(pContext_state->m_ref_count >= 1);
811 VOGL_ASSERT(!pContext_state->m_deleted);
813 if (pContext_state->is_share_context())
815 VOGL_ASSERT(pContext_state->m_ref_count == 1);
817 context_state *pShare_context = pContext_state->m_pShared_state;
818 VOGL_ASSERT(pShare_context->m_ref_count >= 1);
820 pShare_context->m_ref_count--;
821 if (!pShare_context->m_ref_count)
823 VOGL_ASSERT(pShare_context->m_deleted);
825 vogl_trace_context_ptr_value trace_share_context = pShare_context->m_context_desc.get_trace_context();
827 vogl_delete(pShare_context);
829 bool removed = m_contexts.erase(trace_share_context);
830 VOGL_NOTE_UNUSED(removed);
831 VOGL_ASSERT(removed);
834 vogl_delete(pContext_state);
836 bool removed = m_contexts.erase(trace_context);
837 VOGL_NOTE_UNUSED(removed);
838 VOGL_ASSERT(removed);
842 pContext_state->m_deleted = true;
843 pContext_state->m_ref_count--;
845 if (!pContext_state->m_ref_count)
849 vogl_delete(pContext_state);
851 bool removed = m_contexts.erase(trace_context);
852 VOGL_NOTE_UNUSED(removed);
853 VOGL_ASSERT(removed);
860 //----------------------------------------------------------------------------------------------------------------------
861 // vogl_replayer::set_client_side_array_data
862 // glVertexPointer, glNormalPointer, etc. client side data
863 //----------------------------------------------------------------------------------------------------------------------
864 bool vogl_gl_replayer::set_client_side_array_data(const key_value_map &map, GLuint start, GLuint end, GLuint basevertex)
868 // TODO: Add early out
869 GLint prev_client_active_texture = 0;
870 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &prev_client_active_texture);
872 const uint tex_coords = math::minimum<uint>(m_pCur_context_state->m_context_info.is_core_profile() ? m_pCur_context_state->m_context_info.get_max_texture_units() : m_pCur_context_state->m_context_info.get_max_texture_coords(), VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS);
874 for (uint client_array_iter = 0; client_array_iter < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS; client_array_iter++)
876 const vogl_client_side_array_desc_t &desc = g_vogl_client_side_array_descs[client_array_iter];
878 const bool is_texcoord_array = (client_array_iter == vogl_texcoord_pointer_array_id);
881 uint base_key_index = 0x1000 + client_array_iter;
883 // Special case texcoord pointers, which are accessed via the client active texture.
884 if (is_texcoord_array)
887 base_key_index = 0x2000;
890 for (uint inner_iter = 0; inner_iter < n; inner_iter++)
892 uint key_index = base_key_index + inner_iter;
894 const uint8_vec *pVertex_blob = map.get_blob(static_cast<uint16>(key_index));
895 // TODO: Check for case where blob (or map) is not present, but they still access client side data, this is a bad error
899 if (is_texcoord_array)
901 GL_ENTRYPOINT(glClientActiveTexture)(GL_TEXTURE0 + inner_iter);
904 GLboolean is_enabled = GL_ENTRYPOINT(glIsEnabled)(desc.m_is_enabled);
909 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_binding, &binding);
914 GL_ENTRYPOINT(glGetPointerv)(desc.m_get_pointer, &ptr);
918 uint8_vec &array_data = is_texcoord_array ? m_client_side_texcoord_data[inner_iter] : m_client_side_array_data[client_array_iter];
919 if (ptr != array_data.get_ptr())
925 GLint type = GL_BOOL;
928 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_type, &type);
932 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_stride, &stride);
937 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_size, &size);
940 uint type_size = vogl_get_gl_type_size(type);
943 process_entrypoint_error("%s: Can't determine type size of enabled client side array set by func %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
947 if ((desc.m_entrypoint == VOGL_ENTRYPOINT_glIndexPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glIndexPointerEXT) ||
948 (desc.m_entrypoint == VOGL_ENTRYPOINT_glFogCoordPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glFogCoordPointerEXT) ||
949 (desc.m_entrypoint == VOGL_ENTRYPOINT_glEdgeFlagPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glEdgeFlagPointerEXT))
953 else if ((desc.m_entrypoint == VOGL_ENTRYPOINT_glNormalPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glNormalPointerEXT))
957 else if ((size < 1) && (size > 4))
959 process_entrypoint_error("%s: Size of client side array set by func %s must be between 1 and 4\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
964 stride = type_size * size;
966 uint first_vertex_ofs = (start + basevertex) * stride;
967 uint last_vertex_ofs = (end + basevertex) * stride;
968 uint vertex_data_size = (last_vertex_ofs + stride) - first_vertex_ofs;
969 uint total_data_size = last_vertex_ofs + stride;
974 process_entrypoint_error("%s: Failed finding client side vertex data blob set by func %s \n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
980 if (vertex_data_size != pVertex_blob->size())
982 process_entrypoint_error("%s: %s will access more client side data (%u bytes) than stored in the trace (%u bytes), using what is in the trace and using zeros for the rest\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName, vertex_data_size, pVertex_blob->size());
983 temp_blob = *pVertex_blob;
984 temp_blob.resize(vertex_data_size);
985 pVertex_blob = &temp_blob;
988 uint bytes_remaining_at_end = math::maximum<int>(0, (int)VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE - (int)first_vertex_ofs);
989 uint bytes_to_copy = math::minimum<uint>(pVertex_blob->size(), bytes_remaining_at_end);
990 if (bytes_to_copy != pVertex_blob->size())
992 // Can't resize buffer, it could move and that would invalidate any VAO pointer bindings.
993 process_entrypoint_error("%s: %s accesses too much client side data (%u bytes), increase VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName, first_vertex_ofs + total_data_size);
996 VOGL_ASSERT((first_vertex_ofs + bytes_to_copy) <= array_data.size());
998 memcpy(array_data.get_ptr() + first_vertex_ofs, pVertex_blob->get_ptr(), bytes_to_copy);
1002 GL_ENTRYPOINT(glClientActiveTexture)(prev_client_active_texture);
1007 //----------------------------------------------------------------------------------------------------------------------
1008 // vogl_replayer::set_client_side_vertex_attrib_array_data
1009 // glVertexAttrib client side data
1010 //----------------------------------------------------------------------------------------------------------------------
1011 bool vogl_gl_replayer::set_client_side_vertex_attrib_array_data(const key_value_map &map, GLuint start, GLuint end, GLuint basevertex)
1015 // TODO: Add early out
1017 for (int vertex_attrib_index = 0; vertex_attrib_index < static_cast<int>(m_pCur_context_state->m_context_info.get_max_vertex_attribs()); vertex_attrib_index++)
1019 const uint8_vec *pVertex_blob = map.get_blob(static_cast<uint16>(vertex_attrib_index));
1021 // TODO: Check for case where blob (or map) is not present, but they still access client side data, this is a bad error
1026 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
1031 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &cur_buf);
1035 GLvoid *attrib_ptr = NULL;
1036 GL_ENTRYPOINT(glGetVertexAttribPointerv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &attrib_ptr);
1040 if (attrib_ptr != m_client_side_vertex_attrib_data[vertex_attrib_index].get_ptr())
1046 GLint attrib_size = 0;
1047 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &attrib_size);
1049 GLint attrib_type = 0;
1050 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &attrib_type);
1052 GLint attrib_stride = 0;
1053 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attrib_stride);
1058 process_entrypoint_error("%s: Failed finding client side vertex data blob for generic vertex attrib %u\n", VOGL_METHOD_NAME, vertex_attrib_index);
1064 if ((attrib_size != GL_BGRA) && (attrib_size < 1) && (attrib_size > 4))
1066 process_entrypoint_error("%s: Enabled vertex attribute index %i has invalid size 0x%0X\n", VOGL_METHOD_NAME, vertex_attrib_index, attrib_size);
1069 if ((attrib_size >= 1) && (attrib_size <= 4))
1070 num_comps = attrib_size;
1072 uint type_size = vogl_get_gl_type_size(attrib_type);
1075 process_entrypoint_error("%s: Vertex attribute index %i has unsupported type 0x%0X\n", VOGL_METHOD_NAME, vertex_attrib_index, attrib_type);
1079 uint stride = attrib_stride ? attrib_stride : (type_size * num_comps);
1081 uint first_vertex_ofs = (start + basevertex) * stride;
1082 uint last_vertex_ofs = (end + basevertex) * stride;
1083 uint vertex_data_size = (last_vertex_ofs + stride) - first_vertex_ofs;
1084 uint total_data_size = last_vertex_ofs + stride;
1086 uint8_vec temp_blob;
1087 if (vertex_data_size != pVertex_blob->size())
1089 process_entrypoint_error("%s: Vertex attribute index %i will access more client side data (%u bytes) than stored in the trace (%u bytes), using what is in the trace and using zeros for the rest\n", VOGL_METHOD_NAME, vertex_attrib_index, vertex_data_size, pVertex_blob->size());
1090 temp_blob = *pVertex_blob;
1091 temp_blob.resize(vertex_data_size);
1092 pVertex_blob = &temp_blob;
1095 uint bytes_remaining_at_end = math::maximum<int>(0, (int)VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE - (int)first_vertex_ofs);
1096 uint bytes_to_copy = math::minimum<uint>(pVertex_blob->size(), bytes_remaining_at_end);
1097 if (bytes_to_copy != pVertex_blob->size())
1099 // Can't resize buffer, it could move and that would invalidate any VAO pointer bindings.
1100 process_entrypoint_error("%s: Vertex attribute index %i accesses too much client side data (%u bytes), increase VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE\n", VOGL_METHOD_NAME, vertex_attrib_index, first_vertex_ofs + total_data_size);
1103 VOGL_ASSERT((first_vertex_ofs + bytes_to_copy) <= m_client_side_vertex_attrib_data[vertex_attrib_index].size());
1105 memcpy(m_client_side_vertex_attrib_data[vertex_attrib_index].get_ptr() + first_vertex_ofs, pVertex_blob->get_ptr(), bytes_to_copy);
1111 //----------------------------------------------------------------------------------------------------------------------
1112 // vogl_replayer::draw_elements_client_side_array_setup
1113 //----------------------------------------------------------------------------------------------------------------------
1114 bool vogl_gl_replayer::draw_elements_client_side_array_setup(
1120 vogl_trace_ptr_value trace_indices_ptr_value, const GLvoid *&pIndices,
1122 bool has_valid_start_end,
1127 VOGL_NOTE_UNUSED(mode);
1131 GLuint element_array_buffer = 0;
1132 uint index_size = 0;
1135 index_size = vogl_get_gl_type_size(type);
1138 process_entrypoint_error("%s: Invalid type parameter 0x%08X\n", VOGL_METHOD_NAME, type);
1142 element_array_buffer = vogl_get_bound_gl_buffer(GL_ELEMENT_ARRAY_BUFFER);
1143 if (element_array_buffer)
1145 // trace_indices_ptr_value is actually an offset into the buffer, not a real trace ptr
1146 pIndices = reinterpret_cast<GLvoid *>(trace_indices_ptr_value);
1152 process_entrypoint_warning("%s: count parameter is <= 0 (%i)\n", VOGL_METHOD_NAME, count);
1156 const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
1159 if ((indexed) && (!element_array_buffer) && (trace_indices_ptr_value))
1161 process_entrypoint_error("%s: No element array buffer is bound, but key value map doesn't have an indices blob. Can't remap indices pointer!\n", VOGL_METHOD_NAME);
1162 if (trace_indices_ptr_value)
1164 // We can't remap the pointer to valid memory, so give up.
1169 // TODO: Check for client side array usage but no data in blob (which would be a desync or error)
1173 // TODO: If a VAO is bound, client side data isn't supported according to this:
1174 // http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
1176 //GLint current_vertex_array_binding = 0;
1177 //ACTUAL_GL_ENTRYPOINT(glGetIntegerv)(GL_VERTEX_ARRAY_BINDING, ¤t_vertex_array_binding);
1179 if ((indexed) && (!element_array_buffer))
1181 const uint8_vec *pIndices_vec = map.get_blob(string_hash("indices"));
1184 process_entrypoint_error("%s: No element array buffer is bound, but key value map doesn't have an indices blob\n", VOGL_METHOD_NAME);
1188 pIndices = pIndices_vec->get_ptr();
1191 process_entrypoint_error("%s: No element array buffer is bound, but key value map has an empty indices blob\n", VOGL_METHOD_NAME);
1195 if ((pIndices_vec->size() / index_size) != static_cast<uint>(count))
1197 process_entrypoint_error("%s: Client side index data blob stored in packet is too small (wanted %u indices, got %u indices)\n", VOGL_METHOD_NAME, count, pIndices_vec->size() / index_size);
1202 if ((indexed) && (!has_valid_start_end))
1204 uint total_index_data_size = count * index_size;
1206 const uint8 *pIndices_to_scan = static_cast<const uint8 *>(pIndices);
1208 if (element_array_buffer)
1210 if (m_index_data.size() < total_index_data_size)
1211 m_index_data.resize(total_index_data_size);
1213 pIndices_to_scan = m_index_data.get_ptr();
1217 GL_ENTRYPOINT(glGetBufferSubData)(GL_ELEMENT_ARRAY_BUFFER, (GLintptr)pIndices, total_index_data_size, m_index_data.get_ptr());
1219 if (check_gl_error())
1221 process_entrypoint_warning("%s: GL error while trying to retrieve index buffer data\n", VOGL_METHOD_NAME);
1223 memset(m_index_data.get_ptr(), 0, total_index_data_size);
1227 start = cUINT32_MAX;
1230 for (int i = 0; i < count; i++)
1234 if (type == GL_UNSIGNED_BYTE)
1235 v = pIndices_to_scan[i];
1236 else if (type == GL_UNSIGNED_SHORT)
1237 v = reinterpret_cast<const uint16 *>(pIndices_to_scan)[i];
1238 else if (type == GL_UNSIGNED_INT)
1239 v = reinterpret_cast<const uint32 *>(pIndices_to_scan)[i];
1242 process_entrypoint_error("%s: Invalid index type\n", VOGL_METHOD_NAME);
1246 start = math::minimum(start, v);
1247 end = math::maximum(end, v);
1250 has_valid_start_end = true;
1253 if (!set_client_side_array_data(map, start, end, basevertex))
1256 if (!set_client_side_vertex_attrib_array_data(map, start, end, basevertex))
1262 //----------------------------------------------------------------------------------------------------------------------
1263 // vogl_replayer::determine_uniform_replay_location
1264 //----------------------------------------------------------------------------------------------------------------------
1265 GLint vogl_gl_replayer::determine_uniform_replay_location(GLuint trace_program, GLint trace_location)
1269 GLint replay_location = trace_location;
1271 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_program);
1272 if (it == get_shared_state()->m_glsl_program_hash_map.end())
1274 process_entrypoint_warning("%s: Failed looking up current trace program in GLSL program hash map\n", VOGL_METHOD_NAME);
1278 glsl_program_state &state = it->second;
1280 uniform_location_hash_map::const_iterator loc_it = state.m_uniform_locations.find(trace_location);
1281 if (loc_it == state.m_uniform_locations.end())
1283 process_entrypoint_warning("%s: Failed looking up uniform location index\n", VOGL_METHOD_NAME);
1287 replay_location = loc_it->second;
1290 return replay_location;
1293 //----------------------------------------------------------------------------------------------------------------------
1294 // vogl_replayer::process_entrypoint_print_summary_context
1295 //----------------------------------------------------------------------------------------------------------------------
1296 void vogl_gl_replayer::process_entrypoint_print_summary_context(eConsoleMessageType msg_type)
1300 if (!m_pCur_gl_packet)
1303 console::printf(msg_type, "While processing GL entrypoint packet func %s, frame %u, swaps %u, GL call counter %" PRIu64 ", packet start trace context 0x%" PRIX64 ", cur trace context 0x%" PRIX64 ", trace thread 0x%" PRIX64 ":\n",
1304 g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
1305 m_frame_index, m_total_swaps,
1306 m_pCur_gl_packet->get_entrypoint_packet().m_call_counter,
1307 m_pCur_gl_packet->get_entrypoint_packet().m_context_handle,
1308 m_cur_trace_context,
1309 m_pCur_gl_packet->get_entrypoint_packet().m_thread_id);
1312 dynamic_string_array backtrace;
1313 if (get_printable_backtrace(backtrace))
1315 console::printf("Backtrace:\n");
1316 for (uint i = 0; i < backtrace.size(); i++)
1317 console::printf("%s\n", backtrace[i].get_ptr());
1322 //----------------------------------------------------------------------------------------------------------------------
1323 // vogl_replayer::print_detailed_context
1324 //----------------------------------------------------------------------------------------------------------------------
1325 void vogl_gl_replayer::print_detailed_context(eConsoleMessageType msg_type)
1331 vogl_loose_file_blob_manager blob_file_manager;
1332 blob_file_manager.init(cBMFWritable);
1334 vogl_trace_packet::json_serialize_params serialize_params;
1335 serialize_params.m_output_basename = "replay_error";
1336 serialize_params.m_cur_frame = m_frame_index;
1337 serialize_params.m_blob_file_size_threshold = 1024;
1338 serialize_params.m_pBlob_manager = (m_flags & cGLReplayerDumpPacketBlobFilesOnError) ? &blob_file_manager : NULL;
1339 m_pCur_gl_packet->json_serialize(node, serialize_params);
1341 dynamic_string node_str;
1342 node.serialize(node_str, true, 0);
1343 console::printf(msg_type, "Packet at call counter %" PRIu64 " as JSON:\n%s\n", m_pCur_gl_packet->get_entrypoint_packet().m_call_counter, node_str.get_ptr());
1346 //----------------------------------------------------------------------------------------------------------------------
1347 // vogl_replayer::process_entrypoint_msg_print_detailed_context
1348 //----------------------------------------------------------------------------------------------------------------------
1349 void vogl_gl_replayer::process_entrypoint_msg_print_detailed_context(eConsoleMessageType msg_type)
1353 if (!m_pCur_gl_packet)
1356 dump_packet_as_func_call(*m_pCur_gl_packet);
1358 if (!(m_flags & cGLReplayerDumpPacketsOnError))
1361 print_detailed_context(msg_type);
1364 //----------------------------------------------------------------------------------------------------------------------
1365 // vogl_replayer::process_entrypoint_info
1366 //----------------------------------------------------------------------------------------------------------------------
1367 void vogl_gl_replayer::process_entrypoint_info(const char *pFmt, ...)
1371 process_entrypoint_print_summary_context(cInfoConsoleMessage);
1374 va_start(args, pFmt);
1375 console::vprintf(cInfoConsoleMessage, pFmt, args);
1378 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1381 //----------------------------------------------------------------------------------------------------------------------
1382 // vogl_replayer::process_entrypoint_message
1383 //----------------------------------------------------------------------------------------------------------------------
1384 void vogl_gl_replayer::process_entrypoint_message(const char *pFmt, ...)
1388 process_entrypoint_print_summary_context(cMessageConsoleMessage);
1391 va_start(args, pFmt);
1392 console::vprintf(cMessageConsoleMessage, pFmt, args);
1395 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1398 //----------------------------------------------------------------------------------------------------------------------
1399 // vogl_replayer::process_entrypoint_warning
1400 //----------------------------------------------------------------------------------------------------------------------
1401 void vogl_gl_replayer::process_entrypoint_warning(const char *pFmt, ...)
1405 process_entrypoint_print_summary_context(cWarningConsoleMessage);
1408 va_start(args, pFmt);
1409 console::vprintf(cWarningConsoleMessage, pFmt, args);
1412 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1415 //----------------------------------------------------------------------------------------------------------------------
1416 // vogl_replayer::process_entrypoint_error
1417 //----------------------------------------------------------------------------------------------------------------------
1418 void vogl_gl_replayer::process_entrypoint_error(const char *pFmt, ...)
1422 process_entrypoint_print_summary_context(cErrorConsoleMessage);
1425 va_start(args, pFmt);
1426 console::vprintf(cErrorConsoleMessage, pFmt, args);
1429 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1432 //----------------------------------------------------------------------------------------------------------------------
1433 // vogl_replayer::switch_contexts
1434 //----------------------------------------------------------------------------------------------------------------------
1435 vogl_gl_replayer::status_t vogl_gl_replayer::switch_contexts(vogl_trace_context_ptr_value trace_context)
1440 //if (m_pCur_gl_packet->get_call_counter() == 25583)
1441 // vogl_debug_break();
1443 //vogl_trace_context_ptr_value trace_context = gl_packet.m_context_handle;
1444 if (trace_context == m_cur_trace_context)
1447 if (m_flags & cGLReplayerDebugMode)
1449 process_entrypoint_message("%s: Forcing context switch via glXMakeCurrent, from current trace context 0x%" PRIX64 " to new context 0x%" PRIX64 "\n", VOGL_METHOD_NAME, cast_val_to_uint64(m_cur_trace_context), cast_val_to_uint64(trace_context));
1452 // pContext_state will be NULL if they are unmapping!
1453 context_state *pContext_state = get_trace_context_state(trace_context);
1454 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1456 const Display *dpy = m_pWindow->get_display();
1457 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1459 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1462 process_entrypoint_error("%s: Failed switching current trace context to 0x%" PRIX64 "\n", VOGL_METHOD_NAME, trace_context);
1463 return cStatusHardFailure;
1466 m_cur_trace_context = trace_context;
1467 m_cur_replay_context = replay_context;
1468 m_pCur_context_state = pContext_state;
1473 //----------------------------------------------------------------------------------------------------------------------
1474 // vogl_replayer::debug_callback_arb
1475 //----------------------------------------------------------------------------------------------------------------------
1476 void vogl_gl_replayer::debug_callback_arb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *pUser_param)
1480 VOGL_NOTE_UNUSED(length);
1482 char final_message[4096];
1484 context_state *pContext_state = (context_state *)(pUser_param);
1486 vogl_format_debug_output_arb(final_message, sizeof(final_message), source, type, id, severity, reinterpret_cast<const char *>(message));
1490 vogl_warning_printf("%s: Trace context: 0x%" PRIX64 ", Replay context 0x%" PRIX64 ", Last trace call counter: %" PRIu64 "\n%s\n", VOGL_FUNCTION_NAME,
1491 cast_val_to_uint64(pContext_state->m_trace_context), cast_val_to_uint64(pContext_state->m_replay_context), cast_val_to_uint64(pContext_state->m_last_call_counter), final_message);
1495 vogl_warning_printf("%s: %s\n", VOGL_FUNCTION_NAME, final_message);
1499 //----------------------------------------------------------------------------------------------------------------------
1500 // vogl_replayer::is_extension_supported
1501 //----------------------------------------------------------------------------------------------------------------------
1502 bool vogl_gl_replayer::is_extension_supported(const char *pExt)
1506 if ((m_pCur_context_state) && (m_pCur_context_state->m_context_info.is_valid()))
1508 return m_pCur_context_state->m_context_info.supports_extension(pExt);
1516 //----------------------------------------------------------------------------------------------------------------------
1517 // vogl_replayer::context_state::handle_context_made_current
1518 //----------------------------------------------------------------------------------------------------------------------
1519 bool vogl_gl_replayer::context_state::handle_context_made_current()
1523 if (m_has_been_made_current)
1526 VOGL_CHECK_GL_ERROR;
1528 m_has_been_made_current = true;
1530 if (!m_context_info.init(m_context_desc))
1532 vogl_error_printf("%s: vogl_context_info::init() failed!\n", VOGL_METHOD_NAME);
1536 if (!m_context_info.get_max_vertex_attribs())
1538 vogl_warning_printf("%s: GL_MAX_VERTEX_ATTRIBS is 0\n", VOGL_METHOD_NAME);
1540 else if (m_context_info.get_max_vertex_attribs() >= VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES)
1542 vogl_error_printf("%s: GL_MAX_VERTEX_ATTRIBS is too large, max supported is %u. Please increase VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES.\n", VOGL_METHOD_NAME, VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES);
1546 if (m_replayer.m_flags & cGLReplayerLowLevelDebugMode)
1548 vogl_debug_printf("%s: Creating dummy handles\n", VOGL_METHOD_NAME);
1551 // Generate a bunch of replay handles, so the trace and replay namespaces are totally different to shake out handle or target remapping bugs
1552 // TODO: All more object types
1553 vogl::vector<GLuint> dummy_handles(65536);
1555 GL_ENTRYPOINT(glGenTextures)(4000, dummy_handles.get_ptr());
1556 GL_ENTRYPOINT(glGenBuffers)(6000, dummy_handles.get_ptr());
1557 GL_ENTRYPOINT(glGenLists)(8000);
1558 GL_ENTRYPOINT(glGenQueries)(10000, dummy_handles.get_ptr());
1560 GL_ENTRYPOINT(glGenVertexArrays)(12000, dummy_handles.get_ptr());
1561 GL_ENTRYPOINT(glGenProgramsARB)(14000, dummy_handles.get_ptr());
1562 GL_ENTRYPOINT(glGenFramebuffers)(16000, dummy_handles.get_ptr());
1563 GL_ENTRYPOINT(glGenSamplers)(18000, dummy_handles.get_ptr());
1564 GL_ENTRYPOINT(glGenRenderbuffers)(20000, dummy_handles.get_ptr());
1566 for (uint i = 0; i < 22000; i++)
1567 GL_ENTRYPOINT(glCreateProgram)();
1569 vogl_debug_printf("%s: Finished creating dummy handles\n", VOGL_METHOD_NAME);
1572 VOGL_CHECK_GL_ERROR;
1577 //----------------------------------------------------------------------------------------------------------------------
1578 // vogl_replayer::handle_context_made_current
1579 //----------------------------------------------------------------------------------------------------------------------
1580 bool vogl_gl_replayer::handle_context_made_current()
1584 if (!m_pCur_context_state->handle_context_made_current())
1587 if ((m_pCur_context_state->m_context_info.is_debug_context()) && (GL_ENTRYPOINT(glDebugMessageCallbackARB)) && (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_debug_output")))
1589 GL_ENTRYPOINT(glDebugMessageCallbackARB)(debug_callback_arb, (GLvoid *)m_pCur_context_state);
1590 GL_ENTRYPOINT(glEnable)(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
1594 if (m_flags & cGLReplayerVerboseMode)
1596 vogl_debug_printf("%s: Trace context: 0x%" PRIX64 ", replay context 0x%" PRIX64 ", GL_VERSION: %s\n",
1598 (uint64_t)m_cur_trace_context,
1599 (uint64_t)m_cur_replay_context,
1600 m_pCur_context_state->m_context_info.get_version_str().get_ptr());
1606 //----------------------------------------------------------------------------------------------------------------------
1607 // vogl_replayer::dump_context_attrib_list
1608 //----------------------------------------------------------------------------------------------------------------------
1609 void vogl_gl_replayer::dump_context_attrib_list(const int *pAttrib_list, uint size)
1615 vogl_debug_printf("Attrib list is NULL\n");
1618 vogl_debug_printf("Context attribs:\n");
1625 vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1629 uint key = pAttrib_list[ofs];
1636 vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1640 uint value = pAttrib_list[ofs];
1643 vogl_debug_printf("Key: %s (0x%08X), Value: 0x%08X\n", g_gl_enums.find_name(key, "GLX"), key, value);
1645 vogl_debug_printf("End of context attribs\n");
1648 //----------------------------------------------------------------------------------------------------------------------
1649 // vogl_replayer::find_attrib_key
1650 //----------------------------------------------------------------------------------------------------------------------
1651 int vogl_gl_replayer::find_attrib_key(const vogl::vector<int> &attrib_list, int key_to_find)
1656 while (ofs < attrib_list.size())
1658 int key = attrib_list[ofs];
1662 if (++ofs >= attrib_list.size())
1664 process_entrypoint_warning("%s: Failed parsing attrib list, this call is probably going to fail\n", VOGL_METHOD_NAME);
1668 if (key == key_to_find)
1676 //----------------------------------------------------------------------------------------------------------------------
1677 // vogl_replayer::create_context_attribs
1678 //----------------------------------------------------------------------------------------------------------------------
1679 vogl_gl_replayer::status_t vogl_gl_replayer::create_context_attribs(
1680 vogl_trace_context_ptr_value trace_context, Display *dpy, GLXFBConfig config, vogl_trace_context_ptr_value trace_share_context, GLXContext replay_share_context, Bool direct,
1681 const int *pTrace_attrib_list, int trace_attrib_list_size, bool expecting_attribs)
1685 vogl::vector<int> temp_attrib_list;
1687 if ((pTrace_attrib_list) && (trace_attrib_list_size))
1689 temp_attrib_list.append(pTrace_attrib_list, trace_attrib_list_size);
1690 if (temp_attrib_list.back() != 0)
1692 process_entrypoint_warning("%s: attrib list does not end with 0\n", VOGL_METHOD_NAME);
1697 if (expecting_attribs)
1699 if (m_flags & cGLReplayerVerboseMode)
1700 process_entrypoint_message("%s: No attrib list found in trace, assuming an attrib list ending with 0\n", VOGL_METHOD_NAME);
1703 temp_attrib_list.push_back(0);
1706 if (m_flags & cGLReplayerForceDebugContexts)
1708 // See http://www.opengl.org/registry/specs/ARB/glx_create_context.txt
1709 int context_flags_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_FLAGS_ARB);
1710 if (context_flags_ofs < 0)
1712 temp_attrib_list.back() = GLX_CONTEXT_FLAGS_ARB;
1713 temp_attrib_list.push_back(GLX_CONTEXT_DEBUG_BIT_ARB);
1714 temp_attrib_list.push_back(0);
1716 if (m_flags & cGLReplayerVerboseMode)
1717 process_entrypoint_warning("%s: Appending GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB to attrib list to enable debug context\n", VOGL_METHOD_NAME);
1721 temp_attrib_list[context_flags_ofs] |= GLX_CONTEXT_DEBUG_BIT_ARB;
1723 if (m_flags & cGLReplayerVerboseMode)
1724 process_entrypoint_warning("%s: Slamming on GLX_CONTEXT_DEBUG_BIT_ARB bit to enable debug context\n", VOGL_METHOD_NAME);
1727 int context_major_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MAJOR_VERSION_ARB);
1728 int context_minor_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MINOR_VERSION_ARB);
1730 bool slammed_up_to_3_0 = false;
1731 if (context_major_version_ofs < 0)
1733 // Don't slam up if they haven't requested a specific GL version, the driver will give us the most recent version that is backwards compatible with 1.0 (i.e. 4.3 for NVidia's current dirver).
1735 temp_attrib_list.back() = GLX_CONTEXT_MAJOR_VERSION_ARB;
1736 temp_attrib_list.push_back(3);
1737 temp_attrib_list.push_back(0);
1739 slammed_up_to_3_0 = true;
1742 else if (temp_attrib_list[context_major_version_ofs] < 3)
1744 temp_attrib_list[context_major_version_ofs] = 3;
1746 slammed_up_to_3_0 = true;
1749 if (slammed_up_to_3_0)
1751 if (context_minor_version_ofs < 0)
1753 temp_attrib_list.back() = GLX_CONTEXT_MINOR_VERSION_ARB;
1754 temp_attrib_list.push_back(0);
1755 temp_attrib_list.push_back(0);
1759 temp_attrib_list[context_minor_version_ofs] = 0;
1762 process_entrypoint_warning("%s: Forcing GL context version up to 3.0 due to debug context usage\n", VOGL_METHOD_NAME);
1766 const int *pAttrib_list = temp_attrib_list.get_ptr();
1767 const uint attrib_list_size = temp_attrib_list.size();
1769 if (m_flags & cGLReplayerVerboseMode)
1770 dump_context_attrib_list(pAttrib_list, attrib_list_size);
1772 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContextAttribsARB)(dpy, config, replay_share_context, direct, pAttrib_list);
1773 if (!replay_context)
1777 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
1778 return cStatusHardFailure;
1782 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
1790 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContextAttribsARB, pAttrib_list, attrib_list_size);
1791 VOGL_NOTE_UNUSED(pContext_state);
1795 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
1802 //----------------------------------------------------------------------------------------------------------------------
1803 // vogl_replayer::process_pending_make_current
1804 //----------------------------------------------------------------------------------------------------------------------
1805 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_make_current()
1809 if (!m_pending_make_current_packet.is_valid())
1812 vogl_trace_packet &gl_packet = m_pending_make_current_packet;
1814 Bool trace_result = gl_packet.get_return_value<Bool>();
1816 gl_entrypoint_id_t entrypoint_id = gl_packet.get_entrypoint_id();
1817 VOGL_ASSERT((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) || (entrypoint_id == VOGL_ENTRYPOINT_glXMakeContextCurrent));
1819 // pContext_state will be NULL if they are unmapping!
1820 vogl_trace_ptr_value trace_context = gl_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
1821 context_state *pContext_state = get_trace_context_state(trace_context);
1822 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1824 if ((trace_context) && (!replay_context))
1826 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
1827 m_pending_make_current_packet.clear();
1828 return cStatusHardFailure;
1831 const Display *dpy = m_pWindow->get_display();
1832 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1834 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1839 process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
1840 m_pending_make_current_packet.clear();
1841 return cStatusHardFailure;
1845 process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
1850 m_cur_trace_context = trace_context;
1851 m_cur_replay_context = replay_context;
1852 m_pCur_context_state = pContext_state;
1856 process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
1859 if (m_cur_replay_context)
1861 int viewport_x = gl_packet.get_key_value_map().get_int(string_hash("viewport_x"));
1862 int viewport_y = gl_packet.get_key_value_map().get_int(string_hash("viewport_y"));
1863 int viewport_width = gl_packet.get_key_value_map().get_int(string_hash("viewport_width"));
1864 int viewport_height = gl_packet.get_key_value_map().get_int(string_hash("viewport_height"));
1865 int win_width = gl_packet.get_key_value_map().get_int(string_hash("win_width"));
1866 int win_height = gl_packet.get_key_value_map().get_int(string_hash("win_height"));
1868 if (!m_pCur_context_state->m_has_been_made_current)
1870 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1871 viewport_x, viewport_y,
1872 viewport_width, viewport_height,
1873 win_width, win_height);
1876 GLint cur_viewport[4];
1877 GL_ENTRYPOINT(glGetIntegerv)(GL_VIEWPORT, cur_viewport);
1879 uint cur_win_width = 0, cur_win_height = 0;
1880 m_pWindow->get_actual_dimensions(cur_win_width, cur_win_height);
1882 if (!m_pCur_context_state->m_has_been_made_current)
1884 vogl_printf("glXMakeCurrent(): Replay Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1885 cur_viewport[0], cur_viewport[1],
1886 cur_viewport[2], cur_viewport[3],
1887 cur_win_width, cur_win_height);
1890 if ((cur_viewport[0] != viewport_x) || (cur_viewport[1] != viewport_y) || (cur_viewport[2] != viewport_width) || (cur_viewport[3] != viewport_height))
1892 process_entrypoint_warning("%s: Replay viewport differs from traces!\n", VOGL_METHOD_NAME);
1895 if (!handle_context_made_current())
1896 return cStatusHardFailure;
1900 m_last_processed_call_counter = gl_packet.get_call_counter();
1902 m_pending_make_current_packet.clear();
1907 //----------------------------------------------------------------------------------------------------------------------
1908 // vogl_process_internal_trace_command_ctypes_packet
1909 //----------------------------------------------------------------------------------------------------------------------
1910 bool vogl_process_internal_trace_command_ctypes_packet(const key_value_map &kvm, const vogl_ctypes &ctypes)
1914 // TODO: Implement the code to map trace ctypes to replay ctypes. That's going to be fun.
1915 int num_trace_ctypes = kvm.get_int("num_ctypes");
1916 VOGL_VERIFY(num_trace_ctypes == VOGL_NUM_CTYPES);
1918 // TODO: This just verifies that the replayer's idea of each ctype matches the tracer's.
1919 // This will need to be revisited once we port to other OS's.
1920 // TODO: Move the ctypes crap into the SOF packet or something, it's not easy to deal with this packet on the fly.
1921 for (int ctype_iter = 0; ctype_iter < num_trace_ctypes; ctype_iter++)
1923 const vogl_ctype_desc_t &desc = ctypes[static_cast<vogl_ctype_t>(ctype_iter)];
1925 uint base_index = ctype_iter << 8;
1926 dynamic_string name(kvm.get_string(base_index++));
1927 dynamic_string ctype(kvm.get_string(base_index++));
1928 int size = kvm.get_int(base_index++);
1929 uint loki_type_flags = kvm.get_uint(base_index++);
1930 bool is_pointer = kvm.get_bool(base_index++);
1931 bool is_opaque_pointer = kvm.get_bool(base_index++);
1932 bool is_pointer_diff = kvm.get_bool(base_index++);
1933 bool is_opaque_type = kvm.get_bool(base_index++);
1935 VOGL_VERIFY(name.compare(desc.m_pName, true) == 0);
1936 VOGL_VERIFY(ctype.compare(desc.m_pCType, true) == 0);
1937 if (!desc.m_is_opaque_type)
1939 VOGL_VERIFY(size == desc.m_size);
1942 const uint loki_type_check_mask = ~(LOKI_TYPE_BITMASK(LOKI_IS_SIGNED_LONG) | LOKI_TYPE_BITMASK(LOKI_IS_UNSIGNED_LONG));
1943 VOGL_VERIFY((loki_type_flags & loki_type_check_mask) == (desc.m_loki_type_flags & loki_type_check_mask));
1945 VOGL_VERIFY(is_pointer == desc.m_is_pointer);
1946 VOGL_VERIFY(is_opaque_pointer == desc.m_is_opaque_pointer);
1947 VOGL_VERIFY(is_pointer_diff == desc.m_is_pointer_diff);
1948 VOGL_VERIFY(is_opaque_type == desc.m_is_opaque_type);
1954 //----------------------------------------------------------------------------------------------------------------------
1955 // vogl_replayer::process_internal_trace_command
1956 //----------------------------------------------------------------------------------------------------------------------
1957 vogl_gl_replayer::status_t vogl_gl_replayer::process_internal_trace_command(const vogl_trace_gl_entrypoint_packet &gl_packet)
1961 VOGL_NOTE_UNUSED(gl_packet);
1963 GLuint cmd = m_pCur_gl_packet->get_param_value<GLuint>(0);
1964 GLuint size = m_pCur_gl_packet->get_param_value<GLuint>(1);
1965 VOGL_NOTE_UNUSED(size);
1966 vogl_trace_ptr_value trace_data_ptr_value = m_pCur_gl_packet->get_param_ptr_value(2);
1967 VOGL_NOTE_UNUSED(trace_data_ptr_value);
1969 vogl_gl_replayer::status_t status = cStatusOK;
1973 case cITCRDemarcation:
1977 case cITCRKeyValueMap:
1979 const key_value_map &kvm = m_pCur_gl_packet->get_key_value_map();
1981 dynamic_string cmd_type(kvm.get_string("command_type"));
1982 if (cmd_type == "state_snapshot")
1984 dynamic_string text_id(kvm.get_string("id"));
1985 dynamic_string binary_id(kvm.get_string("binary_id"));
1986 if (text_id.is_empty() && binary_id.is_empty())
1988 process_entrypoint_error("%s: Missing id and binary_id fields in glInternalTraceCommandRAD key_value_map command type: \"%s\"\n", VOGL_METHOD_NAME, cmd_type.get_ptr());
1989 return cStatusHardFailure;
1992 dynamic_string id_to_use(text_id.is_empty() ? binary_id : text_id);
1994 // TODO: Make a 1st class snapshot cache class
1995 // TODO: This could fail if the user hand modifies the snapshot in some way - add an option to disable caching.
1996 vogl_gl_state_snapshot *pSnapshot = NULL;
1997 if (m_flags & cGLReplayerSnapshotCaching)
1999 for (uint snapshot_index = 0; snapshot_index < m_snapshots.size(); snapshot_index++)
2001 if (!m_snapshots[snapshot_index].m_name.compare(id_to_use, false))
2003 pSnapshot = m_snapshots[snapshot_index].m_pSnapshot;
2006 snapshot_cache_entry cache_entry(m_snapshots[snapshot_index]);
2007 m_snapshots.erase(snapshot_index);
2008 m_snapshots.insert(0, cache_entry);
2017 timed_scope ts("Deserialize snapshot time");
2019 if (!m_pBlob_manager)
2021 process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2022 return cStatusHardFailure;
2025 uint8_vec snapshot_data;
2027 if (!m_pBlob_manager->get(id_to_use, snapshot_data) || (snapshot_data.is_empty()))
2029 process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2030 return cStatusHardFailure;
2033 vogl_message_printf("%s: Deserializing state snapshot \"%s\", %u bytes\n", VOGL_METHOD_NAME, id_to_use.get_ptr(), snapshot_data.size());
2038 if (id_to_use == text_id)
2039 success = doc.deserialize(reinterpret_cast<const char *>(snapshot_data.get_ptr()), snapshot_data.size());
2041 success = doc.binary_deserialize(snapshot_data);
2042 if (!success || (!doc.get_root()))
2044 process_entrypoint_error("%s: Failed deserializing JSON snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2045 return cStatusHardFailure;
2048 pSnapshot = vogl_new(vogl_gl_state_snapshot);
2049 if (!pSnapshot->deserialize(*doc.get_root(), *m_pBlob_manager, &m_trace_gl_ctypes))
2051 vogl_delete(pSnapshot);
2054 process_entrypoint_error("%s: Failed deserializing snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2055 return cStatusHardFailure;
2058 if (m_flags & cGLReplayerSnapshotCaching)
2060 snapshot_cache_entry new_cache_entry;
2061 new_cache_entry.m_name = id_to_use;
2062 new_cache_entry.m_pSnapshot = pSnapshot;
2063 m_snapshots.insert(0, new_cache_entry);
2065 // FIXME: Even 3-4 snapshots in memory may be too much in 32-bit mode for some large apps.
2066 while (m_snapshots.size() > 3)
2068 vogl_delete(m_snapshots.back().m_pSnapshot);
2069 m_snapshots.resize(m_snapshots.size() - 1);
2074 status = begin_applying_snapshot(pSnapshot, (m_flags & cGLReplayerSnapshotCaching) ? false : true);
2076 if ((status != cStatusOK) && (status != cStatusResizeWindow))
2078 if (m_flags & cGLReplayerSnapshotCaching)
2080 VOGL_ASSERT(m_snapshots[0].m_pSnapshot == pSnapshot);
2082 vogl_delete(m_snapshots[0].m_pSnapshot);
2083 m_snapshots.erase(0U);
2086 if (m_flags & cGLReplayerSnapshotCaching)
2088 vogl_delete(pSnapshot);
2092 process_entrypoint_error("%s: Failed applying GL snapshot from blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2096 vogl_message_printf("%s: Successfully applied GL state snapshot from blob \"%s\"\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2098 else if (cmd_type == "ctypes")
2100 m_ctypes_packet = *m_pCur_gl_packet;
2102 if (!vogl_process_internal_trace_command_ctypes_packet(kvm, m_trace_gl_ctypes))
2103 return cStatusHardFailure;
2105 else if (cmd_type == "entrypoints")
2111 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD key_value_map command type: \"%s\"\n", VOGL_METHOD_NAME, cmd_type.get_ptr());
2117 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD command type: %u\n", VOGL_METHOD_NAME, cmd);
2125 //----------------------------------------------------------------------------------------------------------------------
2126 // vogl_replayer::check_program_binding_shadow
2127 //----------------------------------------------------------------------------------------------------------------------
2128 bool vogl_gl_replayer::check_program_binding_shadow()
2132 if (!m_pCur_context_state)
2135 // Make sure shadow is good
2136 GLint actual_current_replay_program = 0;
2137 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
2140 if (m_pCur_context_state->m_cur_replay_program == static_cast<GLuint>(actual_current_replay_program))
2143 // OK, on AMD it plays games with GL_CURRENT_PROGRAM when the currently bound program is deleted. Check for this scenario.
2144 bool is_still_program = GL_ENTRYPOINT(glIsProgram)(m_pCur_context_state->m_cur_replay_program) != 0;
2145 if ((!check_gl_error()) && (is_still_program))
2147 GLint marked_for_deletion = GL_FALSE;
2148 GL_ENTRYPOINT(glGetProgramiv)(m_pCur_context_state->m_cur_replay_program, GL_DELETE_STATUS, &marked_for_deletion);
2150 if ((!check_gl_error()) && (marked_for_deletion))
2158 //----------------------------------------------------------------------------------------------------------------------
2159 // vogl_replayer::handle_use_program
2160 //----------------------------------------------------------------------------------------------------------------------
2161 void vogl_gl_replayer::handle_use_program(GLuint trace_handle, gl_entrypoint_id_t entrypoint_id)
2165 // TODO: This code assumes the non-ARB entrypoints are being used, which works fine on NV but who knows what'll happen on other drivers.
2166 check_program_binding_shadow();
2168 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2169 VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2170 VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2172 // For safety, absorb any previous error.
2175 GLuint prev_replay_program = m_pCur_context_state->m_cur_replay_program;
2176 GLuint prev_trace_program = m_pCur_context_state->m_cur_trace_program;
2178 bool prev_is_program = false;
2179 GLint prev_link_status = false;
2180 GLint prev_is_marked_for_deletion = false;
2181 vogl::growable_array<GLuint, 8> prev_attached_replay_shaders;
2183 if ((prev_replay_program) && (replay_handle != prev_replay_program))
2185 prev_is_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2186 check_gl_error_quietly();
2188 if (prev_is_program)
2190 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_DELETE_STATUS, &prev_is_marked_for_deletion);
2191 check_gl_error_quietly();
2193 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_LINK_STATUS, &prev_link_status);
2194 check_gl_error_quietly();
2196 if (prev_is_marked_for_deletion)
2198 // The currently bound program is marked for deletion, so record which shaders are attached to it in case the program is actually deleted by the driver on the UseProgram() call.
2199 GLint num_attached_shaders = 0;
2200 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_ATTACHED_SHADERS, &num_attached_shaders);
2201 check_gl_error_quietly();
2203 if (num_attached_shaders)
2205 prev_attached_replay_shaders.resize(num_attached_shaders);
2207 GLsizei actual_count = 0;
2208 GL_ENTRYPOINT(glGetAttachedShaders)(prev_replay_program, num_attached_shaders, &actual_count, prev_attached_replay_shaders.get_ptr());
2209 check_gl_error_quietly();
2211 VOGL_ASSERT(actual_count == num_attached_shaders);
2217 if (entrypoint_id == VOGL_ENTRYPOINT_glUseProgram)
2218 GL_ENTRYPOINT(glUseProgram)(replay_handle);
2220 GL_ENTRYPOINT(glUseProgramObjectARB)(replay_handle);
2222 // Can't shadow if glUseProgram failed.
2223 if (check_gl_error())
2226 if ((prev_replay_program) && (prev_replay_program != replay_handle))
2228 bool is_prev_still_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2229 if (!is_prev_still_program)
2231 VOGL_ASSERT(prev_is_program);
2232 VOGL_ASSERT(prev_is_marked_for_deletion);
2234 // The previously bound program is really dead now, kill it from our tables and also check up on any shaders it was attached to.
2235 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(prev_trace_program);
2236 VOGL_ASSERT(was_deleted);
2237 VOGL_NOTE_UNUSED(was_deleted);
2239 was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(prev_trace_program);
2240 VOGL_ASSERT(was_deleted);
2242 was_deleted = get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(prev_replay_program);
2243 if ((prev_link_status) && (!was_deleted))
2248 for (uint i = 0; i < prev_attached_replay_shaders.size(); i++)
2250 GLuint replay_shader_handle = prev_attached_replay_shaders[i];
2252 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle);
2253 check_gl_error_quietly();
2255 if (is_still_shader)
2258 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2260 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2264 // The attached shader is now really dead.
2265 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2266 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2268 process_entrypoint_error("%s: Failed finding attached GL shader %u in objects hash table, while handling the actual deletion of trace program %u replay program %u\n", VOGL_METHOD_NAME, replay_shader_handle, prev_trace_program, prev_replay_program);
2274 m_pCur_context_state->m_cur_replay_program = replay_handle;
2275 m_pCur_context_state->m_cur_trace_program = trace_handle;
2278 //----------------------------------------------------------------------------------------------------------------------
2279 // vogl_replayer::handle_delete_program
2280 //----------------------------------------------------------------------------------------------------------------------
2281 void vogl_gl_replayer::handle_delete_program(GLuint trace_handle)
2285 check_program_binding_shadow();
2287 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2289 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2290 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2291 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2293 context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
2294 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
2296 if (it->first == m_pCur_context_state->m_context_desc.get_trace_context())
2299 context_state *pContext = it->second;
2300 if (pContext->m_pShared_state == pContext_shareroot)
2302 if (pContext->m_cur_trace_program == trace_handle)
2304 process_entrypoint_error("%s: Trace program %u replay program %u is being deleted on context 0x%" PRIx64 ", but it's currently bound to trace context 0x%" PRIx64 "! This scenario is not currently supported with sharelists.\n",
2305 VOGL_METHOD_NAME, trace_handle, replay_handle,
2306 cast_val_to_uint64(m_pCur_context_state->m_context_desc.get_trace_context()),
2307 cast_val_to_uint64(it->first));
2312 bool is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2313 check_gl_error_quietly();
2315 vogl::growable_array<GLuint, 8> attached_replay_shaders;
2317 if ((is_program) && (replay_handle))
2319 GLint num_attached_shaders = 0;
2320 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ATTACHED_SHADERS, &num_attached_shaders);
2321 check_gl_error_quietly();
2323 if (num_attached_shaders)
2325 attached_replay_shaders.resize(num_attached_shaders);
2327 GLsizei actual_count = 0;
2328 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, num_attached_shaders, &actual_count, attached_replay_shaders.get_ptr());
2329 check_gl_error_quietly();
2331 VOGL_ASSERT(actual_count == num_attached_shaders);
2335 GL_ENTRYPOINT(glDeleteProgram)(replay_handle);
2337 bool deletion_succeeded = !check_gl_error();
2338 if (!deletion_succeeded)
2340 VOGL_ASSERT(!is_program);
2342 process_entrypoint_warning("%s: Failed deleting program, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2349 bool is_still_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2350 check_gl_error_quietly();
2352 GLint marked_for_deletion = 0;
2353 if (is_still_program)
2355 // It must still be bound to the context, or referred to in some other way that we don't know about.
2356 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2357 bool delete_status_check_succeeded = !check_gl_error_quietly();
2359 VOGL_VERIFY(delete_status_check_succeeded);
2360 VOGL_VERIFY(marked_for_deletion);
2362 else if (!is_still_program)
2364 VOGL_ASSERT(is_program);
2366 // The program is really gone now.
2367 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2368 VOGL_ASSERT(was_deleted);
2369 VOGL_NOTE_UNUSED(was_deleted);
2371 was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(trace_handle);
2372 VOGL_ASSERT(was_deleted);
2374 get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(replay_handle);
2376 if (m_pCur_context_state->m_cur_replay_program == replay_handle)
2378 // This shouldn't happen - if the program is still bound to the context then it should still be a program.
2380 m_pCur_context_state->m_cur_replay_program = 0;
2381 m_pCur_context_state->m_cur_trace_program = 0;
2384 for (uint i = 0; i < attached_replay_shaders.size(); i++)
2386 GLuint replay_shader_handle = attached_replay_shaders[i];
2388 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle) != 0;
2389 check_gl_error_quietly();
2391 if (is_still_shader)
2394 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2396 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2400 // The attached shader is now really dead.
2401 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2402 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2404 process_entrypoint_error("%s: Failed finding attached GL shader %u in objects hash table, while handling the actual deletion of trace program %u replay program %u\n", VOGL_METHOD_NAME, replay_shader_handle, trace_handle, replay_handle);
2410 //----------------------------------------------------------------------------------------------------------------------
2411 // vogl_replayer::handle_delete_shader
2412 //----------------------------------------------------------------------------------------------------------------------
2413 void vogl_gl_replayer::handle_delete_shader(GLuint trace_handle)
2417 check_program_binding_shadow();
2421 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2423 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2424 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_SHADER_OBJECT);
2425 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_SHADER_OBJECT);
2427 GL_ENTRYPOINT(glDeleteShader)(replay_handle);
2429 bool deletion_succeeded = !check_gl_error();
2430 if (!deletion_succeeded)
2432 process_entrypoint_warning("%s: Failed deleting shader, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2439 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_handle);
2440 check_gl_error_quietly();
2442 if (!is_still_shader)
2444 // The shader is really gone.
2445 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2446 VOGL_ASSERT(was_deleted);
2447 VOGL_NOTE_UNUSED(was_deleted);
2451 GLint marked_for_deletion = 0;
2452 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2453 check_gl_error_quietly();
2455 VOGL_VERIFY(marked_for_deletion);
2457 // The shader is attached to a live program object (which may or may not be actually in the marked_as_deleted state)
2458 // we'll get around to it when the program object is deleted, or when they remove the program object from the current state.
2462 //----------------------------------------------------------------------------------------------------------------------
2463 // vogl_replayer::handle_detach_shader
2464 //----------------------------------------------------------------------------------------------------------------------
2465 void vogl_gl_replayer::handle_detach_shader(gl_entrypoint_id_t entrypoint_id)
2467 GLuint trace_program = m_pCur_gl_packet->get_param_value<GLuint>(0);
2468 GLuint replay_program = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_program);
2470 GLuint trace_shader = m_pCur_gl_packet->get_param_value<GLuint>(1);
2471 GLuint replay_shader = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_shader);
2475 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2477 GLboolean was_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2478 check_gl_error_quietly();
2480 GLint marked_for_deletion = 0;
2481 GL_ENTRYPOINT(glGetShaderiv)(replay_shader, GL_DELETE_STATUS, &marked_for_deletion);
2482 check_gl_error_quietly();
2484 if (entrypoint_id == VOGL_ENTRYPOINT_glDetachObjectARB)
2485 GL_ENTRYPOINT(glDetachObjectARB)(replay_program, replay_shader);
2488 VOGL_ASSERT(entrypoint_id == VOGL_ENTRYPOINT_glDetachShader);
2489 GL_ENTRYPOINT(glDetachShader)(replay_program, replay_shader);
2492 bool detach_failed = check_gl_error();
2494 GLboolean is_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2495 check_gl_error_quietly();
2499 if ((marked_for_deletion) && (was_shader) && (!is_shader))
2501 // The shader is really gone now.
2502 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_shader);
2503 VOGL_ASSERT(was_deleted);
2504 VOGL_NOTE_UNUSED(was_deleted);
2509 //----------------------------------------------------------------------------------------------------------------------
2510 // vogl_gl_replayer::handle_link_program
2511 //----------------------------------------------------------------------------------------------------------------------
2512 void vogl_gl_replayer::handle_link_program(gl_entrypoint_id_t entrypoint_id)
2516 GLuint trace_handle = m_pCur_gl_packet->get_param_value<GLuint>(0);
2517 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2519 GLboolean is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle);
2523 process_entrypoint_warning("%s: Handle is not a program, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2526 const json_document *pDoc = m_pCur_gl_packet->get_key_value_map().get_json_document("metadata");
2530 process_entrypoint_warning("%s: JSON metadata document is missing, program will be linked without setting its attributes or initializing the uniform location shadow, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2532 else if ((pDoc) && (!pDoc->is_object()))
2534 process_entrypoint_warning("%s: JSON metadata document must be an object, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2538 int trace_active_attributes = 0;
2539 int trace_active_uniforms = 0;
2540 int trace_active_uniform_blocks = 0;
2541 int trace_link_status = 1;
2543 VOGL_NOTE_UNUSED(trace_active_uniforms);
2544 VOGL_NOTE_UNUSED(trace_active_uniform_blocks);
2548 const json_node &doc_root = *pDoc->get_root();
2550 trace_link_status = doc_root.value_as_int("link_status");
2551 trace_active_attributes = doc_root.value_as_int("total_active_attributes");
2552 trace_active_uniforms = doc_root.value_as_int("total_active_uniforms");
2553 trace_active_uniform_blocks = doc_root.value_as_int("active_uniform_blocks");
2555 const json_node *pAttrib_node = doc_root.find_child_array("active_attribs");
2558 for (uint i = 0; i < pAttrib_node->size(); i++)
2560 const json_node *pAttrib = pAttrib_node->get_child(i);
2567 const char *pName = pAttrib->value_as_string_ptr("name");
2568 int attrib_loc = pAttrib->value_as_int("location", -1);
2570 if ((pName) && (pName[0]) && (attrib_loc >= 0))
2572 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2573 GL_ENTRYPOINT(glBindAttribLocationARB)(replay_handle, attrib_loc, pName);
2575 GL_ENTRYPOINT(glBindAttribLocation)(replay_handle, attrib_loc, reinterpret_cast<const GLchar *>(pName));
2582 const json_node *pOutputs_object = doc_root.find_child_array("active_outputs");
2583 if (pOutputs_object)
2585 for (uint i = 0; i < pOutputs_object->size(); i++)
2587 const json_node *pOutput_node = pOutputs_object->get_child(i);
2591 dynamic_string name(pOutput_node->value_as_string("name"));
2592 if ((name.is_empty()) || (name.begins_with("gl_", true)))
2595 int location = pOutput_node->value_as_int("location");
2596 int location_index = pOutput_node->value_as_int("location_index");
2598 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_blend_func_extended") && GL_ENTRYPOINT(glBindFragDataLocationIndexed))
2600 GL_ENTRYPOINT(glBindFragDataLocationIndexed)(replay_handle, location, location_index, reinterpret_cast<const GLchar *>(name.get_ptr()));
2605 process_entrypoint_error("%s: GL_ARB_blend_func_extended is not supported, but trace program %u GL program %u uses a non-zero location index\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2607 GL_ENTRYPOINT(glBindFragDataLocation)(replay_handle, location, reinterpret_cast<const GLchar *>(name.get_ptr()));
2614 GLenum transform_feedback_mode = vogl_get_json_value_as_enum(doc_root, "transform_feedback_mode");
2615 GLint num_varyings = doc_root.value_as_int("transform_feedback_num_varyings");
2618 const json_node *pTransform_feedback_varyings = doc_root.find_child_array("transform_feedback_varyings");
2619 if (pTransform_feedback_varyings)
2621 dynamic_string_array names;
2623 for (uint i = 0; i < pTransform_feedback_varyings->size(); i++)
2625 const json_node *pVarying_node = pTransform_feedback_varyings->get_child(i);
2629 GLint index = pVarying_node->value_as_int("index");
2633 dynamic_string name(pVarying_node->value_as_string("name"));
2635 //GLsizei size(pVarying_node->value_as_int("size"));
2636 //GLenum type(vogl_get_json_value_as_enum(*pVarying_node, "type"));
2638 names.ensure_element_is_valid(index);
2639 names[index] = name;
2642 vogl::vector<GLchar *> varyings(names.size());
2643 for (uint i = 0; i < names.size(); i++)
2644 varyings[i] = (GLchar *)(names[i].get_ptr());
2646 GL_ENTRYPOINT(glTransformFeedbackVaryings)(replay_handle, varyings.size(), varyings.get_ptr(), transform_feedback_mode);
2652 switch (entrypoint_id)
2654 case VOGL_ENTRYPOINT_glLinkProgram:
2656 GL_ENTRYPOINT(glLinkProgram)(replay_handle);
2659 case VOGL_ENTRYPOINT_glLinkProgramARB:
2661 GL_ENTRYPOINT(glLinkProgramARB)(replay_handle);
2664 case VOGL_ENTRYPOINT_glProgramBinary:
2666 GL_ENTRYPOINT(glProgramBinary)(replay_handle, m_pCur_gl_packet->get_param_value<GLenum>(1), m_pCur_gl_packet->get_param_client_memory<GLvoid>(2), m_pCur_gl_packet->get_param_value<GLsizei>(3));
2678 GLint replay_link_status = 0;
2679 GLint replay_active_attributes = 0;
2680 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2682 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_LINK_STATUS_ARB, &replay_link_status);
2685 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &replay_active_attributes);
2690 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_LINK_STATUS, &replay_link_status);
2693 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ACTIVE_ATTRIBUTES, &replay_active_attributes);
2697 if ((replay_link_status) || (!get_shared_state()->m_shadow_state.m_linked_programs.find_snapshot(replay_handle)))
2700 if (entrypoint_id == VOGL_ENTRYPOINT_glProgramBinary)
2701 success = get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, replay_handle, m_pCur_gl_packet->get_param_value<GLenum>(1), m_pCur_gl_packet->get_param_client_memory<GLvoid>(2), m_pCur_gl_packet->get_param_value<GLsizei>(3));
2703 success = get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, replay_handle);
2706 process_entrypoint_warning("%s: Failed inserting into link time program shadow, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2709 if ((pDoc) && (replay_link_status != trace_link_status))
2711 process_entrypoint_warning("%s: Trace link status (%i) differs from replay link status (%i), trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_link_status, replay_link_status, trace_handle, replay_handle);
2714 if (!replay_link_status)
2716 vogl::vector<GLchar> log;
2718 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2721 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
2728 GLint actual_length = 0;
2729 GL_ENTRYPOINT(glGetInfoLogARB)(replay_handle, log.size(), &actual_length, reinterpret_cast<GLcharARB *>(log.get_ptr()));
2736 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_INFO_LOG_LENGTH, &length);
2743 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, log.size(), &length, log.get_ptr());
2748 if ((log.size()) && (log[0]))
2750 process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_handle, replay_handle, log.get_ptr());
2754 if ((pDoc) && (replay_active_attributes != trace_active_attributes))
2756 process_entrypoint_warning("%s: Number of trace active attributes (%i) differs from number of replay active attributes (%i) after linking program, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_active_attributes, replay_active_attributes, trace_handle, replay_handle);
2759 const json_node *pUniforms_node = pDoc ? pDoc->get_root()->find_child_array("active_uniforms") : NULL;
2763 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
2764 if (it == get_shared_state()->m_glsl_program_hash_map.end())
2765 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
2766 glsl_program_state &prog_state = it->second;
2768 for (uint i = 0; i < pUniforms_node->size(); i++)
2770 const json_node *pUniform = pUniforms_node->get_child(i);
2777 const char *pName = pUniform->value_as_string_ptr("name");
2783 int trace_loc = pUniform->value_as_int("location");
2784 int trace_array_size = pUniform->value_as_int("size");
2785 //int trace_type = pUniform->value_as_int("type");
2787 VOGL_ASSERT(trace_array_size >= 1);
2789 if ((trace_loc < 0) || (trace_array_size <= 0))
2792 if (trace_array_size > 1)
2794 dynamic_string element_name;
2795 for (int i = 0; i < trace_array_size; i++)
2797 element_name = pName;
2798 int start_bracket_ofs = element_name.find_right('[');
2799 if (start_bracket_ofs >= 0)
2800 element_name.left(start_bracket_ofs);
2801 element_name.format_append("[%u]", i);
2803 GLint element_trace_loc = trace_loc + i;
2804 GLint element_replay_loc;
2805 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2806 element_replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(element_name.get_ptr()));
2808 element_replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(element_name.get_ptr()));
2811 if (element_replay_loc < 0)
2813 process_entrypoint_warning("%s: glGetUniformLocation: Trace active array uniform %s trace location %i trace array size %i is not active during replay, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, element_name.get_ptr(), trace_loc, trace_array_size, trace_handle, replay_handle);
2817 prog_state.m_uniform_locations.erase(element_trace_loc);
2818 prog_state.m_uniform_locations.insert(element_trace_loc, element_replay_loc);
2822 else if (trace_array_size == 1)
2825 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2826 replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(pName));
2828 replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(pName));
2833 process_entrypoint_warning("%s: glGetUniformLocation: Trace active uniform %s trace location %i is not active during replay, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, pName, trace_loc, trace_handle, replay_handle);
2837 prog_state.m_uniform_locations.erase(trace_loc);
2838 prog_state.m_uniform_locations.insert(trace_loc, replay_loc);
2845 //----------------------------------------------------------------------------------------------------------------------
2846 // vogl_gl_replayer::post_draw_call
2847 // Called after each draw call or blit.
2848 //----------------------------------------------------------------------------------------------------------------------
2849 vogl_gl_replayer::status_t vogl_gl_replayer::post_draw_call()
2853 if (m_pCur_context_state->m_inside_gl_begin)
2856 if (check_gl_error())
2857 return cStatusGLError;
2859 bool is_draw = vogl_is_draw_entrypoint(m_pCur_gl_packet->get_entrypoint_id());
2861 if ((m_flags & cGLReplayerDumpShadersOnDraw) && (is_draw))
2863 dump_current_shaders();
2866 if (m_flags & cGLReplayerDumpFramebufferOnDraws)
2868 bool should_dump = false;
2870 if (m_dump_framebuffer_on_draw_frame_index != -1)
2872 if (m_frame_index == m_dump_framebuffer_on_draw_frame_index)
2875 else if ((m_dump_framebuffer_on_draw_first_gl_call_index >= 0) && (m_dump_framebuffer_on_draw_last_gl_call_index >= 0))
2877 should_dump = math::is_within_closed_range<uint64_t>(m_last_parsed_call_counter, m_dump_framebuffer_on_draw_first_gl_call_index, m_dump_framebuffer_on_draw_last_gl_call_index);
2886 dump_current_framebuffer();
2890 m_frame_draw_counter += is_draw;
2895 //----------------------------------------------------------------------------------------------------------------------
2896 // vogl_gl_replayer::dump_framebuffer
2897 //----------------------------------------------------------------------------------------------------------------------
2898 bool vogl_gl_replayer::dump_framebuffer(uint width, uint height, GLuint read_framebuffer, GLenum read_buffer, GLenum internal_format, uint orig_samples, GLuint replay_texture, GLuint replay_rbo)
2902 uint trace_read_framebuffer = 0;
2903 if (read_framebuffer)
2905 gl_handle_hash_map::const_iterator it = get_context_state()->m_framebuffers.search_table_for_value(read_framebuffer);
2906 if (it != get_context_state()->m_framebuffers.end())
2907 trace_read_framebuffer = it->second;
2910 uint trace_texture = replay_texture;
2913 if (!get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_texture, trace_texture))
2914 vogl_warning_printf("%s: Failed finding GL handle %u in texture handle shadow!\n", VOGL_METHOD_NAME, replay_texture);
2920 if (!get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_rbo, trace_rbo))
2921 vogl_error_printf("%s: Failed finding GL handle %u in RBO handle shadow!\n", VOGL_METHOD_NAME, replay_rbo);
2924 m_screenshot_buffer.resize(width * height * 3);
2926 bool success = vogl_copy_buffer_to_image(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size(), width, height, GL_RGB, GL_UNSIGNED_BYTE, false, read_framebuffer, read_buffer, 0);
2930 process_entrypoint_warning("%s: vogl_copy_buffer_to_image() failed!\n", VOGL_METHOD_NAME);
2934 size_t png_size = 0;
2935 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
2937 dynamic_string screenshot_filename(cVarArg, "%s_GLCTR%08llu_%s_FR%06u_DCTR%05llu_W%04i_H%04i_FBO%04u_%s",
2938 m_dump_framebuffer_on_draw_prefix.get_ptr(),
2939 (unsigned long long)m_pCur_gl_packet->get_call_counter(),
2940 g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
2942 (unsigned long long)m_frame_draw_counter,
2944 trace_read_framebuffer,
2945 g_gl_enums.find_gl_name(read_buffer));
2947 if (internal_format != GL_NONE)
2949 screenshot_filename += "_";
2950 screenshot_filename += g_gl_enums.find_gl_image_format_name(internal_format);
2953 if (orig_samples != 0)
2954 screenshot_filename += dynamic_string(cVarArg, "_MSAA%u", orig_samples);
2956 screenshot_filename += dynamic_string(cVarArg, "_TEX%04u", replay_texture);
2958 screenshot_filename += dynamic_string(cVarArg, "_RBO%04u", replay_rbo);
2960 screenshot_filename += ".png";
2962 file_utils::create_directories(file_utils::get_pathname(screenshot_filename.get_ptr()), false);
2964 if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
2966 process_entrypoint_error("%s: Failed writing framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
2971 vogl_printf("%s: Wrote framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
2979 //----------------------------------------------------------------------------------------------------------------------
2980 // vogl_gl_replayer::dump_current_framebuffer
2981 //----------------------------------------------------------------------------------------------------------------------
2982 void vogl_gl_replayer::dump_current_framebuffer()
2986 uint draw_framebuffer_binding = vogl_get_gl_integer(GL_DRAW_FRAMEBUFFER_BINDING);
2988 uint max_draw_buffers = vogl_get_gl_integer(GL_MAX_DRAW_BUFFERS);
2989 if (!max_draw_buffers)
2991 process_entrypoint_warning("%s: GL_MAX_DRAW_BUFFERS is 0\n", VOGL_METHOD_NAME);
2995 //GL_COLOR_ATTACHMENT0-GL_COLOR_ATTACHMENT15, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT
2997 vogl::vector<GLenum> draw_buffers(max_draw_buffers);
2998 for (uint i = 0; i < max_draw_buffers; i++)
2999 draw_buffers[i] = vogl_get_gl_integer(GL_DRAW_BUFFER0 + i);
3001 if (!draw_framebuffer_binding)
3003 for (uint i = 0; i < max_draw_buffers; i++)
3004 if (draw_buffers[i] != GL_NONE)
3005 dump_framebuffer(m_pWindow->get_width(), m_pWindow->get_height(), 0, draw_buffers[i], GL_NONE, 0, 0, 0);
3009 // TODO: We should probably keep around a persistent set of per-context (or sharelist) remappers
3010 vogl_framebuffer_state fbo_state;
3011 if (!fbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, draw_framebuffer_binding, GL_NONE))
3013 process_entrypoint_warning("%s: Unable to snapshot current FBO %u\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3017 for (uint i = 0; i < draw_buffers.size(); i++)
3019 if (draw_buffers[i] == GL_NONE)
3022 const vogl_framebuffer_attachment *pAttachment = fbo_state.get_attachments().find_value(draw_buffers[i]);
3025 process_entrypoint_warning("%s: Can't find draw buffer %s in currently bound FBO %u\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(draw_buffers[i]), draw_framebuffer_binding);
3029 if (pAttachment->get_type() == GL_FRAMEBUFFER_DEFAULT)
3031 else if (pAttachment->get_type() == GL_RENDERBUFFER)
3033 GLuint rbo_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3037 vogl_renderbuffer_state rbo_state;
3038 if (!rbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, rbo_handle, GL_NONE))
3040 process_entrypoint_warning("%s: Failed getting RBO %u's' state!\n", VOGL_METHOD_NAME, rbo_handle);
3044 if (rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_DEPTH_SIZE) || rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_STENCIL_SIZE))
3047 uint width = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_WIDTH);
3048 uint height = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_HEIGHT);
3049 uint samples = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_SAMPLES);
3050 GLenum internal_format = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_INTERNAL_FORMAT);
3052 if ((!width) || (!height) || (!internal_format))
3054 process_entrypoint_warning("%s: Unable to determine FBO %u color attachment %u's RBO %u's dimensions\n", VOGL_METHOD_NAME, draw_framebuffer_binding, i, rbo_handle);
3060 vogl_scoped_binding_state orig_framebuffers(GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_RENDERBUFFER);
3062 GLuint temp_rbo = 0;
3063 GL_ENTRYPOINT(glGenRenderbuffers)(1, &temp_rbo);
3069 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, temp_rbo);
3072 GL_ENTRYPOINT(glRenderbufferStorage)(GL_RENDERBUFFER, internal_format, width, height);
3075 GLuint temp_fbo = 0;
3076 GL_ENTRYPOINT(glGenFramebuffers)(1, &temp_fbo);
3079 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, temp_fbo);
3082 GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, temp_rbo);
3085 GLenum draw_buf = GL_COLOR_ATTACHMENT0;
3086 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_buf);
3089 GL_ENTRYPOINT(glReadBuffer)(GL_NONE);
3092 GLenum cur_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
3095 if (cur_status == GL_FRAMEBUFFER_COMPLETE)
3097 GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, draw_framebuffer_binding);
3100 // Save the framebuffer's readbuffer (it's per-framebuffer state, not context state).
3101 vogl_scoped_state_saver state_saver(cGSTReadBuffer);
3103 GL_ENTRYPOINT(glReadBuffer)(draw_buffers[i]);
3106 GL_ENTRYPOINT(glBlitFramebuffer)(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3108 if (!check_gl_error())
3109 dump_framebuffer(width, height, temp_fbo, GL_COLOR_ATTACHMENT0, internal_format, samples, 0, rbo_handle);
3112 process_entrypoint_warning("%s: Failed downsampling FBO %u color attachment %u's RBO %u to temporary RBO\n", VOGL_METHOD_NAME, draw_framebuffer_binding, i, rbo_handle);
3116 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, 0);
3119 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
3122 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &temp_fbo);
3125 GL_ENTRYPOINT(glDeleteRenderbuffers)(1, &temp_rbo);
3130 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, 0, rbo_handle);
3133 else if (pAttachment->get_type() == GL_TEXTURE)
3135 GLuint tex_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3138 process_entrypoint_warning("%s: Current FBO %u has a invalid object name\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3142 GLenum target = get_shared_state()->m_shadow_state.m_textures.get_target_inv(tex_handle);
3143 if (target == GL_NONE)
3145 process_entrypoint_warning("%s: Current FBO %u first color attachment's type is GL_TEXTURE, but unable to determine the texture's target type, GL texture handle %u\n", VOGL_METHOD_NAME, draw_framebuffer_binding, tex_handle);
3149 if ((target == GL_TEXTURE_CUBE_MAP) || (target == GL_TEXTURE_CUBE_MAP_ARRAY))
3150 target = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE);
3152 if (!utils::is_in_set<GLenum, GLenum>(target, GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY))
3154 process_entrypoint_warning("%s: Unsupported FBO attachment texture target type (%s), GL texture handle %u\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(target), tex_handle);
3158 uint level = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
3159 uint layer = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
3160 VOGL_NOTE_UNUSED(layer);
3162 GLint width = 0, height = 0, samples = 0;
3163 GLenum internal_format = GL_NONE;
3166 vogl_scoped_binding_state binding_saver;
3167 binding_saver.save_textures();
3169 GL_ENTRYPOINT(glBindTexture)(target, tex_handle);
3172 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_WIDTH, &width);
3175 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_HEIGHT, &height);
3178 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_format));
3181 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_texture_multisample"))
3183 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_SAMPLES, &samples);
3188 if ((!width) || (!height))
3190 process_entrypoint_warning("%s: Unable to determine FBO %u color attachment %u's texture %u's dimensions\n", VOGL_METHOD_NAME, draw_framebuffer_binding, i, tex_handle);
3196 process_entrypoint_warning("%s: Can't dump multisample texture FBO attachments yet\n", VOGL_METHOD_NAME);
3200 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, tex_handle, 0);
3205 //----------------------------------------------------------------------------------------------------------------------
3206 // vogl_gl_replayer::dump_current_shaders
3207 //----------------------------------------------------------------------------------------------------------------------
3208 void vogl_gl_replayer::dump_current_shaders()
3212 if (!m_pCur_context_state)
3217 const GLuint replay_program = m_pCur_context_state->m_cur_replay_program;
3219 // Get the current program.
3220 GLuint current_program = 0;
3221 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, (GLint *)(¤t_program));
3224 VOGL_ASSERT(replay_program == current_program);
3226 if (!current_program)
3229 // Get the attached shaders.
3230 GLsizei attached_shader_count = -1;
3231 GL_ENTRYPOINT(glGetProgramiv)(replay_program, GL_ATTACHED_SHADERS, &attached_shader_count);
3234 if (!attached_shader_count)
3237 vogl::vector<GLuint> shaders(attached_shader_count);
3238 GLsizei actual_shader_count = 0;
3239 GL_ENTRYPOINT(glGetAttachedShaders)(replay_program,
3240 attached_shader_count,
3241 &actual_shader_count,
3245 VOGL_ASSERT(attached_shader_count == actual_shader_count); // Sanity check.
3247 vogl_printf("Trace context 0x%" PRIx64 ", GL draw counter %" PRIu64 ", frame %u, replay program %u trace program %u has %d attached shaders:\n",
3248 cast_val_to_uint64(m_cur_trace_context), m_last_parsed_call_counter, m_frame_index,
3249 replay_program, m_pCur_context_state->m_cur_trace_program,
3250 attached_shader_count);
3252 // Get source from shaders.
3253 vogl::vector<GLchar> source; // Shared buffer for each iteration.
3254 for (GLsizei i = 0; i < attached_shader_count; ++i)
3256 const GLuint shader = shaders[i];
3257 GLint shader_type = 0;
3258 GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_TYPE, &shader_type);
3261 vogl_printf("\n%s: %u\n", g_gl_enums.find_gl_name(shader_type), shader);
3263 GLint source_length = -1; // Includes NUL terminator.
3264 GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
3267 VOGL_ASSERT(source_length > 0);
3269 source.resize(source_length);
3270 GLint actual_length = 0; // Excludes NUL terminator!
3271 GL_ENTRYPOINT(glGetShaderSource)(shader, source_length, &actual_length, source.get_ptr());
3274 VOGL_ASSERT(source_length == actual_length + 1); // Sanity check.
3275 vogl_printf("%.*s\n", source_length, source.get_const_ptr());
3277 vogl_printf("========\n");
3280 //----------------------------------------------------------------------------------------------------------------------
3281 // vogl_gl_replayer::handle_ShaderSource
3282 // Handle ShaderSource and ShaderSourceARB.
3283 //----------------------------------------------------------------------------------------------------------------------
3284 vogl_gl_replayer::status_t vogl_gl_replayer::handle_ShaderSource(GLhandleARB trace_object,
3286 const vogl_client_memory_array trace_strings_glchar_ptr_array,
3287 const GLint *pTrace_lengths)
3291 GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
3293 // m_pCur_gl_packet->get_param_client_memory_data_size(2) / sizeof(const GLchar *);
3294 const uint trace_strings_count = trace_strings_glchar_ptr_array.size();
3295 const uint trace_lengths_count = m_pCur_gl_packet->get_param_client_memory_data_size(3) / sizeof(const GLint);
3297 if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3298 (trace_strings_count != static_cast<uint>(count)))
3300 process_entrypoint_error("%s: Trace strings array has an invalid count (expected %u, got %u)\n",
3301 VOGL_METHOD_NAME, count, trace_strings_count);
3302 return cStatusHardFailure;
3305 if ((pTrace_lengths) && (trace_lengths_count != static_cast<uint>(count)))
3307 process_entrypoint_error("%s: Trace lengths array has an invalid count (expected %u, got %u)\n",
3308 VOGL_METHOD_NAME, count, trace_lengths_count);
3309 return cStatusHardFailure;
3312 vogl::vector<const GLcharARB *> strings(count);
3313 vogl::vector<GLint> lengths(count);
3315 const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
3317 vogl::vector<uint8_vec> blobs(count);
3319 for (GLsizei i = 0; i < count; i++)
3322 if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3323 (trace_strings_glchar_ptr_array.get_element<vogl_trace_ptr_value>(i) != 0))
3328 lengths[i] = pTrace_lengths ? pTrace_lengths[i] : 0;
3330 key_value_map::const_iterator it = map.find(i);
3331 if (it == map.end())
3335 process_entrypoint_error("%s: Failed finding blob for non-empty string %i in packet's key value map\n",
3336 VOGL_METHOD_NAME, i);
3337 return cStatusHardFailure;
3342 const uint8_vec *pBlob = it->second.get_blob();
3345 process_entrypoint_error("%s: Can't convert string %i to a blob\n", VOGL_METHOD_NAME, i);
3346 return cStatusHardFailure;
3350 uint8_vec &blob = blobs[i];
3352 if ((pTrace_lengths) && (pTrace_lengths[i] >= 0))
3354 if (static_cast<uint>(pTrace_lengths[i]) != blob.size())
3356 process_entrypoint_warning("%s: Length value (%u) stored in length array at index %u doesn't match string %u's length - changing to match\n", VOGL_METHOD_NAME, pTrace_lengths[i], i, blob.size());
3357 lengths[i] = blob.size();
3362 if ((blob.size()) && (blob.back() != '\0'))
3364 process_entrypoint_warning("%s: String %u doesn't end in 0 terminator - appending terminator\n", VOGL_METHOD_NAME, i);
3366 blob.push_back('\0');
3369 VOGL_ASSERT(blob.size() &&
3370 (blob.back() == '\0') &&
3371 (blob.size() == (1 + vogl_strlen(reinterpret_cast<const char *>(blob.get_ptr())))));
3374 strings[i] = reinterpret_cast<const GLcharARB *>(blob.get_ptr());
3377 if (m_pCur_gl_packet->get_entrypoint_id() == VOGL_ENTRYPOINT_glShaderSource)
3379 GL_ENTRYPOINT(glShaderSource)(replay_object,
3381 trace_strings_glchar_ptr_array.get_ptr() ? (GLchar * const *)strings.get_ptr() : NULL,
3382 pTrace_lengths ? lengths.get_ptr() : NULL);
3386 GL_ENTRYPOINT(glShaderSourceARB)(replay_object,
3388 trace_strings_glchar_ptr_array.get_ptr() ? strings.get_ptr() : NULL,
3389 pTrace_lengths ? lengths.get_ptr() : NULL);
3394 //----------------------------------------------------------------------------------------------------------------------
3395 // vogl_gl_replayer::display_list_bind_callback
3396 // handle is in the trace namespace
3397 //----------------------------------------------------------------------------------------------------------------------
3398 void vogl_gl_replayer::display_list_bind_callback(vogl_namespace_t handle_namespace, GLenum target, GLuint handle, void *pOpaque)
3402 vogl_gl_replayer *pReplayer = static_cast<vogl_gl_replayer *>(pOpaque);
3404 if (handle_namespace == VOGL_NAMESPACE_TEXTURES)
3406 if ((handle) && (target != GL_NONE))
3408 // A conditional update because we can't really test to see if the bind inside the display list really succeeded.
3409 pReplayer->get_shared_state()->m_shadow_state.m_textures.conditional_update(handle, GL_NONE, target);
3414 // TODO - right now the display list whitelist doens't let anything else get bound.
3415 pReplayer->process_entrypoint_warning("%s: Unsupported bind in display lists, namespace %s target %s trace handle %u\n", VOGL_FUNCTION_NAME, vogl_get_namespace_name(handle_namespace), g_gl_enums.find_gl_name(target), handle);
3419 //----------------------------------------------------------------------------------------------------------------------
3420 // Helper macros - slightly simplifies hand-generating entrypoints with EXT/ARB/etc. variants
3421 //----------------------------------------------------------------------------------------------------------------------
3422 #define SWITCH_GL_ENTRYPOINT2(e0, e1, ...) \
3423 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3424 result = GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3426 result = GL_ENTRYPOINT(e1)(__VA_ARGS__);
3428 #define SWITCH_GL_ENTRYPOINT3(e0, e1, e2, ...) \
3429 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3430 result = GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3431 else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3432 result = GL_ENTRYPOINT(e1)(__VA_ARGS__); \
3434 result = GL_ENTRYPOINT(e2)(__VA_ARGS__);
3436 #define SWITCH_GL_ENTRYPOINT2_VOID(e0, e1, ...) \
3437 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3438 GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3440 GL_ENTRYPOINT(e1)(__VA_ARGS__);
3442 #define SWITCH_GL_ENTRYPOINT3_VOID(e0, e1, e2, ...) \
3443 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3444 GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3445 else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3446 GL_ENTRYPOINT(e1)(__VA_ARGS__); \
3448 GL_ENTRYPOINT(e2)(__VA_ARGS__);
3450 //----------------------------------------------------------------------------------------------------------------------
3451 // vogl_replayer::process_gl_entrypoint_packet
3452 // This will be called during replaying, or when building display lists during state restoring.
3453 //----------------------------------------------------------------------------------------------------------------------
3454 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet(vogl_trace_packet& trace_packet)
3456 m_pCur_gl_packet = &trace_packet;
3458 status_t status = cStatusOK;
3460 if (m_pPending_snapshot)
3462 status = process_applying_pending_snapshot();
3463 if (status != cStatusOK)
3467 if (m_pending_make_current_packet.is_valid())
3469 status = process_pending_make_current();
3470 if (status != cStatusOK)
3474 const vogl_trace_gl_entrypoint_packet &entrypoint_packet = trace_packet.get_entrypoint_packet();
3476 m_last_parsed_call_counter = entrypoint_packet.m_call_counter;
3478 status = process_gl_entrypoint_packet_internal(trace_packet);
3480 if (status != cStatusResizeWindow)
3481 m_last_processed_call_counter = entrypoint_packet.m_call_counter;
3483 m_pCur_gl_packet = NULL;
3488 //----------------------------------------------------------------------------------------------------------------------
3489 // vogl_replayer::process_gl_entrypoint_packet_internal
3490 // This will be called during replaying, or when building display lists during state restoring.
3491 //----------------------------------------------------------------------------------------------------------------------
3492 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet_internal(vogl_trace_packet& trace_packet)
3496 m_at_frame_boundary = false;
3498 const vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = trace_packet.get_entrypoint_packet();
3499 const gl_entrypoint_id_t entrypoint_id = trace_packet.get_entrypoint_id();
3501 if (m_flags & cGLReplayerDebugMode)
3502 dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
3504 if (m_flags & cGLReplayerDebugMode)
3505 dump_packet_as_func_call(trace_packet);
3507 if (m_flags & cGLReplayerDumpAllPackets)
3508 print_detailed_context(cDebugConsoleMessage);
3510 if (entrypoint_id == VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
3511 return process_internal_trace_command(gl_entrypoint_packet);
3513 status_t status = cStatusOK;
3515 if (gl_entrypoint_packet.m_context_handle != m_cur_trace_context)
3517 status = switch_contexts(gl_entrypoint_packet.m_context_handle);
3518 if (status != cStatusOK)
3522 bool processed_glx_packet = true;
3523 switch (entrypoint_id)
3525 case VOGL_ENTRYPOINT_glXDestroyContext:
3527 const Display *dpy = m_pWindow->get_display();
3529 vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3530 GLXContext replay_context = remap_context(trace_context);
3532 if ((trace_context) && (!replay_context))
3534 process_entrypoint_error("%s: Failed remapping GL trace context 0x%" PRIx64 "\n", VOGL_METHOD_NAME, (uint64_t)trace_context);
3535 return cStatusHardFailure;
3538 if (trace_context == m_cur_trace_context)
3540 process_entrypoint_warning("%s: glXDestroyContext() called while trace context 0x%" PRIx64 " is still current, forcing it to not be current\n",
3541 VOGL_METHOD_NAME, (uint64_t)trace_context);
3543 m_cur_trace_context = 0;
3544 m_cur_replay_context = 0;
3545 m_pCur_context_state = NULL;
3548 GL_ENTRYPOINT(glXDestroyContext)(dpy, replay_context);
3550 destroy_context(trace_context);
3554 case VOGL_ENTRYPOINT_glXMakeCurrent:
3555 case VOGL_ENTRYPOINT_glXMakeContextCurrent:
3557 Bool trace_result = trace_packet.get_return_value<Bool>();
3559 vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
3561 // pContext_state can be NULL!
3562 context_state *pContext_state = get_trace_context_state(trace_context);
3563 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
3565 if ((trace_context) && (!replay_context))
3567 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
3568 return cStatusHardFailure;
3571 int viewport_x = trace_packet.get_key_value_map().get_int(string_hash("viewport_x"));
3572 VOGL_NOTE_UNUSED(viewport_x);
3573 int viewport_y = trace_packet.get_key_value_map().get_int(string_hash("viewport_y"));
3574 VOGL_NOTE_UNUSED(viewport_y);
3575 int viewport_width = trace_packet.get_key_value_map().get_int(string_hash("viewport_width"));
3576 VOGL_NOTE_UNUSED(viewport_width);
3577 int viewport_height = trace_packet.get_key_value_map().get_int(string_hash("viewport_height"));
3578 VOGL_NOTE_UNUSED(viewport_height);
3579 int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3580 int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3582 // We may need to defer the make current until the window is the proper size, because the initial GL viewport's state depends on the Window size. Ugh.
3583 if ((trace_context) && (trace_result))
3585 if ((win_width) && (win_height))
3587 if (!(m_flags & cGLReplayerLockWindowDimensions))
3589 if ((m_pWindow->get_width() != win_width) || (m_pWindow->get_height() != win_height))
3591 m_pending_make_current_packet = *m_pCur_gl_packet;
3593 status = trigger_pending_window_resize(win_width, win_height);
3595 vogl_printf("%s: Deferring glXMakeCurrent() until window resizes to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3601 if (status != cStatusResizeWindow)
3603 const Display *dpy = m_pWindow->get_display();
3604 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
3606 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
3611 process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
3612 return cStatusHardFailure;
3616 process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
3621 m_cur_trace_context = trace_context;
3622 m_cur_replay_context = replay_context;
3623 m_pCur_context_state = pContext_state;
3627 process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
3631 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
3632 viewport_x, viewport_y,
3633 viewport_width, viewport_height,
3634 win_width, win_height);
3637 if (m_cur_replay_context)
3639 if (!handle_context_made_current())
3640 return cStatusHardFailure;
3647 case VOGL_ENTRYPOINT_glXQueryVersion:
3649 int major = 0, minor = 0;
3650 Bool status = GL_ENTRYPOINT(glXQueryVersion)(m_pWindow->get_display(), &major, &minor);
3651 process_entrypoint_message("%s: glXQueryVersion returned major %u minor %u status %u, trace recorded major %u minor %u status %u\n", VOGL_METHOD_NAME, major, minor, status,
3652 *trace_packet.get_param_client_memory<int>(1),
3653 *trace_packet.get_param_client_memory<int>(2),
3654 trace_packet.get_return_value<Bool>());
3658 case VOGL_ENTRYPOINT_glXChooseFBConfig:
3663 case VOGL_ENTRYPOINT_glXGetFBConfigAttrib:
3668 case VOGL_ENTRYPOINT_glXGetVisualFromFBConfig:
3673 case VOGL_ENTRYPOINT_glXGetProcAddress:
3674 case VOGL_ENTRYPOINT_glXGetProcAddressARB:
3676 const GLubyte *procName = trace_packet.get_param_client_memory<GLubyte>(0);
3677 vogl_trace_ptr_value trace_func_ptr_value = trace_packet.get_return_ptr_value();
3679 void *pFunc = (void *)GL_ENTRYPOINT(glXGetProcAddress)(procName);
3681 if ((pFunc != NULL) != (trace_func_ptr_value != 0))
3683 process_entrypoint_warning("%s: glXGetProcAddress of function %s %s in the replay, but %s in the trace\n", VOGL_METHOD_NAME,
3684 (const char *)procName,
3685 (pFunc != NULL) ? "succeeded" : "failed",
3686 (trace_func_ptr_value != 0) ? "succeeded" : "failed");
3691 case VOGL_ENTRYPOINT_glXCreateNewContext:
3693 Display *dpy = m_pWindow->get_display();
3694 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3695 int render_type = trace_packet.get_param_value<GLint>(2);
3697 vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(3);
3698 GLXContext replay_share_context = remap_context(trace_share_context);
3700 if ((trace_share_context) && (!replay_share_context))
3702 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3705 Bool direct = trace_packet.get_param_value<Bool>(4);
3706 vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3708 if (m_flags & cGLReplayerForceDebugContexts)
3710 process_entrypoint_warning("%s: glxCreateNewContext() called but we're trying to force debug contexts, which requires us to call glXCreateContextAttribsARB(). This may fail if the user has called glXCreateWindow().\n", VOGL_METHOD_NAME);
3712 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3713 if (status != cStatusOK)
3718 GLXContext replay_context = GL_ENTRYPOINT(glXCreateNewContext)(dpy, fb_config, render_type, replay_share_context, direct);
3720 if (!replay_context)
3724 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3725 return cStatusHardFailure;
3729 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3737 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateNewContext, NULL, 0);
3738 VOGL_NOTE_UNUSED(pContext_state);
3742 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3749 case VOGL_ENTRYPOINT_glXCreateContext:
3751 Display *dpy = m_pWindow->get_display();
3753 vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3754 GLXContext replay_share_context = remap_context(trace_share_context);
3756 if ((trace_share_context) && (!replay_share_context))
3758 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3761 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3762 Bool direct = trace_packet.get_param_value<Bool>(3);
3763 vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3765 if (m_flags & cGLReplayerForceDebugContexts)
3767 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3768 if (status != cStatusOK)
3773 XVisualInfo *pVisual_info = GL_ENTRYPOINT(glXGetVisualFromFBConfig)(dpy, fb_config);
3775 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContext)(dpy, pVisual_info, replay_share_context, direct);
3777 if (!replay_context)
3781 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3782 return cStatusHardFailure;
3786 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3794 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContext, NULL, 0);
3795 VOGL_NOTE_UNUSED(pContext_state);
3799 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3806 case VOGL_ENTRYPOINT_glXCreateContextAttribsARB:
3808 Display *dpy = m_pWindow->get_display();
3809 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3811 vogl_trace_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3812 GLXContext replay_share_context = remap_context(trace_share_context);
3814 if ((trace_share_context) && (!replay_share_context))
3816 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3819 Bool direct = trace_packet.get_param_value<Bool>(3);
3820 const int *pTrace_attrib_list = static_cast<const int *>(trace_packet.get_param_client_memory_ptr(4));
3821 const uint trace_attrib_list_size = trace_packet.get_param_client_memory_data_size(4) / sizeof(int);
3823 vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3825 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, pTrace_attrib_list, trace_attrib_list_size, true);
3826 if (status != cStatusOK)
3831 case VOGL_ENTRYPOINT_glXSwapBuffers:
3833 check_program_binding_shadow();
3835 if (m_flags & cGLReplayerLowLevelDebugMode)
3837 if (!validate_program_and_shader_handle_tables())
3838 vogl_warning_printf("%s: Failed validating program/shaders against handle mapping tables\n", VOGL_METHOD_NAME);
3839 if (!validate_textures())
3840 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
3843 const Display *dpy = m_pWindow->get_display();
3844 GLXDrawable drawable = m_pWindow->get_xwindow();
3846 if ((m_flags & cGLReplayerHashBackbuffer) || (m_flags & cGLReplayerDumpScreenshots) || (m_flags & cGLReplayerDumpBackbufferHashes))
3848 snapshot_backbuffer();
3851 if (m_dump_frontbuffer_filename.has_content())
3853 dump_frontbuffer_to_file(m_dump_frontbuffer_filename);
3854 m_dump_frontbuffer_filename.clear();
3857 GL_ENTRYPOINT(glXSwapBuffers)(dpy, drawable);
3859 if (m_swap_sleep_time)
3860 vogl_sleep(m_swap_sleep_time);
3862 status = cStatusNextFrame;
3864 m_at_frame_boundary = true;
3866 if (m_flags & cGLReplayerDebugMode)
3868 vogl_debug_printf("%s: glXSwapBuffers() processed at end of frame %u, swap %u, last GL call counter %" PRIu64 "\n", VOGL_METHOD_NAME, m_frame_index, m_total_swaps, m_last_parsed_call_counter);
3874 m_frame_draw_counter = 0;
3876 int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3877 int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3878 if ((win_width) && (win_height))
3880 if (!(m_flags & cGLReplayerLockWindowDimensions))
3882 if ((win_width != m_pWindow->get_width()) || (win_height != m_pWindow->get_height()))
3884 // TODO: This resize might need to be deferred until the window system actually resizes the window.
3885 //m_pWindow->resize(win_width, win_height);
3886 trigger_pending_window_resize(win_width, win_height);
3888 vogl_printf("%s: Resizing window after swap to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3895 case VOGL_ENTRYPOINT_glXWaitX:
3897 VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitX;
3899 VOGL_REPLAY_CALL_GL_HELPER_glXWaitX;
3903 case VOGL_ENTRYPOINT_glXWaitGL:
3905 VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitGL;
3907 VOGL_REPLAY_CALL_GL_HELPER_glXWaitGL;
3911 case VOGL_ENTRYPOINT_glXIsDirect:
3913 const Display *dpy = m_pWindow->get_display();
3915 vogl_trace_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3916 GLXContext replay_context = remap_context(trace_context);
3918 Bool replay_is_direct = GL_ENTRYPOINT(glXIsDirect)(dpy, replay_context);
3919 Bool trace_is_direct = trace_packet.get_return_value<Bool>();
3921 if (replay_is_direct != trace_is_direct)
3923 process_entrypoint_warning("%s: glXIsDirect() returned different results while replaying (%u) vs tracing (%u)!\n", VOGL_METHOD_NAME, replay_is_direct, trace_is_direct);
3928 case VOGL_ENTRYPOINT_glXGetCurrentContext:
3930 GLXContext replay_context = GL_ENTRYPOINT(glXGetCurrentContext)();
3931 vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3933 if ((replay_context != 0) != (trace_context != 0))
3935 process_entrypoint_warning("%s: glXGetCurrentContext() returned different results while replaying (0x%" PRIX64 ") vs tracing (0x%" PRIX64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_context, (uint64_t)trace_context);
3940 case VOGL_ENTRYPOINT_glXCreateWindow:
3941 case VOGL_ENTRYPOINT_glXDestroyWindow:
3942 case VOGL_ENTRYPOINT_glXChooseVisual:
3943 case VOGL_ENTRYPOINT_glXGetCurrentDisplay:
3944 case VOGL_ENTRYPOINT_glXQueryDrawable:
3945 case VOGL_ENTRYPOINT_glXQueryExtension:
3946 case VOGL_ENTRYPOINT_glXQueryExtensionsString:
3947 case VOGL_ENTRYPOINT_glXSwapIntervalEXT:
3948 case VOGL_ENTRYPOINT_glXSwapIntervalSGI:
3949 case VOGL_ENTRYPOINT_glXGetCurrentDrawable:
3950 case VOGL_ENTRYPOINT_glXGetCurrentReadDrawable:
3951 case VOGL_ENTRYPOINT_glXQueryContext:
3952 case VOGL_ENTRYPOINT_glXGetClientString:
3953 case VOGL_ENTRYPOINT_glXGetConfig:
3954 case VOGL_ENTRYPOINT_glXGetFBConfigs:
3961 processed_glx_packet = false;
3966 if (processed_glx_packet)
3968 // TODO: Check for GLX errors?
3972 if (!m_cur_replay_context)
3974 process_entrypoint_error("%s: Trace contains a GL call with no current context! Skipping call.\n", VOGL_METHOD_NAME);
3975 return cStatusSoftFailure;
3978 VOGL_ASSERT(m_pCur_context_state);
3979 m_pCur_context_state->m_last_call_counter = m_last_parsed_call_counter;
3981 #ifdef VOGL_BUILD_DEBUG
3982 VOGL_ASSERT(get_trace_context_state(m_cur_trace_context) == m_pCur_context_state);
3985 // Add call to current display list
3986 if ((get_context_state()->is_composing_display_list()) && (g_vogl_entrypoint_descs[entrypoint_id].m_is_listable))
3988 if (!vogl_display_list_state::is_call_listable(entrypoint_id, trace_packet))
3990 if (!g_vogl_entrypoint_descs[entrypoint_id].m_whitelisted_for_displaylists)
3991 process_entrypoint_error("%s: Failed serializing trace packet into display list shadow! Call is not listable.\n", VOGL_FUNCTION_NAME);
3993 process_entrypoint_warning("%s: Failed serializing trace packet into display list shadow! Call with these parameters is not listable.\n", VOGL_FUNCTION_NAME);
3997 if (!get_shared_state()->m_shadow_state.m_display_lists.add_packet_to_list(get_context_state()->m_current_display_list_handle, entrypoint_id, trace_packet))
3999 process_entrypoint_warning("%s: Failed adding current packet to display list shadow!\n", VOGL_METHOD_NAME);
4004 switch (entrypoint_id)
4006 // ----- Create simple auto-generated replay funcs - voglgen creates this inc file from the funcs in gl_glx_simple_replay_funcs.txt
4007 // These simple GL entrypoints only take value params that don't require handle remapping, or simple pointers to client memory
4008 // (typically pointers to fixed size buffers, or params directly controlling the size of buffers).
4009 #define VOGL_SIMPLE_REPLAY_FUNC_BEGIN(name, num_params) \
4010 case VOGL_ENTRYPOINT_##name: \
4011 { if (!GL_ENTRYPOINT(name)) { process_entrypoint_error("vogl_gl_replayer::process_gl_entrypoint_packet_internal: Can't call NULL GL entrypoint %s (maybe a missing extension?)\n", #name); } else \
4012 GL_ENTRYPOINT(name)(
4013 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE(type, index) trace_packet.get_param_value<type>(index)
4014 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR ,
4015 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY(type, index) trace_packet.get_param_client_memory<type>(index)
4016 #define VOGL_SIMPLE_REPLAY_FUNC_END(name) ); \
4019 #include "gl_glx_simple_replay_funcs.inc"
4020 #undef VOGL_SIMPLE_REPLAY_FUNC_BEGIN
4021 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE
4022 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR
4023 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY
4024 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_END
4026 case VOGL_ENTRYPOINT_glXUseXFont:
4028 const key_value_map &key_value_map = trace_packet.get_key_value_map();
4030 const dynamic_string *pFont_name = key_value_map.get_string_ptr("font_name");
4031 if ((!pFont_name) || (pFont_name->is_empty()))
4033 process_entrypoint_warning("%s: Couldn't find font_name key, or key was empty - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME);
4037 XFontStruct *pFont = XLoadQueryFont(m_pWindow->get_display(), pFont_name->get_ptr());
4040 process_entrypoint_warning("%s: Couldn't load X font %s - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME, pFont_name->get_ptr());
4044 GLint first = trace_packet.get_param_value<int>(1);
4045 GLint count = trace_packet.get_param_value<int>(2);
4046 int trace_list_base = trace_packet.get_param_value<int>(3);
4047 GLuint replay_list_base = map_handle(get_shared_state()->m_lists, trace_list_base);
4049 GL_ENTRYPOINT(glXUseXFont)(pFont->fid, first, count, replay_list_base);
4051 XFreeFont(m_pWindow->get_display(), pFont);
4053 if (get_context_state()->is_composing_display_list())
4055 process_entrypoint_warning("%s: glXUseXFont() called while composing a display list!\n", VOGL_METHOD_NAME);
4059 if (!get_shared_state()->m_shadow_state.m_display_lists.glx_font(pFont_name->get_ptr(), first, count, trace_list_base))
4061 process_entrypoint_warning("%s: Failed updating display list shadow\n", VOGL_METHOD_NAME);
4069 case VOGL_ENTRYPOINT_glBlitFramebufferEXT:
4071 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebufferEXT;
4073 VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebufferEXT;
4075 if ((status = post_draw_call()) != cStatusOK)
4080 case VOGL_ENTRYPOINT_glBlitFramebuffer:
4082 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebuffer;
4084 VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebuffer;
4086 if ((status = post_draw_call()) != cStatusOK)
4091 case VOGL_ENTRYPOINT_glBegin:
4093 if (m_pCur_context_state->m_inside_gl_begin)
4095 process_entrypoint_warning("%s: Got a glBegin while already inside a glBegin\n", VOGL_METHOD_NAME);
4097 m_pCur_context_state->m_inside_gl_begin = true;
4099 g_vogl_actual_gl_entrypoints.m_glBegin(trace_packet.get_param_value<GLenum>(0));
4103 case VOGL_ENTRYPOINT_glEnd:
4105 if (!m_pCur_context_state->m_inside_gl_begin)
4107 process_entrypoint_warning("%s: Got glEnd without a matching glBegin\n", VOGL_METHOD_NAME);
4109 m_pCur_context_state->m_inside_gl_begin = false;
4111 g_vogl_actual_gl_entrypoints.m_glEnd();
4113 if ((status = post_draw_call()) != cStatusOK)
4118 case VOGL_ENTRYPOINT_glGetError:
4120 // TODO: Compare trace error vs. replay error
4124 case VOGL_ENTRYPOINT_glGetStringi:
4126 if (!benchmark_mode())
4128 const GLubyte *pStr = GL_ENTRYPOINT(glGetStringi)(
4129 trace_packet.get_param_value<GLenum>(0),
4130 trace_packet.get_param_value<GLuint>(1));
4131 VOGL_NOTE_UNUSED(pStr);
4133 // TODO: Compare vs. trace's?
4138 case VOGL_ENTRYPOINT_glGetString:
4140 if (!benchmark_mode())
4142 const GLubyte *pStr = GL_ENTRYPOINT(glGetString)(
4143 trace_packet.get_param_value<GLenum>(0));
4144 VOGL_NOTE_UNUSED(pStr);
4146 // TODO: Compare vs. trace's?
4151 case VOGL_ENTRYPOINT_glGenFramebuffers:
4152 case VOGL_ENTRYPOINT_glGenFramebuffersEXT:
4154 if (!gen_handles(get_context_state()->m_framebuffers,
4155 trace_packet.get_param_value<GLsizei>(0),
4156 static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)),
4157 (entrypoint_id == VOGL_ENTRYPOINT_glGenFramebuffers) ? GL_ENTRYPOINT(glGenFramebuffers) : GL_ENTRYPOINT(glGenFramebuffersEXT), NULL))
4158 return cStatusHardFailure;
4162 case VOGL_ENTRYPOINT_glBindFramebuffer:
4163 case VOGL_ENTRYPOINT_glBindFramebufferEXT:
4165 GLenum target = trace_packet.get_param_value<GLenum>(0);
4166 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
4168 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
4170 SWITCH_GL_ENTRYPOINT2_VOID(glBindFramebuffer, glBindFramebufferEXT, target, replay_handle);
4174 case VOGL_ENTRYPOINT_glGetRenderbufferParameterivEXT:
4175 case VOGL_ENTRYPOINT_glGetRenderbufferParameteriv:
4177 if (!benchmark_mode())
4179 GLenum target = trace_packet.get_param_value<GLenum>(0);
4180 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4181 GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(2);
4182 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
4183 uint trace_params_count = trace_params_size / sizeof(GLint);
4185 int n = g_gl_enums.get_pname_count(pname);
4188 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4189 return cStatusSoftFailure;
4191 else if (n < static_cast<int>(trace_params_count))
4193 process_entrypoint_error("%s: Expected %i GLint's for GL pname 0x%08X, but trace only contains %i GLint's\n", VOGL_METHOD_NAME, n, pname, trace_params_count);
4194 return cStatusSoftFailure;
4198 vogl::growable_array<GLint, 16> params(n + 1);
4199 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4201 SWITCH_GL_ENTRYPOINT2_VOID(glGetRenderbufferParameteriv, glGetRenderbufferParameterivEXT, target, pname, params.get_ptr());
4203 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4205 if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
4207 process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s target %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname), g_gl_enums.find_gl_name(target));
4214 case VOGL_ENTRYPOINT_glCheckFramebufferStatus:
4215 case VOGL_ENTRYPOINT_glCheckFramebufferStatusEXT:
4218 SWITCH_GL_ENTRYPOINT2(glCheckFramebufferStatus, glCheckFramebufferStatusEXT, trace_packet.get_param_value<GLenum>(0));
4220 GLenum trace_status = trace_packet.get_return_value<GLenum>();
4221 if (result != trace_status)
4223 process_entrypoint_warning("%s: glCheckFramebufferStatus returned status 0x%08X during trace, but status 0x%08X during replay\n", VOGL_METHOD_NAME, trace_status, result);
4227 case VOGL_ENTRYPOINT_glDeleteFramebuffers:
4229 delete_handles(get_context_state()->m_framebuffers, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteFramebuffers));
4232 case VOGL_ENTRYPOINT_glDeleteFramebuffersEXT:
4234 delete_handles(get_context_state()->m_framebuffers, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteFramebuffersEXT));
4237 case VOGL_ENTRYPOINT_glFramebufferTexture:
4239 GLenum target = trace_packet.get_param_value<GLenum>(0);
4240 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4241 GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4242 GLuint replay_texture = trace_texture;
4243 GLint level = trace_packet.get_param_value<GLint>(3);
4245 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4248 process_entrypoint_warning("%s: Couldn't map trace texture ID %u to GL texture ID, using trace texture ID instead\n", VOGL_METHOD_NAME, trace_texture);
4251 GL_ENTRYPOINT(glFramebufferTexture)(target, attachment, replay_texture, level);
4255 case VOGL_ENTRYPOINT_glFramebufferTextureLayer:
4256 case VOGL_ENTRYPOINT_glFramebufferTextureLayerEXT:
4258 GLenum target = trace_packet.get_param_value<GLenum>(0);
4259 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4260 GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4261 GLuint replay_texture = trace_texture;
4262 GLint level = trace_packet.get_param_value<GLint>(3);
4263 GLint layer = trace_packet.get_param_value<GLint>(4);
4265 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4268 process_entrypoint_warning("%s: Couldn't map trace texture ID %u to GL texture ID, using trace texture ID instead\n", VOGL_METHOD_NAME, trace_texture);
4271 SWITCH_GL_ENTRYPOINT2_VOID(glFramebufferTextureLayer, glFramebufferTextureLayerEXT, target, attachment, replay_texture, level, layer);
4275 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4276 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4277 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4278 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4279 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4280 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4282 GLenum target = trace_packet.get_param_value<GLenum>(0);
4283 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4284 GLenum textarget = trace_packet.get_param_value<GLenum>(2);
4285 GLuint trace_texture = trace_packet.get_param_value<GLuint>(3);
4286 GLuint replay_texture = trace_texture;
4287 GLint level = trace_packet.get_param_value<GLint>(4);
4289 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4292 process_entrypoint_warning("%s: Couldn't map trace texture ID %u to GL texture ID, using trace texture ID instead\n", VOGL_METHOD_NAME, trace_texture);
4295 switch (entrypoint_id)
4297 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4298 GL_ENTRYPOINT(glFramebufferTexture1DEXT)(target, attachment, textarget, replay_texture, level);
4300 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4301 GL_ENTRYPOINT(glFramebufferTexture1D)(target, attachment, textarget, replay_texture, level);
4303 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4304 GL_ENTRYPOINT(glFramebufferTexture2DEXT)(target, attachment, textarget, replay_texture, level);
4306 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4307 GL_ENTRYPOINT(glFramebufferTexture2D)(target, attachment, textarget, replay_texture, level);
4309 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4310 GL_ENTRYPOINT(glFramebufferTexture3DEXT)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4312 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4313 GL_ENTRYPOINT(glFramebufferTexture3D)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4321 case VOGL_ENTRYPOINT_glGenTextures:
4323 if (!gen_handles(get_shared_state()->m_shadow_state.m_textures, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenTextures), NULL, GL_NONE))
4324 return cStatusHardFailure;
4327 case VOGL_ENTRYPOINT_glGenTexturesEXT:
4329 if (!gen_handles(get_shared_state()->m_shadow_state.m_textures, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenTexturesEXT), NULL, GL_NONE))
4330 return cStatusHardFailure;
4333 case VOGL_ENTRYPOINT_glDeleteTextures:
4335 delete_handles(get_shared_state()->m_shadow_state.m_textures, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteTextures));
4338 case VOGL_ENTRYPOINT_glDeleteTexturesEXT:
4340 delete_handles(get_shared_state()->m_shadow_state.m_textures, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteTexturesEXT));
4343 case VOGL_ENTRYPOINT_glBindMultiTextureEXT:
4345 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindMultiTextureEXT;
4347 GLuint trace_texture = texture;
4348 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4350 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4353 VOGL_REPLAY_CALL_GL_HELPER_glBindMultiTextureEXT;
4355 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4357 if (!check_gl_error())
4358 get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4363 case VOGL_ENTRYPOINT_glBindTexture:
4364 case VOGL_ENTRYPOINT_glBindTextureEXT:
4366 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindTexture;
4368 GLuint trace_texture = texture;
4369 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4371 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4374 SWITCH_GL_ENTRYPOINT2_VOID(glBindTexture, glBindTextureEXT, target, texture);
4376 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4378 if (!check_gl_error())
4379 get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4384 case VOGL_ENTRYPOINT_glBindSampler:
4386 GLuint replay_handle = map_handle(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLuint>(1));
4387 GL_ENTRYPOINT(glBindSampler)(trace_packet.get_param_value<GLuint>(0), replay_handle);
4390 case VOGL_ENTRYPOINT_glDeleteSamplers:
4392 delete_handles(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteSamplers));
4395 case VOGL_ENTRYPOINT_glGenSamplers:
4397 if (!gen_handles(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenSamplers), NULL))
4398 return cStatusHardFailure;
4402 case VOGL_ENTRYPOINT_glSamplerParameterf:
4404 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterf;
4405 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4406 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterf;
4409 case VOGL_ENTRYPOINT_glSamplerParameteri:
4411 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteri;
4412 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4413 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteri;
4416 case VOGL_ENTRYPOINT_glSamplerParameterfv:
4418 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterfv;
4419 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4420 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterfv;
4423 case VOGL_ENTRYPOINT_glSamplerParameteriv:
4425 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteriv;
4426 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4427 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteriv;
4430 case VOGL_ENTRYPOINT_glSamplerParameterIiv:
4432 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIiv;
4433 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4434 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIiv;
4437 case VOGL_ENTRYPOINT_glSamplerParameterIuiv:
4439 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIuiv;
4440 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4441 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIuiv;
4444 case VOGL_ENTRYPOINT_glGenBuffers:
4445 case VOGL_ENTRYPOINT_glGenBuffersARB:
4447 uint n = trace_packet.get_param_value<GLsizei>(0);
4448 const GLuint *pTrace_handles = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4450 if (entrypoint_id == VOGL_ENTRYPOINT_glGenBuffers)
4452 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffers), NULL))
4453 return cStatusHardFailure;
4457 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffersARB), NULL))
4458 return cStatusHardFailure;
4463 for (uint i = 0; i < n; i++)
4465 if (pTrace_handles[i])
4466 get_shared_state()->m_buffer_targets.insert(pTrace_handles[i], GL_NONE);
4472 case VOGL_ENTRYPOINT_glDeleteBuffers:
4473 case VOGL_ENTRYPOINT_glDeleteBuffersARB:
4475 GLsizei trace_n = trace_packet.get_param_value<GLsizei>(0);
4476 const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4477 uint trace_ids_count = trace_packet.get_param_client_memory_data_size(1);
4479 if ((pTrace_ids) && (static_cast<GLsizei>(trace_ids_count) < trace_n))
4481 process_entrypoint_warning("%s: trace_ids trace array is too small\n", VOGL_METHOD_NAME);
4482 return cStatusHardFailure;
4485 for (GLsizei iter = 0; iter < trace_n; iter++)
4487 GLuint trace_id = pTrace_ids[iter];
4491 if (!get_shared_state()->m_buffer_targets.erase(trace_id))
4493 process_entrypoint_warning("%s: Couldn't find trace buffer id %u in buffer target map!\n", VOGL_METHOD_NAME, trace_id);
4496 gl_handle_hash_map::const_iterator it = get_shared_state()->m_buffers.find(trace_id);
4497 if (it == get_shared_state()->m_buffers.end())
4499 process_entrypoint_warning("%s: Couldn't map trace buffer id %u to GL buffer id\n", VOGL_METHOD_NAME, trace_id);
4503 GLuint replay_id = it->second;
4505 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
4507 for (uint i = 0; i < mapped_bufs.size(); i++)
4509 if (mapped_bufs[i].m_buffer == replay_id)
4511 process_entrypoint_warning("%s: glDeleteBuffers() called on mapped trace buffer %u GL buffer %u\n", VOGL_METHOD_NAME, trace_id, replay_id);
4513 mapped_bufs.erase_unordered(i);
4519 if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteBuffers)
4520 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffers));
4522 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffersARB));
4526 case VOGL_ENTRYPOINT_glGenProgramsARB:
4528 // arb program objects
4529 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGenProgramsARB;
4531 if (!gen_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glGenProgramsARB), NULL))
4532 return cStatusHardFailure;
4534 for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4535 if (pTrace_programs[i])
4536 get_shared_state()->m_arb_program_targets.insert(pTrace_programs[i], GL_NONE);
4540 case VOGL_ENTRYPOINT_glDeleteProgramsARB:
4542 // arb program objects
4543 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDeleteProgramsARB;
4545 for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4546 get_shared_state()->m_arb_program_targets.erase(pTrace_programs[i]);
4548 delete_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glDeleteProgramsARB));
4551 case VOGL_ENTRYPOINT_glBindProgramARB:
4553 // arb program objects
4554 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindProgramARB;
4556 GLuint trace_program = program;
4557 gl_handle_hash_map::const_iterator it;
4560 it = get_shared_state()->m_arb_programs.find(program);
4561 if (it != get_shared_state()->m_arb_programs.end())
4562 program = it->second;
4564 process_entrypoint_warning("%s: Couldn't map trace handle %u to GL handle, using trace handle instead (handle may not have been genned)\n", VOGL_METHOD_NAME, program);
4569 VOGL_REPLAY_CALL_GL_HELPER_glBindProgramARB;
4571 if (!check_gl_error() && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4575 if (it == get_shared_state()->m_arb_programs.end())
4576 get_shared_state()->m_arb_programs.insert(trace_program, program);
4578 get_shared_state()->m_arb_program_targets[trace_program] = target;
4583 process_entrypoint_warning("%s: GL error while binding ARB program, trace handle %u GL handle %u target %s\n", VOGL_METHOD_NAME, trace_program, program, g_gl_enums.find_gl_name(target));
4584 return cStatusGLError;
4589 case VOGL_ENTRYPOINT_glIsProgramARB:
4591 if (!benchmark_mode())
4593 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIsProgramARB;
4595 GLuint trace_program = program;
4596 program = map_handle(get_shared_state()->m_arb_programs, program);
4598 GLboolean replay_result = VOGL_REPLAY_CALL_GL_HELPER_glIsProgramARB;
4599 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4601 if (trace_result != replay_result)
4602 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u, trace ARB program: %u replay ARB program %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result), trace_program, program);
4607 case VOGL_ENTRYPOINT_glGenQueries:
4608 case VOGL_ENTRYPOINT_glGenQueriesARB:
4610 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4611 vogl::growable_array<GLuint, 16> replay_handles(n);
4613 if (!gen_handles(get_shared_state()->m_queries, n, static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), (entrypoint_id == VOGL_ENTRYPOINT_glGenQueries) ? GL_ENTRYPOINT(glGenQueries) : GL_ENTRYPOINT(glGenQueriesARB), replay_handles.get_ptr()))
4614 return cStatusHardFailure;
4616 for (GLsizei i = 0; i < n; i++)
4617 get_shared_state()->m_query_targets[replay_handles[i]] = GL_NONE;
4621 case VOGL_ENTRYPOINT_glDeleteQueries:
4622 case VOGL_ENTRYPOINT_glDeleteQueriesARB:
4624 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4625 const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4629 for (GLsizei i = 0; i < n; i++)
4631 GLuint trace_id = pTrace_ids[i];
4634 gl_handle_hash_map::const_iterator it(get_shared_state()->m_queries.find(trace_id));
4635 if (it != get_shared_state()->m_queries.end())
4636 get_shared_state()->m_query_targets.erase(it->second);
4640 if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteQueries)
4641 delete_handles(get_shared_state()->m_queries, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteQueries));
4643 delete_handles(get_shared_state()->m_queries, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteQueriesARB));
4647 case VOGL_ENTRYPOINT_glGenRenderbuffersEXT:
4649 if (!gen_handles(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenRenderbuffersEXT), NULL, GL_NONE))
4650 return cStatusHardFailure;
4653 case VOGL_ENTRYPOINT_glGenRenderbuffers:
4655 if (!gen_handles(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenRenderbuffers), NULL, GL_NONE))
4656 return cStatusHardFailure;
4659 case VOGL_ENTRYPOINT_glDeleteRenderbuffersEXT:
4661 delete_handles(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteRenderbuffersEXT));
4664 case VOGL_ENTRYPOINT_glDeleteRenderbuffers:
4666 delete_handles(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteRenderbuffers));
4669 case VOGL_ENTRYPOINT_glIsRenderbuffer:
4671 if (!benchmark_mode())
4673 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbuffer)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4674 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4675 if (replay_result != trace_result)
4677 process_entrypoint_warning("%s: Replay's returned GLboolean data differed from trace's (got %i, expected %i)\n", VOGL_METHOD_NAME, replay_result, replay_result);
4682 case VOGL_ENTRYPOINT_glIsRenderbufferEXT:
4684 if (!benchmark_mode())
4686 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbufferEXT)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4687 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4688 if (replay_result != trace_result)
4690 process_entrypoint_warning("%s: Replay's returned GLboolean data differed from trace's (got %i, expected %i)\n", VOGL_METHOD_NAME, replay_result, replay_result);
4695 case VOGL_ENTRYPOINT_glBindRenderbufferEXT:
4697 GL_ENTRYPOINT(glBindRenderbufferEXT)(trace_packet.get_param_value<GLenum>(0), map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(1)));
4700 case VOGL_ENTRYPOINT_glBindRenderbuffer:
4702 GL_ENTRYPOINT(glBindRenderbuffer)(trace_packet.get_param_value<GLenum>(0), map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(1)));
4705 case VOGL_ENTRYPOINT_glFramebufferRenderbufferEXT:
4707 GL_ENTRYPOINT(glFramebufferRenderbufferEXT)(
4708 trace_packet.get_param_value<GLenum>(0),
4709 trace_packet.get_param_value<GLenum>(1),
4710 trace_packet.get_param_value<GLenum>(2),
4711 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4714 case VOGL_ENTRYPOINT_glFramebufferRenderbuffer:
4716 GL_ENTRYPOINT(glFramebufferRenderbuffer)(
4717 trace_packet.get_param_value<GLenum>(0),
4718 trace_packet.get_param_value<GLenum>(1),
4719 trace_packet.get_param_value<GLenum>(2),
4720 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4723 case VOGL_ENTRYPOINT_glUseProgramObjectARB:
4724 case VOGL_ENTRYPOINT_glUseProgram:
4726 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4727 handle_use_program(trace_handle, entrypoint_id);
4730 case VOGL_ENTRYPOINT_glProgramParameteri:
4731 case VOGL_ENTRYPOINT_glProgramParameteriARB:
4732 case VOGL_ENTRYPOINT_glProgramParameteriEXT:
4734 VOGL_REPLAY_LOAD_PARAMS_HELPER_glProgramParameteri;
4736 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4738 if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriARB)
4739 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriARB;
4740 else if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriEXT)
4741 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriEXT;
4743 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteri;
4747 case VOGL_ENTRYPOINT_glBindFragDataLocation:
4748 case VOGL_ENTRYPOINT_glBindFragDataLocationEXT:
4750 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocation;
4752 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4754 if (entrypoint_id == VOGL_ENTRYPOINT_glBindFragDataLocation)
4755 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocation;
4757 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationEXT;
4761 case VOGL_ENTRYPOINT_glBindFragDataLocationIndexed:
4763 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocationIndexed;
4765 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4767 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationIndexed;
4771 case VOGL_ENTRYPOINT_glValidateProgramARB:
4773 VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgramARB;
4775 programObj = map_handle(get_shared_state()->m_shadow_state.m_objs, programObj);
4777 VOGL_REPLAY_CALL_GL_HELPER_glValidateProgramARB;
4781 case VOGL_ENTRYPOINT_glValidateProgram:
4783 VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgram;
4785 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4787 VOGL_REPLAY_CALL_GL_HELPER_glValidateProgram;
4791 case VOGL_ENTRYPOINT_glCreateProgram:
4792 case VOGL_ENTRYPOINT_glCreateProgramObjectARB:
4794 GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4797 GLuint replay_handle;
4799 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateProgram)
4800 replay_handle = GL_ENTRYPOINT(glCreateProgram)();
4802 replay_handle = GL_ENTRYPOINT(glCreateProgramObjectARB)();
4804 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0));
4806 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_PROGRAM_OBJECT))
4807 return cStatusHardFailure;
4811 case VOGL_ENTRYPOINT_glDeleteProgram:
4813 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4814 handle_delete_program(trace_handle);
4818 case VOGL_ENTRYPOINT_glDeleteObjectARB:
4820 GLuint trace_handle = trace_packet.get_param_value<GLenum>(0);
4821 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle);
4823 if (target == VOGL_SHADER_OBJECT)
4824 handle_delete_shader(trace_handle);
4825 else if (target == VOGL_PROGRAM_OBJECT)
4826 handle_delete_program(trace_handle);
4829 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
4831 process_entrypoint_error("%s: Failed determining if trace handle %u relay handle %u is a shader or program -- unable to delete object!\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
4832 return cStatusSoftFailure;
4837 case VOGL_ENTRYPOINT_glDeleteShader:
4839 GLuint trace_shader = trace_packet.get_param_value<GLuint>(0);
4840 handle_delete_shader(trace_shader);
4844 case VOGL_ENTRYPOINT_glCreateShader:
4845 case VOGL_ENTRYPOINT_glCreateShaderObjectARB:
4847 GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4850 GLuint replay_handle;
4852 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateShader)
4853 replay_handle = GL_ENTRYPOINT(glCreateShader)(trace_packet.get_param_value<GLenum>(0));
4855 replay_handle = GL_ENTRYPOINT(glCreateShaderObjectARB)(trace_packet.get_param_value<GLenum>(0));
4857 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsShader)(replay_handle) != 0));
4859 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_SHADER_OBJECT))
4860 return cStatusHardFailure;
4864 case VOGL_ENTRYPOINT_glAttachShader:
4866 GL_ENTRYPOINT(glAttachShader)(
4867 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4868 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(1)));
4871 case VOGL_ENTRYPOINT_glAttachObjectARB:
4873 GL_ENTRYPOINT(glAttachObjectARB)(
4874 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4875 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(1)));
4878 case VOGL_ENTRYPOINT_glDetachShader:
4880 handle_detach_shader(entrypoint_id);
4884 case VOGL_ENTRYPOINT_glDetachObjectARB:
4886 GLhandleARB trace_object_handle = trace_packet.get_param_value<GLhandleARB>(1);
4888 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_object_handle);
4890 if (target == VOGL_SHADER_OBJECT)
4891 handle_detach_shader(entrypoint_id);
4894 GLuint replay_object_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object_handle);
4895 GL_ENTRYPOINT(glDetachObjectARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)), replay_object_handle);
4900 case VOGL_ENTRYPOINT_glBindAttribLocation:
4902 GL_ENTRYPOINT(glBindAttribLocation)(
4903 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4904 trace_packet.get_param_value<GLuint>(1),
4905 trace_packet.get_param_client_memory<GLchar>(2));
4908 case VOGL_ENTRYPOINT_glBindAttribLocationARB:
4910 GL_ENTRYPOINT(glBindAttribLocationARB)(
4911 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4912 trace_packet.get_param_value<GLuint>(1),
4913 trace_packet.get_param_client_memory<GLcharARB>(2));
4916 case VOGL_ENTRYPOINT_glGetObjectParameterivARB:
4918 if (!benchmark_mode())
4920 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4921 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
4923 int n = g_gl_enums.get_pname_count(pname);
4926 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4927 return cStatusSoftFailure;
4931 vogl::growable_array<GLint, 16> params(n + 1);
4932 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4934 GL_ENTRYPOINT(glGetObjectParameterivARB)(
4935 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4939 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4941 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
4943 process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname));
4949 case VOGL_ENTRYPOINT_glGetBufferParameteriv:
4951 if (!benchmark_mode())
4953 GLenum target = trace_packet.get_param_value<GLenum>(0);
4954 GLenum value = trace_packet.get_param_value<GLenum>(1);
4955 const GLint *pTrace_data = trace_packet.get_param_client_memory<GLint>(2);
4957 int n = g_gl_enums.get_pname_count(value);
4960 process_entrypoint_error("%s: Can't determine count of GL value 0x%08X\n", VOGL_METHOD_NAME, value);
4961 return cStatusSoftFailure;
4965 vogl::growable_array<GLint, 16> data(n + 1);
4966 data[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4968 GL_ENTRYPOINT(glGetBufferParameteriv)(target, value, data.get_ptr());
4970 VOGL_VERIFY(data[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4972 GLint trace_data = pTrace_data ? pTrace_data[0] : -1;
4973 if (data[0] != trace_data)
4975 process_entrypoint_warning("%s: Replay's returned GLint differed from trace's!\n", VOGL_METHOD_NAME);
4976 vogl_warning_printf("Trace data: %i, Replay data: %i\n", trace_data, data[0]);
4984 case VOGL_ENTRYPOINT_glGetBufferPointerv:
4986 if (!benchmark_mode())
4988 GLvoid *pReplay_ptr = NULL;
4989 GL_ENTRYPOINT(glGetBufferPointerv)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLenum>(1), &pReplay_ptr);
4991 vogl_client_memory_array trace_void_ptr_array = trace_packet.get_param_client_memory_array(2);
4992 vogl_trace_ptr_value first_trace_ptr = trace_void_ptr_array.get_ptr() ? trace_void_ptr_array.get_element<vogl_trace_ptr_value>(0) : 0;
4994 if ((pReplay_ptr != NULL) != (first_trace_ptr != 0))
4996 process_entrypoint_warning("%s: First replay's returned GLvoid* differed from trace's!\n", VOGL_METHOD_NAME);
4997 vogl_warning_printf("Trace: 0x%" PRIx64 ", Replay: 0x%" PRIx64 "\n", first_trace_ptr, reinterpret_cast<uint64_t>(pReplay_ptr));
5003 case VOGL_ENTRYPOINT_glShaderSource:
5004 case VOGL_ENTRYPOINT_glShaderSourceARB:
5006 const status_t status = handle_ShaderSource(trace_packet.get_param_value<GLhandleARB>(0),
5007 trace_packet.get_param_value<GLsizei>(1),
5008 trace_packet.get_param_client_memory_array(2),
5009 trace_packet.get_param_client_memory<const GLint>(3));
5010 if (status != cStatusOK)
5014 case VOGL_ENTRYPOINT_glGetProgramInfoLog:
5016 GLuint trace_object = trace_packet.get_param_value<GLuint>(0);
5017 GLuint replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5020 GL_ENTRYPOINT(glGetProgramiv)(replay_object, GL_INFO_LOG_LENGTH, &length);
5023 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5024 return cStatusSoftFailure;
5028 vogl::vector<GLchar> log(length);
5030 GLsizei actual_length = 0;
5031 GL_ENTRYPOINT(glGetProgramInfoLog)(replay_object, length, &actual_length, log.get_ptr());
5035 process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_object, replay_object, log.get_ptr());
5041 case VOGL_ENTRYPOINT_glGetPointerv:
5043 if (!benchmark_mode())
5046 GL_ENTRYPOINT(glGetPointerv)(trace_packet.get_param_value<GLenum>(0), &ptr);
5048 // TODO: Differ vs. trace's in some way?
5053 case VOGL_ENTRYPOINT_glGetInfoLogARB:
5055 GLhandleARB trace_object = trace_packet.get_param_value<GLhandleARB>(0);
5056 GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5058 GLsizei length = -1;
5059 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
5062 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5063 return cStatusSoftFailure;
5067 vogl::vector<GLcharARB> log(length);
5069 GLsizei actual_length = 0;
5070 GL_ENTRYPOINT(glGetInfoLogARB)(replay_object, length, &actual_length, log.get_ptr());
5074 process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_object, replay_object, log.get_ptr());
5080 case VOGL_ENTRYPOINT_glGetUniformLocation:
5082 GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5083 GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5084 GLint trace_loc = trace_packet.get_return_value<GLint>();
5088 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5090 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, pName);
5094 process_entrypoint_warning("%s: glGetUniformLocation: Function succeeded during trace, but failed during replay! (name: %s trace_handle: %u, trace_loc: %i)\n", VOGL_METHOD_NAME, (const char *)pName, trace_handle, trace_loc);
5099 process_entrypoint_warning("%s: glGetUniformLocation: Function failed during trace, but succeeded during replay! (name: %s trace_handle: %u, trace_loc: %i)\n", VOGL_METHOD_NAME, (const char *)pName, trace_handle, trace_loc);
5102 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5103 if (it == get_shared_state()->m_glsl_program_hash_map.end())
5104 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5106 glsl_program_state &state = it->second;
5107 state.m_uniform_locations.erase(trace_loc);
5108 state.m_uniform_locations.insert(trace_loc, replay_loc);
5115 case VOGL_ENTRYPOINT_glGetUniformLocationARB:
5117 GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5118 GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5119 GLint trace_loc = trace_packet.get_return_value<GLint>();
5123 const GLcharARB *pName = trace_packet.get_param_client_memory<GLcharARB>(1);
5125 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, pName);
5129 process_entrypoint_warning("%s: glGetUniformLocationARB: Function succeeded during trace, but failed during replay! (name: %s trace_handle: %u, trace_loc: %i)\n", VOGL_METHOD_NAME, (const char *)pName, trace_handle, trace_loc);
5134 process_entrypoint_warning("%s: glGetUniformLocationARB: Function failed during trace, but succeeded during replay! (name: %s trace_handle: %u, trace_loc: %i)\n", VOGL_METHOD_NAME, (const char *)pName, trace_handle, trace_loc);
5137 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5138 if (it == get_shared_state()->m_glsl_program_hash_map.end())
5139 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5141 glsl_program_state &state = it->second;
5142 state.m_uniform_locations.erase(trace_loc);
5143 state.m_uniform_locations.insert(trace_loc, replay_loc);
5150 case VOGL_ENTRYPOINT_glGetActiveAttrib:
5151 case VOGL_ENTRYPOINT_glGetActiveUniform:
5153 if (!benchmark_mode())
5155 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5156 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5158 GLuint index = trace_packet.get_param_value<GLuint>(1);
5159 GLsizei bufSize = trace_packet.get_param_value<GLsizei>(2);
5161 GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(3);
5162 GLint *pTrace_size = trace_packet.get_param_client_memory<GLint>(4);
5163 GLenum *pTrace_type = trace_packet.get_param_client_memory<GLenum>(5);
5164 GLchar *pTrace_name = trace_packet.get_param_client_memory<GLchar>(6);
5166 vogl::growable_array<GLchar, 1024> name_buf(bufSize + 1); // + 1 guarantees non-empty and null terminated
5172 if (entrypoint_id == VOGL_ENTRYPOINT_glGetActiveAttrib)
5173 GL_ENTRYPOINT(glGetActiveAttrib)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5175 GL_ENTRYPOINT(glGetActiveUniform)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5177 bool mismatch = false;
5179 GLsizei trace_len = 0;
5182 trace_len = pTrace_length[0];
5183 if (trace_len != len)
5187 GLint trace_size = 0;
5190 trace_size = pTrace_size[0];
5191 if (trace_size != size)
5195 GLenum trace_type = 0;
5198 trace_type = pTrace_type[0];
5199 if (trace_type != type)
5203 if ((bufSize) && (pTrace_name))
5205 uint n = vogl_strlen((const char *)pTrace_name) + 1;
5206 if (bufSize < (GLsizei)n)
5208 else if (memcmp(name_buf.get_ptr(), pTrace_name, n) != 0)
5214 process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5215 vogl_warning_printf("Trace handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5216 (uint)trace_handle, (uint)index, (uint)bufSize, (uint)trace_len, (uint)trace_type, (pTrace_name != NULL) ? (const char *)pTrace_name : "");
5217 vogl_warning_printf("GL handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5218 (uint)replay_handle, (uint)index, (uint)bufSize, (uint)len, (uint)type, name_buf.get_ptr());
5224 case VOGL_ENTRYPOINT_glGetAttachedShaders:
5226 if (!benchmark_mode())
5228 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5229 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5231 GLsizei max_count = trace_packet.get_param_value<GLsizei>(1);
5233 vogl::growable_array<GLuint, 16> shaders(max_count);
5235 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, trace_packet.get_param_value<GLsizei>(1), &count, shaders.get_ptr());
5237 // TODO: Diff results
5242 case VOGL_ENTRYPOINT_glGetAttribLocation:
5244 if (!benchmark_mode())
5246 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5247 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5249 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5251 GLint replay_result = GL_ENTRYPOINT(glGetAttribLocation)(replay_handle, pName);
5252 GLint trace_result = trace_packet.get_return_value<GLint>();
5254 if (replay_result != trace_result)
5256 process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5257 vogl_warning_printf("Trace value: %i, replay: %i\n", trace_result, replay_result);
5263 case VOGL_ENTRYPOINT_glGetProgramivARB:
5265 if (!benchmark_mode())
5267 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5268 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5269 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5270 uint params_count = params_size / sizeof(GLint);
5272 int n = g_gl_enums.get_pname_count(pname);
5275 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5276 return cStatusSoftFailure;
5280 vogl::growable_array<GLint, 16> params(n + 1);
5281 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5283 GL_ENTRYPOINT(glGetProgramivARB)(
5284 trace_packet.get_param_value<GLenum>(0),
5288 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5290 if (params_count != static_cast<uint>(n))
5292 process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5294 else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5296 process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname));
5303 case VOGL_ENTRYPOINT_glGetProgramiv:
5305 if (!benchmark_mode())
5307 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5308 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5310 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5312 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5313 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5314 uint params_count = params_size / sizeof(GLint);
5316 int n = g_gl_enums.get_pname_count(pname);
5319 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5320 return cStatusSoftFailure;
5324 vogl::growable_array<GLint, 16> params(n + 1);
5325 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5327 GL_ENTRYPOINT(glGetProgramiv)(
5332 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5334 if (params_count != static_cast<uint>(n))
5336 process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5338 else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5340 process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname));
5347 case VOGL_ENTRYPOINT_glLinkProgram:
5348 case VOGL_ENTRYPOINT_glLinkProgramARB:
5349 case VOGL_ENTRYPOINT_glProgramBinary:
5351 handle_link_program(entrypoint_id);
5355 case VOGL_ENTRYPOINT_glCompileShader:
5357 GL_ENTRYPOINT(glCompileShader)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)));
5360 case VOGL_ENTRYPOINT_glCompileShaderARB:
5362 GL_ENTRYPOINT(glCompileShaderARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)));
5365 case VOGL_ENTRYPOINT_glGetShaderiv:
5367 if (!benchmark_mode())
5369 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5370 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5372 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5375 const GLint *pClient_params = trace_packet.get_param_client_memory<GLint>(2);
5377 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, pname, ¶ms);
5379 if ((pClient_params) && (*pClient_params != params))
5381 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
5382 vogl_warning_printf("Trace data: %i, Replay data: %i\n", pClient_params ? *pClient_params : 0, params);
5388 case VOGL_ENTRYPOINT_glGetShaderInfoLog:
5390 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5391 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5393 GLsizei trace_max_length = trace_packet.get_param_value<GLsizei>(1);
5394 const GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(2);
5395 VOGL_NOTE_UNUSED(pTrace_length);
5396 const GLchar *pTrace_info_log = trace_packet.get_param_client_memory<GLchar>(3);
5397 VOGL_NOTE_UNUSED(pTrace_info_log);
5399 vogl::growable_array<GLchar, 512> log(trace_max_length);
5401 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, trace_max_length, &length, log.get_ptr());
5405 process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_handle, replay_handle, log.get_ptr());
5410 case VOGL_ENTRYPOINT_glGetBooleanv:
5412 if (!benchmark_mode())
5414 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5415 const GLboolean *pParams = trace_packet.get_param_client_memory<GLboolean>(1);
5417 int n = g_gl_enums.get_pname_count(pname);
5420 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X (%s)\n", VOGL_METHOD_NAME, pname, g_gl_enums.find_gl_name(pname));
5421 return cStatusSoftFailure;
5425 vogl::growable_array<GLboolean, 16> params(n + 1);
5426 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC;
5428 GL_ENTRYPOINT(glGetBooleanv)(pname, params.get_ptr());
5430 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC);
5432 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLboolean)) != 0)
5434 process_entrypoint_warning("%s: Replay's returned GLboolean data for pname 0x%08X (%s) differed from trace's\n", VOGL_METHOD_NAME, pname, g_gl_enums.find_gl_name(pname));
5441 case VOGL_ENTRYPOINT_glGetDoublev:
5443 if (!benchmark_mode())
5445 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5446 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(1);
5448 int n = g_gl_enums.get_pname_count(pname);
5451 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5452 return cStatusSoftFailure;
5456 vogl::growable_array<GLdouble, 17> params(n + 1);
5457 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5459 GL_ENTRYPOINT(glGetDoublev)(pname, params.get_ptr());
5461 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5463 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLdouble)) != 0)
5465 process_entrypoint_warning("%s: Replay's returned GLdouble data differed from trace's\n", VOGL_METHOD_NAME);
5472 case VOGL_ENTRYPOINT_glGetFloatv:
5474 if (!benchmark_mode())
5476 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5477 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<GLfloat>(1);
5478 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLfloat);
5480 int n = g_gl_enums.get_pname_count(pname);
5483 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5484 return cStatusSoftFailure;
5487 vogl::growable_array<GLfloat, 17> params(n + 1);
5488 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5490 GL_ENTRYPOINT(glGetFloatv)(pname, params.get_ptr());
5492 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5494 if (static_cast<int>(trace_params_count) < n)
5495 process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5496 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLfloat)) != 0)
5498 process_entrypoint_warning("%s: Replay's returned GLfloat data differed from trace's\n", VOGL_METHOD_NAME);
5504 case VOGL_ENTRYPOINT_glGetIntegerv:
5506 if (!benchmark_mode())
5508 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5509 const GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(1);
5510 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLint);
5512 int n = g_gl_enums.get_pname_count(pname);
5515 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5516 return cStatusSoftFailure;
5519 vogl::growable_array<GLint, 16> params(n + 1);
5520 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5522 GL_ENTRYPOINT(glGetIntegerv)(pname, params.get_ptr());
5524 VOGL_VERIFY(params[n] == (GLint)VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5526 bool is_binding = false;
5529 case GL_ARRAY_BUFFER_BINDING:
5530 case GL_COLOR_ARRAY_BUFFER_BINDING:
5531 case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
5532 case GL_DRAW_FRAMEBUFFER_BINDING:
5533 case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
5534 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5535 case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
5536 case GL_INDEX_ARRAY_BUFFER_BINDING:
5537 case GL_NORMAL_ARRAY_BUFFER_BINDING:
5538 case GL_PIXEL_PACK_BUFFER_BINDING:
5539 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5540 case GL_PROGRAM_PIPELINE_BINDING:
5541 case GL_READ_FRAMEBUFFER_BINDING:
5542 case GL_RENDERBUFFER_BINDING:
5543 case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
5544 case GL_SHADER_STORAGE_BUFFER_BINDING:
5545 case GL_TEXTURE_BINDING_1D:
5546 case GL_TEXTURE_BINDING_1D_ARRAY:
5547 case GL_TEXTURE_BINDING_2D:
5548 case GL_TEXTURE_BINDING_2D_ARRAY:
5549 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
5550 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
5551 case GL_TEXTURE_BINDING_3D:
5552 case GL_TEXTURE_BINDING_BUFFER:
5553 case GL_TEXTURE_BINDING_CUBE_MAP:
5554 case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
5555 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5556 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
5557 case GL_UNIFORM_BUFFER_BINDING:
5558 case GL_VERTEX_ARRAY_BINDING:
5559 case GL_VERTEX_ARRAY_BUFFER_BINDING:
5560 case GL_CURRENT_PROGRAM:
5569 // Don't bother diffing bindings, the trace's are in the trace domain while the glGet's results are in the replay domain.
5572 if (static_cast<int>(trace_params_count) < n)
5574 process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5576 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
5578 process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname));
5579 for (int i = 0; i < n; i++)
5580 vogl_printf("GLint %u: Trace: %i, Replay: %i\n", i, pTrace_params[i], params[i]);
5587 // glProgramUniform's
5588 case VOGL_ENTRYPOINT_glProgramUniform1f:
5590 set_program_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glProgramUniform1f));
5593 case VOGL_ENTRYPOINT_glProgramUniform1i:
5595 set_program_uniform_helper1<GLint>(GL_ENTRYPOINT(glProgramUniform1i));
5598 case VOGL_ENTRYPOINT_glProgramUniform1ui:
5600 set_program_uniform_helper1<GLuint>(GL_ENTRYPOINT(glProgramUniform1ui));
5603 case VOGL_ENTRYPOINT_glProgramUniform2f:
5605 set_program_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glProgramUniform2f));
5608 case VOGL_ENTRYPOINT_glProgramUniform2i:
5610 set_program_uniform_helper2<GLint>(GL_ENTRYPOINT(glProgramUniform2i));
5613 case VOGL_ENTRYPOINT_glProgramUniform2ui:
5615 set_program_uniform_helper2<GLuint>(GL_ENTRYPOINT(glProgramUniform2ui));
5618 case VOGL_ENTRYPOINT_glProgramUniform3f:
5620 set_program_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glProgramUniform3f));
5623 case VOGL_ENTRYPOINT_glProgramUniform3i:
5625 set_program_uniform_helper3<GLint>(GL_ENTRYPOINT(glProgramUniform3i));
5628 case VOGL_ENTRYPOINT_glProgramUniform3ui:
5630 set_program_uniform_helper3<GLuint>(GL_ENTRYPOINT(glProgramUniform3ui));
5633 case VOGL_ENTRYPOINT_glProgramUniform4f:
5635 set_program_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glProgramUniform4f));
5638 case VOGL_ENTRYPOINT_glProgramUniform4i:
5640 set_program_uniform_helper4<GLint>(GL_ENTRYPOINT(glProgramUniform4i));
5643 case VOGL_ENTRYPOINT_glProgramUniform4ui:
5645 set_program_uniform_helper4<GLuint>(GL_ENTRYPOINT(glProgramUniform4ui));
5648 case VOGL_ENTRYPOINT_glProgramUniform1fv:
5650 set_program_uniformv_helper<1, float>(GL_ENTRYPOINT(glProgramUniform1fv));
5653 case VOGL_ENTRYPOINT_glProgramUniform2fv:
5655 set_program_uniformv_helper<2, float>(GL_ENTRYPOINT(glProgramUniform2fv));
5658 case VOGL_ENTRYPOINT_glProgramUniform3fv:
5660 set_program_uniformv_helper<3, float>(GL_ENTRYPOINT(glProgramUniform3fv));
5663 case VOGL_ENTRYPOINT_glProgramUniform4fv:
5665 set_program_uniformv_helper<4, float>(GL_ENTRYPOINT(glProgramUniform4fv));
5668 case VOGL_ENTRYPOINT_glProgramUniform1iv:
5670 set_program_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glProgramUniform1iv));
5673 case VOGL_ENTRYPOINT_glProgramUniform2iv:
5675 set_program_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glProgramUniform2iv));
5678 case VOGL_ENTRYPOINT_glProgramUniform3iv:
5680 set_program_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glProgramUniform3iv));
5683 case VOGL_ENTRYPOINT_glProgramUniform4iv:
5685 set_program_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glProgramUniform4iv));
5688 case VOGL_ENTRYPOINT_glProgramUniform1uiv:
5690 set_program_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glProgramUniform1uiv));
5693 case VOGL_ENTRYPOINT_glProgramUniform2uiv:
5695 set_program_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glProgramUniform2uiv));
5698 case VOGL_ENTRYPOINT_glProgramUniform3uiv:
5700 set_program_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glProgramUniform3uiv));
5703 case VOGL_ENTRYPOINT_glProgramUniform4uiv:
5705 set_program_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glProgramUniform4uiv));
5708 case VOGL_ENTRYPOINT_glProgramUniformMatrix2fv:
5710 set_program_uniform_matrixv_helper<2, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix2fv));
5713 case VOGL_ENTRYPOINT_glProgramUniformMatrix3fv:
5715 set_program_uniform_matrixv_helper<3, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix3fv));
5718 case VOGL_ENTRYPOINT_glProgramUniformMatrix4fv:
5720 set_program_uniform_matrixv_helper<4, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix4fv));
5723 case VOGL_ENTRYPOINT_glProgramUniformMatrix2x3fv:
5725 set_program_uniform_matrixv_helper<2, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x3fv));
5728 case VOGL_ENTRYPOINT_glProgramUniformMatrix3x2fv:
5730 set_program_uniform_matrixv_helper<3, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x2fv));
5733 case VOGL_ENTRYPOINT_glProgramUniformMatrix2x4fv:
5735 set_program_uniform_matrixv_helper<2, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x4fv));
5738 case VOGL_ENTRYPOINT_glProgramUniformMatrix4x2fv:
5740 set_program_uniform_matrixv_helper<4, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x2fv));
5743 case VOGL_ENTRYPOINT_glProgramUniformMatrix3x4fv:
5745 set_program_uniform_matrixv_helper<3, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x4fv));
5748 case VOGL_ENTRYPOINT_glProgramUniformMatrix4x3fv:
5750 set_program_uniform_matrixv_helper<4, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x3fv));
5754 case VOGL_ENTRYPOINT_glUniform1f:
5756 set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1f));
5759 case VOGL_ENTRYPOINT_glUniform1fARB:
5761 set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1fARB));
5764 case VOGL_ENTRYPOINT_glUniform2f:
5766 set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2f));
5769 case VOGL_ENTRYPOINT_glUniform2fARB:
5771 set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2fARB));
5774 case VOGL_ENTRYPOINT_glUniform3f:
5776 set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3f));
5779 case VOGL_ENTRYPOINT_glUniform3fARB:
5781 set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3fARB));
5784 case VOGL_ENTRYPOINT_glUniform4f:
5786 set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4f));
5789 case VOGL_ENTRYPOINT_glUniform4fARB:
5791 set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4fARB));
5794 case VOGL_ENTRYPOINT_glUniform1i:
5796 set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1i));
5799 case VOGL_ENTRYPOINT_glUniform1iARB:
5801 set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1iARB));
5804 case VOGL_ENTRYPOINT_glUniform2i:
5806 set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2i));
5809 case VOGL_ENTRYPOINT_glUniform2iARB:
5811 set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2iARB));
5814 case VOGL_ENTRYPOINT_glUniform3i:
5816 set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3i));
5819 case VOGL_ENTRYPOINT_glUniform3iARB:
5821 set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3iARB));
5824 case VOGL_ENTRYPOINT_glUniform4i:
5826 set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4i));
5829 case VOGL_ENTRYPOINT_glUniform4iARB:
5831 set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4iARB));
5834 case VOGL_ENTRYPOINT_glUniform1ui:
5836 set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1ui));
5839 case VOGL_ENTRYPOINT_glUniform1uiEXT:
5841 set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1uiEXT));
5844 case VOGL_ENTRYPOINT_glUniform2ui:
5846 set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2ui));
5849 case VOGL_ENTRYPOINT_glUniform2uiEXT:
5851 set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2uiEXT));
5854 case VOGL_ENTRYPOINT_glUniform3ui:
5856 set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3ui));
5859 case VOGL_ENTRYPOINT_glUniform3uiEXT:
5861 set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3uiEXT));
5864 case VOGL_ENTRYPOINT_glUniform4ui:
5866 set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4ui));
5869 case VOGL_ENTRYPOINT_glUniform4uiEXT:
5871 set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4uiEXT));
5874 case VOGL_ENTRYPOINT_glUniform1uiv:
5876 set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uiv));
5879 case VOGL_ENTRYPOINT_glUniform1uivEXT:
5881 set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uivEXT));
5884 case VOGL_ENTRYPOINT_glUniform2uiv:
5886 set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uiv));
5889 case VOGL_ENTRYPOINT_glUniform2uivEXT:
5891 set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uivEXT));
5894 case VOGL_ENTRYPOINT_glUniform3uiv:
5896 set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uiv));
5899 case VOGL_ENTRYPOINT_glUniform3uivEXT:
5901 set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uivEXT));
5904 case VOGL_ENTRYPOINT_glUniform4uiv:
5906 set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uiv));
5909 case VOGL_ENTRYPOINT_glUniform4uivEXT:
5911 set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uivEXT));
5914 case VOGL_ENTRYPOINT_glUniform1iv:
5916 set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1iv));
5919 case VOGL_ENTRYPOINT_glUniform1ivARB:
5921 set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1ivARB));
5924 case VOGL_ENTRYPOINT_glUniform2iv:
5926 set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2iv));
5929 case VOGL_ENTRYPOINT_glUniform2ivARB:
5931 set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2ivARB));
5934 case VOGL_ENTRYPOINT_glUniform3iv:
5936 set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3iv));
5939 case VOGL_ENTRYPOINT_glUniform3ivARB:
5941 set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3ivARB));
5944 case VOGL_ENTRYPOINT_glUniform4iv:
5946 set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4iv));
5949 case VOGL_ENTRYPOINT_glUniform4ivARB:
5951 set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4ivARB));
5954 case VOGL_ENTRYPOINT_glUniform1fv:
5956 set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fv));
5959 case VOGL_ENTRYPOINT_glUniform1fvARB:
5961 set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fvARB));
5964 case VOGL_ENTRYPOINT_glUniform2fv:
5966 set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fv));
5969 case VOGL_ENTRYPOINT_glUniform2fvARB:
5971 set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fvARB));
5974 case VOGL_ENTRYPOINT_glUniform3fv:
5976 set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fv));
5979 case VOGL_ENTRYPOINT_glUniform3fvARB:
5981 set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fvARB));
5984 case VOGL_ENTRYPOINT_glUniform4fv:
5986 set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fv));
5989 case VOGL_ENTRYPOINT_glUniform4fvARB:
5991 set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fvARB));
5994 case VOGL_ENTRYPOINT_glUniformMatrix2fvARB:
5996 set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fvARB));
5999 case VOGL_ENTRYPOINT_glUniformMatrix2fv:
6001 set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fv));
6004 case VOGL_ENTRYPOINT_glUniformMatrix3fvARB:
6006 set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fvARB));
6009 case VOGL_ENTRYPOINT_glUniformMatrix3fv:
6011 set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fv));
6014 case VOGL_ENTRYPOINT_glUniformMatrix4fvARB:
6016 set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fvARB));
6019 case VOGL_ENTRYPOINT_glUniformMatrix4fv:
6021 set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fv));
6024 case VOGL_ENTRYPOINT_glUniformMatrix2x3fv:
6026 set_uniform_matrixv_helper<2, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x3fv));
6029 case VOGL_ENTRYPOINT_glUniformMatrix3x2fv:
6031 set_uniform_matrixv_helper<3, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x2fv));
6034 case VOGL_ENTRYPOINT_glUniformMatrix2x4fv:
6036 set_uniform_matrixv_helper<2, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x4fv));
6039 case VOGL_ENTRYPOINT_glUniformMatrix4x2fv:
6041 set_uniform_matrixv_helper<4, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x2fv));
6044 case VOGL_ENTRYPOINT_glUniformMatrix3x4fv:
6046 set_uniform_matrixv_helper<3, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x4fv));
6049 case VOGL_ENTRYPOINT_glUniformMatrix4x3fv:
6051 set_uniform_matrixv_helper<4, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x3fv));
6054 case VOGL_ENTRYPOINT_glBeginQuery:
6055 case VOGL_ENTRYPOINT_glBeginQueryARB:
6057 GLenum target = trace_packet.get_param_value<GLenum>(0);
6058 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6059 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6061 if (!m_pCur_context_state->m_inside_gl_begin)
6064 if (entrypoint_id == VOGL_ENTRYPOINT_glBeginQuery)
6065 GL_ENTRYPOINT(glBeginQuery)(target, replay_handle);
6067 GL_ENTRYPOINT(glBeginQueryARB)(target, replay_handle);
6069 if ((replay_handle) && (!m_pCur_context_state->m_inside_gl_begin) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6071 if (check_gl_error())
6072 return cStatusGLError;
6074 get_shared_state()->m_query_targets[replay_handle] = target;
6079 case VOGL_ENTRYPOINT_glEndQuery:
6081 GL_ENTRYPOINT(glEndQuery)(trace_packet.get_param_value<GLenum>(0));
6084 case VOGL_ENTRYPOINT_glEndQueryARB:
6086 GL_ENTRYPOINT(glEndQueryARB)(trace_packet.get_param_value<GLenum>(0));
6089 case VOGL_ENTRYPOINT_glGetQueryObjectiv:
6091 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6092 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6094 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6096 int n = g_gl_enums.get_pname_count(pname);
6099 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6100 return cStatusSoftFailure;
6104 vogl::growable_array<GLint, 16> params(n + 1);
6105 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6107 GL_ENTRYPOINT(glGetQueryObjectiv)(replay_handle, pname, params.get_ptr());
6109 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6114 case VOGL_ENTRYPOINT_glGetQueryObjectivARB:
6116 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6117 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6119 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6121 int n = g_gl_enums.get_pname_count(pname);
6124 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6125 return cStatusSoftFailure;
6129 vogl::growable_array<GLint, 16> params(n + 1);
6130 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6132 GL_ENTRYPOINT(glGetQueryObjectivARB)(replay_handle, pname, params.get_ptr());
6134 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6139 case VOGL_ENTRYPOINT_glGetQueryObjectuiv:
6141 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6142 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6144 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6146 int n = g_gl_enums.get_pname_count(pname);
6149 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6150 return cStatusSoftFailure;
6154 vogl::growable_array<GLuint, 16> params(n + 1);
6155 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6157 GL_ENTRYPOINT(glGetQueryObjectuiv)(replay_handle, pname, params.get_ptr());
6159 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6164 case VOGL_ENTRYPOINT_glGetQueryObjectuivARB:
6166 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6167 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6169 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6171 int n = g_gl_enums.get_pname_count(pname);
6174 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6175 return cStatusSoftFailure;
6179 vogl::growable_array<GLuint, 16> params(n + 1);
6180 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6182 GL_ENTRYPOINT(glGetQueryObjectuivARB)(replay_handle, pname, params.get_ptr());
6184 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6189 case VOGL_ENTRYPOINT_glQueryCounter:
6191 VOGL_REPLAY_LOAD_PARAMS_HELPER_glQueryCounter;
6193 id = map_handle(get_shared_state()->m_queries, id);
6195 VOGL_REPLAY_CALL_GL_HELPER_glQueryCounter;
6199 case VOGL_ENTRYPOINT_glGetQueryObjecti64v:
6201 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjecti64v;
6202 VOGL_NOTE_UNUSED(pTrace_params);
6204 id = map_handle(get_shared_state()->m_queries, id);
6206 int n = g_gl_enums.get_pname_count(pname);
6209 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6210 return cStatusSoftFailure;
6213 vogl::growable_array<GLint64, 16> temp_params(n + 1);
6214 temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6216 GLint64 *pReplay_params = temp_params.get_ptr();
6218 VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjecti64v;
6220 VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6224 case VOGL_ENTRYPOINT_glGetQueryObjectui64v:
6226 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjectui64v;
6227 VOGL_NOTE_UNUSED(pTrace_params);
6229 id = map_handle(get_shared_state()->m_queries, id);
6231 int n = g_gl_enums.get_pname_count(pname);
6234 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6235 return cStatusSoftFailure;
6238 vogl::growable_array<GLuint64, 16> temp_params(n + 1);
6239 temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6241 GLuint64 *pReplay_params = temp_params.get_ptr();
6243 VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjectui64v;
6245 VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6249 case VOGL_ENTRYPOINT_glBindBuffer:
6250 case VOGL_ENTRYPOINT_glBindBufferARB:
6252 GLenum target = trace_packet.get_param_value<GLenum>(0);
6253 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6254 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
6258 SWITCH_GL_ENTRYPOINT2_VOID(glBindBuffer, glBindBufferARB, target, replay_handle);
6260 if (check_gl_error())
6261 return cStatusGLError;
6263 if ((trace_handle) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6265 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_handle);
6267 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_handle);
6268 else if (*pBinding == GL_NONE)
6274 case VOGL_ENTRYPOINT_glBindBufferBase:
6275 case VOGL_ENTRYPOINT_glBindBufferBaseEXT:
6276 case VOGL_ENTRYPOINT_glBindBufferBaseNV:
6278 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferBase;
6280 GLuint trace_buffer = buffer;
6281 buffer = map_handle(get_shared_state()->m_buffers, buffer);
6285 if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseNV)
6286 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseNV;
6287 else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseEXT)
6288 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseEXT;
6290 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBase;
6292 if (check_gl_error())
6293 return cStatusGLError;
6295 if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6297 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6299 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6300 else if (*pBinding == GL_NONE)
6306 case VOGL_ENTRYPOINT_glBindBufferRange:
6307 case VOGL_ENTRYPOINT_glBindBufferRangeEXT:
6308 case VOGL_ENTRYPOINT_glBindBufferRangeNV:
6310 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferRange;
6312 GLuint trace_buffer = buffer;
6313 buffer = map_handle(get_shared_state()->m_buffers, buffer);
6317 if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeNV)
6318 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeNV;
6319 else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeEXT)
6320 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeEXT;
6322 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRange;
6324 if (check_gl_error())
6325 return cStatusGLError;
6327 if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6329 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6331 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6332 else if (*pBinding == GL_NONE)
6338 case VOGL_ENTRYPOINT_glFenceSync:
6340 vogl_sync_ptr_value trace_handle = trace_packet.get_return_ptr_value();
6343 GLsync replay_handle = GL_ENTRYPOINT(glFenceSync)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLbitfield>(1));
6346 process_entrypoint_error("%s: glFenceSync on trace handle 0x%" PRIX64 " succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME, trace_handle);
6347 return cStatusHardFailure;
6351 get_shared_state()->m_syncs.insert(trace_handle, replay_handle);
6357 case VOGL_ENTRYPOINT_glWaitSync:
6358 case VOGL_ENTRYPOINT_glClientWaitSync:
6360 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6361 GLsync replay_sync = NULL;
6363 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6364 if (it == get_shared_state()->m_syncs.end())
6368 process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6369 return cStatusHardFailure;
6374 replay_sync = it->second;
6377 if (entrypoint_id == VOGL_ENTRYPOINT_glWaitSync)
6378 GL_ENTRYPOINT(glWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6380 GL_ENTRYPOINT(glClientWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6384 case VOGL_ENTRYPOINT_glDeleteSync:
6386 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6387 GLsync replay_sync = NULL;
6389 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6390 if (it == get_shared_state()->m_syncs.end())
6394 process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6395 return cStatusHardFailure;
6400 replay_sync = it->second;
6403 GL_ENTRYPOINT(glDeleteSync)(replay_sync);
6407 get_shared_state()->m_syncs.erase(trace_sync);
6412 case VOGL_ENTRYPOINT_glVertexPointer:
6414 vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6415 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6418 case VOGL_ENTRYPOINT_glVertexPointerEXT:
6420 VOGL_REPLAY_LOAD_PARAMS_HELPER_glVertexPointerEXT;
6421 VOGL_NOTE_UNUSED(pTrace_pointer);
6423 vertex_array_helper_count(size, type, stride, count, trace_packet.get_param_ptr_value(4), vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointerEXT), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6426 case VOGL_ENTRYPOINT_glColorPointer:
6428 vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6429 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6432 case VOGL_ENTRYPOINT_glColorPointerEXT:
6434 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorPointerEXT;
6435 VOGL_NOTE_UNUSED(pTrace_pointer);
6437 vertex_array_helper_count(size, type, stride, count, trace_packet.get_param_ptr_value(4), vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointerEXT), m_client_side_array_data[vogl_color_pointer_array_id]);
6440 case VOGL_ENTRYPOINT_glSecondaryColorPointer:
6442 vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6443 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointer), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6446 case VOGL_ENTRYPOINT_glSecondaryColorPointerEXT:
6448 vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6449 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointerEXT), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6452 case VOGL_ENTRYPOINT_glTexCoordPointer:
6454 GLint cur_client_active_texture = 0;
6455 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6457 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6458 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6460 process_entrypoint_error("%s: glTexCoordPointer/glTexCoordPointerEXT called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6461 return cStatusSoftFailure;
6464 vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6465 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6468 case VOGL_ENTRYPOINT_glTexCoordPointerEXT:
6470 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexCoordPointerEXT;
6471 VOGL_NOTE_UNUSED(pTrace_pointer);
6473 GLint cur_client_active_texture = 0;
6474 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6476 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6477 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6479 process_entrypoint_error("%s: glTexCoordPointer/glTexCoordPointerEXT called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6480 return cStatusSoftFailure;
6483 vertex_array_helper_count(size, type, stride, count, trace_packet.get_param_ptr_value(4), vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointerEXT), m_client_side_texcoord_data[tex_index]);
6486 case VOGL_ENTRYPOINT_glFogCoordPointer:
6488 vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6489 vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointer));
6492 case VOGL_ENTRYPOINT_glFogCoordPointerEXT:
6494 vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6495 vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointerEXT));
6498 case VOGL_ENTRYPOINT_glIndexPointer:
6500 vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6501 vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointer));
6504 case VOGL_ENTRYPOINT_glIndexPointerEXT:
6506 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIndexPointerEXT;
6507 VOGL_NOTE_UNUSED(pTrace_pointer);
6509 vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointerEXT));
6512 case VOGL_ENTRYPOINT_glNormalPointer:
6514 vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6515 vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6518 case VOGL_ENTRYPOINT_glNormalPointerEXT:
6520 VOGL_REPLAY_LOAD_PARAMS_HELPER_glNormalPointerEXT;
6521 VOGL_NOTE_UNUSED(pTrace_pointer);
6523 vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointerEXT));
6526 case VOGL_ENTRYPOINT_glEdgeFlagPointer:
6528 vertex_array_helper_no_type_no_size(trace_packet.get_param_value<GLsizei>(0), trace_packet.get_param_ptr_value(1),
6529 vogl_edge_flag_pointer_array_id, GL_ENTRYPOINT(glEdgeFlagPointer));
6532 case VOGL_ENTRYPOINT_glEdgeFlagPointerEXT:
6534 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEdgeFlagPointerEXT;
6535 VOGL_NOTE_UNUSED(pTrace_pointer);
6537 vertex_array_helper_no_type_no_size_count(stride, count, trace_packet.get_param_ptr_value(2), vogl_edge_flag_pointer_array_id, GL_ENTRYPOINT(glEdgeFlagPointerEXT));
6540 case VOGL_ENTRYPOINT_glInterleavedArrays:
6542 // TODO: Test this more!
6543 GLenum format = trace_packet.get_param_value<GLenum>(0);
6544 GLsizei stride = trace_packet.get_param_value<GLsizei>(1);
6545 const vogl_trace_ptr_value trace_pointer_value = trace_packet.get_param_ptr_value(2);
6548 for (fmt_index = 0; fmt_index < VOGL_INTERLEAVED_ARRAY_SIZE; fmt_index++)
6549 if (format == vogl_g_interleaved_array_descs[fmt_index].fmt)
6551 if (fmt_index == VOGL_INTERLEAVED_ARRAY_SIZE)
6553 process_entrypoint_error("%s: Invalid interleaved vertex format: 0x%X \n", VOGL_METHOD_NAME, format);
6554 return cStatusSoftFailure;
6559 process_entrypoint_error("%s: Invalid interleaved vertex stride: %i\n", VOGL_METHOD_NAME, static_cast<int>(stride));
6560 return cStatusSoftFailure;
6563 const interleaved_array_desc_entry_t &fmt = vogl_g_interleaved_array_descs[fmt_index];
6568 VOGL_ASSERT(stride > 0);
6571 GL_ENTRYPOINT(glDisableClientState)(GL_EDGE_FLAG_ARRAY);
6572 GL_ENTRYPOINT(glDisableClientState)(GL_INDEX_ARRAY);
6573 GL_ENTRYPOINT(glDisableClientState)(GL_SECONDARY_COLOR_ARRAY);
6574 GL_ENTRYPOINT(glDisableClientState)(GL_FOG_COORD_ARRAY);
6580 GLint cur_client_active_texture = 0;
6581 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6583 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6584 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6586 process_entrypoint_error("%s: glInterleavedArrays called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6587 return cStatusSoftFailure;
6590 GL_ENTRYPOINT(glEnableClientState)(GL_TEXTURE_COORD_ARRAY);
6591 vertex_array_helper(fmt.st, GL_FLOAT, stride, trace_pointer_value,
6592 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6596 GL_ENTRYPOINT(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
6603 GL_ENTRYPOINT(glEnableClientState)(GL_COLOR_ARRAY);
6604 vertex_array_helper(fmt.sc, fmt.tc, stride, trace_pointer_value + fmt.pc,
6605 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6609 GL_ENTRYPOINT(glDisableClientState)(GL_COLOR_ARRAY);
6616 GL_ENTRYPOINT(glEnableClientState)(GL_NORMAL_ARRAY);
6617 vertex_array_helper_no_size(GL_FLOAT, stride, trace_pointer_value + fmt.pn,
6618 vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6622 GL_ENTRYPOINT(glDisableClientState)(GL_NORMAL_ARRAY);
6627 GL_ENTRYPOINT(glEnableClientState)(GL_VERTEX_ARRAY);
6628 vertex_array_helper(fmt.sv, GL_FLOAT, stride, trace_pointer_value + fmt.pv,
6629 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6633 case VOGL_ENTRYPOINT_glVertexAttribIPointer:
6634 case VOGL_ENTRYPOINT_glVertexAttribIPointerEXT:
6636 GLuint index = trace_packet.get_param_value<GLuint>(0);
6637 GLint size = trace_packet.get_param_value<GLint>(1);
6638 GLenum type = trace_packet.get_param_value<GLenum>(2);
6639 GLsizei stride = trace_packet.get_param_value<GLsizei>(3);
6640 vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(4);
6642 if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6644 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6645 return cStatusSoftFailure;
6648 GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6649 void *pPtr = reinterpret_cast<void *>(trace_pointer);
6650 if ((!buffer) && (trace_pointer))
6652 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6653 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6654 if (!m_client_side_vertex_attrib_data[index].size())
6656 m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6658 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6661 if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribIPointer)
6662 GL_ENTRYPOINT(glVertexAttribIPointer)(index, size, type, stride, pPtr);
6664 GL_ENTRYPOINT(glVertexAttribIPointerEXT)(index, size, type, stride, pPtr);
6668 case VOGL_ENTRYPOINT_glVertexAttribPointerARB:
6669 case VOGL_ENTRYPOINT_glVertexAttribPointer:
6671 GLuint index = trace_packet.get_param_value<GLuint>(0);
6672 GLint size = trace_packet.get_param_value<GLint>(1);
6673 GLenum type = trace_packet.get_param_value<GLenum>(2);
6674 GLboolean normalized = trace_packet.get_param_value<GLboolean>(3);
6675 GLsizei stride = trace_packet.get_param_value<GLsizei>(4);
6676 vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(5);
6678 if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6680 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6681 return cStatusSoftFailure;
6684 GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6685 void *pPtr = reinterpret_cast<void *>(trace_pointer);
6686 if ((!buffer) && (trace_pointer))
6688 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6689 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6690 if (!m_client_side_vertex_attrib_data[index].size())
6692 m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6694 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6697 if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribPointer)
6698 GL_ENTRYPOINT(glVertexAttribPointer)(index, size, type, normalized, stride, pPtr);
6700 GL_ENTRYPOINT(glVertexAttribPointerARB)(index, size, type, normalized, stride, pPtr);
6704 case VOGL_ENTRYPOINT_glDrawRangeElements:
6705 case VOGL_ENTRYPOINT_glDrawRangeElementsEXT:
6707 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6708 GLuint start = trace_packet.get_param_value<GLuint>(1);
6709 GLuint end = trace_packet.get_param_value<GLuint>(2);
6710 GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6711 GLenum type = trace_packet.get_param_value<GLenum>(4);
6712 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6714 const GLvoid *pIndices;
6715 if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, 0, true, true))
6716 return cStatusSoftFailure;
6718 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6720 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawRangeElements)
6721 GL_ENTRYPOINT(glDrawRangeElements)(mode, start, end, count, type, pIndices);
6723 GL_ENTRYPOINT(glDrawRangeElementsEXT)(mode, start, end, count, type, pIndices);
6728 case VOGL_ENTRYPOINT_glDrawRangeElementsBaseVertex:
6730 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6731 GLuint start = trace_packet.get_param_value<GLuint>(1);
6732 GLuint end = trace_packet.get_param_value<GLuint>(2);
6733 GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6734 GLenum type = trace_packet.get_param_value<GLenum>(4);
6735 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6736 GLint basevertex = trace_packet.get_param_value<GLint>(6);
6738 const GLvoid *pIndices;
6739 if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, basevertex, true, true))
6740 return cStatusSoftFailure;
6742 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6744 GL_ENTRYPOINT(glDrawRangeElementsBaseVertex)(mode, start, end, count, type, pIndices, basevertex);
6749 case VOGL_ENTRYPOINT_glDrawElements:
6751 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6752 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6753 GLenum type = trace_packet.get_param_value<GLenum>(2);
6754 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6756 const GLvoid *pIndices;
6757 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6758 return cStatusSoftFailure;
6760 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6762 GL_ENTRYPOINT(glDrawElements)(mode, count, type, pIndices);
6767 case VOGL_ENTRYPOINT_glDrawArraysInstanced:
6768 case VOGL_ENTRYPOINT_glDrawArraysInstancedEXT:
6770 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawArraysInstanced;
6772 const GLvoid *pIndices = NULL;
6773 if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6774 return cStatusSoftFailure;
6776 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysInstancedEXT)
6778 GLsizei start = first, primcount = instancecount;
6779 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstancedEXT;
6782 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstanced;
6786 case VOGL_ENTRYPOINT_glDrawArrays:
6787 case VOGL_ENTRYPOINT_glDrawArraysEXT:
6789 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6790 GLint first = trace_packet.get_param_value<GLint>(1);
6791 GLsizei count = trace_packet.get_param_value<GLsizei>(2);
6793 const GLvoid *pIndices = NULL;
6794 if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6795 return cStatusSoftFailure;
6797 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6799 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysEXT)
6800 GL_ENTRYPOINT(glDrawArraysEXT)(mode, first, count);
6802 GL_ENTRYPOINT(glDrawArrays)(mode, first, count);
6807 case VOGL_ENTRYPOINT_glDrawElementsInstanced:
6808 case VOGL_ENTRYPOINT_glDrawElementsInstancedARB:
6809 case VOGL_ENTRYPOINT_glDrawElementsInstancedEXT:
6811 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6812 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6813 GLenum type = trace_packet.get_param_value<GLenum>(2);
6814 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6815 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6817 const GLvoid *pIndices;
6818 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6819 return cStatusSoftFailure;
6821 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6823 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstanced)
6824 GL_ENTRYPOINT(glDrawElementsInstanced)(mode, count, type, pIndices, primcount);
6825 else if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstancedEXT)
6826 GL_ENTRYPOINT(glDrawElementsInstancedEXT)(mode, count, type, pIndices, primcount);
6828 GL_ENTRYPOINT(glDrawElementsInstancedARB)(mode, count, type, pIndices, primcount);
6833 case VOGL_ENTRYPOINT_glDrawElementsInstancedBaseVertex:
6835 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6836 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6837 GLenum type = trace_packet.get_param_value<GLenum>(2);
6838 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6839 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6840 GLint basevertex = trace_packet.get_param_value<GLint>(5);
6842 const GLvoid *pIndices;
6843 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, basevertex, false, true))
6844 return cStatusSoftFailure;
6846 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6848 GL_ENTRYPOINT(glDrawElementsInstancedBaseVertex)(mode, count, type, pIndices, primcount, basevertex);
6853 case VOGL_ENTRYPOINT_glMultiDrawArrays:
6854 case VOGL_ENTRYPOINT_glMultiDrawArraysEXT:
6856 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6858 const GLint *pFirst = trace_packet.get_param_client_memory<const GLint>(1);
6859 uint first_size = trace_packet.get_param_client_memory_data_size(1);
6861 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(2);
6862 uint count_size = trace_packet.get_param_client_memory_data_size(2);
6864 GLsizei primcount = trace_packet.get_param_value<GLsizei>(3);
6866 if ((first_size != primcount * sizeof(GLint)) || (count_size != primcount * sizeof(GLsizei)))
6868 process_entrypoint_error("%s: first and/or count params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6869 return cStatusSoftFailure;
6872 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6874 // Multi-draws with client side arrays are not supported for replay.
6875 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6876 GL_ENTRYPOINT(glMultiDrawArrays)(mode, pFirst, pCount, primcount);
6878 GL_ENTRYPOINT(glMultiDrawArraysEXT)(mode, pFirst, pCount, primcount);
6883 case VOGL_ENTRYPOINT_glMultiDrawElements:
6884 case VOGL_ENTRYPOINT_glMultiDrawElementsEXT:
6886 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6888 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6889 uint count_size = trace_packet.get_param_client_memory_data_size(1);
6891 GLenum type = trace_packet.get_param_value<GLenum>(2);
6893 const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6895 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6897 if ((count_size != static_cast<uint>(primcount * sizeof(GLsizei))) || (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)))
6899 process_entrypoint_error("%s: count and/or indices params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6900 return cStatusSoftFailure;
6903 vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6904 for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6905 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6907 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6909 // Multi-draws with client side arrays are not supported for replay.
6910 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6911 GL_ENTRYPOINT(glMultiDrawElements)(mode, pCount, type, replay_indices.get_ptr(), primcount);
6913 GL_ENTRYPOINT(glMultiDrawElementsEXT)(mode, pCount, type, (const GLvoid **)replay_indices.get_ptr(), primcount);
6918 case VOGL_ENTRYPOINT_glMultiDrawElementsBaseVertex:
6920 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6922 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6923 uint count_size = trace_packet.get_param_client_memory_data_size(1);
6925 GLenum type = trace_packet.get_param_value<GLenum>(2);
6927 const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6928 //GLvoid * const *ppIndices = trace_packet.get_param_client_memory<GLvoid *>(3);
6929 //uint index_size = trace_packet.get_param_client_memory_data_size(3);
6931 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6933 const GLint *pBase_vertex = trace_packet.get_param_client_memory<const GLint>(5);
6934 uint base_vertex_size = trace_packet.get_param_client_memory_data_size(5);
6936 if ((count_size != primcount * sizeof(GLsizei)) ||
6937 (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)) ||
6938 (base_vertex_size != primcount * sizeof(GLint)))
6940 process_entrypoint_error("%s: count, indices, and/or base_vertex_size params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6941 return cStatusSoftFailure;
6944 vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6945 for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6946 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6948 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6950 // Multi-draws with client side arrays are not supported for replay.
6951 GL_ENTRYPOINT(glMultiDrawElementsBaseVertex)(mode, pCount, type, replay_indices.get_ptr(), primcount, pBase_vertex);
6956 case VOGL_ENTRYPOINT_glDrawElementsBaseVertex:
6958 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6959 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6960 GLenum type = trace_packet.get_param_value<GLenum>(2);
6961 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6962 GLint base_vertex = trace_packet.get_param_value<GLint>(4);
6964 const GLvoid *pIndices;
6965 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, base_vertex, false, true))
6966 return cStatusSoftFailure;
6968 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6970 GL_ENTRYPOINT(glDrawElementsBaseVertex)(mode, count, type, pIndices, base_vertex);
6975 case VOGL_ENTRYPOINT_glGetBufferSubData:
6977 if (!benchmark_mode())
6979 GLenum target = trace_packet.get_param_value<GLenum>(0);
6980 vogl_trace_ptr_value offset = trace_packet.get_param_ptr_value(1);
6981 vogl_trace_ptr_value size = trace_packet.get_param_ptr_value(2);
6982 GLvoid *pTrace_ptr = trace_packet.get_param_client_memory<GLvoid>(3);
6984 if (offset != static_cast<uintptr_t>(offset))
6986 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)offset);
6987 return cStatusHardFailure;
6990 if ((size > cUINT32_MAX) || (size != static_cast<uintptr_t>(size)))
6992 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)size);
6993 return cStatusHardFailure;
6996 vogl::growable_array<uint8, 1024> buf(pTrace_ptr ? static_cast<uint>(size) : 0);
6998 GL_ENTRYPOINT(glGetBufferSubData)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), pTrace_ptr ? buf.get_ptr() : NULL);
7000 if ((buf.size()) && (pTrace_ptr))
7002 if (memcmp(buf.get_ptr(), pTrace_ptr, static_cast<size_t>(size)) != 0)
7004 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7011 case VOGL_ENTRYPOINT_glGetClipPlane:
7013 if (!benchmark_mode())
7015 GLenum plane = trace_packet.get_param_value<GLenum>(0);
7016 const GLdouble *pTrace_equation = trace_packet.get_param_client_memory<GLdouble>(1);
7018 GLdouble equation[4];
7019 GL_ENTRYPOINT(glGetClipPlane)(plane, pTrace_equation ? equation : NULL);
7021 if (pTrace_equation)
7023 if (memcmp(equation, pTrace_equation, sizeof(GLdouble) * 4) != 0)
7025 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7032 case VOGL_ENTRYPOINT_glBufferData:
7033 case VOGL_ENTRYPOINT_glBufferDataARB:
7035 GLenum target = trace_packet.get_param_value<GLenum>(0);
7036 vogl_trace_ptr_value size = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLsizeiptrARB
7037 const GLvoid *data = trace_packet.get_param_client_memory_ptr(2);
7038 uint data_size = trace_packet.get_param_client_memory_data_size(2);
7039 GLenum usage = trace_packet.get_param_value<GLenum>(3);
7041 if ((data) && (static_cast<vogl_trace_ptr_value>(data_size) < size))
7043 process_entrypoint_error("%s: trace's data array is too small\n", VOGL_METHOD_NAME);
7044 return cStatusHardFailure;
7047 if (size != static_cast<uintptr_t>(size))
7049 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(size));
7050 return cStatusHardFailure;
7053 if (entrypoint_id == VOGL_ENTRYPOINT_glBufferData)
7054 g_vogl_actual_gl_entrypoints.m_glBufferData(target, static_cast<GLsizeiptr>(size), data, usage);
7056 g_vogl_actual_gl_entrypoints.m_glBufferDataARB(target, static_cast<GLsizeiptrARB>(size), data, usage);
7058 GLuint buffer = vogl_get_bound_gl_buffer(target);
7061 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7064 for (i = 0; i < mapped_bufs.size(); i++)
7066 if (mapped_bufs[i].m_buffer == buffer)
7068 process_entrypoint_warning("%s: glBufferData() called on already mapped GL buffer %u, assuming GL will be unmapping it\n", VOGL_METHOD_NAME, buffer);
7070 mapped_bufs.erase_unordered(i);
7078 case VOGL_ENTRYPOINT_glMapBufferARB:
7079 case VOGL_ENTRYPOINT_glMapBuffer:
7081 GLenum target = trace_packet.get_param_value<GLenum>(0);
7082 GLenum access = trace_packet.get_param_value<GLenum>(1);
7083 vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7085 // FIXME - must call GL even if !pTrace_result
7086 if (trace_result_ptr_value)
7089 if (entrypoint_id == VOGL_ENTRYPOINT_glMapBuffer)
7090 pMap = GL_ENTRYPOINT(glMapBuffer)(target, access);
7092 pMap = GL_ENTRYPOINT(glMapBufferARB)(target, access);
7096 process_entrypoint_error("%s: glMapBuffer succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7097 return cStatusHardFailure;
7100 GLuint buffer = vogl_get_bound_gl_buffer(target);
7102 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7105 for (i = 0; i < mapped_bufs.size(); i++)
7107 if (mapped_bufs[i].m_buffer == buffer)
7109 process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7110 return cStatusHardFailure;
7114 if (i == mapped_bufs.size())
7117 GL_ENTRYPOINT(glGetBufferParameteriv)(target, GL_BUFFER_SIZE, &length);
7119 vogl_mapped_buffer_desc m;
7120 m.m_buffer = buffer;
7121 m.m_target = target;
7123 m.m_length = length;
7124 m.m_access = access;
7127 mapped_bufs.push_back(m);
7133 case VOGL_ENTRYPOINT_glMapBufferRange:
7135 GLenum target = trace_packet.get_param_value<GLenum>(0);
7136 vogl_trace_ptr_value offset = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLintptr
7137 vogl_trace_ptr_value length = trace_packet.get_param_value<vogl_trace_ptr_value>(2); // GLsizeiptr
7138 GLbitfield access = trace_packet.get_param_value<GLbitfield>(3);
7139 vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7141 if (offset != static_cast<uintptr_t>(offset))
7143 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(offset));
7144 return cStatusHardFailure;
7146 if (length != static_cast<uintptr_t>(length))
7148 process_entrypoint_error("%s: length parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(length));
7149 return cStatusHardFailure;
7152 // FIXME - must call GL even if !pTrace_result
7153 if (trace_result_ptr_value)
7155 void *pMap = GL_ENTRYPOINT(glMapBufferRange)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(length), access);
7158 process_entrypoint_error("%s: glMapBufferRange succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7159 return cStatusHardFailure;
7162 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7164 GLuint buffer = vogl_get_bound_gl_buffer(target);
7166 for (i = 0; i < mapped_bufs.size(); i++)
7168 if (mapped_bufs[i].m_buffer == buffer)
7170 process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7171 return cStatusHardFailure;
7175 if (i == mapped_bufs.size())
7177 vogl_mapped_buffer_desc m;
7178 m.m_buffer = buffer;
7179 m.m_target = target;
7180 m.m_offset = offset;
7181 m.m_length = length;
7182 m.m_access = access;
7185 mapped_bufs.push_back(m);
7191 case VOGL_ENTRYPOINT_glFlushMappedBufferRange:
7193 // vogltrace queues up the flushes, will process them while handling the glUnmapBuffer() call
7196 case VOGL_ENTRYPOINT_glUnmapBufferARB:
7197 case VOGL_ENTRYPOINT_glUnmapBuffer:
7199 GLenum target = trace_packet.get_param_value<GLenum>(0);
7200 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7202 GLuint buffer = vogl_get_bound_gl_buffer(target);
7204 // FIXME - must call GL even if !buffer
7207 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7209 uint mapped_buffers_index;
7210 for (mapped_buffers_index = 0; mapped_buffers_index < mapped_bufs.size(); mapped_buffers_index++)
7211 if (mapped_bufs[mapped_buffers_index].m_buffer == buffer)
7213 if (mapped_buffers_index == mapped_bufs.size())
7215 process_entrypoint_error("%s: Unable to find mapped buffer during unmap\n", VOGL_METHOD_NAME);
7216 return cStatusHardFailure;
7219 vogl_mapped_buffer_desc &map_desc = mapped_bufs[mapped_buffers_index];
7221 bool writable_map = false;
7222 bool explicit_bit = false;
7223 if (map_desc.m_range)
7225 writable_map = ((map_desc.m_access & GL_MAP_WRITE_BIT) != 0);
7226 explicit_bit = (map_desc.m_access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0;
7230 writable_map = (map_desc.m_access != GL_READ_ONLY);
7235 const key_value_map &unmap_data = trace_packet.get_key_value_map();
7239 int num_flushed_ranges = unmap_data.get_int(string_hash("flushed_ranges"));
7241 for (int i = 0; i < num_flushed_ranges; i++)
7243 int64_t ofs = unmap_data.get_int64(i * 4 + 0);
7244 int64_t size = unmap_data.get_int64(i * 4 + 1);
7245 VOGL_NOTE_UNUSED(size);
7246 const uint8_vec *pData = unmap_data.get_blob(i * 4 + 2);
7249 process_entrypoint_error("%s: Failed finding flushed range data in key value map\n", VOGL_METHOD_NAME);
7250 return cStatusHardFailure;
7253 if (ofs != static_cast<GLintptr>(ofs))
7255 process_entrypoint_error("%s: Flush offset is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(ofs));
7256 return cStatusHardFailure;
7259 VOGL_ASSERT(size == pData->size());
7261 memcpy(static_cast<uint8 *>(map_desc.m_pPtr) + ofs, pData->get_ptr(), pData->size());
7263 GL_ENTRYPOINT(glFlushMappedBufferRange)(target, static_cast<GLintptr>(ofs), pData->size());
7268 int64_t ofs = unmap_data.get_int64(0);
7269 VOGL_NOTE_UNUSED(ofs);
7270 int64_t size = unmap_data.get_int64(1);
7271 VOGL_NOTE_UNUSED(size);
7272 const uint8_vec *pData = unmap_data.get_blob(2);
7275 process_entrypoint_error("%s: Failed finding mapped data in key value map\n", VOGL_METHOD_NAME);
7276 return cStatusHardFailure;
7280 memcpy(map_desc.m_pPtr, pData->get_ptr(), pData->size());
7285 get_shared_state()->m_shadow_state.m_mapped_buffers.erase_unordered(mapped_buffers_index);
7288 GLboolean replay_result;
7289 if (entrypoint_id == VOGL_ENTRYPOINT_glUnmapBuffer)
7290 replay_result = GL_ENTRYPOINT(glUnmapBuffer)(target);
7292 replay_result = GL_ENTRYPOINT(glUnmapBufferARB)(target);
7294 if (trace_result != replay_result)
7295 process_entrypoint_warning("%s: Replay glUnmapBuffer's return value differs from trace's (replay: %u vs. trace: %u)\n", VOGL_METHOD_NAME, replay_result, trace_result);
7299 case VOGL_ENTRYPOINT_glGenVertexArrays:
7301 if (!gen_handles(get_context_state()->m_vertex_array_objects, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenVertexArrays), NULL))
7302 return cStatusHardFailure;
7305 case VOGL_ENTRYPOINT_glBindVertexArray:
7307 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7308 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7310 GL_ENTRYPOINT(glBindVertexArray)(replay_handle);
7313 case VOGL_ENTRYPOINT_glDeleteVertexArrays:
7315 delete_handles(get_context_state()->m_vertex_array_objects, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteVertexArrays));
7318 case VOGL_ENTRYPOINT_glIsFramebuffer:
7319 case VOGL_ENTRYPOINT_glIsFramebufferEXT:
7321 if (!benchmark_mode())
7323 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7324 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
7325 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7327 GLboolean replay_result;
7328 if (entrypoint_id == VOGL_ENTRYPOINT_glIsFramebuffer)
7329 replay_result = GL_ENTRYPOINT(glIsFramebuffer)(replay_handle);
7331 replay_result = GL_ENTRYPOINT(glIsFramebufferEXT)(replay_handle);
7333 if (trace_result != replay_result)
7334 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7339 case VOGL_ENTRYPOINT_glIsBuffer:
7341 if (!benchmark_mode())
7343 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7344 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
7345 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7347 GLboolean replay_result = GL_ENTRYPOINT(glIsBuffer)(replay_handle);
7348 if (trace_result != replay_result)
7349 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7353 case VOGL_ENTRYPOINT_glIsEnabledi:
7355 if (!benchmark_mode())
7357 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7358 GLuint index = trace_packet.get_param_value<GLuint>(1);
7359 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7361 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabledi)(cap, index);
7362 if (trace_result != replay_result)
7363 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7367 case VOGL_ENTRYPOINT_glIsEnabled:
7369 if (!benchmark_mode())
7371 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7372 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7374 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabled)(cap);
7375 if (trace_result != replay_result)
7376 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7380 case VOGL_ENTRYPOINT_glIsProgram:
7382 if (!benchmark_mode())
7384 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7385 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7386 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7388 GLboolean replay_result = GL_ENTRYPOINT(glIsProgram)(replay_handle);
7390 if (trace_result != replay_result)
7391 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7395 case VOGL_ENTRYPOINT_glIsQuery:
7397 if (!benchmark_mode())
7399 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7400 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
7401 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7403 GLboolean replay_result = GL_ENTRYPOINT(glIsQuery)(replay_handle);
7404 if (trace_result != replay_result)
7405 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7409 case VOGL_ENTRYPOINT_glIsShader:
7411 if (!benchmark_mode())
7413 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7414 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7415 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7417 GLboolean replay_result = GL_ENTRYPOINT(glIsShader)(replay_handle);
7418 if (trace_result != replay_result)
7419 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7423 case VOGL_ENTRYPOINT_glIsTexture:
7424 case VOGL_ENTRYPOINT_glIsTextureEXT:
7426 if (!benchmark_mode())
7428 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7429 GLuint replay_handle = trace_handle;
7430 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7432 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_handle, replay_handle);
7434 GLboolean replay_result;
7435 if (entrypoint_id == VOGL_ENTRYPOINT_glIsTexture)
7436 replay_result = GL_ENTRYPOINT(glIsTexture)(replay_handle);
7438 replay_result = GL_ENTRYPOINT(glIsTextureEXT)(replay_handle);
7440 if (trace_result != replay_result)
7441 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7446 case VOGL_ENTRYPOINT_glIsVertexArray:
7448 if (!benchmark_mode())
7450 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7451 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7452 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7454 GLboolean replay_result = GL_ENTRYPOINT(glIsVertexArray)(replay_handle);
7455 if (trace_result != replay_result)
7456 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7461 case VOGL_ENTRYPOINT_glReadPixels:
7463 // TODO: This is causing huge stalls when replaying metro, not sure why. Also, the # of traced bytes is zero in metro.
7465 if (!benchmark_mode())
7467 GLint x = trace_packet.get_param_value<GLint>(0);
7468 GLint y = trace_packet.get_param_value<GLint>(1);
7469 GLsizei width = trace_packet.get_param_value<GLsizei>(2);
7470 GLsizei height = trace_packet.get_param_value<GLsizei>(3);
7471 GLenum format = trace_packet.get_param_value<GLenum>(4);
7472 GLenum type = trace_packet.get_param_value<GLenum>(5);
7473 const GLvoid *trace_data = trace_packet.get_param_client_memory<const GLvoid>(6);
7474 uint trace_data_size = trace_packet.get_param_client_memory_data_size(6);
7476 size_t replay_data_size = vogl_get_image_size(format, type, width, height, 1);
7477 if (replay_data_size != trace_data_size)
7479 process_entrypoint_warning("%s: Unexpected trace data size, got %u expected %" PRIu64 "\n", VOGL_METHOD_NAME, trace_data_size, (uint64_t)replay_data_size);
7481 else if (!trace_data)
7483 process_entrypoint_warning("%s: Trace data is missing from packet\n", VOGL_METHOD_NAME);
7486 if (replay_data_size > cUINT32_MAX)
7488 process_entrypoint_error("%s: Replay data size is too large (%" PRIu64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_data_size);
7489 return cStatusHardFailure;
7492 vogl::vector<uint8> data(static_cast<uint>(replay_data_size));
7493 GL_ENTRYPOINT(glReadPixels)(x, y, width, height, format, type, data.get_ptr());
7495 if ((trace_data_size == replay_data_size) && (trace_data_size) && (trace_data))
7497 if (memcmp(data.get_ptr(), trace_data, trace_data_size) != 0)
7499 process_entrypoint_error("%s: Replay's returned pixel data differed from trace's!\n", VOGL_METHOD_NAME);
7506 case VOGL_ENTRYPOINT_glGetTexLevelParameterfv:
7508 if (!benchmark_mode())
7510 GLenum target = trace_packet.get_param_value<GLenum>(0);
7511 GLint level = trace_packet.get_param_value<GLint>(1);
7512 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7513 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(3);
7514 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7516 int n = g_gl_enums.get_pname_count(pname);
7519 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7520 return cStatusSoftFailure;
7523 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7524 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7526 GL_ENTRYPOINT(glGetTexLevelParameterfv)(target, level, pname, replay_params.get_ptr());
7528 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7531 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7532 else if (trace_params_size != sizeof(GLfloat) * n)
7533 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7534 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7535 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7540 case VOGL_ENTRYPOINT_glGetTexLevelParameteriv:
7542 if (!benchmark_mode())
7544 GLenum target = trace_packet.get_param_value<GLenum>(0);
7545 GLint level = trace_packet.get_param_value<GLint>(1);
7546 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7547 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(3);
7548 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7550 int n = g_gl_enums.get_pname_count(pname);
7553 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7554 return cStatusSoftFailure;
7557 vogl::growable_array<GLint, 16> replay_params(n + 1);
7558 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7560 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, pname, replay_params.get_ptr());
7562 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7565 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7566 else if (trace_params_size != sizeof(GLint) * n)
7567 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7568 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7569 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7574 case VOGL_ENTRYPOINT_glGetTexParameterIiv:
7575 case VOGL_ENTRYPOINT_glGetTexParameteriv:
7577 if (!benchmark_mode())
7579 GLenum target = trace_packet.get_param_value<GLenum>(0);
7580 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7581 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(2);
7582 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7584 int n = g_gl_enums.get_pname_count(pname);
7587 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7588 return cStatusSoftFailure;
7591 vogl::growable_array<GLint, 16> replay_params(n + 1);
7592 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7594 if (entrypoint_id == VOGL_ENTRYPOINT_glGetTexParameterIiv)
7595 GL_ENTRYPOINT(glGetTexParameterIiv)(target, pname, replay_params.get_ptr());
7597 GL_ENTRYPOINT(glGetTexParameteriv)(target, pname, replay_params.get_ptr());
7599 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7602 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7603 else if (trace_params_size != sizeof(GLint) * n)
7604 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7605 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7606 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7611 case VOGL_ENTRYPOINT_glGetTexParameterIuiv:
7613 if (!benchmark_mode())
7615 GLenum target = trace_packet.get_param_value<GLenum>(0);
7616 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7617 const GLuint *pTrace_params = trace_packet.get_param_client_memory<const GLuint>(2);
7618 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7620 int n = g_gl_enums.get_pname_count(pname);
7623 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7624 return cStatusSoftFailure;
7627 vogl::growable_array<GLuint, 16> replay_params(n + 1);
7628 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7630 GL_ENTRYPOINT(glGetTexParameterIuiv)(target, pname, replay_params.get_ptr());
7632 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7635 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7636 else if (trace_params_size != sizeof(GLuint) * n)
7637 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7638 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLuint) * n) != 0)
7639 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7644 case VOGL_ENTRYPOINT_glGetTexParameterfv:
7646 if (!benchmark_mode())
7648 GLenum target = trace_packet.get_param_value<GLenum>(0);
7649 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7650 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(2);
7651 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7653 int n = g_gl_enums.get_pname_count(pname);
7656 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7657 return cStatusSoftFailure;
7660 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7661 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7663 GL_ENTRYPOINT(glGetTexParameterfv)(target, pname, replay_params.get_ptr());
7665 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7668 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7669 else if (trace_params_size != sizeof(GLfloat) * n)
7670 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7671 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7672 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7678 case VOGL_ENTRYPOINT_glGetVertexAttribdv:
7680 status = get_vertex_attrib_helper<GLdouble>(GL_ENTRYPOINT(glGetVertexAttribdv));
7681 if (status != cStatusOK)
7685 case VOGL_ENTRYPOINT_glGetVertexAttribfv:
7687 status = get_vertex_attrib_helper<GLfloat>(GL_ENTRYPOINT(glGetVertexAttribfv));
7688 if (status != cStatusOK)
7692 case VOGL_ENTRYPOINT_glGetVertexAttribiv:
7694 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribiv));
7695 if (status != cStatusOK)
7699 case VOGL_ENTRYPOINT_glGetVertexAttribIiv:
7701 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIiv));
7702 if (status != cStatusOK)
7706 case VOGL_ENTRYPOINT_glGetVertexAttribIivEXT:
7708 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIivEXT));
7709 if (status != cStatusOK)
7713 case VOGL_ENTRYPOINT_glGetVertexAttribIuiv:
7715 status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuiv));
7716 if (status != cStatusOK)
7720 case VOGL_ENTRYPOINT_glGetVertexAttribIuivEXT:
7722 status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuivEXT));
7723 if (status != cStatusOK)
7727 case VOGL_ENTRYPOINT_glGenLists:
7729 GLsizei range = trace_packet.get_param_value<GLsizei>(0);
7730 GLuint trace_base_handle = trace_packet.get_return_value<GLuint>();
7732 if (trace_base_handle)
7736 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7738 if ((check_gl_error()) || (!replay_base_handle))
7740 process_entrypoint_error("%s: glGenLists() succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME);
7741 return cStatusHardFailure;
7744 for (GLsizei i = 0; i < range; i++)
7746 GLuint trace_handle = trace_base_handle + i;
7747 GLuint replay_handle = replay_base_handle + i;
7749 if (!gen_handle(get_shared_state()->m_lists, trace_handle, replay_handle))
7750 return cStatusHardFailure;
7752 if (!get_shared_state()->m_shadow_state.m_display_lists.gen_lists(trace_handle, 1, &replay_handle))
7754 process_entrypoint_warning("%s: Failed genning list into display list shadow, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7760 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7761 if (replay_base_handle)
7763 process_entrypoint_warning("%s: glGenLists() failed in the trace, but succeeded during replay!\n", VOGL_METHOD_NAME);
7765 GL_ENTRYPOINT(glDeleteLists)(replay_base_handle, range);
7771 case VOGL_ENTRYPOINT_glCallList:
7773 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7774 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7776 GL_ENTRYPOINT(glCallList)(replay_handle);
7778 if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7780 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7783 if ((status = post_draw_call()) != cStatusOK)
7788 case VOGL_ENTRYPOINT_glCallLists:
7790 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
7791 GLenum type = trace_packet.get_param_value<GLenum>(1);
7792 const GLvoid *pTrace_lists = trace_packet.get_param_client_memory<const GLvoid>(2);
7793 uint trace_lists_size = trace_packet.get_param_client_memory_data_size(2);
7795 uint type_size = vogl_get_gl_type_size(type);
7798 process_entrypoint_error("%s: Unable to execute glCallLists, type is invalid\n", VOGL_METHOD_NAME);
7799 return cStatusSoftFailure;
7802 if ((n) && (!pTrace_lists))
7804 process_entrypoint_error("%s: Unable to execute glCallLists, lists param is NULL\n", VOGL_METHOD_NAME);
7805 return cStatusSoftFailure;
7808 if (trace_lists_size < (type_size * n))
7810 process_entrypoint_error("%s: Unable to execute glCallLists, lists param data size is too small in trace\n", VOGL_METHOD_NAME);
7811 return cStatusSoftFailure;
7814 GLuint list_base = 0;
7815 GL_ENTRYPOINT(glGetIntegerv)(GL_LIST_BASE, reinterpret_cast<GLint *>(&list_base));
7817 const uint8 *pTrace_lists_ptr = static_cast<const uint8 *>(pTrace_lists);
7818 for (GLsizei i = 0; i < n; i++)
7820 GLint trace_handle = list_base;
7825 trace_handle += *reinterpret_cast<const signed char *>(pTrace_lists_ptr);
7829 case GL_UNSIGNED_BYTE:
7831 trace_handle += *pTrace_lists_ptr;
7837 trace_handle += *reinterpret_cast<const int16 *>(pTrace_lists_ptr);
7838 pTrace_lists_ptr += sizeof(int16);
7841 case GL_UNSIGNED_SHORT:
7843 trace_handle += *reinterpret_cast<const uint16 *>(pTrace_lists_ptr);
7844 pTrace_lists_ptr += sizeof(uint16);
7849 trace_handle += *reinterpret_cast<const int32 *>(pTrace_lists_ptr);
7850 pTrace_lists_ptr += sizeof(int32);
7853 case GL_UNSIGNED_INT:
7855 trace_handle += *reinterpret_cast<const uint32 *>(pTrace_lists_ptr);
7856 pTrace_lists_ptr += sizeof(uint32);
7861 trace_handle += static_cast<GLint>(*reinterpret_cast<const float *>(pTrace_lists_ptr));
7862 pTrace_lists_ptr += sizeof(float);
7867 trace_handle += ((pTrace_lists_ptr[0] << 8U) + pTrace_lists_ptr[1]);
7868 pTrace_lists_ptr += 2;
7873 trace_handle += ((pTrace_lists_ptr[0] << 16U) + (pTrace_lists_ptr[1] << 8U) + pTrace_lists_ptr[2]);
7874 pTrace_lists_ptr += 3;
7879 trace_handle += ((pTrace_lists_ptr[0] << 24U) + (pTrace_lists_ptr[1] << 16U) + (pTrace_lists_ptr[2] << 8U) + pTrace_lists_ptr[3]);
7880 pTrace_lists_ptr += 4;
7885 process_entrypoint_error("%s: Invalid type parameter (0x%08X)\n", VOGL_METHOD_NAME, type);
7886 return cStatusSoftFailure;
7890 if (trace_handle <= 0)
7892 process_entrypoint_error("%s: Trace handle after adding list base is negative (%i), skipping this list index\n", VOGL_METHOD_NAME, trace_handle);
7896 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7897 GL_ENTRYPOINT(glCallList)(replay_handle);
7899 if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7901 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7906 if ((status = post_draw_call()) != cStatusOK)
7911 case VOGL_ENTRYPOINT_glDeleteLists:
7913 GLuint trace_list = trace_packet.get_param_value<GLuint>(0);
7914 GLsizei range = trace_packet.get_param_value<GLsizei>(1);
7916 for (GLsizei i = 0; i < range; i++)
7918 GLuint trace_handle = trace_list + i;
7919 delete_handles(get_shared_state()->m_lists, 1, &trace_handle, delete_list_helper);
7921 if (!get_shared_state()->m_shadow_state.m_display_lists.del_lists(trace_handle, 1))
7923 process_entrypoint_warning("%s: Unable to delete list in display list shadow, trace handle %u\n", VOGL_METHOD_NAME, trace_handle);
7929 case VOGL_ENTRYPOINT_glIsList:
7931 if (!benchmark_mode())
7933 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7934 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7935 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7937 GLboolean replay_result = GL_ENTRYPOINT(glIsList)(replay_handle);
7938 if (trace_result != replay_result)
7939 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7944 case VOGL_ENTRYPOINT_glNewList:
7946 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7947 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7948 GLenum mode = trace_packet.get_param_value<GLenum>(1);
7952 GL_ENTRYPOINT(glNewList)(replay_handle, mode);
7954 if (!check_gl_error())
7956 get_shared_state()->m_shadow_state.m_display_lists.new_list(trace_handle, replay_handle);
7958 get_context_state()->m_current_display_list_mode = mode;
7959 get_context_state()->m_current_display_list_handle = trace_handle;
7962 // TODO: Check if glNewList() failed vs the replay.
7963 // This is important, because if the new failed during tracing but succeeded during replay then we've seriously diverged.
7964 // This is a bigger topic, we really should have the option of calling glGetError() during tracing after each GL call and recording the results to check for divergence.
7967 case VOGL_ENTRYPOINT_glListBase:
7969 GLuint base = trace_packet.get_param_value<GLuint>(0);
7970 GL_ENTRYPOINT(glListBase)(base);
7973 case VOGL_ENTRYPOINT_glEndList:
7975 GL_ENTRYPOINT(glEndList)();
7977 if (!get_context_state()->is_composing_display_list())
7979 process_entrypoint_warning("%s: glEndList() called without calling glNewList()!\n", VOGL_METHOD_NAME);
7983 if (!get_shared_state()->m_shadow_state.m_display_lists.end_list(get_context_state()->m_current_display_list_handle))
7984 process_entrypoint_warning("%s: Failed ending display list, trace handle %u\n", VOGL_METHOD_NAME, get_context_state()->m_current_display_list_handle);
7986 get_context_state()->m_current_display_list_mode = GL_NONE;
7987 get_context_state()->m_current_display_list_handle = -1;
7992 case VOGL_ENTRYPOINT_glFeedbackBuffer:
7994 GLsizei size = trace_packet.get_param_value<GLsizei>(0);
7995 GLenum type = trace_packet.get_param_value<GLenum>(1);
7997 if (static_cast<GLsizei>(m_pCur_context_state->m_feedback_buffer.size()) < size)
7998 m_pCur_context_state->m_feedback_buffer.resize(size);
8000 GL_ENTRYPOINT(glFeedbackBuffer)(size, type, m_pCur_context_state->m_feedback_buffer.get_ptr());
8004 case VOGL_ENTRYPOINT_glSeparableFilter2D:
8006 GLenum target = trace_packet.get_param_value<GLenum>(0);
8007 GLenum internalformat = trace_packet.get_param_value<GLenum>(1);
8008 GLsizei width = trace_packet.get_param_value<GLsizei>(2);
8009 GLsizei height = trace_packet.get_param_value<GLsizei>(3);
8010 GLenum format = trace_packet.get_param_value<GLenum>(4);
8011 GLenum type = trace_packet.get_param_value<GLenum>(5);
8013 const GLvoid *row = trace_packet.get_param_client_memory<const GLvoid>(6);
8014 uint row_size = trace_packet.get_param_client_memory_data_size(6);
8015 if (row_size < vogl_get_image_size(format, type, width, 1, 1))
8017 process_entrypoint_error("%s: row trace array is too small\n", VOGL_METHOD_NAME);
8018 return cStatusSoftFailure;
8021 const GLvoid *column = trace_packet.get_param_client_memory<const GLvoid>(7);
8022 uint col_size = trace_packet.get_param_client_memory_data_size(7);
8023 if (col_size < vogl_get_image_size(format, type, width, 1, 1))
8025 process_entrypoint_error("%s: column trace array is too small\n", VOGL_METHOD_NAME);
8026 return cStatusSoftFailure;
8029 GL_ENTRYPOINT(glSeparableFilter2D)(target, internalformat, width, height, format, type, row, column);
8033 case VOGL_ENTRYPOINT_glNamedProgramLocalParameters4fvEXT:
8035 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8036 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8038 GL_ENTRYPOINT(glNamedProgramLocalParameters4fvEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_value<GLsizei>(3), trace_packet.get_param_client_memory<const GLfloat>(4));
8042 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4iEXT:
8044 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8045 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8047 GL_ENTRYPOINT(glNamedProgramLocalParameterI4iEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_value<GLint>(3), trace_packet.get_param_value<GLint>(4), trace_packet.get_param_value<GLint>(5), trace_packet.get_param_value<GLint>(6));
8050 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4ivEXT:
8052 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8053 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8055 GL_ENTRYPOINT(glNamedProgramLocalParameterI4ivEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_client_memory<GLint>(3));
8059 case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4ivEXT:
8061 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8062 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8064 GL_ENTRYPOINT(glNamedProgramLocalParametersI4ivEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_value<GLsizei>(3), trace_packet.get_param_client_memory<GLint>(4));
8067 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uiEXT:
8069 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8070 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8072 GL_ENTRYPOINT(glNamedProgramLocalParameterI4uiEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2),
8073 trace_packet.get_param_value<GLuint>(3), trace_packet.get_param_value<GLuint>(4),
8074 trace_packet.get_param_value<GLuint>(5), trace_packet.get_param_value<GLuint>(6));
8077 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uivEXT:
8079 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8080 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8082 GL_ENTRYPOINT(glNamedProgramLocalParameterI4uivEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_client_memory<GLuint>(3));
8085 case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4uivEXT:
8087 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8088 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8090 GL_ENTRYPOINT(glNamedProgramLocalParametersI4uivEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_value<GLsizei>(3), trace_packet.get_param_client_memory<GLuint>(4));
8093 case VOGL_ENTRYPOINT_glNamedProgramLocalParameter4fvEXT:
8095 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8096 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8098 GL_ENTRYPOINT(glNamedProgramLocalParameter4fvEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_client_memory<const GLfloat>(3));
8101 case VOGL_ENTRYPOINT_glGetTexEnvfv:
8103 if (!benchmark_mode())
8105 GLenum target = trace_packet.get_param_value<GLenum>(0);
8106 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8107 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8109 GLfloat vals[4] = { 0, 0, 0, 0 };
8111 int n = g_gl_enums.get_pname_count(pname);
8112 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8114 GL_ENTRYPOINT(glGetTexEnvfv)(target, pname, vals);
8118 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8120 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8122 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8128 case VOGL_ENTRYPOINT_glGetTexEnviv:
8130 if (!benchmark_mode())
8132 GLenum target = trace_packet.get_param_value<GLenum>(0);
8133 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8134 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8136 GLint vals[4] = { 0, 0, 0, 0 };
8138 int n = g_gl_enums.get_pname_count(pname);
8139 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8141 GL_ENTRYPOINT(glGetTexEnviv)(target, pname, vals);
8145 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8147 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8149 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8155 case VOGL_ENTRYPOINT_glGetTexGendv:
8157 if (!benchmark_mode())
8159 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8160 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8161 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(2);
8163 GLdouble vals[4] = { 0, 0, 0, 0 };
8165 int n = g_gl_enums.get_pname_count(pname);
8166 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8168 GL_ENTRYPOINT(glGetTexGendv)(coord, pname, vals);
8172 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8174 else if (memcmp(pParams, vals, n * sizeof(GLdouble)) != 0)
8176 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8182 case VOGL_ENTRYPOINT_glGetTexGenfv:
8184 if (!benchmark_mode())
8186 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8187 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8188 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8190 GLfloat vals[4] = { 0, 0, 0, 0 };
8192 int n = g_gl_enums.get_pname_count(pname);
8193 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8195 GL_ENTRYPOINT(glGetTexGenfv)(coord, pname, vals);
8199 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8201 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8203 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8209 case VOGL_ENTRYPOINT_glGetTexGeniv:
8211 if (!benchmark_mode())
8213 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8214 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8215 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8217 GLint vals[4] = { 0, 0, 0, 0 };
8219 int n = g_gl_enums.get_pname_count(pname);
8220 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8222 GL_ENTRYPOINT(glGetTexGeniv)(coord, pname, vals);
8226 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8228 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8230 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8236 case VOGL_ENTRYPOINT_glGetLightfv:
8238 if (!benchmark_mode())
8240 GLenum light = trace_packet.get_param_value<GLenum>(0);
8241 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8242 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8244 GLfloat vals[4] = { 0, 0, 0, 0 };
8246 int n = g_gl_enums.get_pname_count(pname);
8247 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8249 GL_ENTRYPOINT(glGetLightfv)(light, pname, vals);
8253 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8255 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8257 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8263 case VOGL_ENTRYPOINT_glGetLightiv:
8265 if (!benchmark_mode())
8267 GLenum light = trace_packet.get_param_value<GLenum>(0);
8268 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8269 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8271 GLint vals[4] = { 0, 0, 0, 0 };
8273 int n = g_gl_enums.get_pname_count(pname);
8274 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8276 GL_ENTRYPOINT(glGetLightiv)(light, pname, vals);
8280 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8282 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8284 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8290 case VOGL_ENTRYPOINT_glSelectBuffer:
8292 GLsizei size = trace_packet.get_param_value<GLsizei>(0);
8294 if (m_pCur_context_state->m_select_buffer.try_resize(size))
8296 GL_ENTRYPOINT(glSelectBuffer)(size, m_pCur_context_state->m_select_buffer.get_ptr());
8300 process_entrypoint_error("%s: Failed resizing context's select buffer\n", VOGL_METHOD_NAME);
8305 case VOGL_ENTRYPOINT_glClearBufferfv:
8307 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferfv;
8309 // TODO: Check params
8311 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferfv;
8315 case VOGL_ENTRYPOINT_glClearBufferiv:
8317 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferiv;
8319 // TODO: Check params
8321 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferiv;
8325 case VOGL_ENTRYPOINT_glClearBufferuiv:
8327 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferuiv;
8329 // TODO: Check params
8331 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferuiv;
8335 case VOGL_ENTRYPOINT_glTexBuffer:
8336 case VOGL_ENTRYPOINT_glTexBufferARB:
8337 case VOGL_ENTRYPOINT_glTexBufferEXT:
8339 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexBuffer;
8341 buffer = map_handle(get_shared_state()->m_buffers, buffer);
8343 SWITCH_GL_ENTRYPOINT3_VOID(glTexBuffer, glTexBufferARB, glTexBufferEXT, target, internalformat, buffer);
8346 case VOGL_ENTRYPOINT_glBeginConditionalRender:
8348 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginConditionalRender;
8350 id = map_handle(get_shared_state()->m_queries, id);
8352 VOGL_REPLAY_CALL_GL_HELPER_glBeginConditionalRender;
8355 case VOGL_ENTRYPOINT_glEndConditionalRender:
8357 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndConditionalRender;
8359 VOGL_REPLAY_CALL_GL_HELPER_glEndConditionalRender;
8362 case VOGL_ENTRYPOINT_glBeginTransformFeedback:
8364 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginTransformFeedback;
8366 VOGL_REPLAY_CALL_GL_HELPER_glBeginTransformFeedback;
8369 case VOGL_ENTRYPOINT_glEndTransformFeedback:
8371 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndTransformFeedback;
8373 VOGL_REPLAY_CALL_GL_HELPER_glEndTransformFeedback;
8377 case VOGL_ENTRYPOINT_glTransformFeedbackVaryings:
8379 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTransformFeedbackVaryings;
8380 VOGL_NOTE_UNUSED(pTrace_varyings);
8382 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8384 dynamic_string_array replay_varyings(count);
8386 const key_value_map &key_value_map = trace_packet.get_key_value_map();
8387 const value_to_value_hash_map &hash_map = key_value_map.get_map();
8389 for (value_to_value_hash_map::const_iterator it = hash_map.begin(); it != hash_map.end(); ++it)
8391 int key_index = it->first.get_int();
8393 if ((key_index >= 0) && (key_index < count))
8395 const dynamic_string *pName = it->second.get_string_ptr();
8398 replay_varyings[key_index] = pName ? *pName : "";
8406 vogl::vector<const GLchar *> str_ptrs(count);
8407 for (int i = 0; i < count; i++)
8408 str_ptrs[i] = reinterpret_cast<const GLchar *>(replay_varyings[i].get_ptr());
8410 GLchar *const *pReplay_varyings = (GLchar *const *)(str_ptrs.get_ptr());
8412 VOGL_REPLAY_CALL_GL_HELPER_glTransformFeedbackVaryings;
8416 case VOGL_ENTRYPOINT_glUniformBufferEXT:
8418 VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBufferEXT;
8420 GLuint trace_program = program;
8422 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8423 location = determine_uniform_replay_location(trace_program, location);
8424 buffer = map_handle(get_shared_state()->m_buffers, buffer);
8426 VOGL_REPLAY_CALL_GL_HELPER_glUniformBufferEXT;
8429 case VOGL_ENTRYPOINT_glUniformBlockBinding:
8431 // TODO: Does any of this other stuff need to be remapped?
8432 VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBlockBinding;
8434 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8436 VOGL_REPLAY_CALL_GL_HELPER_glUniformBlockBinding;
8439 case VOGL_ENTRYPOINT_glFrameTerminatorGREMEDY:
8441 // TODO - we need to hook up this extension to the tracer
8444 case VOGL_ENTRYPOINT_glStringMarkerGREMEDY:
8446 // TODO - we need to hook up this extension to the tracer
8449 case VOGL_ENTRYPOINT_glDebugMessageCallbackARB:
8450 case VOGL_ENTRYPOINT_glGetDebugMessageLogARB:
8451 case VOGL_ENTRYPOINT_glDebugMessageControlARB:
8452 case VOGL_ENTRYPOINT_glDebugMessageInsertARB:
8457 case VOGL_ENTRYPOINT_glBitmap:
8459 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBitmap;
8461 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8463 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8464 pTrace_bitmap = (const GLubyte *)ptr_val;
8467 VOGL_REPLAY_CALL_GL_HELPER_glBitmap;
8471 case VOGL_ENTRYPOINT_glColorSubTable:
8473 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTable;
8475 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8477 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8478 pTrace_data = (const GLvoid *)ptr_val;
8481 VOGL_REPLAY_CALL_GL_HELPER_glColorSubTable;
8485 case VOGL_ENTRYPOINT_glColorSubTableEXT:
8487 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTableEXT;
8489 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8491 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8492 pTrace_data = (const GLvoid *)ptr_val;
8495 VOGL_REPLAY_CALL_GL_HELPER_glColorSubTableEXT;
8499 case VOGL_ENTRYPOINT_glColorTable:
8501 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTable;
8503 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8505 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8506 pTrace_table = (const GLvoid *)ptr_val;
8509 VOGL_REPLAY_CALL_GL_HELPER_glColorTable;
8513 case VOGL_ENTRYPOINT_glColorTableEXT:
8515 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTableEXT;
8517 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8519 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8520 pTrace_table = (const GLvoid *)ptr_val;
8523 VOGL_REPLAY_CALL_GL_HELPER_glColorTableEXT;
8527 case VOGL_ENTRYPOINT_glConvolutionFilter1D:
8529 VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter1D;
8531 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8533 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8534 pTrace_image = (const GLvoid *)ptr_val;
8537 VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter1D;
8541 case VOGL_ENTRYPOINT_glConvolutionFilter2D:
8543 VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter2D;
8545 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8547 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8548 pTrace_image = (const GLvoid *)ptr_val;
8551 VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter2D;
8555 case VOGL_ENTRYPOINT_glDrawPixels:
8557 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawPixels;
8559 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8561 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(4);
8562 pTrace_pixels = (const GLvoid *)ptr_val;
8565 VOGL_REPLAY_CALL_GL_HELPER_glDrawPixels;
8569 case VOGL_ENTRYPOINT_glPolygonStipple:
8571 VOGL_REPLAY_LOAD_PARAMS_HELPER_glPolygonStipple;
8573 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8575 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(0);
8576 pTrace_mask = (const GLubyte *)ptr_val;
8579 VOGL_REPLAY_CALL_GL_HELPER_glPolygonStipple;
8583 case VOGL_ENTRYPOINT_glTexImage1D:
8585 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage1D;
8587 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8589 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(7);
8590 pTrace_pixels = (const GLvoid *)ptr_val;
8593 VOGL_REPLAY_CALL_GL_HELPER_glTexImage1D;
8597 case VOGL_ENTRYPOINT_glTexImage2D:
8599 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage2D;
8601 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8603 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8604 pTrace_pixels = (const GLvoid *)ptr_val;
8607 VOGL_REPLAY_CALL_GL_HELPER_glTexImage2D;
8611 case VOGL_ENTRYPOINT_glTexImage3D:
8613 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3D;
8615 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8617 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8618 pTrace_pixels = (const GLvoid *)ptr_val;
8621 VOGL_REPLAY_CALL_GL_HELPER_glTexImage3D;
8625 case VOGL_ENTRYPOINT_glTexImage3DEXT:
8627 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3DEXT;
8629 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8631 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8632 pTrace_pixels = (const GLvoid *)ptr_val;
8635 VOGL_REPLAY_CALL_GL_HELPER_glTexImage3DEXT;
8639 case VOGL_ENTRYPOINT_glTexSubImage1D:
8641 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1D;
8643 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8645 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8646 pTrace_pixels = (const GLvoid *)ptr_val;
8649 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1D;
8653 case VOGL_ENTRYPOINT_glTexSubImage1DEXT:
8655 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1DEXT;
8657 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8659 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8660 pTrace_pixels = (const GLvoid *)ptr_val;
8663 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1DEXT;
8667 case VOGL_ENTRYPOINT_glTexSubImage2D:
8669 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2D;
8671 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8673 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8674 pTrace_pixels = (const GLvoid *)ptr_val;
8677 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2D;
8681 case VOGL_ENTRYPOINT_glTexSubImage2DEXT:
8683 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2DEXT;
8685 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8687 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8688 pTrace_pixels = (const GLvoid *)ptr_val;
8691 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2DEXT;
8695 case VOGL_ENTRYPOINT_glTexSubImage3D:
8697 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3D;
8699 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8701 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8702 pTrace_pixels = (const GLvoid *)ptr_val;
8705 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3D;
8709 case VOGL_ENTRYPOINT_glTexSubImage3DEXT:
8711 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3DEXT;
8713 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8715 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8716 pTrace_pixels = (const GLvoid *)ptr_val;
8719 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3DEXT;
8723 case VOGL_ENTRYPOINT_glAreTexturesResident:
8724 case VOGL_ENTRYPOINT_glAreTexturesResidentEXT:
8725 case VOGL_ENTRYPOINT_glGetActiveAtomicCounterBufferiv:
8726 case VOGL_ENTRYPOINT_glGetActiveAttribARB:
8727 case VOGL_ENTRYPOINT_glGetActiveSubroutineName:
8728 case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformName:
8729 case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformiv:
8730 case VOGL_ENTRYPOINT_glGetActiveUniformARB:
8731 case VOGL_ENTRYPOINT_glGetActiveUniformBlockName:
8732 case VOGL_ENTRYPOINT_glGetActiveUniformBlockiv:
8733 case VOGL_ENTRYPOINT_glGetActiveUniformName:
8734 case VOGL_ENTRYPOINT_glGetActiveUniformsiv:
8735 case VOGL_ENTRYPOINT_glGetActiveVaryingNV:
8736 case VOGL_ENTRYPOINT_glGetArrayObjectfvATI:
8737 case VOGL_ENTRYPOINT_glGetArrayObjectivATI:
8738 case VOGL_ENTRYPOINT_glGetAttachedObjectsARB:
8739 case VOGL_ENTRYPOINT_glGetAttribLocationARB:
8740 case VOGL_ENTRYPOINT_glGetBooleanIndexedvEXT:
8741 case VOGL_ENTRYPOINT_glGetBooleani_v:
8742 case VOGL_ENTRYPOINT_glGetBufferParameteri64v:
8743 case VOGL_ENTRYPOINT_glGetBufferParameterivARB:
8744 case VOGL_ENTRYPOINT_glGetBufferParameterui64vNV:
8745 case VOGL_ENTRYPOINT_glGetBufferPointervARB:
8746 case VOGL_ENTRYPOINT_glGetBufferSubDataARB:
8747 case VOGL_ENTRYPOINT_glGetClipPlanefOES:
8748 case VOGL_ENTRYPOINT_glGetClipPlanexOES:
8749 case VOGL_ENTRYPOINT_glGetColorTable:
8750 case VOGL_ENTRYPOINT_glGetColorTableEXT:
8751 case VOGL_ENTRYPOINT_glGetColorTableParameterfv:
8752 case VOGL_ENTRYPOINT_glGetColorTableParameterfvEXT:
8753 case VOGL_ENTRYPOINT_glGetColorTableParameterfvSGI:
8754 case VOGL_ENTRYPOINT_glGetColorTableParameteriv:
8755 case VOGL_ENTRYPOINT_glGetColorTableParameterivEXT:
8756 case VOGL_ENTRYPOINT_glGetColorTableParameterivSGI:
8757 case VOGL_ENTRYPOINT_glGetColorTableSGI:
8758 case VOGL_ENTRYPOINT_glGetCombinerInputParameterfvNV:
8759 case VOGL_ENTRYPOINT_glGetCombinerInputParameterivNV:
8760 case VOGL_ENTRYPOINT_glGetCombinerOutputParameterfvNV:
8761 case VOGL_ENTRYPOINT_glGetCombinerOutputParameterivNV:
8762 case VOGL_ENTRYPOINT_glGetCombinerStageParameterfvNV:
8763 case VOGL_ENTRYPOINT_glGetCompressedMultiTexImageEXT:
8764 case VOGL_ENTRYPOINT_glGetCompressedTexImage:
8765 case VOGL_ENTRYPOINT_glGetCompressedTexImageARB:
8766 case VOGL_ENTRYPOINT_glGetCompressedTextureImageEXT:
8767 case VOGL_ENTRYPOINT_glGetConvolutionFilter:
8768 case VOGL_ENTRYPOINT_glGetConvolutionFilterEXT:
8769 case VOGL_ENTRYPOINT_glGetConvolutionParameterfv:
8770 case VOGL_ENTRYPOINT_glGetConvolutionParameterfvEXT:
8771 case VOGL_ENTRYPOINT_glGetConvolutionParameteriv:
8772 case VOGL_ENTRYPOINT_glGetConvolutionParameterivEXT:
8773 case VOGL_ENTRYPOINT_glGetConvolutionParameterxvOES:
8774 case VOGL_ENTRYPOINT_glGetDebugMessageLog:
8775 case VOGL_ENTRYPOINT_glGetDebugMessageLogAMD:
8776 case VOGL_ENTRYPOINT_glGetDetailTexFuncSGIS:
8777 case VOGL_ENTRYPOINT_glGetDoubleIndexedvEXT:
8778 case VOGL_ENTRYPOINT_glGetDoublei_v:
8779 case VOGL_ENTRYPOINT_glGetFenceivNV:
8780 case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterfvNV:
8781 case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterivNV:
8782 case VOGL_ENTRYPOINT_glGetFixedvOES:
8783 case VOGL_ENTRYPOINT_glGetFloatIndexedvEXT:
8784 case VOGL_ENTRYPOINT_glGetFloati_v:
8785 case VOGL_ENTRYPOINT_glGetFogFuncSGIS:
8786 case VOGL_ENTRYPOINT_glGetFragDataIndex:
8787 case VOGL_ENTRYPOINT_glGetFragDataLocation:
8788 case VOGL_ENTRYPOINT_glGetFragDataLocationEXT:
8789 case VOGL_ENTRYPOINT_glGetFragmentLightfvSGIX:
8790 case VOGL_ENTRYPOINT_glGetFragmentLightivSGIX:
8791 case VOGL_ENTRYPOINT_glGetFragmentMaterialfvSGIX:
8792 case VOGL_ENTRYPOINT_glGetFragmentMaterialivSGIX:
8793 case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameteriv:
8794 case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameterivEXT:
8795 case VOGL_ENTRYPOINT_glGetFramebufferParameteriv:
8796 case VOGL_ENTRYPOINT_glGetFramebufferParameterivEXT:
8797 case VOGL_ENTRYPOINT_glGetGraphicsResetStatusARB:
8798 case VOGL_ENTRYPOINT_glGetHandleARB:
8799 case VOGL_ENTRYPOINT_glGetHistogram:
8800 case VOGL_ENTRYPOINT_glGetHistogramEXT:
8801 case VOGL_ENTRYPOINT_glGetHistogramParameterfv:
8802 case VOGL_ENTRYPOINT_glGetHistogramParameterfvEXT:
8803 case VOGL_ENTRYPOINT_glGetHistogramParameteriv:
8804 case VOGL_ENTRYPOINT_glGetHistogramParameterivEXT:
8805 case VOGL_ENTRYPOINT_glGetHistogramParameterxvOES:
8806 case VOGL_ENTRYPOINT_glGetImageHandleNV:
8807 case VOGL_ENTRYPOINT_glGetImageTransformParameterfvHP:
8808 case VOGL_ENTRYPOINT_glGetImageTransformParameterivHP:
8809 case VOGL_ENTRYPOINT_glGetInstrumentsSGIX:
8810 case VOGL_ENTRYPOINT_glGetInteger64i_v:
8811 case VOGL_ENTRYPOINT_glGetInteger64v:
8812 case VOGL_ENTRYPOINT_glGetIntegerIndexedvEXT:
8813 case VOGL_ENTRYPOINT_glGetIntegeri_v:
8814 case VOGL_ENTRYPOINT_glGetIntegerui64i_vNV:
8815 case VOGL_ENTRYPOINT_glGetIntegerui64vNV:
8816 case VOGL_ENTRYPOINT_glGetInternalformati64v:
8817 case VOGL_ENTRYPOINT_glGetInternalformativ:
8818 case VOGL_ENTRYPOINT_glGetInvariantBooleanvEXT:
8819 case VOGL_ENTRYPOINT_glGetInvariantFloatvEXT:
8820 case VOGL_ENTRYPOINT_glGetInvariantIntegervEXT:
8821 case VOGL_ENTRYPOINT_glGetLightxOES:
8822 case VOGL_ENTRYPOINT_glGetListParameterfvSGIX:
8823 case VOGL_ENTRYPOINT_glGetListParameterivSGIX:
8824 case VOGL_ENTRYPOINT_glGetLocalConstantBooleanvEXT:
8825 case VOGL_ENTRYPOINT_glGetLocalConstantFloatvEXT:
8826 case VOGL_ENTRYPOINT_glGetLocalConstantIntegervEXT:
8827 case VOGL_ENTRYPOINT_glGetMapAttribParameterfvNV:
8828 case VOGL_ENTRYPOINT_glGetMapAttribParameterivNV:
8829 case VOGL_ENTRYPOINT_glGetMapControlPointsNV:
8830 case VOGL_ENTRYPOINT_glGetMapParameterfvNV:
8831 case VOGL_ENTRYPOINT_glGetMapParameterivNV:
8832 case VOGL_ENTRYPOINT_glGetMapdv:
8833 case VOGL_ENTRYPOINT_glGetMapfv:
8834 case VOGL_ENTRYPOINT_glGetMapiv:
8835 case VOGL_ENTRYPOINT_glGetMapxvOES:
8836 case VOGL_ENTRYPOINT_glGetMaterialfv:
8837 case VOGL_ENTRYPOINT_glGetMaterialiv:
8838 case VOGL_ENTRYPOINT_glGetMaterialxOES:
8839 case VOGL_ENTRYPOINT_glGetMinmax:
8840 case VOGL_ENTRYPOINT_glGetMinmaxEXT:
8841 case VOGL_ENTRYPOINT_glGetMinmaxParameterfv:
8842 case VOGL_ENTRYPOINT_glGetMinmaxParameterfvEXT:
8843 case VOGL_ENTRYPOINT_glGetMinmaxParameteriv:
8844 case VOGL_ENTRYPOINT_glGetMinmaxParameterivEXT:
8845 case VOGL_ENTRYPOINT_glGetMultiTexEnvfvEXT:
8846 case VOGL_ENTRYPOINT_glGetMultiTexEnvivEXT:
8847 case VOGL_ENTRYPOINT_glGetMultiTexGendvEXT:
8848 case VOGL_ENTRYPOINT_glGetMultiTexGenfvEXT:
8849 case VOGL_ENTRYPOINT_glGetMultiTexGenivEXT:
8850 case VOGL_ENTRYPOINT_glGetMultiTexImageEXT:
8851 case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterfvEXT:
8852 case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterivEXT:
8853 case VOGL_ENTRYPOINT_glGetMultiTexParameterIivEXT:
8854 case VOGL_ENTRYPOINT_glGetMultiTexParameterIuivEXT:
8855 case VOGL_ENTRYPOINT_glGetMultiTexParameterfvEXT:
8856 case VOGL_ENTRYPOINT_glGetMultiTexParameterivEXT:
8857 case VOGL_ENTRYPOINT_glGetMultisamplefv:
8858 case VOGL_ENTRYPOINT_glGetMultisamplefvNV:
8859 case VOGL_ENTRYPOINT_glGetNamedBufferParameterivEXT:
8860 case VOGL_ENTRYPOINT_glGetNamedBufferParameterui64vNV:
8861 case VOGL_ENTRYPOINT_glGetNamedBufferPointervEXT:
8862 case VOGL_ENTRYPOINT_glGetNamedBufferSubDataEXT:
8863 case VOGL_ENTRYPOINT_glGetNamedFramebufferAttachmentParameterivEXT:
8864 case VOGL_ENTRYPOINT_glGetNamedFramebufferParameterivEXT:
8865 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIivEXT:
8866 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIuivEXT:
8867 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterdvEXT:
8868 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterfvEXT:
8869 case VOGL_ENTRYPOINT_glGetNamedProgramStringEXT:
8870 case VOGL_ENTRYPOINT_glGetNamedProgramivEXT:
8871 case VOGL_ENTRYPOINT_glGetNamedRenderbufferParameterivEXT:
8872 case VOGL_ENTRYPOINT_glGetNamedStringARB:
8873 case VOGL_ENTRYPOINT_glGetNamedStringivARB:
8874 case VOGL_ENTRYPOINT_glGetObjectBufferfvATI:
8875 case VOGL_ENTRYPOINT_glGetObjectBufferivATI:
8876 case VOGL_ENTRYPOINT_glGetObjectLabel:
8877 case VOGL_ENTRYPOINT_glGetObjectParameterfvARB:
8878 case VOGL_ENTRYPOINT_glGetObjectParameterivAPPLE:
8879 case VOGL_ENTRYPOINT_glGetObjectPtrLabel:
8880 case VOGL_ENTRYPOINT_glGetOcclusionQueryivNV:
8881 case VOGL_ENTRYPOINT_glGetOcclusionQueryuivNV:
8882 case VOGL_ENTRYPOINT_glGetPathColorGenfvNV:
8883 case VOGL_ENTRYPOINT_glGetPathColorGenivNV:
8884 case VOGL_ENTRYPOINT_glGetPathCommandsNV:
8885 case VOGL_ENTRYPOINT_glGetPathCoordsNV:
8886 case VOGL_ENTRYPOINT_glGetPathDashArrayNV:
8887 case VOGL_ENTRYPOINT_glGetPathLengthNV:
8888 case VOGL_ENTRYPOINT_glGetPathMetricRangeNV:
8889 case VOGL_ENTRYPOINT_glGetPathMetricsNV:
8890 case VOGL_ENTRYPOINT_glGetPathParameterfvNV:
8891 case VOGL_ENTRYPOINT_glGetPathParameterivNV:
8892 case VOGL_ENTRYPOINT_glGetPathSpacingNV:
8893 case VOGL_ENTRYPOINT_glGetPathTexGenfvNV:
8894 case VOGL_ENTRYPOINT_glGetPathTexGenivNV:
8895 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterDataAMD:
8896 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterInfoAMD:
8897 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterStringAMD:
8898 case VOGL_ENTRYPOINT_glGetPerfMonitorCountersAMD:
8899 case VOGL_ENTRYPOINT_glGetPerfMonitorGroupStringAMD:
8900 case VOGL_ENTRYPOINT_glGetPerfMonitorGroupsAMD:
8901 case VOGL_ENTRYPOINT_glGetPixelMapfv:
8902 case VOGL_ENTRYPOINT_glGetPixelMapuiv:
8903 case VOGL_ENTRYPOINT_glGetPixelMapusv:
8904 case VOGL_ENTRYPOINT_glGetPixelMapxv:
8905 case VOGL_ENTRYPOINT_glGetPixelTexGenParameterfvSGIS:
8906 case VOGL_ENTRYPOINT_glGetPixelTexGenParameterivSGIS:
8907 case VOGL_ENTRYPOINT_glGetPixelTransformParameterfvEXT:
8908 case VOGL_ENTRYPOINT_glGetPixelTransformParameterivEXT:
8909 case VOGL_ENTRYPOINT_glGetPointerIndexedvEXT:
8910 case VOGL_ENTRYPOINT_glGetPointervEXT:
8911 case VOGL_ENTRYPOINT_glGetPolygonStipple:
8912 case VOGL_ENTRYPOINT_glGetProgramBinary:
8913 case VOGL_ENTRYPOINT_glGetProgramEnvParameterIivNV:
8914 case VOGL_ENTRYPOINT_glGetProgramEnvParameterIuivNV:
8915 case VOGL_ENTRYPOINT_glGetProgramEnvParameterdvARB:
8916 case VOGL_ENTRYPOINT_glGetProgramEnvParameterfvARB:
8917 case VOGL_ENTRYPOINT_glGetProgramInterfaceiv:
8918 case VOGL_ENTRYPOINT_glGetProgramLocalParameterIivNV:
8919 case VOGL_ENTRYPOINT_glGetProgramLocalParameterIuivNV:
8920 case VOGL_ENTRYPOINT_glGetProgramLocalParameterdvARB:
8921 case VOGL_ENTRYPOINT_glGetProgramLocalParameterfvARB:
8922 case VOGL_ENTRYPOINT_glGetProgramNamedParameterdvNV:
8923 case VOGL_ENTRYPOINT_glGetProgramNamedParameterfvNV:
8924 case VOGL_ENTRYPOINT_glGetProgramParameterdvNV:
8925 case VOGL_ENTRYPOINT_glGetProgramParameterfvNV:
8926 case VOGL_ENTRYPOINT_glGetProgramPipelineInfoLog:
8927 case VOGL_ENTRYPOINT_glGetProgramPipelineiv:
8928 case VOGL_ENTRYPOINT_glGetProgramResourceIndex:
8929 case VOGL_ENTRYPOINT_glGetProgramResourceLocation:
8930 case VOGL_ENTRYPOINT_glGetProgramResourceLocationIndex:
8931 case VOGL_ENTRYPOINT_glGetProgramResourceName:
8932 case VOGL_ENTRYPOINT_glGetProgramResourceiv:
8933 case VOGL_ENTRYPOINT_glGetProgramStageiv:
8934 case VOGL_ENTRYPOINT_glGetProgramStringARB:
8935 case VOGL_ENTRYPOINT_glGetProgramStringNV:
8936 case VOGL_ENTRYPOINT_glGetProgramSubroutineParameteruivNV:
8937 case VOGL_ENTRYPOINT_glGetProgramivNV:
8938 case VOGL_ENTRYPOINT_glGetQueryIndexediv:
8939 case VOGL_ENTRYPOINT_glGetQueryObjecti64vEXT:
8940 case VOGL_ENTRYPOINT_glGetQueryObjectui64vEXT:
8941 case VOGL_ENTRYPOINT_glGetQueryiv:
8942 case VOGL_ENTRYPOINT_glGetQueryivARB:
8943 case VOGL_ENTRYPOINT_glGetSamplerParameterIiv:
8944 case VOGL_ENTRYPOINT_glGetSamplerParameterIuiv:
8945 case VOGL_ENTRYPOINT_glGetSamplerParameterfv:
8946 case VOGL_ENTRYPOINT_glGetSamplerParameteriv:
8947 case VOGL_ENTRYPOINT_glGetSeparableFilter:
8948 case VOGL_ENTRYPOINT_glGetSeparableFilterEXT:
8949 case VOGL_ENTRYPOINT_glGetShaderPrecisionFormat:
8950 case VOGL_ENTRYPOINT_glGetShaderSource:
8951 case VOGL_ENTRYPOINT_glGetShaderSourceARB:
8952 case VOGL_ENTRYPOINT_glGetSharpenTexFuncSGIS:
8953 case VOGL_ENTRYPOINT_glGetSubroutineIndex:
8954 case VOGL_ENTRYPOINT_glGetSubroutineUniformLocation:
8955 case VOGL_ENTRYPOINT_glGetSynciv:
8956 case VOGL_ENTRYPOINT_glGetTexBumpParameterfvATI:
8957 case VOGL_ENTRYPOINT_glGetTexBumpParameterivATI:
8958 case VOGL_ENTRYPOINT_glGetTexEnvxvOES:
8959 case VOGL_ENTRYPOINT_glGetTexFilterFuncSGIS:
8960 case VOGL_ENTRYPOINT_glGetTexGenxvOES:
8961 case VOGL_ENTRYPOINT_glGetTexImage:
8962 case VOGL_ENTRYPOINT_glGetTexLevelParameterxvOES:
8963 case VOGL_ENTRYPOINT_glGetTexParameterIivEXT:
8964 case VOGL_ENTRYPOINT_glGetTexParameterIuivEXT:
8965 case VOGL_ENTRYPOINT_glGetTexParameterPointervAPPLE:
8966 case VOGL_ENTRYPOINT_glGetTexParameterxvOES:
8967 case VOGL_ENTRYPOINT_glGetTextureHandleNV:
8968 case VOGL_ENTRYPOINT_glGetTextureImageEXT:
8969 case VOGL_ENTRYPOINT_glGetTextureLevelParameterfvEXT:
8970 case VOGL_ENTRYPOINT_glGetTextureLevelParameterivEXT:
8971 case VOGL_ENTRYPOINT_glGetTextureParameterIivEXT:
8972 case VOGL_ENTRYPOINT_glGetTextureParameterIuivEXT:
8973 case VOGL_ENTRYPOINT_glGetTextureParameterfvEXT:
8974 case VOGL_ENTRYPOINT_glGetTextureParameterivEXT:
8975 case VOGL_ENTRYPOINT_glGetTextureSamplerHandleNV:
8976 case VOGL_ENTRYPOINT_glGetTrackMatrixivNV:
8977 case VOGL_ENTRYPOINT_glGetTransformFeedbackVarying:
8978 case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingEXT:
8979 case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingNV:
8980 case VOGL_ENTRYPOINT_glGetUniformBlockIndex:
8981 case VOGL_ENTRYPOINT_glGetUniformBufferSizeEXT:
8982 case VOGL_ENTRYPOINT_glGetUniformIndices:
8983 case VOGL_ENTRYPOINT_glGetUniformOffsetEXT:
8984 case VOGL_ENTRYPOINT_glGetUniformSubroutineuiv:
8985 case VOGL_ENTRYPOINT_glGetUniformdv:
8986 case VOGL_ENTRYPOINT_glGetUniformfv:
8987 case VOGL_ENTRYPOINT_glGetUniformfvARB:
8988 case VOGL_ENTRYPOINT_glGetUniformi64vNV:
8989 case VOGL_ENTRYPOINT_glGetUniformiv:
8990 case VOGL_ENTRYPOINT_glGetUniformivARB:
8991 case VOGL_ENTRYPOINT_glGetUniformui64vNV:
8992 case VOGL_ENTRYPOINT_glGetUniformuiv:
8993 case VOGL_ENTRYPOINT_glGetUniformuivEXT:
8994 case VOGL_ENTRYPOINT_glGetVariantArrayObjectfvATI:
8995 case VOGL_ENTRYPOINT_glGetVariantArrayObjectivATI:
8996 case VOGL_ENTRYPOINT_glGetVariantBooleanvEXT:
8997 case VOGL_ENTRYPOINT_glGetVariantFloatvEXT:
8998 case VOGL_ENTRYPOINT_glGetVariantIntegervEXT:
8999 case VOGL_ENTRYPOINT_glGetVariantPointervEXT:
9000 case VOGL_ENTRYPOINT_glGetVaryingLocationNV:
9001 case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectfvATI:
9002 case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectivATI:
9003 case VOGL_ENTRYPOINT_glGetVertexAttribLdv:
9004 case VOGL_ENTRYPOINT_glGetVertexAttribLdvEXT:
9005 case VOGL_ENTRYPOINT_glGetVertexAttribLi64vNV:
9006 case VOGL_ENTRYPOINT_glGetVertexAttribLui64vNV:
9007 case VOGL_ENTRYPOINT_glGetVertexAttribPointerv:
9008 case VOGL_ENTRYPOINT_glGetVertexAttribPointervARB:
9009 case VOGL_ENTRYPOINT_glGetVertexAttribPointervNV:
9010 case VOGL_ENTRYPOINT_glGetVertexAttribdvARB:
9011 case VOGL_ENTRYPOINT_glGetVertexAttribdvNV:
9012 case VOGL_ENTRYPOINT_glGetVertexAttribfvARB:
9013 case VOGL_ENTRYPOINT_glGetVertexAttribfvNV:
9014 case VOGL_ENTRYPOINT_glGetVertexAttribivARB:
9015 case VOGL_ENTRYPOINT_glGetVertexAttribivNV:
9016 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamdvNV:
9017 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamfvNV:
9018 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamivNV:
9019 case VOGL_ENTRYPOINT_glGetVideoCaptureivNV:
9020 case VOGL_ENTRYPOINT_glGetVideoi64vNV:
9021 case VOGL_ENTRYPOINT_glGetVideoivNV:
9022 case VOGL_ENTRYPOINT_glGetVideoui64vNV:
9023 case VOGL_ENTRYPOINT_glGetVideouivNV:
9024 case VOGL_ENTRYPOINT_glGetnColorTableARB:
9025 case VOGL_ENTRYPOINT_glGetnCompressedTexImageARB:
9026 case VOGL_ENTRYPOINT_glGetnConvolutionFilterARB:
9027 case VOGL_ENTRYPOINT_glGetnHistogramARB:
9028 case VOGL_ENTRYPOINT_glGetnMapdvARB:
9029 case VOGL_ENTRYPOINT_glGetnMapfvARB:
9030 case VOGL_ENTRYPOINT_glGetnMapivARB:
9031 case VOGL_ENTRYPOINT_glGetnMinmaxARB:
9032 case VOGL_ENTRYPOINT_glGetnPixelMapfvARB:
9033 case VOGL_ENTRYPOINT_glGetnPixelMapuivARB:
9034 case VOGL_ENTRYPOINT_glGetnPixelMapusvARB:
9035 case VOGL_ENTRYPOINT_glGetnPolygonStippleARB:
9036 case VOGL_ENTRYPOINT_glGetnSeparableFilterARB:
9037 case VOGL_ENTRYPOINT_glGetnTexImageARB:
9038 case VOGL_ENTRYPOINT_glGetnUniformdvARB:
9039 case VOGL_ENTRYPOINT_glGetnUniformfvARB:
9040 case VOGL_ENTRYPOINT_glGetnUniformivARB:
9041 case VOGL_ENTRYPOINT_glGetnUniformuivARB:
9042 case VOGL_ENTRYPOINT_glIsBufferARB:
9043 case VOGL_ENTRYPOINT_glIsEnabledIndexedEXT:
9044 case VOGL_ENTRYPOINT_glIsQueryARB:
9045 case VOGL_ENTRYPOINT_glIsSync:
9046 case VOGL_ENTRYPOINT_glPrioritizeTextures:
9047 case VOGL_ENTRYPOINT_glPrioritizeTexturesEXT:
9049 if (!(g_vogl_entrypoint_descs[entrypoint_id].m_flags & cGLEFPrintedUnimplementedWarning))
9051 process_entrypoint_warning("%s: TODO: Implement glGet() function %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[entrypoint_id].m_pName);
9053 g_vogl_entrypoint_descs[entrypoint_id].m_flags |= cGLEFPrintedUnimplementedWarning;
9059 if (g_vogl_entrypoint_descs[entrypoint_id].m_is_whitelisted)
9060 process_entrypoint_error("%s: Unhandled GL function %s. This function is marked as whitelisted but was not handled!\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[entrypoint_id].m_pName);
9062 process_entrypoint_error("%s: Unhandled GL function %s. This function needs to be added to the whitelist!\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[entrypoint_id].m_pName);
9063 return cStatusSoftFailure;
9067 m_last_processed_call_counter = trace_packet.get_call_counter();
9069 if (!m_pCur_context_state->m_inside_gl_begin)
9071 if (check_gl_error())
9072 return cStatusGLError;
9075 if (vogl_is_draw_entrypoint(entrypoint_id) || vogl_is_clear_entrypoint(entrypoint_id) || (entrypoint_id == VOGL_ENTRYPOINT_glBitmap))
9077 if ((status = post_draw_call()) != cStatusOK)
9084 //----------------------------------------------------------------------------------------------------------------------
9085 // vogl_gl_replayer::snapshot_backbuffer
9086 //----------------------------------------------------------------------------------------------------------------------
9087 void vogl_gl_replayer::snapshot_backbuffer()
9091 if (!m_pCur_context_state)
9093 vogl_warning_printf("%s: Can't take snapshot without an active context\n", VOGL_METHOD_NAME);
9097 uint recorded_width = m_pWindow->get_width();
9098 uint recorded_height = m_pWindow->get_height();
9100 uint width = 0, height = 0;
9101 m_pWindow->get_actual_dimensions(width, height);
9103 VOGL_ASSERT((recorded_width == width) && (recorded_height == height));
9104 VOGL_NOTE_UNUSED(recorded_width);
9105 VOGL_NOTE_UNUSED(recorded_height);
9107 m_screenshot_buffer.resize(width * height * 3);
9109 bool success = vogl_copy_buffer_to_image(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size(), width, height, GL_RGB, GL_UNSIGNED_BYTE, false, 0, GL_BACK);
9112 process_entrypoint_error("%s: Failed calling glReadPixels() to take screenshot\n", VOGL_METHOD_NAME);
9115 if (m_flags & cGLReplayerDumpScreenshots)
9117 size_t png_size = 0;
9118 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
9120 dynamic_string screenshot_filename(cVarArg, "%s_%07u.png", m_screenshot_prefix.get_ptr(), m_total_swaps);
9121 if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
9123 process_entrypoint_error("Failed writing PNG screenshot to file %s\n", screenshot_filename.get_ptr());
9127 vogl_message_printf("Wrote screenshot to file %s\n", screenshot_filename.get_ptr());
9133 if ((m_flags & cGLReplayerDumpBackbufferHashes) || (m_flags & cGLReplayerHashBackbuffer))
9135 uint64_t backbuffer_crc64;
9137 if (m_flags & cGLReplayerSumHashing)
9139 backbuffer_crc64 = calc_sum64(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9143 backbuffer_crc64 = calc_crc64(CRC64_INIT, m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9146 vogl_printf("Frame %u hash: 0x%016" PRIX64 "\n", m_frame_index, backbuffer_crc64);
9148 if (m_backbuffer_hash_filename.has_content())
9150 FILE *pFile = vogl_fopen(m_backbuffer_hash_filename.get_ptr(), "a");
9152 vogl_error_printf("Failed writing to backbuffer hash file %s\n", m_backbuffer_hash_filename.get_ptr());
9155 vogl_fprintf(pFile, "0x%016" PRIX64 "\n", cast_val_to_uint64(backbuffer_crc64));
9162 //----------------------------------------------------------------------------------------------------------------------
9163 // vogl_gl_replayer::is_valid_handle
9164 //----------------------------------------------------------------------------------------------------------------------
9165 bool vogl_gl_replayer::replay_to_trace_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9172 uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9174 switch (handle_namespace)
9176 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9178 VOGL_ASSERT(replay_handle32 == replay_handle);
9179 return (m_replayer.get_context_state()->m_vertex_array_objects.search_table_for_value_get_count(replay_handle32) != 0);
9181 case VOGL_NAMESPACE_FRAMEBUFFERS:
9183 VOGL_ASSERT(replay_handle32 == replay_handle);
9184 return (m_replayer.get_context_state()->m_framebuffers.search_table_for_value_get_count(replay_handle32) != 0);
9186 case VOGL_NAMESPACE_TEXTURES:
9188 VOGL_ASSERT(replay_handle32 == replay_handle);
9189 return (m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle32) != 0);
9191 case VOGL_NAMESPACE_RENDER_BUFFERS:
9193 VOGL_ASSERT(replay_handle32 == replay_handle);
9194 return (m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains_inv(replay_handle32) != 0);
9196 case VOGL_NAMESPACE_QUERIES:
9198 VOGL_ASSERT(replay_handle32 == replay_handle);
9199 return (m_replayer.get_shared_state()->m_queries.search_table_for_value_get_count(replay_handle32) != 0);
9201 case VOGL_NAMESPACE_SAMPLERS:
9203 VOGL_ASSERT(replay_handle32 == replay_handle);
9204 return (m_replayer.get_shared_state()->m_sampler_objects.search_table_for_value_get_count(replay_handle32) != 0);
9206 case VOGL_NAMESPACE_PROGRAMS:
9208 VOGL_ASSERT(replay_handle32 == replay_handle);
9209 return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT;
9211 case VOGL_NAMESPACE_SHADERS:
9213 VOGL_ASSERT(replay_handle32 == replay_handle);
9214 return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT;
9216 case VOGL_NAMESPACE_BUFFERS:
9218 VOGL_ASSERT(replay_handle32 == replay_handle);
9219 return m_replayer.get_shared_state()->m_buffers.search_table_for_value_get_count(replay_handle32);
9221 case VOGL_NAMESPACE_SYNCS:
9223 GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9224 return m_replayer.get_shared_state()->m_syncs.search_table_for_value_get_count(replay_sync) != 0;
9226 case VOGL_NAMESPACE_PROGRAM_ARB:
9228 VOGL_ASSERT(replay_handle32 == replay_handle);
9229 return m_replayer.get_shared_state()->m_arb_programs.search_table_for_value_get_count(replay_handle32) != 0;
9240 //----------------------------------------------------------------------------------------------------------------------
9241 // vogl_gl_replayer::remap_handle
9242 //----------------------------------------------------------------------------------------------------------------------
9243 uint64_t vogl_gl_replayer::replay_to_trace_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9250 uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9252 switch (handle_namespace)
9254 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9256 VOGL_ASSERT(replay_handle32 == replay_handle);
9257 if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_vertex_array_objects, replay_handle32))
9258 return replay_handle32;
9261 case VOGL_NAMESPACE_FRAMEBUFFERS:
9263 VOGL_ASSERT(replay_handle32 == replay_handle);
9264 if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_framebuffers, replay_handle32))
9265 return replay_handle32;
9268 case VOGL_NAMESPACE_TEXTURES:
9270 VOGL_ASSERT(replay_handle32 == replay_handle);
9272 uint32 trace_handle = replay_handle32;
9273 if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle32, trace_handle))
9274 return trace_handle;
9278 case VOGL_NAMESPACE_RENDER_BUFFERS:
9280 VOGL_ASSERT(replay_handle32 == replay_handle);
9281 GLuint trace_handle = replay_handle32;
9282 if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_handle32, trace_handle))
9283 return trace_handle;
9287 case VOGL_NAMESPACE_QUERIES:
9289 VOGL_ASSERT(replay_handle32 == replay_handle);
9290 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_queries, replay_handle32))
9291 return replay_handle32;
9294 case VOGL_NAMESPACE_SAMPLERS:
9296 VOGL_ASSERT(replay_handle32 == replay_handle);
9297 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_sampler_objects, replay_handle32))
9298 return replay_handle32;
9301 case VOGL_NAMESPACE_PROGRAMS:
9303 VOGL_ASSERT(replay_handle32 == replay_handle);
9304 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT);
9305 GLuint trace_handle = replay_handle32;
9306 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9307 return trace_handle;
9310 case VOGL_NAMESPACE_SHADERS:
9312 VOGL_ASSERT(replay_handle32 == replay_handle);
9313 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT);
9314 GLuint trace_handle = replay_handle32;
9315 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9316 return trace_handle;
9319 case VOGL_NAMESPACE_BUFFERS:
9321 VOGL_ASSERT(replay_handle32 == replay_handle);
9322 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_buffers, replay_handle32))
9323 return replay_handle32;
9326 case VOGL_NAMESPACE_SYNCS:
9328 GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9330 gl_sync_hash_map::const_iterator it(m_replayer.get_shared_state()->m_syncs.search_table_for_value(replay_sync));
9331 if (it != m_replayer.get_shared_state()->m_syncs.end())
9333 VOGL_ASSERT(it->second == replay_sync);
9339 case VOGL_NAMESPACE_PROGRAM_ARB:
9341 VOGL_ASSERT(replay_handle32 == replay_handle);
9342 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_arb_programs, replay_handle32))
9343 return replay_handle32;
9353 vogl_error_printf("%s: Failed remapping handle %" PRIu64 " in namespace %s. This is either a handle shadowing bug, or this object was deleted while it was still bound on another context or attached to an object.\n", VOGL_METHOD_NAME, replay_handle, vogl_get_namespace_name(handle_namespace));
9357 return replay_handle;
9360 //----------------------------------------------------------------------------------------------------------------------
9361 // vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location
9362 //----------------------------------------------------------------------------------------------------------------------
9363 int32 vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location(uint32 replay_program, int32 replay_location)
9367 if ((!replay_program) || (replay_location < 0))
9368 return replay_location;
9370 GLuint trace_program = static_cast<GLuint>(remap_handle(VOGL_NAMESPACE_PROGRAMS, replay_program));
9372 glsl_program_hash_map::const_iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.find(trace_program));
9373 if (it != m_replayer.get_shared_state()->m_glsl_program_hash_map.end())
9375 const glsl_program_state &state = it->second;
9377 uniform_location_hash_map::const_iterator loc_it(state.m_uniform_locations.search_table_for_value(replay_location));
9378 if (loc_it != state.m_uniform_locations.end())
9379 return loc_it->first;
9382 vogl_warning_printf("%s: Failed remapping location %i of program %u\n", VOGL_METHOD_NAME, replay_location, replay_program);
9384 return replay_location;
9387 //----------------------------------------------------------------------------------------------------------------------
9388 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target
9389 //----------------------------------------------------------------------------------------------------------------------
9390 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
9396 uint32 handle32 = static_cast<uint32>(replay_handle);
9398 switch (handle_namespace)
9400 case VOGL_NAMESPACE_TEXTURES:
9402 VOGL_ASSERT(handle32 == replay_handle);
9403 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
9406 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
9417 //----------------------------------------------------------------------------------------------------------------------
9418 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target
9419 //----------------------------------------------------------------------------------------------------------------------
9420 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
9426 uint32 handle32 = static_cast<uint32>(trace_handle);
9428 switch (handle_namespace)
9430 case VOGL_NAMESPACE_TEXTURES:
9432 VOGL_ASSERT(handle32 == trace_handle);
9433 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
9436 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
9447 //----------------------------------------------------------------------------------------------------------------------
9448 // vogl_replayer::determine_used_program_handles
9449 //----------------------------------------------------------------------------------------------------------------------
9450 bool vogl_gl_replayer::determine_used_program_handles(const vogl_trace_packet_array &trim_packets, vogl_handle_hash_set &replay_program_handles)
9454 trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
9457 GLint cur_program_handle = 0;
9458 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &cur_program_handle);
9461 if (cur_program_handle)
9462 replay_program_handles.insert(cur_program_handle);
9465 // Scan for bound programs on all contexts in this sharegroup
9466 context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
9467 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
9469 context_state *pContext = it->second;
9470 if (pContext->m_pShared_state == pContext_shareroot)
9472 if (pContext->m_cur_replay_program)
9473 replay_program_handles.insert(pContext->m_cur_replay_program);
9477 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
9479 if (trim_packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
9482 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
9484 // Important note: This purposesly doesn't process ctype packets, because they don't really do anything and I'm going to be redesigning the ctype/entrypoint stuff anyway so they are always processed after SOF.
9485 if (!m_temp2_gl_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
9488 GLuint trace_handle = 0;
9489 bool refers_to_program = vogl_does_packet_refer_to_program(m_temp2_gl_packet, trace_handle);
9490 if (!refers_to_program)
9495 // trace_handle is conservative, and it's fine if it can't be actually mapped into the replay space because as we process packets it's possible for the trace to create/delete program handles
9496 // All that matters is that we're conservative (i.e. we can't filter out any programs that are actually referenced in this trace packet array).
9497 if (!trace_to_replay_remapper.is_valid_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle))
9500 uint64_t replay_handle = trace_to_replay_remapper.remap_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle);
9504 VOGL_ASSERT(utils::is_32bit(replay_handle));
9506 replay_program_handles.insert(static_cast<uint32>(replay_handle));
9509 vogl_message_printf("%s: Found %u actually referenced program handles\n", VOGL_METHOD_NAME, replay_program_handles.size());
9514 //----------------------------------------------------------------------------------------------------------------------
9515 // vogl_replayer::fill_replay_handle_hash_set
9516 //----------------------------------------------------------------------------------------------------------------------
9517 void vogl_gl_replayer::fill_replay_handle_hash_set(vogl_handle_hash_set &replay_handle_hash, const gl_handle_hash_map &trace_to_replay_hash)
9521 replay_handle_hash.reset();
9522 replay_handle_hash.reserve(trace_to_replay_hash.size());
9523 for (gl_handle_hash_map::const_iterator it = trace_to_replay_hash.begin(); it != trace_to_replay_hash.end(); ++it)
9525 // Insert replay handles into destination hash table
9526 bool success = replay_handle_hash.insert(it->second).second;
9527 VOGL_ASSERT(success);
9528 VOGL_NOTE_UNUSED(success);
9532 //----------------------------------------------------------------------------------------------------------------------
9533 // vogl_replayer::snapshot_state
9534 //----------------------------------------------------------------------------------------------------------------------
9535 vogl_gl_state_snapshot *vogl_gl_replayer::snapshot_state(const vogl_trace_packet_array *pTrim_packets, bool optimize_snapshot)
9539 timed_scope ts(VOGL_METHOD_NAME);
9541 vogl_gl_state_snapshot *pSnapshot = vogl_new(vogl_gl_state_snapshot);
9543 vogl_message_printf("%s: Beginning capture: width %u, height %u, trace context 0x%" PRIx64 ", frame index %u, last call counter %" PRIu64 ", at frame boundary: %u\n", VOGL_METHOD_NAME,
9544 m_pWindow->get_width(), m_pWindow->get_height(), m_cur_trace_context, m_frame_index, m_last_parsed_call_counter, m_at_frame_boundary);
9546 if (!pSnapshot->begin_capture(m_pWindow->get_width(), m_pWindow->get_height(), m_cur_trace_context, m_frame_index, m_last_parsed_call_counter, m_at_frame_boundary))
9548 vogl_error_printf("%s: Failed beginning capture\n", VOGL_METHOD_NAME);
9550 vogl_delete(pSnapshot);
9556 vogl_client_side_array_desc_vec client_side_vertex_attrib_ptrs;
9557 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_vertex_attrib_data); i++)
9558 client_side_vertex_attrib_ptrs.push_back(vogl_client_side_array_desc(reinterpret_cast<vogl_trace_ptr_value>(m_client_side_vertex_attrib_data[i].get_ptr()), m_client_side_vertex_attrib_data[i].size()));
9560 vogl_client_side_array_desc_vec client_side_array_ptrs;
9561 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_array_data); i++)
9562 client_side_array_ptrs.push_back(vogl_client_side_array_desc(reinterpret_cast<vogl_trace_ptr_value>(m_client_side_array_data[i].get_ptr()), m_client_side_array_data[i].size()));
9564 vogl_client_side_array_desc_vec client_side_texcoord_ptrs;
9565 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_texcoord_data); i++)
9566 client_side_texcoord_ptrs.push_back(vogl_client_side_array_desc(reinterpret_cast<vogl_trace_ptr_value>(m_client_side_texcoord_data[i].get_ptr()), m_client_side_texcoord_data[i].size()));
9568 pSnapshot->add_client_side_array_ptrs(client_side_vertex_attrib_ptrs, client_side_array_ptrs, client_side_texcoord_ptrs);
9570 vogl_printf("%s: Capturing %u context(s)\n", VOGL_METHOD_NAME, m_contexts.size());
9572 context_hash_map::iterator it;
9573 for (it = m_contexts.begin(); it != m_contexts.end(); ++it)
9575 context_state *pContext_state = it->second;
9577 if (pContext_state->m_deleted)
9579 vogl_error_printf("%s: Sharelist root context 0x%" PRIx64 " was destroyed - this scenario is not yet supported for state snapshotting.\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first));
9583 vogl_capture_context_params temp_shadow_state;
9584 vogl_capture_context_params *pShadow_state = &temp_shadow_state;
9586 if (pContext_state->m_has_been_made_current)
9588 status_t status = switch_contexts(it->first);
9589 if (status != cStatusOK)
9591 vogl_error_printf("%s: Failed switching to trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first));
9595 VOGL_ASSERT(m_pCur_context_state == pContext_state);
9597 if (m_pCur_context_state->m_inside_gl_begin)
9599 vogl_warning_printf("%s: Trace context 0x%" PRIX64 " is inside a glBegin, which is not fully supported for state capturing. Capture will continue but will not be replayable.\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first));
9600 pSnapshot->set_is_restorable(false);
9604 // Init the shadow state needed by the snapshot code.
9605 if (!m_pCur_context_state->is_root_context())
9607 // Only fill in non-shared state.
9608 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9609 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9613 pShadow_state = &m_pCur_context_state->m_shadow_state;
9615 pShadow_state->m_query_targets = get_shared_state()->m_query_targets;
9617 fill_replay_handle_hash_set(pShadow_state->m_samplers, get_shared_state()->m_sampler_objects);
9618 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9619 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9622 pShadow_state->m_buffer_targets.reset();
9623 for (gl_handle_hash_map::const_iterator buf_it = get_shared_state()->m_buffers.begin(); buf_it != get_shared_state()->m_buffers.end(); ++buf_it)
9625 GLuint trace_handle = buf_it->first;
9626 GLuint replay_handle = buf_it->second;
9628 gl_handle_hash_map::const_iterator target_it = get_shared_state()->m_buffer_targets.find(trace_handle);
9629 if (target_it == get_shared_state()->m_buffer_targets.end())
9631 vogl_error_printf("%s: Unable to find buffer trace handle 0x%X GL handle 0x%X in buffer target map! This should not happen!\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
9634 GLenum target = target_it->second;
9636 pShadow_state->m_buffer_targets.insert(replay_handle, target);
9640 pShadow_state->m_syncs.reset();
9641 pShadow_state->m_syncs.reserve(get_shared_state()->m_syncs.size());
9642 for (gl_sync_hash_map::const_iterator sync_it = get_shared_state()->m_syncs.begin(); sync_it != get_shared_state()->m_syncs.end(); ++sync_it)
9644 bool success = pShadow_state->m_syncs.insert(vogl_sync_to_handle(sync_it->second)).second;
9645 VOGL_ASSERT(success);
9646 VOGL_NOTE_UNUSED(success);
9649 // Program handles filter
9650 pShadow_state->m_filter_program_handles = false;
9651 pShadow_state->m_program_handles_filter.reset();
9654 // TODO: The program optimization code works, but we also need to delete any unused shaders (or shaders that have been marked as deleted but are referred to by optimized out programs).
9655 // This is an optimization issue, and we're concentrating on correctness right now so let's figure this out later.
9656 if ((pTrim_packets) && (optimize_snapshot))
9658 if (!determine_used_program_handles(*pTrim_packets, pShadow_state->m_program_handles_filter))
9660 vogl_warning_printf("%s: Failed determining used program handles\n", VOGL_METHOD_NAME);
9661 pShadow_state->m_program_handles_filter.clear();
9665 pShadow_state->m_filter_program_handles = true;
9669 VOGL_NOTE_UNUSED(optimize_snapshot);
9670 VOGL_NOTE_UNUSED(pTrim_packets);
9673 // ARB program targets
9674 pShadow_state->m_arb_program_targets.reset();
9675 for (gl_handle_hash_map::const_iterator arb_prog_it = get_shared_state()->m_arb_program_targets.begin(); arb_prog_it != get_shared_state()->m_arb_program_targets.end(); ++arb_prog_it)
9677 GLuint trace_handle = arb_prog_it->first;
9678 GLuint replay_handle = get_shared_state()->m_arb_programs.value(trace_handle);
9679 if ((!trace_handle) || (!replay_handle))
9685 GLenum target = arb_prog_it->second;
9686 pShadow_state->m_arb_program_targets.insert(replay_handle, target);
9689 // Deal with any currently mapped buffers.
9690 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9692 pShadow_state->m_mapped_buffers = mapped_bufs;
9694 if (mapped_bufs.size())
9696 vogl_warning_printf("%s: %u buffer(s) are currently mapped, these will be temporarily unmapped in order to snapshot them and then remapped\n", VOGL_METHOD_NAME, m_pCur_context_state->m_shadow_state.m_mapped_buffers.size());
9698 for (uint i = 0; i < mapped_bufs.size(); i++)
9700 vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9702 GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9704 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9705 VOGL_CHECK_GL_ERROR;
9707 GL_ENTRYPOINT(glUnmapBuffer)(desc.m_target);
9708 VOGL_CHECK_GL_ERROR;
9712 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9713 VOGL_CHECK_GL_ERROR;
9717 } // if (!m_pCur_context_state->is_root_context())
9719 } // if (pContext_state->m_has_been_made_current)
9721 if (!pSnapshot->capture_context(pContext_state->m_context_desc, pContext_state->m_context_info, m_replay_to_trace_remapper, *pShadow_state))
9723 vogl_error_printf("%s: Failed capturing trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, static_cast<uint64_t>(it->first));
9727 if ((pContext_state->m_has_been_made_current) && (m_pCur_context_state->is_root_context()))
9729 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9731 // Now remap any mapped buffers
9732 for (uint i = 0; i < mapped_bufs.size(); i++)
9734 vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9736 GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9738 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9739 VOGL_CHECK_GL_ERROR;
9743 desc.m_pPtr = GL_ENTRYPOINT(glMapBufferRange)(desc.m_target, static_cast<GLintptr>(desc.m_offset), static_cast<GLsizeiptr>(desc.m_length), desc.m_access);
9744 VOGL_CHECK_GL_ERROR;
9748 desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(desc.m_target, desc.m_access);
9749 VOGL_CHECK_GL_ERROR;
9752 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9753 VOGL_CHECK_GL_ERROR;
9759 if ((it == m_contexts.end()) && (pSnapshot->end_capture()))
9761 vogl_printf("%s: Capture succeeded\n", VOGL_METHOD_NAME);
9765 vogl_printf("%s: Capture failed\n", VOGL_METHOD_NAME);
9767 vogl_delete(pSnapshot);
9774 //----------------------------------------------------------------------------------------------------------------------
9775 // vogl_replayer::reset_state
9776 //----------------------------------------------------------------------------------------------------------------------
9777 void vogl_gl_replayer::reset_state()
9781 // Purposely does NOT destroy the cached snapshots
9783 destroy_pending_snapshot();
9786 m_pending_make_current_packet.clear();
9787 m_pending_window_resize_width = 0;
9788 m_pending_window_resize_height = 0;
9789 m_pending_window_resize_attempt_counter = 0;
9792 m_last_parsed_call_counter = -1;
9793 m_last_processed_call_counter = -1;
9794 m_at_frame_boundary = true;
9796 m_cur_trace_context = 0;
9797 m_cur_replay_context = 0;
9798 m_pCur_context_state = NULL;
9801 //if (m_pWindow->is_opened())
9802 // m_pWindow->clear_window();
9805 //----------------------------------------------------------------------------------------------------------------------
9806 // trace_to_replay_handle_remapper::is_valid_handle
9807 //----------------------------------------------------------------------------------------------------------------------
9808 bool vogl_gl_replayer::trace_to_replay_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9815 uint32 from_handle32 = static_cast<uint32>(from_handle);
9817 switch (handle_namespace)
9819 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9821 VOGL_ASSERT(from_handle32 == from_handle);
9822 return m_replayer.get_context_state()->m_vertex_array_objects.contains(from_handle32);
9824 case VOGL_NAMESPACE_TEXTURES:
9826 VOGL_ASSERT(from_handle32 == from_handle);
9827 return m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(from_handle32);
9829 case VOGL_NAMESPACE_SAMPLERS:
9831 VOGL_ASSERT(from_handle32 == from_handle);
9832 return m_replayer.get_shared_state()->m_sampler_objects.contains(from_handle32);
9834 case VOGL_NAMESPACE_BUFFERS:
9836 VOGL_ASSERT(from_handle32 == from_handle);
9837 return m_replayer.get_shared_state()->m_buffers.contains(from_handle32);
9839 case VOGL_NAMESPACE_SHADERS:
9840 case VOGL_NAMESPACE_PROGRAMS:
9842 VOGL_ASSERT(from_handle32 == from_handle);
9843 return m_replayer.get_shared_state()->m_shadow_state.m_objs.contains(from_handle32);
9845 case VOGL_NAMESPACE_FRAMEBUFFERS:
9847 VOGL_ASSERT(from_handle32 == from_handle);
9848 return m_replayer.get_context_state()->m_framebuffers.contains(from_handle32);
9850 case VOGL_NAMESPACE_RENDER_BUFFERS:
9852 VOGL_ASSERT(from_handle32 == from_handle);
9853 return m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains(from_handle32);
9855 case VOGL_NAMESPACE_QUERIES:
9857 VOGL_ASSERT(from_handle32 == from_handle);
9858 return m_replayer.get_shared_state()->m_queries.contains(from_handle32);
9860 case VOGL_NAMESPACE_SYNCS:
9862 return m_replayer.get_shared_state()->m_syncs.contains(from_handle);
9864 case VOGL_NAMESPACE_PROGRAM_ARB:
9866 return m_replayer.get_shared_state()->m_arb_programs.contains(from_handle32);
9877 //----------------------------------------------------------------------------------------------------------------------
9878 // trace_to_replay_handle_remapper::remap_handle
9879 //----------------------------------------------------------------------------------------------------------------------
9880 uint64_t vogl_gl_replayer::trace_to_replay_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9887 uint32 from_handle32 = static_cast<uint32>(from_handle);
9889 switch (handle_namespace)
9891 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9893 VOGL_ASSERT(from_handle32 == from_handle);
9894 return m_replayer.get_context_state()->m_vertex_array_objects.value(from_handle32, from_handle32);
9896 case VOGL_NAMESPACE_TEXTURES:
9898 VOGL_ASSERT(from_handle32 == from_handle);
9900 uint32 replay_handle = from_handle32;
9901 if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(from_handle32, replay_handle))
9902 return replay_handle;
9905 case VOGL_NAMESPACE_SAMPLERS:
9907 VOGL_ASSERT(from_handle32 == from_handle);
9908 return m_replayer.get_shared_state()->m_sampler_objects.value(from_handle32, from_handle32);
9910 case VOGL_NAMESPACE_BUFFERS:
9912 VOGL_ASSERT(from_handle32 == from_handle);
9913 return m_replayer.get_shared_state()->m_buffers.value(from_handle32, from_handle32);
9915 case VOGL_NAMESPACE_SHADERS:
9916 case VOGL_NAMESPACE_PROGRAMS:
9918 VOGL_ASSERT(from_handle32 == from_handle);
9920 GLuint replay_handle = from_handle32;
9921 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_handle32, replay_handle))
9922 return replay_handle;
9925 case VOGL_NAMESPACE_FRAMEBUFFERS:
9927 VOGL_ASSERT(from_handle32 == from_handle);
9928 return m_replayer.get_context_state()->m_framebuffers.value(from_handle32, from_handle32);
9930 case VOGL_NAMESPACE_RENDER_BUFFERS:
9932 VOGL_ASSERT(from_handle32 == from_handle);
9934 GLuint replay_handle = from_handle32;
9935 if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_handle_to_inv_handle(from_handle32, replay_handle))
9936 return replay_handle;
9940 case VOGL_NAMESPACE_QUERIES:
9942 VOGL_ASSERT(from_handle32 == from_handle);
9943 return m_replayer.get_shared_state()->m_queries.value(from_handle32, from_handle32);
9945 case VOGL_NAMESPACE_SYNCS:
9947 return vogl_sync_to_handle(m_replayer.get_shared_state()->m_syncs.value(from_handle, vogl_handle_to_sync(from_handle)));
9949 case VOGL_NAMESPACE_PROGRAM_ARB:
9951 return m_replayer.get_shared_state()->m_arb_programs.value(from_handle32, from_handle32);
9961 vogl_error_printf("%s: Failed remapping handle %" PRIu64 " in namespace %s.\n", VOGL_METHOD_NAME, from_handle, vogl_get_namespace_name(handle_namespace));
9966 //----------------------------------------------------------------------------------------------------------------------
9967 // trace_to_replay_handle_remapper::remap_location
9968 //----------------------------------------------------------------------------------------------------------------------
9969 int32 vogl_gl_replayer::trace_to_replay_handle_remapper::remap_location(uint32 trace_program, int32 from_location)
9973 VOGL_NOTE_UNUSED(trace_program);
9975 // restoring declares, but doesn't need to remap
9978 return from_location;
9981 //----------------------------------------------------------------------------------------------------------------------
9982 // trace_to_replay_handle_remapper::remap_vertex_attrib_ptr
9983 //----------------------------------------------------------------------------------------------------------------------
9984 vogl_trace_ptr_value vogl_gl_replayer::trace_to_replay_handle_remapper::remap_vertex_attrib_ptr(uint index, vogl_trace_ptr_value ptr_val)
9991 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_vertex_attrib_data));
9992 if (!m_replayer.m_client_side_vertex_attrib_data[index].size())
9994 m_replayer.m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
9997 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_vertex_attrib_data[index].get_ptr());
10000 //----------------------------------------------------------------------------------------------------------------------
10001 // trace_to_replay_handle_remapper::remap_vertex_array_ptr
10002 //----------------------------------------------------------------------------------------------------------------------
10003 vogl_trace_ptr_value vogl_gl_replayer::trace_to_replay_handle_remapper::remap_vertex_array_ptr(vogl_client_side_array_desc_id_t id, uint index, vogl_trace_ptr_value ptr_val)
10007 VOGL_ASSERT(id < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS);
10012 if (id == vogl_texcoord_pointer_array_id)
10014 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_texcoord_data));
10016 if (!m_replayer.m_client_side_texcoord_data[index].size())
10018 m_replayer.m_client_side_texcoord_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10021 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_texcoord_data[index].get_ptr());
10025 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_array_data));
10027 if (!m_replayer.m_client_side_array_data[id].size())
10029 m_replayer.m_client_side_array_data[id].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10032 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_array_data[id].get_ptr());
10036 //----------------------------------------------------------------------------------------------------------------------
10037 // trace_to_replay_handle_remapper::declare_handle
10038 //----------------------------------------------------------------------------------------------------------------------
10039 void vogl_gl_replayer::trace_to_replay_handle_remapper::declare_handle(vogl_namespace_t handle_namespace, uint64_t from_handle, uint64_t to_handle, GLenum target)
10043 if ((!from_handle) || (!to_handle))
10045 VOGL_ASSERT_ALWAYS;
10049 uint32 from_handle32 = static_cast<uint32>(from_handle);
10050 uint32 to_handle32 = static_cast<uint32>(to_handle);
10052 switch (handle_namespace)
10054 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10056 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10057 m_replayer.get_context_state()->m_vertex_array_objects.insert(from_handle32, to_handle32);
10060 case VOGL_NAMESPACE_TEXTURES:
10062 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10063 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.update(from_handle32, to_handle32, target))
10064 vogl_warning_printf("%s: Failed inserting trace texture %u GL texture %u handle into texture handle tracker!\n", VOGL_METHOD_NAME, from_handle32, to_handle32);
10067 case VOGL_NAMESPACE_SAMPLERS:
10069 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10070 m_replayer.get_shared_state()->m_sampler_objects.insert(from_handle32, to_handle32);
10073 case VOGL_NAMESPACE_BUFFERS:
10075 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10076 m_replayer.get_shared_state()->m_buffers.insert(from_handle32, to_handle32);
10077 m_replayer.get_shared_state()->m_buffer_targets.insert(from_handle32, target);
10080 case VOGL_NAMESPACE_SHADERS:
10082 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10083 if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_SHADER_OBJECT))
10084 vogl_warning_printf("%s: Failed inserting trace shader handle %u GL handle %u into object handle tracker!\n", VOGL_METHOD_NAME, from_handle32, to_handle32);
10087 case VOGL_NAMESPACE_PROGRAMS:
10089 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10090 if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_PROGRAM_OBJECT))
10091 vogl_warning_printf("%s: Failed inserting trace program handle %u GL handle %u into object handle tracker!\n", VOGL_METHOD_NAME, from_handle32, to_handle32);
10094 case VOGL_NAMESPACE_FRAMEBUFFERS:
10096 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10097 m_replayer.get_context_state()->m_framebuffers.insert(from_handle32, to_handle32);
10100 case VOGL_NAMESPACE_RENDER_BUFFERS:
10102 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10103 if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.insert(from_handle32, to_handle32, GL_NONE))
10104 vogl_warning_printf("%s: Failed inserting trace RBO handle %u GL handle %u into RBO handle tracker!\n", VOGL_METHOD_NAME, from_handle32, to_handle32);
10107 case VOGL_NAMESPACE_QUERIES:
10109 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10110 m_replayer.get_shared_state()->m_queries.insert(from_handle32, to_handle32);
10111 m_replayer.get_shared_state()->m_query_targets[to_handle32] = target;
10114 case VOGL_NAMESPACE_SYNCS:
10116 m_replayer.get_shared_state()->m_syncs.insert(from_handle, vogl_handle_to_sync(to_handle));
10119 case VOGL_NAMESPACE_PROGRAM_ARB:
10121 m_replayer.get_shared_state()->m_arb_programs.insert(from_handle32, to_handle32);
10122 m_replayer.get_shared_state()->m_arb_program_targets.insert(from_handle32, target);
10133 //----------------------------------------------------------------------------------------------------------------------
10134 // trace_to_replay_handle_remapper::delete_handle_and_object
10135 //----------------------------------------------------------------------------------------------------------------------
10136 void vogl_gl_replayer::trace_to_replay_handle_remapper::delete_handle_and_object(vogl_namespace_t handle_namespace, uint64_t from_handle, uint64_t to_handle)
10140 if ((!from_handle) || (!to_handle))
10142 VOGL_ASSERT_ALWAYS;
10146 uint32 from_handle32 = static_cast<uint32>(from_handle);
10147 uint32 to_handle32 = static_cast<uint32>(to_handle);
10148 VOGL_NOTE_UNUSED(to_handle32);
10150 switch (handle_namespace)
10152 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10154 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10155 m_replayer.get_context_state()->m_vertex_array_objects.erase(from_handle32);
10156 vogl_destroy_gl_object(handle_namespace, to_handle);
10159 case VOGL_NAMESPACE_TEXTURES:
10161 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10162 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.erase(from_handle32))
10163 vogl_warning_printf("%s: Failed deleting trace texture handle %u GL handle %u from texture handle tracker!\n", VOGL_METHOD_NAME, from_handle32, to_handle32);
10165 vogl_destroy_gl_object(handle_namespace, to_handle);
10168 case VOGL_NAMESPACE_SAMPLERS:
10170 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10171 m_replayer.get_shared_state()->m_sampler_objects.erase(from_handle32);
10172 vogl_destroy_gl_object(handle_namespace, to_handle);
10175 case VOGL_NAMESPACE_BUFFERS:
10177 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10178 m_replayer.get_shared_state()->m_buffers.erase(from_handle32);
10179 m_replayer.get_shared_state()->m_buffer_targets.erase(from_handle32);
10180 vogl_destroy_gl_object(handle_namespace, to_handle);
10183 case VOGL_NAMESPACE_SHADERS:
10185 m_replayer.handle_delete_shader(from_handle32);
10188 case VOGL_NAMESPACE_PROGRAMS:
10190 m_replayer.handle_delete_program(from_handle32);
10193 case VOGL_NAMESPACE_FRAMEBUFFERS:
10195 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10196 m_replayer.get_context_state()->m_framebuffers.erase(from_handle32);
10197 vogl_destroy_gl_object(handle_namespace, to_handle);
10200 case VOGL_NAMESPACE_RENDER_BUFFERS:
10202 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10204 if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.erase(from_handle32))
10205 vogl_warning_printf("%s: Failed deleting trace texture handle %u GL handle %u from RBO handle tracker!\n", VOGL_METHOD_NAME, from_handle32, to_handle32);
10207 vogl_destroy_gl_object(handle_namespace, to_handle);
10210 case VOGL_NAMESPACE_QUERIES:
10212 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10213 m_replayer.get_shared_state()->m_queries.erase(from_handle32);
10214 vogl_destroy_gl_object(handle_namespace, to_handle);
10217 case VOGL_NAMESPACE_SYNCS:
10219 m_replayer.get_shared_state()->m_syncs.erase(from_handle);
10220 vogl_destroy_gl_object(handle_namespace, to_handle);
10223 case VOGL_NAMESPACE_PROGRAM_ARB:
10225 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10226 m_replayer.get_shared_state()->m_arb_programs.erase(from_handle32);
10227 m_replayer.get_shared_state()->m_arb_program_targets.erase(from_handle32);
10228 vogl_destroy_gl_object(handle_namespace, to_handle);
10239 //----------------------------------------------------------------------------------------------------------------------
10240 // vogl_replayer::trace_to_replay_handle_remapper::declare_location
10241 //----------------------------------------------------------------------------------------------------------------------
10242 void vogl_gl_replayer::trace_to_replay_handle_remapper::declare_location(uint32 from_program_handle, uint32 to_program_handle, int32 from_location, int32 to_location)
10246 GLuint check_replay_handle = 0;
10247 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_program_handle, check_replay_handle));
10248 VOGL_ASSERT(check_replay_handle == to_program_handle);
10249 VOGL_NOTE_UNUSED(check_replay_handle);
10251 VOGL_NOTE_UNUSED(to_program_handle);
10253 glsl_program_hash_map::iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.insert(from_program_handle).first);
10255 glsl_program_state &prog_state = it->second;
10257 VOGL_ASSERT(!prog_state.m_uniform_locations.contains(from_location));
10259 prog_state.m_uniform_locations.insert(from_location, to_location);
10262 //----------------------------------------------------------------------------------------------------------------------
10263 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target
10264 //----------------------------------------------------------------------------------------------------------------------
10265 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
10271 uint32 handle32 = static_cast<uint32>(trace_handle);
10273 switch (handle_namespace)
10275 case VOGL_NAMESPACE_TEXTURES:
10277 VOGL_ASSERT(handle32 == trace_handle);
10278 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
10281 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
10292 //----------------------------------------------------------------------------------------------------------------------
10293 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target
10294 //----------------------------------------------------------------------------------------------------------------------
10295 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
10301 uint32 handle32 = static_cast<uint32>(replay_handle);
10303 switch (handle_namespace)
10305 case VOGL_NAMESPACE_TEXTURES:
10307 VOGL_ASSERT(handle32 == replay_handle);
10308 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
10311 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
10322 //----------------------------------------------------------------------------------------------------------------------
10323 // vogl_replayer::restore_objects
10324 //----------------------------------------------------------------------------------------------------------------------
10325 vogl_gl_replayer::status_t vogl_gl_replayer::restore_objects(
10326 vogl_handle_remapper &trace_to_replay_remapper, const vogl_gl_state_snapshot &snapshot, const vogl_context_snapshot &context_state, vogl_gl_object_state_type state_type,
10327 vogl_const_gl_object_state_ptr_vec &objects_to_delete)
10331 VOGL_NOTE_UNUSED(snapshot);
10333 if (m_flags & cGLReplayerVerboseMode)
10334 vogl_printf("%s: Restoring %s objects\n", VOGL_METHOD_NAME, get_gl_object_state_type_str(state_type));
10337 if (m_flags & cGLReplayerVerboseMode)
10340 const vogl_gl_object_state_ptr_vec &object_ptrs = context_state.get_objects();
10344 for (uint i = 0; i < object_ptrs.size(); i++)
10346 const vogl_gl_object_state *pState_obj = object_ptrs[i];
10348 if (pState_obj->get_type() != state_type)
10351 GLuint64 restore_handle = 0;
10352 if (!pState_obj->restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, restore_handle))
10354 vogl_error_printf("%s: Failed restoring object type %s object index %u trace handle 0x%" PRIX64 " restore handle 0x%" PRIX64 "\n", VOGL_METHOD_NAME, get_gl_object_state_type_str(state_type), i, (uint64_t)pState_obj->get_snapshot_handle(), (uint64_t)restore_handle);
10355 return cStatusHardFailure;
10359 if (pState_obj->get_marked_for_deletion())
10361 objects_to_delete.push_back(pState_obj);
10364 VOGL_ASSERT(trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle()) == restore_handle);
10366 switch (pState_obj->get_type())
10370 const vogl_query_state *pQuery = static_cast<const vogl_query_state *>(pState_obj);
10372 VOGL_ASSERT(restore_handle <= cUINT32_MAX);
10373 get_shared_state()->m_query_targets[static_cast<GLuint>(restore_handle)] = pQuery->get_target();
10379 const vogl_program_state *pProg = static_cast<const vogl_program_state *>(pState_obj);
10381 if (pProg->has_link_time_snapshot())
10383 vogl_program_state link_snapshot(*pProg->get_link_time_snapshot());
10384 if (!link_snapshot.remap_handles(trace_to_replay_remapper))
10386 vogl_error_printf("%s: Failed remapping handles in program link time snapshot, object index %u trace handle 0x%" PRIX64 " restore handle 0x%" PRIX64 "\n", VOGL_METHOD_NAME, i, (uint64_t)pState_obj->get_snapshot_handle(), (uint64_t)restore_handle);
10390 get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(static_cast<uint32>(restore_handle), link_snapshot);
10394 if (m_flags & cGLReplayerVerboseMode)
10396 if ((n & 255) == 255)
10397 vogl_printf("%s: Restored %u programs\n", VOGL_METHOD_NAME, n);
10404 const vogl_buffer_state *pBuf = static_cast<const vogl_buffer_state *>(pState_obj);
10406 // Check if the buffer was mapped during the snapshot, if so remap it and record the ptr in the replayer's context shadow.
10407 if (pBuf->get_is_mapped())
10409 vogl_mapped_buffer_desc map_desc;
10410 map_desc.m_buffer = static_cast<GLuint>(restore_handle);
10411 map_desc.m_target = pBuf->get_target();
10412 map_desc.m_offset = pBuf->get_map_ofs();
10413 map_desc.m_length = pBuf->get_map_size();
10414 map_desc.m_access = pBuf->get_map_access();
10415 map_desc.m_range = pBuf->get_is_map_range();
10417 GLuint prev_handle = vogl_get_bound_gl_buffer(map_desc.m_target);
10419 GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, map_desc.m_buffer);
10420 VOGL_CHECK_GL_ERROR;
10422 if (map_desc.m_range)
10424 map_desc.m_pPtr = GL_ENTRYPOINT(glMapBufferRange)(map_desc.m_target, static_cast<GLintptr>(map_desc.m_offset), static_cast<GLintptr>(map_desc.m_length), map_desc.m_access);
10425 VOGL_CHECK_GL_ERROR;
10429 map_desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(map_desc.m_target, map_desc.m_access);
10430 VOGL_CHECK_GL_ERROR;
10433 GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, prev_handle);
10434 VOGL_CHECK_GL_ERROR;
10436 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
10437 mapped_bufs.push_back(map_desc);
10447 if (m_flags & cGLReplayerVerboseMode)
10450 vogl_printf("%s: Restore took %f secs\n", VOGL_METHOD_NAME, tm.get_elapsed_secs());
10452 vogl_printf("%s: Finished restoring %u %s objects\n", VOGL_METHOD_NAME, n, get_gl_object_state_type_str(state_type));
10458 //----------------------------------------------------------------------------------------------------------------------
10459 // vogl_xfont_cache
10460 //----------------------------------------------------------------------------------------------------------------------
10461 class vogl_xfont_cache
10463 VOGL_NO_COPY_OR_ASSIGNMENT_OP(vogl_xfont_cache);
10466 vogl_xfont_cache(Display *dpy)
10472 ~vogl_xfont_cache()
10483 for (xfont_map::iterator it = m_xfonts.begin(); it != m_xfonts.end(); ++it)
10484 XFreeFont(m_dpy, it->second);
10488 XFontStruct *get_or_create(const char *pName)
10492 XFontStruct **ppXFont = m_xfonts.find_value(pName);
10496 XFontStruct *pXFont = XLoadQueryFont(m_dpy, pName);
10498 m_xfonts.insert(pName, pXFont);
10506 typedef vogl::map<dynamic_string, XFontStruct *> xfont_map;
10507 xfont_map m_xfonts;
10510 //----------------------------------------------------------------------------------------------------------------------
10511 // vogl_replayer::restore_display_lists
10512 //----------------------------------------------------------------------------------------------------------------------
10513 vogl_gl_replayer::status_t vogl_gl_replayer::restore_display_lists(vogl_handle_remapper &trace_to_replay_remapper, const vogl_gl_state_snapshot &snapshot, const vogl_context_snapshot &context_snapshot)
10517 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10518 VOGL_NOTE_UNUSED(snapshot);
10520 VOGL_ASSERT(m_cur_trace_context);
10524 const vogl_display_list_state &disp_lists = context_snapshot.get_display_list_state();
10526 if (!disp_lists.size())
10529 vogl_message_printf("%s: Recreating %u display lists\n", VOGL_METHOD_NAME, disp_lists.get_display_list_map().size());
10531 vogl_xfont_cache xfont_cache(m_pWindow->get_display());
10533 const vogl_display_list_map &disp_list_map = disp_lists.get_display_list_map();
10535 for (vogl_display_list_map::const_iterator it = disp_list_map.begin(); it != disp_list_map.end(); ++it)
10537 GLuint trace_handle = it->first;
10538 const vogl_display_list &disp_list = it->second;
10542 VOGL_ASSERT_ALWAYS;
10546 GLuint replay_handle = GL_ENTRYPOINT(glGenLists)(1);
10547 if (check_gl_error() || !replay_handle)
10548 goto handle_failure;
10550 if (disp_list.is_valid())
10552 if (disp_list.is_xfont())
10554 XFontStruct *pXFont = xfont_cache.get_or_create(disp_list.get_xfont_name().get_ptr());
10557 vogl_error_printf("%s: Unable to load XFont \"%s\", can't recreate trace display list %u!\n", VOGL_METHOD_NAME, disp_list.get_xfont_name().get_ptr(), trace_handle);
10561 GL_ENTRYPOINT(glXUseXFont)(pXFont->fid, disp_list.get_xfont_glyph(), 1, replay_handle);
10566 GL_ENTRYPOINT(glNewList)(replay_handle, GL_COMPILE);
10568 if (check_gl_error() || !replay_handle)
10570 GL_ENTRYPOINT(glDeleteLists)(replay_handle, 1);
10573 goto handle_failure;
10576 const vogl_trace_packet_array &packets = disp_list.get_packets();
10578 for (uint packet_index = 0; packet_index < packets.size(); packet_index++)
10580 if (packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
10582 vogl_error_printf("%s: Unexpected display list packet type %u, packet index %u, can't fully recreate trace display list %u!\n", VOGL_METHOD_NAME, packets.get_packet_type(packet_index), packet_index, trace_handle);
10586 const uint8_vec &packet_buf = packets.get_packet_buf(packet_index);
10588 if (!m_temp2_gl_packet.deserialize(packet_buf, true))
10590 vogl_error_printf("%s: Failed deserializing display list at packet index %u, can't fully recreate trace display list %u!\n", VOGL_METHOD_NAME, packet_index, trace_handle);
10594 vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = m_temp2_gl_packet.get_entrypoint_packet();
10596 gl_entrypoint_packet.m_context_handle = m_cur_trace_context;
10598 if (m_flags & cGLReplayerDebugMode)
10599 dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
10601 int64_t prev_parsed_call_counter = m_last_parsed_call_counter;
10602 int64_t prev_processed_call_counter = m_last_processed_call_counter;
10603 m_last_parsed_call_counter = gl_entrypoint_packet.m_call_counter;
10604 m_last_processed_call_counter = gl_entrypoint_packet.m_call_counter;
10605 bool prev_at_frame_boundary = m_at_frame_boundary;
10607 const vogl_trace_packet *pPrev_gl_packet = m_pCur_gl_packet;
10609 m_pCur_gl_packet = &m_temp2_gl_packet;
10611 vogl_gl_replayer::status_t status = process_gl_entrypoint_packet_internal(m_temp2_gl_packet);
10613 m_pCur_gl_packet = pPrev_gl_packet;
10615 m_last_parsed_call_counter = prev_parsed_call_counter;
10616 m_last_processed_call_counter = prev_processed_call_counter;
10617 m_at_frame_boundary = prev_at_frame_boundary;
10619 if (status != cStatusOK)
10621 vogl_error_printf("%s: Failed recreating display list at packet index %u, can't fully recreate trace display list %u!\n", VOGL_METHOD_NAME, packet_index, trace_handle);
10626 // TODO: Set context state because we're currently generating a display list!
10627 if (disp_list.is_generating())
10629 VOGL_ASSERT_ALWAYS;
10632 GL_ENTRYPOINT(glEndList)();
10637 get_shared_state()->m_lists.insert(trace_handle, replay_handle);
10639 if (!get_shared_state()->m_shadow_state.m_display_lists.define_list(trace_handle, replay_handle, disp_list))
10641 vogl_error_printf("%s: Failed adding display list trace handle %u GL handle %u into display list shadow!\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
10647 vogl_message_printf("%s: Done recreating display lists\n", VOGL_METHOD_NAME);
10652 return cStatusHardFailure;
10655 //----------------------------------------------------------------------------------------------------------------------
10656 // vogl_replayer::restore_general_state
10657 //----------------------------------------------------------------------------------------------------------------------
10658 vogl_gl_replayer::status_t vogl_gl_replayer::restore_general_state(vogl_handle_remapper &trace_to_replay_remapper, const vogl_gl_state_snapshot &snapshot, const vogl_context_snapshot &context_snapshot)
10662 VOGL_NOTE_UNUSED(snapshot);
10664 vogl_general_context_state::vogl_persistent_restore_state persistent_restore_state;
10665 persistent_restore_state.m_pSelect_buffer = &m_pCur_context_state->m_select_buffer;
10667 if (!context_snapshot.get_general_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, persistent_restore_state))
10668 return cStatusHardFailure;
10670 if (!m_pCur_context_state->m_context_info.is_core_profile())
10672 if (context_snapshot.get_texenv_state().is_valid())
10674 if (!context_snapshot.get_texenv_state().restore(m_pCur_context_state->m_context_info))
10675 return cStatusHardFailure;
10678 if (context_snapshot.get_material_state().is_valid())
10680 if (!context_snapshot.get_material_state().restore(m_pCur_context_state->m_context_info))
10681 return cStatusHardFailure;
10684 if (context_snapshot.get_light_state().is_valid())
10686 if (!context_snapshot.get_light_state().restore(m_pCur_context_state->m_context_info))
10687 return cStatusHardFailure;
10690 if (context_snapshot.get_matrix_state().is_valid())
10692 if (!context_snapshot.get_matrix_state().restore(m_pCur_context_state->m_context_info))
10693 return cStatusHardFailure;
10696 if (context_snapshot.get_polygon_stipple_state().is_valid())
10698 if (!context_snapshot.get_polygon_stipple_state().restore(m_pCur_context_state->m_context_info))
10699 return cStatusHardFailure;
10702 if (context_snapshot.get_arb_program_environment_state().is_valid())
10704 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_vertex_program"))
10706 if (!context_snapshot.get_arb_program_environment_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper))
10707 return cStatusHardFailure;
10711 vogl_error_printf("%s: Unable to restore ARB program environment state to context because it does not support the \"GL_ARB_vertex_program\" extension\n", VOGL_METHOD_NAME);
10716 if (context_snapshot.get_current_vertex_attrib_state().is_valid())
10718 if (!context_snapshot.get_current_vertex_attrib_state().restore(m_pCur_context_state->m_context_info))
10719 return cStatusHardFailure;
10725 //----------------------------------------------------------------------------------------------------------------------
10726 // vogl_replayer::validate_program_and_shader_handle_tables
10727 //----------------------------------------------------------------------------------------------------------------------
10728 bool vogl_gl_replayer::validate_program_and_shader_handle_tables()
10732 if (!m_pCur_context_state)
10735 if (!get_shared_state()->m_shadow_state.m_objs.check())
10736 vogl_error_printf("%s: Object handle tracker failed validation!\n", VOGL_METHOD_NAME);
10738 uint_vec replay_handles;
10739 get_shared_state()->m_shadow_state.m_objs.get_inv_handles(replay_handles);
10741 for (uint i = 0; i < replay_handles.size(); i++)
10743 GLuint replay_handle = replay_handles[i];
10744 GLuint trace_handle = replay_handle;
10745 bool map_succeeded = get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle, trace_handle);
10746 VOGL_ASSERT(map_succeeded);
10747 VOGL_NOTE_UNUSED(map_succeeded);
10749 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle);
10750 VOGL_ASSERT(target == get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle));
10752 if (target == VOGL_PROGRAM_OBJECT)
10754 if (!GL_ENTRYPOINT(glIsProgram)(replay_handle))
10756 vogl_error_printf("%s: GL handle %u is being tracked, but glIsProgram() reports the handle is not a program\n", VOGL_METHOD_NAME, replay_handle);
10759 if (!get_shared_state()->m_glsl_program_hash_map.contains(trace_handle))
10761 vogl_error_printf("%s: Found program at trace handle %u GL handle %u, but the GLSL program hash map doesn't contain an entry for this object!\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
10764 else if (target == VOGL_SHADER_OBJECT)
10766 if (!GL_ENTRYPOINT(glIsShader)(replay_handle))
10768 vogl_error_printf("%s: GL handle %u is being tracked, but glIsShader() reports the handle is not a program\n", VOGL_METHOD_NAME, replay_handle);
10773 VOGL_ASSERT_ALWAYS;
10780 //----------------------------------------------------------------------------------------------------------------------
10781 // vogl_replayer::validate_textures
10782 //----------------------------------------------------------------------------------------------------------------------
10783 bool vogl_gl_replayer::validate_textures()
10787 if (!m_pCur_context_state)
10790 if (!get_shared_state()->m_shadow_state.m_textures.check())
10791 vogl_error_printf("%s: Texture handle tracker failed validation!\n", VOGL_METHOD_NAME);
10793 for (uint replay_handle = 1; replay_handle <= 0xFFFFU; replay_handle++)
10795 bool is_tex = GL_ENTRYPOINT(glIsTexture)(replay_handle) != 0;
10797 bool found_in_shadow = get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle);
10801 if (found_in_shadow)
10803 GLuint trace_handle = 0;
10804 get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle, trace_handle);
10805 vogl_debug_printf("%s: Texture %u is not a name, but it has a valid mapping to trace handle %u\n", VOGL_METHOD_NAME, replay_handle, trace_handle);
10810 if (!found_in_shadow)
10812 vogl_debug_printf("%s: Texture %u is a valid name, but it does have a mapping to a trace handle!\n", VOGL_METHOD_NAME, replay_handle);
10820 //----------------------------------------------------------------------------------------------------------------------
10821 // vogl_replayer::update_context_shadows
10822 //----------------------------------------------------------------------------------------------------------------------
10823 vogl_gl_replayer::status_t vogl_gl_replayer::update_context_shadows(vogl_handle_remapper &trace_to_replay_remapper, const vogl_gl_state_snapshot &snapshot, const vogl_context_snapshot &context_snapshot)
10827 VOGL_NOTE_UNUSED(snapshot);
10828 VOGL_NOTE_UNUSED(context_snapshot);
10829 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10833 // Make sure shadow is good
10834 GLint actual_current_replay_program = 0;
10835 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
10838 m_pCur_context_state->m_cur_replay_program = actual_current_replay_program;
10839 if (!actual_current_replay_program)
10840 m_pCur_context_state->m_cur_trace_program = 0;
10843 GLuint trace_handle = actual_current_replay_program;
10844 if (!get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(actual_current_replay_program, trace_handle))
10846 process_entrypoint_error("%s: Failed finding restored GL shader %u in program/shader object handle hashmap\n", VOGL_METHOD_NAME, actual_current_replay_program);
10848 m_pCur_context_state->m_cur_replay_program = 0;
10849 m_pCur_context_state->m_cur_trace_program = 0;
10853 m_pCur_context_state->m_cur_trace_program = trace_handle;
10857 check_program_binding_shadow();
10862 //----------------------------------------------------------------------------------------------------------------------
10863 // vogl_replayer::handle_marked_for_deleted_objects
10864 //----------------------------------------------------------------------------------------------------------------------
10865 void vogl_gl_replayer::handle_marked_for_deleted_objects(vogl_const_gl_object_state_ptr_vec &objects_to_delete, trace_to_replay_handle_remapper &trace_to_replay_remapper)
10869 if (m_flags & cGLReplayerVerboseMode)
10871 vogl_debug_printf("%s: %u program/shader objects where marked as deleted\n", VOGL_METHOD_NAME, objects_to_delete.size());
10874 for (uint i = 0; i < objects_to_delete.size(); i++)
10876 const vogl_gl_object_state *pState_obj = objects_to_delete[i];
10878 GLuint64 trace_handle = pState_obj->get_snapshot_handle();
10879 GLuint64 restore_handle = trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle());
10881 if (m_flags & cGLReplayerVerboseMode)
10883 // This should be a rare/exception case so let's try to be a little paranoid.
10884 vogl_debug_printf("%s: Snapshot object type %s trace handle 0x%" PRIX64 " restore handle 0x%" PRIX64 ", was marked as deleted, deleting object after restoring (object should still be referenced by state in the GL context)\n", VOGL_METHOD_NAME,
10885 get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
10888 GLboolean object_is_still_a_name = true;
10890 switch (pState_obj->get_type())
10894 handle_delete_program(static_cast<GLuint>(trace_handle));
10896 object_is_still_a_name = GL_ENTRYPOINT(glIsProgram)(static_cast<GLuint>(restore_handle));
10902 handle_delete_shader(static_cast<GLuint>(trace_handle));
10904 object_is_still_a_name = GL_ENTRYPOINT(glIsShader)(static_cast<GLuint>(restore_handle));
10910 VOGL_ASSERT_ALWAYS;
10915 // "A program object marked for deletion with glDeleteProgram but still in use as part of current rendering state is still considered a program object and glIsProgram will return GL_TRUE."
10916 // Same for shaders.
10917 if (!object_is_still_a_name)
10919 vogl_debug_printf("%s: Snapshot object type %s trace handle 0x%" PRIX64 " restore handle 0x%" PRIX64 ", was marked as deleted, then deleted after a full state restore, but the object which should still be referenced by state in the GL context fails the glIsProgram()/glIsShader()/etc. test\n", VOGL_METHOD_NAME,
10920 get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
10925 //----------------------------------------------------------------------------------------------------------------------
10926 // vogl_replayer::begin_applying_snapshot
10927 // Takes ownership (even on errors) when delete_snapshot_after_applying is true.
10928 //----------------------------------------------------------------------------------------------------------------------
10929 vogl_gl_replayer::status_t vogl_gl_replayer::begin_applying_snapshot(const vogl_gl_state_snapshot *pSnapshot, bool delete_snapshot_after_applying)
10933 if (!pSnapshot->is_valid())
10935 if (delete_snapshot_after_applying)
10936 vogl_delete(const_cast<vogl_gl_state_snapshot *>(pSnapshot));
10938 return cStatusHardFailure;
10943 m_pPending_snapshot = pSnapshot;
10944 m_delete_pending_snapshot_after_applying = delete_snapshot_after_applying;
10946 m_frame_index = pSnapshot->get_frame_index();
10947 m_last_parsed_call_counter = pSnapshot->get_gl_call_counter();
10948 m_last_processed_call_counter = pSnapshot->get_gl_call_counter();
10949 m_at_frame_boundary = false;
10951 if (!(m_flags & cGLReplayerLockWindowDimensions))
10953 return trigger_pending_window_resize(pSnapshot->get_window_width(), pSnapshot->get_window_height());
10956 return process_applying_pending_snapshot();
10959 //----------------------------------------------------------------------------------------------------------------------
10960 // vogl_replayer::restore_context
10961 //----------------------------------------------------------------------------------------------------------------------
10962 vogl_gl_replayer::status_t vogl_gl_replayer::restore_context(vogl_handle_remapper &trace_to_replay_remapper, const vogl_gl_state_snapshot &snapshot, const vogl_context_snapshot &context_snapshot)
10966 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10967 VOGL_NOTE_UNUSED(snapshot);
10969 // TODO: This always creates with attribs, also need to support plain glXCreateContext()
10971 Display *dpy = m_pWindow->get_display();
10972 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
10974 vogl_trace_context_ptr_value trace_share_context = context_snapshot.get_context_desc().get_trace_share_context();
10976 GLXContext replay_share_context = remap_context(trace_share_context);
10977 if ((trace_share_context) && (!replay_share_context))
10979 vogl_error_printf("%s: Failed remapping trace share context handle 0x%" PRIx64 " to replay context!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
10980 return cStatusHardFailure;
10983 GLboolean direct = context_snapshot.get_context_desc().get_direct();
10985 vogl_trace_context_ptr_value trace_context = context_snapshot.get_context_desc().get_trace_context();
10987 status_t status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct,
10988 context_snapshot.get_context_desc().get_attribs().get_vec().get_ptr(),
10989 context_snapshot.get_context_desc().get_attribs().get_vec().size(), true);
10990 if (status != cStatusOK)
10992 vogl_error_printf("%s: Failed creating new context\n", VOGL_METHOD_NAME);
10996 // Has this context ever been made current?
10997 if (context_snapshot.get_context_info().is_valid())
10999 context_state *pContext_state = get_trace_context_state(trace_context);
11000 if (!pContext_state)
11002 vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11003 return cStatusHardFailure;
11006 GLXContext replay_context = pContext_state->m_replay_context;
11007 if (!replay_context)
11009 vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11010 return cStatusHardFailure;
11013 GLXDrawable drawable = m_pWindow->get_xwindow();
11015 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
11018 vogl_error_printf("%s: Failed making context current\n", VOGL_METHOD_NAME);
11019 return cStatusHardFailure;
11022 m_cur_trace_context = trace_context;
11023 m_cur_replay_context = replay_context;
11024 m_pCur_context_state = pContext_state;
11026 if (!handle_context_made_current())
11027 return cStatusHardFailure;
11033 //----------------------------------------------------------------------------------------------------------------------
11034 // vogl_replayer::process_applying_pending_snapshot
11035 //----------------------------------------------------------------------------------------------------------------------
11036 vogl_gl_replayer::status_t vogl_gl_replayer::process_applying_pending_snapshot()
11040 if (!m_pPending_snapshot)
11043 timed_scope ts(VOGL_METHOD_NAME);
11045 const vogl_gl_state_snapshot &snapshot = *m_pPending_snapshot;
11047 trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
11049 m_frame_index = snapshot.get_frame_index();
11050 m_last_parsed_call_counter = snapshot.get_gl_call_counter();
11051 m_last_processed_call_counter = snapshot.get_gl_call_counter();
11052 m_at_frame_boundary = snapshot.get_at_frame_boundary();
11054 // Ensure the client side array bufs are large enough (we don't care about the actual ptr values).
11055 for (uint i = 0; i < snapshot.get_client_side_vertex_attrib_ptrs().size(); i++)
11056 m_client_side_vertex_attrib_data[i].resize(snapshot.get_client_side_vertex_attrib_ptrs()[i].m_size);
11058 for (uint i = 0; i < snapshot.get_client_side_array_ptrs().size(); i++)
11059 m_client_side_array_data[i].resize(snapshot.get_client_side_array_ptrs()[i].m_size);
11061 for (uint i = 0; i < snapshot.get_client_side_texcoord_ptrs().size(); i++)
11062 m_client_side_texcoord_data[i].resize(snapshot.get_client_side_texcoord_ptrs()[i].m_size);
11064 const vogl_context_snapshot_ptr_vec &context_ptrs = snapshot.get_contexts();
11066 vogl_context_snapshot_ptr_vec restore_context_ptrs(snapshot.get_contexts());
11067 vogl::vector<vogl_const_gl_object_state_ptr_vec> objects_to_delete_vec(context_ptrs.size());
11069 status_t status = cStatusOK;
11070 uint total_contexts_restored = 0;
11071 bool restored_default_framebuffer = false;
11075 uint num_contexts_restored_in_this_pass = 0;
11077 for (uint context_index = 0; context_index < restore_context_ptrs.size(); context_index++)
11079 if (!restore_context_ptrs[context_index])
11082 const vogl_context_snapshot &context_state = *restore_context_ptrs[context_index];
11084 if (context_state.get_context_desc().get_trace_share_context())
11086 // Don't restore this context if its sharelist context hasn't been restored yet
11087 if (!remap_context(context_state.get_context_desc().get_trace_share_context()))
11091 status = restore_context(trace_to_replay_remapper, snapshot, context_state);
11092 if (status != cStatusOK)
11095 // Has this context ever been made current?
11096 if (context_state.get_context_info().is_valid())
11098 // Keep this in sync with vogl_gl_object_state_type (the order doesn't need to match the enum, but be sure to restore leaf GL objects first!)
11099 const vogl_gl_object_state_type s_object_type_restore_order[] = { cGLSTBuffer, cGLSTSampler, cGLSTQuery, cGLSTRenderbuffer, cGLSTTexture, cGLSTFramebuffer, cGLSTVertexArray, cGLSTShader, cGLSTProgram, cGLSTSync, cGLSTARBProgram };
11100 VOGL_ASSUME(VOGL_ARRAY_SIZE(s_object_type_restore_order) == (cGLSTTotalTypes - 1));
11102 if (m_flags & cGLReplayerLowLevelDebugMode)
11104 if (!validate_textures())
11105 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11108 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11110 for (uint i = 0; i < VOGL_ARRAY_SIZE(s_object_type_restore_order); i++)
11112 status = restore_objects(trace_to_replay_remapper, snapshot, context_state, s_object_type_restore_order[i], objects_to_delete);
11113 if (status != cStatusOK)
11116 if (m_flags & cGLReplayerLowLevelDebugMode)
11118 if (!validate_program_and_shader_handle_tables())
11119 vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11121 if (!validate_textures())
11122 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11126 if (m_flags & cGLReplayerLowLevelDebugMode)
11128 if (!validate_textures())
11129 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11132 status = restore_display_lists(trace_to_replay_remapper, snapshot, context_state);
11133 if (status != cStatusOK)
11136 // Restore default framebuffer
11137 if ((!restored_default_framebuffer) && (snapshot.get_default_framebuffer().is_valid()))
11139 restored_default_framebuffer = true;
11141 if (!snapshot.get_default_framebuffer().restore(m_pCur_context_state->m_context_info))
11143 vogl_warning_printf("%s: Failed restoring default framebuffer!\n", VOGL_METHOD_NAME);
11147 // Beware: restore_general_state() will bind a bunch of stuff from the trace!
11148 status = restore_general_state(trace_to_replay_remapper, snapshot, context_state);
11149 if (status != cStatusOK)
11152 status = update_context_shadows(trace_to_replay_remapper, snapshot, context_state);
11153 if (status != cStatusOK)
11156 if (m_flags & cGLReplayerLowLevelDebugMode)
11158 if (!validate_program_and_shader_handle_tables())
11159 vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11161 if (!validate_textures())
11162 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11166 num_contexts_restored_in_this_pass++;
11168 total_contexts_restored++;
11170 restore_context_ptrs[context_index] = NULL;
11173 if (!num_contexts_restored_in_this_pass)
11177 if (total_contexts_restored != snapshot.get_contexts().size())
11179 vogl_error_printf("%s: Failed satisfying sharelist dependency during context restoration\n", VOGL_METHOD_NAME);
11183 for (uint context_index = 0; context_index < context_ptrs.size(); context_index++)
11185 const vogl_context_snapshot &context_state = *context_ptrs[context_index];
11187 if (!context_state.get_context_info().is_valid())
11190 status_t status = switch_contexts(context_state.get_context_desc().get_trace_context());
11191 if (status != cStatusOK)
11193 vogl_error_printf("%s: Failed switching to trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, cast_val_to_uint64(context_state.get_context_desc().get_trace_context()));
11197 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11199 handle_marked_for_deleted_objects(objects_to_delete, trace_to_replay_remapper);
11202 destroy_pending_snapshot();
11213 //----------------------------------------------------------------------------------------------------------------------
11214 // vogl_gl_replayer::write_trim_file_internal
11215 //----------------------------------------------------------------------------------------------------------------------
11216 bool vogl_gl_replayer::write_trim_file_internal(vogl_trace_packet_array &trim_packets, const dynamic_string &trim_filename, vogl_trace_file_reader &trace_reader, bool optimize_snapshot, dynamic_string *pSnapshot_id)
11218 // Open the output trace
11219 // TODO: This pretty much ignores the ctypes packet, and uses the one based off the ptr size in the header. The ctypes stuff needs to be refactored, storing it in an explicit packet is bad.
11220 const vogl_ctypes &trace_gl_ctypes = get_trace_gl_ctypes();
11222 vogl_trace_packet trace_packet(&trace_gl_ctypes);
11224 // TODO: This seems like WAY too much work! Move the snapshot to the beginning of the trace, in the header!
11225 bool found_state_snapshot = false;
11226 dynamic_string binary_snapshot_id, text_snapshot_id;
11228 bool is_at_start_of_trace = false;
11229 VOGL_NOTE_UNUSED(is_at_start_of_trace);
11231 int demarcation_packet_index = -1;
11232 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11234 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11235 if (packet_type != cTSPTGLEntrypoint)
11238 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11240 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11241 if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11244 if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11246 console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11250 GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11251 if (cmd == cITCRDemarcation)
11253 is_at_start_of_trace = true;
11254 demarcation_packet_index = packet_index;
11256 else if (cmd == cITCRKeyValueMap)
11258 key_value_map &kvm = trace_packet.get_key_value_map();
11260 dynamic_string cmd_type(kvm.get_string("command_type"));
11262 if (cmd_type == "state_snapshot")
11264 found_state_snapshot = true;
11266 text_snapshot_id = kvm.get_string("id");
11267 binary_snapshot_id = kvm.get_string("binary_id");
11272 vogl_trace_file_writer trace_writer(&trace_gl_ctypes);
11273 if (!trace_writer.open(trim_filename.get_ptr(), NULL, true, false, m_trace_pointer_size_in_bytes))
11275 console::error("%s: Failed creating trimmed trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11279 if (found_state_snapshot)
11281 // Copy over the source trace's archive (it contains the snapshot, along with any files it refers to).
11282 if (trace_reader.get_archive_blob_manager().is_initialized())
11284 dynamic_string_array blob_files(trace_reader.get_archive_blob_manager().enumerate());
11285 for (uint i = 0; i < blob_files.size(); i++)
11287 if ((blob_files[i].is_empty()) || (blob_files[i] == VOGL_TRACE_ARCHIVE_FRAME_FILE_OFFSETS_FILENAME))
11290 vogl_message_printf("Adding blob file %s to output trace archive\n", blob_files[i].get_ptr());
11292 if (!trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), blob_files[i], blob_files[i]).has_content())
11294 vogl_error_printf("%s: Failed copying blob data for file \"%s\" to output trace archive!\n", VOGL_FUNCTION_NAME, blob_files[i].get_ptr());
11302 // Copy over the source trace's backtrace map, machine info, etc. files.
11303 if (trace_reader.get_archive_blob_manager().is_initialized())
11305 // compiler_info.json
11306 trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), VOGL_TRACE_ARCHIVE_COMPILER_INFO_FILENAME, VOGL_TRACE_ARCHIVE_COMPILER_INFO_FILENAME);
11307 // machine_info.json
11308 trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), VOGL_TRACE_ARCHIVE_MACHINE_INFO_FILENAME, VOGL_TRACE_ARCHIVE_MACHINE_INFO_FILENAME);
11309 // backtrace_map_syms.json
11310 trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), VOGL_TRACE_ARCHIVE_BACKTRACE_MAP_SYMS_FILENAME, VOGL_TRACE_ARCHIVE_BACKTRACE_MAP_SYMS_FILENAME);
11311 // backtrace_map_addrs.json
11312 trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), VOGL_TRACE_ARCHIVE_BACKTRACE_MAP_ADDRS_FILENAME, VOGL_TRACE_ARCHIVE_BACKTRACE_MAP_ADDRS_FILENAME);
11315 vogl_unique_ptr<vogl_gl_state_snapshot> pTrim_snapshot(snapshot_state(&trim_packets, optimize_snapshot));
11317 if (!pTrim_snapshot.get())
11319 console::error("%s: Failed creating replayer GL snapshot!\n", VOGL_FUNCTION_NAME);
11323 pTrim_snapshot->set_frame_index(0);
11326 if (!pTrim_snapshot->serialize(*doc.get_root(), *trace_writer.get_trace_archive(), &trace_gl_ctypes))
11328 console::error("%s: Failed serializing GL state snapshot!\n", VOGL_FUNCTION_NAME);
11329 trace_writer.close();
11330 file_utils::delete_file(trim_filename.get_ptr());
11334 vogl::vector<char> snapshot_data;
11335 doc.serialize(snapshot_data, true, 0, false);
11337 uint8_vec binary_snapshot_data;
11338 doc.binary_serialize(binary_snapshot_data);
11340 pTrim_snapshot.reset();
11342 // Write the state_snapshot file to the trace archive
11343 dynamic_string snapshot_id(trace_writer.get_trace_archive()->add_buf_compute_unique_id(snapshot_data.get_ptr(), snapshot_data.size(), "state_snapshot", VOGL_TEXT_JSON_EXTENSION));
11344 if (snapshot_id.is_empty())
11346 console::error("%s: Failed adding GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11347 trace_writer.close();
11348 file_utils::delete_file(trim_filename.get_ptr());
11353 *pSnapshot_id = snapshot_id;
11355 snapshot_data.clear();
11357 // Write the binary_state_snapshot file to the trace archive
11358 dynamic_string binary_snapshot_id(trace_writer.get_trace_archive()->add_buf_compute_unique_id(binary_snapshot_data.get_ptr(), binary_snapshot_data.size(), "binary_state_snapshot", VOGL_BINARY_JSON_EXTENSION));
11359 if (binary_snapshot_id.is_empty())
11361 console::error("%s: Failed adding binary GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11362 trace_writer.close();
11363 file_utils::delete_file(trim_filename.get_ptr());
11367 binary_snapshot_data.clear();
11369 key_value_map snapshot_key_value_map;
11370 snapshot_key_value_map.insert("command_type", "state_snapshot");
11371 snapshot_key_value_map.insert("id", snapshot_id);
11372 snapshot_key_value_map.insert("binary_id", binary_snapshot_id);
11374 dynamic_stream snapshot_stream(0);
11375 if (!vogl_write_glInternalTraceCommandRAD(snapshot_stream, &trace_gl_ctypes, cITCRKeyValueMap, sizeof(snapshot_key_value_map), reinterpret_cast<const GLubyte *>(&snapshot_key_value_map)))
11377 console::error("%s: Failed serializing snapshot packet!\n", VOGL_FUNCTION_NAME);
11378 trace_writer.close();
11379 file_utils::delete_file(trim_filename.get_ptr());
11383 if (demarcation_packet_index >= 0)
11385 trim_packets.insert(demarcation_packet_index, snapshot_stream.get_buf());
11386 demarcation_packet_index++;
11390 dynamic_stream demarcation_stream(0);
11391 vogl_write_glInternalTraceCommandRAD(demarcation_stream, &trace_gl_ctypes, cITCRDemarcation, 0, NULL);
11393 // Screw the ctypes packet, it's only used for debugging right now anyway.
11394 trim_packets.insert(0, snapshot_stream.get_buf());
11395 trim_packets.insert(1, demarcation_stream.get_buf());
11399 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11401 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11403 const bool is_swap = trim_packets.is_swap_buffers_packet(packet_index);
11405 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11406 if (packet_type == cTSPTEOF)
11408 else if (packet_type != cTSPTGLEntrypoint)
11410 VOGL_ASSERT_ALWAYS;
11413 if (!trace_writer.write_packet(packet_buf.get_ptr(), packet_buf.size(), is_swap))
11415 console::error("%s: Failed writing trace packet to output trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11416 trace_writer.close();
11417 file_utils::delete_file(trim_filename.get_ptr());
11422 bool success = trace_writer.close();
11424 console::error("%s: Failed closing wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11426 console::message("%s: Successfully wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11431 //----------------------------------------------------------------------------------------------------------------------
11432 // vogl_gl_replayer::write_trim_file
11433 //----------------------------------------------------------------------------------------------------------------------
11434 bool vogl_gl_replayer::write_trim_file(uint flags, const dynamic_string &trim_filename, uint trim_len, vogl_trace_file_reader &trace_reader, dynamic_string *pSnapshot_id)
11440 console::error("%s: Trace is not open\n", VOGL_METHOD_NAME);
11444 bool from_start_of_frame = (flags & cWriteTrimFileFromStartOfFrame) != 0;
11446 if ((!from_start_of_frame) || (!trim_len))
11447 flags &= ~cWriteTrimFileOptimizeSnapshot;
11449 const uint trim_frame = static_cast<uint>(get_frame_index());
11450 const int64_t trim_call_counter = get_last_parsed_call_counter();
11452 // Read the desired packets from the source trace file
11453 vogl_trace_packet_array trim_packets;
11455 if ((trim_len) || (!trim_frame))
11457 console::message("%s: Reading trim packets from source trace file\n", VOGL_FUNCTION_NAME);
11459 uint frames_to_read = trim_len;
11460 if ((from_start_of_frame) && (!trim_frame) && (!trim_len))
11461 frames_to_read = 1;
11463 uint actual_trim_len = 0;
11464 vogl_trace_file_reader::trace_file_reader_status_t read_packets_status = trace_reader.read_frame_packets(trim_frame, frames_to_read, trim_packets, actual_trim_len);
11465 if (read_packets_status == vogl_trace_file_reader::cFailed)
11467 console::error("%s: Failed reading source trace file packets beginning at frame %u!\n", VOGL_FUNCTION_NAME, trim_frame);
11471 if (actual_trim_len != frames_to_read)
11473 console::warning("%s: Only able to read %u frames from trim file beginning at frame %u, not the requested %u\n", VOGL_FUNCTION_NAME, actual_trim_len, trim_frame, frames_to_read);
11476 if (from_start_of_frame)
11478 console::message("%s: Read %u trim packets beginning at frame %u actual len %u from source trace file\n", VOGL_FUNCTION_NAME, trim_packets.size(), trim_frame, actual_trim_len);
11480 if ((!trim_frame) && (!trim_len))
11482 // Special case: They want frame 0 with no packets, so be sure to copy any internal trace commands at the very beginning of the trace.
11483 // TODO: Most of this will go away once we move the state snapshot into the trace archive.
11485 vogl_trace_packet_array new_trim_packets;
11487 vogl_trace_packet trace_packet(&get_trace_gl_ctypes());
11489 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11491 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11492 if (packet_type != cTSPTGLEntrypoint)
11495 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11497 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11498 if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11501 if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11503 console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11507 GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11509 new_trim_packets.push_back(packet_buf);
11511 if (cmd == cITCRDemarcation)
11515 trim_packets.swap(new_trim_packets);
11518 else if (trim_call_counter >= 0)
11520 uint orig_num_packets = trim_packets.size();
11521 uint total_erased_packets = 0;
11523 // Remove any calls before the current one.
11524 for (int64_t packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11526 if (trim_packets.get_packet_type(static_cast<uint>(packet_index)) != cTSPTGLEntrypoint)
11529 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(static_cast<uint>(packet_index));
11531 if (static_cast<int64_t>(pGL_packet->m_call_counter) <= trim_call_counter)
11533 trim_packets.erase(static_cast<uint>(packet_index));
11536 total_erased_packets++;
11540 console::message("%s: Read %u packets from frame %u, erased %u packets before call counter %" PRIu64 ", storing %u trim packets from source trace file\n", VOGL_FUNCTION_NAME, orig_num_packets, trim_frame, total_erased_packets, trim_call_counter, trim_packets.size());
11544 if (!write_trim_file_internal(trim_packets, trim_filename, trace_reader, (flags & cWriteTrimFileOptimizeSnapshot) != 0, pSnapshot_id))
11546 console::warning("%s: Trim file write failed, deleting invalid trim trace file %s\n", VOGL_METHOD_NAME, trim_filename.get_ptr());
11548 file_utils::delete_file(trim_filename.get_ptr());