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 // Seems better to return -1 when we can't find the uniform (which can happen if the driver optimizes the program differently vs. tracing).
1270 // Otherwise, we can pass an invalid handle down to the driver and this will crash AMD's fglrx.
1271 //GLint replay_location = trace_location;
1272 GLint replay_location = -1;
1274 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_program);
1275 if (it == get_shared_state()->m_glsl_program_hash_map.end())
1277 process_entrypoint_warning("%s: Failed looking up current trace program in GLSL program hash map\n", VOGL_METHOD_NAME);
1281 glsl_program_state &state = it->second;
1283 uniform_location_hash_map::const_iterator loc_it = state.m_uniform_locations.find(trace_location);
1284 if (loc_it == state.m_uniform_locations.end())
1286 process_entrypoint_warning("%s: Failed looking up uniform location index\n", VOGL_METHOD_NAME);
1290 replay_location = loc_it->second;
1293 return replay_location;
1296 //----------------------------------------------------------------------------------------------------------------------
1297 // vogl_replayer::process_entrypoint_print_summary_context
1298 //----------------------------------------------------------------------------------------------------------------------
1299 void vogl_gl_replayer::process_entrypoint_print_summary_context(eConsoleMessageType msg_type)
1303 if (!m_pCur_gl_packet)
1306 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",
1307 g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
1308 m_frame_index, m_total_swaps,
1309 m_pCur_gl_packet->get_entrypoint_packet().m_call_counter,
1310 m_pCur_gl_packet->get_entrypoint_packet().m_context_handle,
1311 m_cur_trace_context,
1312 m_pCur_gl_packet->get_entrypoint_packet().m_thread_id);
1315 dynamic_string_array backtrace;
1316 if (get_printable_backtrace(backtrace))
1318 console::printf("Backtrace:\n");
1319 for (uint i = 0; i < backtrace.size(); i++)
1320 console::printf("%s\n", backtrace[i].get_ptr());
1325 //----------------------------------------------------------------------------------------------------------------------
1326 // vogl_replayer::print_detailed_context
1327 //----------------------------------------------------------------------------------------------------------------------
1328 void vogl_gl_replayer::print_detailed_context(eConsoleMessageType msg_type)
1334 vogl_loose_file_blob_manager blob_file_manager;
1335 blob_file_manager.init(cBMFWritable);
1337 vogl_trace_packet::json_serialize_params serialize_params;
1338 serialize_params.m_output_basename = "replay_error";
1339 serialize_params.m_cur_frame = m_frame_index;
1340 serialize_params.m_blob_file_size_threshold = 1024;
1341 serialize_params.m_pBlob_manager = (m_flags & cGLReplayerDumpPacketBlobFilesOnError) ? &blob_file_manager : NULL;
1342 m_pCur_gl_packet->json_serialize(node, serialize_params);
1344 dynamic_string node_str;
1345 node.serialize(node_str, true, 0);
1346 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());
1349 //----------------------------------------------------------------------------------------------------------------------
1350 // vogl_replayer::process_entrypoint_msg_print_detailed_context
1351 //----------------------------------------------------------------------------------------------------------------------
1352 void vogl_gl_replayer::process_entrypoint_msg_print_detailed_context(eConsoleMessageType msg_type)
1356 if (!m_pCur_gl_packet)
1359 dump_packet_as_func_call(*m_pCur_gl_packet);
1361 if (!(m_flags & cGLReplayerDumpPacketsOnError))
1364 print_detailed_context(msg_type);
1367 //----------------------------------------------------------------------------------------------------------------------
1368 // vogl_replayer::process_entrypoint_info
1369 //----------------------------------------------------------------------------------------------------------------------
1370 void vogl_gl_replayer::process_entrypoint_info(const char *pFmt, ...)
1374 process_entrypoint_print_summary_context(cInfoConsoleMessage);
1377 va_start(args, pFmt);
1378 console::vprintf(cInfoConsoleMessage, pFmt, args);
1381 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1384 //----------------------------------------------------------------------------------------------------------------------
1385 // vogl_replayer::process_entrypoint_message
1386 //----------------------------------------------------------------------------------------------------------------------
1387 void vogl_gl_replayer::process_entrypoint_message(const char *pFmt, ...)
1391 process_entrypoint_print_summary_context(cMessageConsoleMessage);
1394 va_start(args, pFmt);
1395 console::vprintf(cMessageConsoleMessage, pFmt, args);
1398 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1401 //----------------------------------------------------------------------------------------------------------------------
1402 // vogl_replayer::process_entrypoint_warning
1403 //----------------------------------------------------------------------------------------------------------------------
1404 void vogl_gl_replayer::process_entrypoint_warning(const char *pFmt, ...)
1408 process_entrypoint_print_summary_context(cWarningConsoleMessage);
1411 va_start(args, pFmt);
1412 console::vprintf(cWarningConsoleMessage, pFmt, args);
1415 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1418 //----------------------------------------------------------------------------------------------------------------------
1419 // vogl_replayer::process_entrypoint_error
1420 //----------------------------------------------------------------------------------------------------------------------
1421 void vogl_gl_replayer::process_entrypoint_error(const char *pFmt, ...)
1425 process_entrypoint_print_summary_context(cErrorConsoleMessage);
1428 va_start(args, pFmt);
1429 console::vprintf(cErrorConsoleMessage, pFmt, args);
1432 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1435 //----------------------------------------------------------------------------------------------------------------------
1436 // vogl_replayer::switch_contexts
1437 //----------------------------------------------------------------------------------------------------------------------
1438 vogl_gl_replayer::status_t vogl_gl_replayer::switch_contexts(vogl_trace_context_ptr_value trace_context)
1443 //if (m_pCur_gl_packet->get_call_counter() == 25583)
1444 // vogl_debug_break();
1446 //vogl_trace_context_ptr_value trace_context = gl_packet.m_context_handle;
1447 if (trace_context == m_cur_trace_context)
1450 if (m_flags & cGLReplayerDebugMode)
1452 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));
1455 // pContext_state will be NULL if they are unmapping!
1456 context_state *pContext_state = get_trace_context_state(trace_context);
1457 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1459 const Display *dpy = m_pWindow->get_display();
1460 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1462 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1465 process_entrypoint_error("%s: Failed switching current trace context to 0x%" PRIX64 "\n", VOGL_METHOD_NAME, trace_context);
1466 return cStatusHardFailure;
1469 m_cur_trace_context = trace_context;
1470 m_cur_replay_context = replay_context;
1471 m_pCur_context_state = pContext_state;
1476 //----------------------------------------------------------------------------------------------------------------------
1477 // vogl_replayer::debug_callback_arb
1478 //----------------------------------------------------------------------------------------------------------------------
1479 void vogl_gl_replayer::debug_callback_arb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *pUser_param)
1483 VOGL_NOTE_UNUSED(length);
1485 char final_message[4096];
1487 context_state *pContext_state = (context_state *)(pUser_param);
1489 vogl_format_debug_output_arb(final_message, sizeof(final_message), source, type, id, severity, reinterpret_cast<const char *>(message));
1493 vogl_warning_printf("%s: Trace context: 0x%" PRIX64 ", Replay context 0x%" PRIX64 ", Last trace call counter: %" PRIu64 "\n%s\n", VOGL_FUNCTION_NAME,
1494 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);
1498 vogl_warning_printf("%s: %s\n", VOGL_FUNCTION_NAME, final_message);
1502 //----------------------------------------------------------------------------------------------------------------------
1503 // vogl_replayer::debug_callback
1504 //----------------------------------------------------------------------------------------------------------------------
1505 void vogl_gl_replayer::debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *pUser_param)
1509 VOGL_NOTE_UNUSED(length);
1511 char final_message[4096];
1513 context_state *pContext_state = (context_state *)(pUser_param);
1515 vogl_format_debug_output_arb(final_message, sizeof(final_message), source, type, id, severity, reinterpret_cast<const char *>(message));
1519 vogl_warning_printf("%s: Trace context: 0x%" PRIX64 ", Replay context 0x%" PRIX64 ", Last trace call counter: %" PRIu64 "\n%s\n", VOGL_FUNCTION_NAME,
1520 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);
1524 vogl_warning_printf("%s: %s\n", VOGL_FUNCTION_NAME, final_message);
1528 //----------------------------------------------------------------------------------------------------------------------
1529 // vogl_replayer::is_extension_supported
1530 //----------------------------------------------------------------------------------------------------------------------
1531 bool vogl_gl_replayer::is_extension_supported(const char *pExt)
1535 if ((m_pCur_context_state) && (m_pCur_context_state->m_context_info.is_valid()))
1537 return m_pCur_context_state->m_context_info.supports_extension(pExt);
1545 //----------------------------------------------------------------------------------------------------------------------
1546 // vogl_replayer::context_state::handle_context_made_current
1547 //----------------------------------------------------------------------------------------------------------------------
1548 bool vogl_gl_replayer::context_state::handle_context_made_current()
1552 if (m_has_been_made_current)
1555 VOGL_CHECK_GL_ERROR;
1557 m_has_been_made_current = true;
1559 if (!m_context_info.init(m_context_desc))
1561 vogl_error_printf("%s: vogl_context_info::init() failed!\n", VOGL_METHOD_NAME);
1565 if (!m_context_info.get_max_vertex_attribs())
1567 vogl_warning_printf("%s: GL_MAX_VERTEX_ATTRIBS is 0\n", VOGL_METHOD_NAME);
1569 else if (m_context_info.get_max_vertex_attribs() >= VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES)
1571 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);
1575 if (m_replayer.m_flags & cGLReplayerLowLevelDebugMode)
1577 vogl_debug_printf("%s: Creating dummy handles\n", VOGL_METHOD_NAME);
1580 // Generate a bunch of replay handles, so the trace and replay namespaces are totally different to shake out handle or target remapping bugs
1581 // TODO: All more object types
1582 vogl::vector<GLuint> dummy_handles(65536);
1584 GL_ENTRYPOINT(glGenTextures)(4000, dummy_handles.get_ptr());
1585 GL_ENTRYPOINT(glGenBuffers)(6000, dummy_handles.get_ptr());
1586 GL_ENTRYPOINT(glGenLists)(8000);
1587 GL_ENTRYPOINT(glGenQueries)(10000, dummy_handles.get_ptr());
1589 GL_ENTRYPOINT(glGenVertexArrays)(12000, dummy_handles.get_ptr());
1590 GL_ENTRYPOINT(glGenProgramsARB)(14000, dummy_handles.get_ptr());
1591 GL_ENTRYPOINT(glGenFramebuffers)(16000, dummy_handles.get_ptr());
1592 GL_ENTRYPOINT(glGenSamplers)(18000, dummy_handles.get_ptr());
1593 GL_ENTRYPOINT(glGenRenderbuffers)(20000, dummy_handles.get_ptr());
1595 for (uint i = 0; i < 22000; i++)
1596 GL_ENTRYPOINT(glCreateProgram)();
1598 vogl_debug_printf("%s: Finished creating dummy handles\n", VOGL_METHOD_NAME);
1601 VOGL_CHECK_GL_ERROR;
1606 //----------------------------------------------------------------------------------------------------------------------
1607 // vogl_replayer::handle_context_made_current
1608 //----------------------------------------------------------------------------------------------------------------------
1609 bool vogl_gl_replayer::handle_context_made_current()
1613 if (!m_pCur_context_state->handle_context_made_current())
1616 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")))
1618 GL_ENTRYPOINT(glDebugMessageCallbackARB)(debug_callback_arb, (GLvoid *)m_pCur_context_state);
1619 GL_ENTRYPOINT(glEnable)(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
1623 if (m_flags & cGLReplayerVerboseMode)
1625 vogl_debug_printf("%s: Trace context: 0x%" PRIX64 ", replay context 0x%" PRIX64 ", GL_VERSION: %s\n",
1627 (uint64_t)m_cur_trace_context,
1628 (uint64_t)m_cur_replay_context,
1629 m_pCur_context_state->m_context_info.get_version_str().get_ptr());
1635 //----------------------------------------------------------------------------------------------------------------------
1636 // vogl_replayer::dump_context_attrib_list
1637 //----------------------------------------------------------------------------------------------------------------------
1638 void vogl_gl_replayer::dump_context_attrib_list(const int *pAttrib_list, uint size)
1644 vogl_debug_printf("Attrib list is NULL\n");
1647 vogl_debug_printf("Context attribs:\n");
1654 vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1658 uint key = pAttrib_list[ofs];
1665 vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1669 uint value = pAttrib_list[ofs];
1672 vogl_debug_printf("Key: %s (0x%08X), Value: 0x%08X\n", g_gl_enums.find_name(key, "GLX"), key, value);
1674 vogl_debug_printf("End of context attribs\n");
1677 //----------------------------------------------------------------------------------------------------------------------
1678 // vogl_replayer::find_attrib_key
1679 //----------------------------------------------------------------------------------------------------------------------
1680 int vogl_gl_replayer::find_attrib_key(const vogl::vector<int> &attrib_list, int key_to_find)
1685 while (ofs < attrib_list.size())
1687 int key = attrib_list[ofs];
1691 if (++ofs >= attrib_list.size())
1693 process_entrypoint_warning("%s: Failed parsing attrib list, this call is probably going to fail\n", VOGL_METHOD_NAME);
1697 if (key == key_to_find)
1705 //----------------------------------------------------------------------------------------------------------------------
1706 // vogl_replayer::create_context_attribs
1707 //----------------------------------------------------------------------------------------------------------------------
1708 vogl_gl_replayer::status_t vogl_gl_replayer::create_context_attribs(
1709 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,
1710 const int *pTrace_attrib_list, int trace_attrib_list_size, bool expecting_attribs)
1714 vogl::vector<int> temp_attrib_list;
1716 if ((pTrace_attrib_list) && (trace_attrib_list_size))
1718 temp_attrib_list.append(pTrace_attrib_list, trace_attrib_list_size);
1719 if (temp_attrib_list.back() != 0)
1721 process_entrypoint_warning("%s: attrib list does not end with 0\n", VOGL_METHOD_NAME);
1726 if (expecting_attribs)
1728 if (m_flags & cGLReplayerVerboseMode)
1729 process_entrypoint_message("%s: No attrib list found in trace, assuming an attrib list ending with 0\n", VOGL_METHOD_NAME);
1732 temp_attrib_list.push_back(0);
1735 if (m_flags & cGLReplayerForceDebugContexts)
1737 // See http://www.opengl.org/registry/specs/ARB/glx_create_context.txt
1738 int context_flags_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_FLAGS_ARB);
1739 if (context_flags_ofs < 0)
1741 temp_attrib_list.back() = GLX_CONTEXT_FLAGS_ARB;
1742 temp_attrib_list.push_back(GLX_CONTEXT_DEBUG_BIT_ARB);
1743 temp_attrib_list.push_back(0);
1745 if (m_flags & cGLReplayerVerboseMode)
1746 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);
1750 temp_attrib_list[context_flags_ofs] |= GLX_CONTEXT_DEBUG_BIT_ARB;
1752 if (m_flags & cGLReplayerVerboseMode)
1753 process_entrypoint_warning("%s: Slamming on GLX_CONTEXT_DEBUG_BIT_ARB bit to enable debug context\n", VOGL_METHOD_NAME);
1756 int context_major_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MAJOR_VERSION_ARB);
1757 int context_minor_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MINOR_VERSION_ARB);
1759 bool slammed_up_to_3_0 = false;
1760 if (context_major_version_ofs < 0)
1762 // 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).
1764 temp_attrib_list.back() = GLX_CONTEXT_MAJOR_VERSION_ARB;
1765 temp_attrib_list.push_back(3);
1766 temp_attrib_list.push_back(0);
1768 slammed_up_to_3_0 = true;
1771 else if (temp_attrib_list[context_major_version_ofs] < 3)
1773 temp_attrib_list[context_major_version_ofs] = 3;
1775 slammed_up_to_3_0 = true;
1778 if (slammed_up_to_3_0)
1780 if (context_minor_version_ofs < 0)
1782 temp_attrib_list.back() = GLX_CONTEXT_MINOR_VERSION_ARB;
1783 temp_attrib_list.push_back(0);
1784 temp_attrib_list.push_back(0);
1788 temp_attrib_list[context_minor_version_ofs] = 0;
1791 process_entrypoint_warning("%s: Forcing GL context version up to 3.0 due to debug context usage\n", VOGL_METHOD_NAME);
1795 const int *pAttrib_list = temp_attrib_list.get_ptr();
1796 const uint attrib_list_size = temp_attrib_list.size();
1798 if (m_flags & cGLReplayerVerboseMode)
1799 dump_context_attrib_list(pAttrib_list, attrib_list_size);
1801 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContextAttribsARB)(dpy, config, replay_share_context, direct, pAttrib_list);
1802 if (!replay_context)
1806 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
1807 return cStatusHardFailure;
1811 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
1819 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContextAttribsARB, pAttrib_list, attrib_list_size);
1820 VOGL_NOTE_UNUSED(pContext_state);
1824 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
1831 //----------------------------------------------------------------------------------------------------------------------
1832 // vogl_replayer::process_pending_make_current
1833 //----------------------------------------------------------------------------------------------------------------------
1834 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_make_current()
1838 if (!m_pending_make_current_packet.is_valid())
1841 vogl_trace_packet &gl_packet = m_pending_make_current_packet;
1843 Bool trace_result = gl_packet.get_return_value<Bool>();
1845 gl_entrypoint_id_t entrypoint_id = gl_packet.get_entrypoint_id();
1846 VOGL_ASSERT((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) || (entrypoint_id == VOGL_ENTRYPOINT_glXMakeContextCurrent));
1848 // pContext_state will be NULL if they are unmapping!
1849 vogl_trace_ptr_value trace_context = gl_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
1850 context_state *pContext_state = get_trace_context_state(trace_context);
1851 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1853 if ((trace_context) && (!replay_context))
1855 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
1856 m_pending_make_current_packet.clear();
1857 return cStatusHardFailure;
1860 const Display *dpy = m_pWindow->get_display();
1861 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1863 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1868 process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
1869 m_pending_make_current_packet.clear();
1870 return cStatusHardFailure;
1874 process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
1879 m_cur_trace_context = trace_context;
1880 m_cur_replay_context = replay_context;
1881 m_pCur_context_state = pContext_state;
1885 process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
1888 if (m_cur_replay_context)
1890 int viewport_x = gl_packet.get_key_value_map().get_int(string_hash("viewport_x"));
1891 int viewport_y = gl_packet.get_key_value_map().get_int(string_hash("viewport_y"));
1892 int viewport_width = gl_packet.get_key_value_map().get_int(string_hash("viewport_width"));
1893 int viewport_height = gl_packet.get_key_value_map().get_int(string_hash("viewport_height"));
1894 int win_width = gl_packet.get_key_value_map().get_int(string_hash("win_width"));
1895 int win_height = gl_packet.get_key_value_map().get_int(string_hash("win_height"));
1897 if (!m_pCur_context_state->m_has_been_made_current)
1899 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1900 viewport_x, viewport_y,
1901 viewport_width, viewport_height,
1902 win_width, win_height);
1905 GLint cur_viewport[4];
1906 GL_ENTRYPOINT(glGetIntegerv)(GL_VIEWPORT, cur_viewport);
1908 uint cur_win_width = 0, cur_win_height = 0;
1909 m_pWindow->get_actual_dimensions(cur_win_width, cur_win_height);
1911 if (!m_pCur_context_state->m_has_been_made_current)
1913 vogl_printf("glXMakeCurrent(): Replay Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1914 cur_viewport[0], cur_viewport[1],
1915 cur_viewport[2], cur_viewport[3],
1916 cur_win_width, cur_win_height);
1919 if ((cur_viewport[0] != viewport_x) || (cur_viewport[1] != viewport_y) || (cur_viewport[2] != viewport_width) || (cur_viewport[3] != viewport_height))
1921 process_entrypoint_warning("%s: Replay viewport differs from traces!\n", VOGL_METHOD_NAME);
1924 if (!handle_context_made_current())
1925 return cStatusHardFailure;
1929 m_last_processed_call_counter = gl_packet.get_call_counter();
1931 m_pending_make_current_packet.clear();
1936 //----------------------------------------------------------------------------------------------------------------------
1937 // vogl_process_internal_trace_command_ctypes_packet
1938 //----------------------------------------------------------------------------------------------------------------------
1939 bool vogl_process_internal_trace_command_ctypes_packet(const key_value_map &kvm, const vogl_ctypes &ctypes)
1943 // TODO: Implement the code to map trace ctypes to replay ctypes. That's going to be fun.
1944 int num_trace_ctypes = kvm.get_int("num_ctypes");
1945 VOGL_VERIFY(num_trace_ctypes == VOGL_NUM_CTYPES);
1947 // TODO: This just verifies that the replayer's idea of each ctype matches the tracer's.
1948 // This will need to be revisited once we port to other OS's.
1949 // TODO: Move the ctypes crap into the SOF packet or something, it's not easy to deal with this packet on the fly.
1950 for (int ctype_iter = 0; ctype_iter < num_trace_ctypes; ctype_iter++)
1952 const vogl_ctype_desc_t &desc = ctypes[static_cast<vogl_ctype_t>(ctype_iter)];
1954 uint base_index = ctype_iter << 8;
1955 dynamic_string name(kvm.get_string(base_index++));
1956 dynamic_string ctype(kvm.get_string(base_index++));
1957 int size = kvm.get_int(base_index++);
1958 uint loki_type_flags = kvm.get_uint(base_index++);
1959 bool is_pointer = kvm.get_bool(base_index++);
1960 bool is_opaque_pointer = kvm.get_bool(base_index++);
1961 bool is_pointer_diff = kvm.get_bool(base_index++);
1962 bool is_opaque_type = kvm.get_bool(base_index++);
1964 VOGL_VERIFY(name.compare(desc.m_pName, true) == 0);
1965 VOGL_VERIFY(ctype.compare(desc.m_pCType, true) == 0);
1966 if (!desc.m_is_opaque_type)
1968 VOGL_VERIFY(size == desc.m_size);
1971 const uint loki_type_check_mask = ~(LOKI_TYPE_BITMASK(LOKI_IS_SIGNED_LONG) | LOKI_TYPE_BITMASK(LOKI_IS_UNSIGNED_LONG));
1972 VOGL_VERIFY((loki_type_flags & loki_type_check_mask) == (desc.m_loki_type_flags & loki_type_check_mask));
1974 VOGL_VERIFY(is_pointer == desc.m_is_pointer);
1975 VOGL_VERIFY(is_opaque_pointer == desc.m_is_opaque_pointer);
1976 VOGL_VERIFY(is_pointer_diff == desc.m_is_pointer_diff);
1977 VOGL_VERIFY(is_opaque_type == desc.m_is_opaque_type);
1983 //----------------------------------------------------------------------------------------------------------------------
1984 // vogl_replayer::process_internal_trace_command
1985 //----------------------------------------------------------------------------------------------------------------------
1986 vogl_gl_replayer::status_t vogl_gl_replayer::process_internal_trace_command(const vogl_trace_gl_entrypoint_packet &gl_packet)
1990 VOGL_NOTE_UNUSED(gl_packet);
1992 GLuint cmd = m_pCur_gl_packet->get_param_value<GLuint>(0);
1993 GLuint size = m_pCur_gl_packet->get_param_value<GLuint>(1);
1994 VOGL_NOTE_UNUSED(size);
1995 vogl_trace_ptr_value trace_data_ptr_value = m_pCur_gl_packet->get_param_ptr_value(2);
1996 VOGL_NOTE_UNUSED(trace_data_ptr_value);
1998 vogl_gl_replayer::status_t status = cStatusOK;
2002 case cITCRDemarcation:
2006 case cITCRKeyValueMap:
2008 const key_value_map &kvm = m_pCur_gl_packet->get_key_value_map();
2010 dynamic_string cmd_type(kvm.get_string("command_type"));
2011 if (cmd_type == "state_snapshot")
2013 dynamic_string text_id(kvm.get_string("id"));
2014 dynamic_string binary_id(kvm.get_string("binary_id"));
2015 if (text_id.is_empty() && binary_id.is_empty())
2017 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());
2018 return cStatusHardFailure;
2021 dynamic_string id_to_use(text_id.is_empty() ? binary_id : text_id);
2023 // TODO: Make a 1st class snapshot cache class
2024 // TODO: This could fail if the user hand modifies the snapshot in some way - add an option to disable caching.
2025 vogl_gl_state_snapshot *pSnapshot = NULL;
2026 if (m_flags & cGLReplayerSnapshotCaching)
2028 for (uint snapshot_index = 0; snapshot_index < m_snapshots.size(); snapshot_index++)
2030 if (!m_snapshots[snapshot_index].m_name.compare(id_to_use, false))
2032 pSnapshot = m_snapshots[snapshot_index].m_pSnapshot;
2035 snapshot_cache_entry cache_entry(m_snapshots[snapshot_index]);
2036 m_snapshots.erase(snapshot_index);
2037 m_snapshots.insert(0, cache_entry);
2046 timed_scope ts("Deserialize snapshot time");
2048 if (!m_pBlob_manager)
2050 process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2051 return cStatusHardFailure;
2054 uint8_vec snapshot_data;
2056 if (!m_pBlob_manager->get(id_to_use, snapshot_data) || (snapshot_data.is_empty()))
2058 process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2059 return cStatusHardFailure;
2062 vogl_message_printf("%s: Deserializing state snapshot \"%s\", %u bytes\n", VOGL_METHOD_NAME, id_to_use.get_ptr(), snapshot_data.size());
2067 if (id_to_use == text_id)
2068 success = doc.deserialize(reinterpret_cast<const char *>(snapshot_data.get_ptr()), snapshot_data.size());
2070 success = doc.binary_deserialize(snapshot_data);
2071 if (!success || (!doc.get_root()))
2073 process_entrypoint_error("%s: Failed deserializing JSON snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2074 return cStatusHardFailure;
2077 pSnapshot = vogl_new(vogl_gl_state_snapshot);
2078 if (!pSnapshot->deserialize(*doc.get_root(), *m_pBlob_manager, &m_trace_gl_ctypes))
2080 vogl_delete(pSnapshot);
2083 process_entrypoint_error("%s: Failed deserializing snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2084 return cStatusHardFailure;
2087 if (m_flags & cGLReplayerSnapshotCaching)
2089 snapshot_cache_entry new_cache_entry;
2090 new_cache_entry.m_name = id_to_use;
2091 new_cache_entry.m_pSnapshot = pSnapshot;
2092 m_snapshots.insert(0, new_cache_entry);
2094 // FIXME: Even 3-4 snapshots in memory may be too much in 32-bit mode for some large apps.
2095 while (m_snapshots.size() > 3)
2097 vogl_delete(m_snapshots.back().m_pSnapshot);
2098 m_snapshots.resize(m_snapshots.size() - 1);
2103 status = begin_applying_snapshot(pSnapshot, (m_flags & cGLReplayerSnapshotCaching) ? false : true);
2105 if ((status != cStatusOK) && (status != cStatusResizeWindow))
2107 if (m_flags & cGLReplayerSnapshotCaching)
2109 VOGL_ASSERT(m_snapshots[0].m_pSnapshot == pSnapshot);
2111 vogl_delete(m_snapshots[0].m_pSnapshot);
2112 m_snapshots.erase(0U);
2115 if (m_flags & cGLReplayerSnapshotCaching)
2117 vogl_delete(pSnapshot);
2121 process_entrypoint_error("%s: Failed applying GL snapshot from blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2125 vogl_message_printf("%s: Successfully applied GL state snapshot from blob \"%s\"\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2127 else if (cmd_type == "ctypes")
2129 m_ctypes_packet = *m_pCur_gl_packet;
2131 if (!vogl_process_internal_trace_command_ctypes_packet(kvm, m_trace_gl_ctypes))
2132 return cStatusHardFailure;
2134 else if (cmd_type == "entrypoints")
2140 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD key_value_map command type: \"%s\"\n", VOGL_METHOD_NAME, cmd_type.get_ptr());
2146 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD command type: %u\n", VOGL_METHOD_NAME, cmd);
2154 //----------------------------------------------------------------------------------------------------------------------
2155 // vogl_replayer::check_program_binding_shadow
2156 //----------------------------------------------------------------------------------------------------------------------
2157 bool vogl_gl_replayer::check_program_binding_shadow()
2161 if (!m_pCur_context_state)
2164 // Make sure shadow is good
2165 GLint actual_current_replay_program = 0;
2166 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
2169 if (m_pCur_context_state->m_cur_replay_program == static_cast<GLuint>(actual_current_replay_program))
2172 // OK, on AMD it plays games with GL_CURRENT_PROGRAM when the currently bound program is deleted. Check for this scenario.
2173 bool is_still_program = GL_ENTRYPOINT(glIsProgram)(m_pCur_context_state->m_cur_replay_program) != 0;
2174 if ((!check_gl_error()) && (is_still_program))
2176 GLint marked_for_deletion = GL_FALSE;
2177 GL_ENTRYPOINT(glGetProgramiv)(m_pCur_context_state->m_cur_replay_program, GL_DELETE_STATUS, &marked_for_deletion);
2179 if ((!check_gl_error()) && (marked_for_deletion))
2187 //----------------------------------------------------------------------------------------------------------------------
2188 // vogl_replayer::handle_use_program
2189 //----------------------------------------------------------------------------------------------------------------------
2190 void vogl_gl_replayer::handle_use_program(GLuint trace_handle, gl_entrypoint_id_t entrypoint_id)
2194 // 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.
2195 check_program_binding_shadow();
2197 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2198 VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2199 VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2201 // For safety, absorb any previous error.
2204 GLuint prev_replay_program = m_pCur_context_state->m_cur_replay_program;
2205 GLuint prev_trace_program = m_pCur_context_state->m_cur_trace_program;
2207 bool prev_is_program = false;
2208 GLint prev_link_status = false;
2209 GLint prev_is_marked_for_deletion = false;
2210 vogl::growable_array<GLuint, 8> prev_attached_replay_shaders;
2212 if ((prev_replay_program) && (replay_handle != prev_replay_program))
2214 prev_is_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2215 check_gl_error_quietly();
2217 if (prev_is_program)
2219 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_DELETE_STATUS, &prev_is_marked_for_deletion);
2220 check_gl_error_quietly();
2222 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_LINK_STATUS, &prev_link_status);
2223 check_gl_error_quietly();
2225 if (prev_is_marked_for_deletion)
2227 // 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.
2228 GLint num_attached_shaders = 0;
2229 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_ATTACHED_SHADERS, &num_attached_shaders);
2230 check_gl_error_quietly();
2232 if (num_attached_shaders)
2234 prev_attached_replay_shaders.resize(num_attached_shaders);
2236 GLsizei actual_count = 0;
2237 GL_ENTRYPOINT(glGetAttachedShaders)(prev_replay_program, num_attached_shaders, &actual_count, prev_attached_replay_shaders.get_ptr());
2238 check_gl_error_quietly();
2240 VOGL_ASSERT(actual_count == num_attached_shaders);
2246 if (entrypoint_id == VOGL_ENTRYPOINT_glUseProgram)
2247 GL_ENTRYPOINT(glUseProgram)(replay_handle);
2249 GL_ENTRYPOINT(glUseProgramObjectARB)(replay_handle);
2251 // Can't shadow if glUseProgram failed.
2252 if (check_gl_error())
2255 if ((prev_replay_program) && (prev_replay_program != replay_handle))
2257 bool is_prev_still_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2258 if (!is_prev_still_program)
2260 VOGL_ASSERT(prev_is_program);
2261 VOGL_ASSERT(prev_is_marked_for_deletion);
2263 // The previously bound program is really dead now, kill it from our tables and also check up on any shaders it was attached to.
2264 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(prev_trace_program);
2265 VOGL_ASSERT(was_deleted);
2266 VOGL_NOTE_UNUSED(was_deleted);
2268 was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(prev_trace_program);
2269 VOGL_ASSERT(was_deleted);
2271 was_deleted = get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(prev_replay_program);
2272 if ((prev_link_status) && (!was_deleted))
2277 for (uint i = 0; i < prev_attached_replay_shaders.size(); i++)
2279 GLuint replay_shader_handle = prev_attached_replay_shaders[i];
2281 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle);
2282 check_gl_error_quietly();
2284 if (is_still_shader)
2287 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2289 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2293 // The attached shader is now really dead.
2294 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2295 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2297 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);
2303 m_pCur_context_state->m_cur_replay_program = replay_handle;
2304 m_pCur_context_state->m_cur_trace_program = trace_handle;
2307 //----------------------------------------------------------------------------------------------------------------------
2308 // vogl_replayer::handle_delete_program
2309 //----------------------------------------------------------------------------------------------------------------------
2310 void vogl_gl_replayer::handle_delete_program(GLuint trace_handle)
2314 check_program_binding_shadow();
2316 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2318 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2319 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2320 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2322 context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
2323 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
2325 if (it->first == m_pCur_context_state->m_context_desc.get_trace_context())
2328 context_state *pContext = it->second;
2329 if (pContext->m_pShared_state == pContext_shareroot)
2331 if (pContext->m_cur_trace_program == trace_handle)
2333 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",
2334 VOGL_METHOD_NAME, trace_handle, replay_handle,
2335 cast_val_to_uint64(m_pCur_context_state->m_context_desc.get_trace_context()),
2336 cast_val_to_uint64(it->first));
2341 bool is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2342 check_gl_error_quietly();
2344 vogl::growable_array<GLuint, 8> attached_replay_shaders;
2346 if ((is_program) && (replay_handle))
2348 GLint num_attached_shaders = 0;
2349 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ATTACHED_SHADERS, &num_attached_shaders);
2350 check_gl_error_quietly();
2352 if (num_attached_shaders)
2354 attached_replay_shaders.resize(num_attached_shaders);
2356 GLsizei actual_count = 0;
2357 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, num_attached_shaders, &actual_count, attached_replay_shaders.get_ptr());
2358 check_gl_error_quietly();
2360 VOGL_ASSERT(actual_count == num_attached_shaders);
2364 GL_ENTRYPOINT(glDeleteProgram)(replay_handle);
2366 bool deletion_succeeded = !check_gl_error();
2367 if (!deletion_succeeded)
2369 VOGL_ASSERT(!is_program);
2371 process_entrypoint_warning("%s: Failed deleting program, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2378 bool is_still_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2379 check_gl_error_quietly();
2381 GLint marked_for_deletion = 0;
2382 if (is_still_program)
2384 // It must still be bound to the context, or referred to in some other way that we don't know about.
2385 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2386 bool delete_status_check_succeeded = !check_gl_error_quietly();
2388 VOGL_VERIFY(delete_status_check_succeeded);
2389 VOGL_VERIFY(marked_for_deletion);
2391 else if (!is_still_program)
2393 VOGL_ASSERT(is_program);
2395 // The program is really gone now.
2396 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2397 VOGL_ASSERT(was_deleted);
2398 VOGL_NOTE_UNUSED(was_deleted);
2400 was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(trace_handle);
2401 VOGL_ASSERT(was_deleted);
2403 get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(replay_handle);
2405 if (m_pCur_context_state->m_cur_replay_program == replay_handle)
2407 // This shouldn't happen - if the program is still bound to the context then it should still be a program.
2409 m_pCur_context_state->m_cur_replay_program = 0;
2410 m_pCur_context_state->m_cur_trace_program = 0;
2413 for (uint i = 0; i < attached_replay_shaders.size(); i++)
2415 GLuint replay_shader_handle = attached_replay_shaders[i];
2417 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle) != 0;
2418 check_gl_error_quietly();
2420 if (is_still_shader)
2423 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2425 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2429 // The attached shader is now really dead.
2430 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2431 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2433 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);
2439 //----------------------------------------------------------------------------------------------------------------------
2440 // vogl_replayer::handle_delete_shader
2441 //----------------------------------------------------------------------------------------------------------------------
2442 void vogl_gl_replayer::handle_delete_shader(GLuint trace_handle)
2446 check_program_binding_shadow();
2450 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2452 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2453 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_SHADER_OBJECT);
2454 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_SHADER_OBJECT);
2456 GL_ENTRYPOINT(glDeleteShader)(replay_handle);
2458 bool deletion_succeeded = !check_gl_error();
2459 if (!deletion_succeeded)
2461 process_entrypoint_warning("%s: Failed deleting shader, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2468 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_handle);
2469 check_gl_error_quietly();
2471 if (!is_still_shader)
2473 // The shader is really gone.
2474 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2475 VOGL_ASSERT(was_deleted);
2476 VOGL_NOTE_UNUSED(was_deleted);
2480 GLint marked_for_deletion = 0;
2481 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2482 check_gl_error_quietly();
2484 VOGL_VERIFY(marked_for_deletion);
2486 // The shader is attached to a live program object (which may or may not be actually in the marked_as_deleted state)
2487 // we'll get around to it when the program object is deleted, or when they remove the program object from the current state.
2491 //----------------------------------------------------------------------------------------------------------------------
2492 // vogl_replayer::handle_detach_shader
2493 //----------------------------------------------------------------------------------------------------------------------
2494 void vogl_gl_replayer::handle_detach_shader(gl_entrypoint_id_t entrypoint_id)
2496 GLuint trace_program = m_pCur_gl_packet->get_param_value<GLuint>(0);
2497 GLuint replay_program = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_program);
2499 GLuint trace_shader = m_pCur_gl_packet->get_param_value<GLuint>(1);
2500 GLuint replay_shader = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_shader);
2504 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2506 GLboolean was_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2507 check_gl_error_quietly();
2509 GLint marked_for_deletion = 0;
2510 GL_ENTRYPOINT(glGetShaderiv)(replay_shader, GL_DELETE_STATUS, &marked_for_deletion);
2511 check_gl_error_quietly();
2513 if (entrypoint_id == VOGL_ENTRYPOINT_glDetachObjectARB)
2514 GL_ENTRYPOINT(glDetachObjectARB)(replay_program, replay_shader);
2517 VOGL_ASSERT(entrypoint_id == VOGL_ENTRYPOINT_glDetachShader);
2518 GL_ENTRYPOINT(glDetachShader)(replay_program, replay_shader);
2521 bool detach_failed = check_gl_error();
2523 GLboolean is_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2524 check_gl_error_quietly();
2528 if ((marked_for_deletion) && (was_shader) && (!is_shader))
2530 // The shader is really gone now.
2531 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_shader);
2532 VOGL_ASSERT(was_deleted);
2533 VOGL_NOTE_UNUSED(was_deleted);
2538 //----------------------------------------------------------------------------------------------------------------------
2539 // vogl_gl_replayer::handle_link_program
2540 //----------------------------------------------------------------------------------------------------------------------
2541 void vogl_gl_replayer::handle_link_program(gl_entrypoint_id_t entrypoint_id)
2545 GLuint trace_handle = m_pCur_gl_packet->get_param_value<GLuint>(0);
2546 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2548 GLboolean is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle);
2552 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);
2555 const json_document *pDoc = m_pCur_gl_packet->get_key_value_map().get_json_document("metadata");
2559 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);
2561 else if ((pDoc) && (!pDoc->is_object()))
2563 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);
2567 int trace_active_attributes = 0;
2568 int trace_active_uniforms = 0;
2569 int trace_active_uniform_blocks = 0;
2570 int trace_link_status = 1;
2572 VOGL_NOTE_UNUSED(trace_active_uniforms);
2573 VOGL_NOTE_UNUSED(trace_active_uniform_blocks);
2577 const json_node &doc_root = *pDoc->get_root();
2579 trace_link_status = doc_root.value_as_int("link_status");
2580 trace_active_attributes = doc_root.value_as_int("total_active_attributes");
2581 trace_active_uniforms = doc_root.value_as_int("total_active_uniforms");
2582 trace_active_uniform_blocks = doc_root.value_as_int("active_uniform_blocks");
2584 const json_node *pAttrib_node = doc_root.find_child_array("active_attribs");
2587 for (uint i = 0; i < pAttrib_node->size(); i++)
2589 const json_node *pAttrib = pAttrib_node->get_child(i);
2596 const char *pName = pAttrib->value_as_string_ptr("name");
2597 int attrib_loc = pAttrib->value_as_int("location", -1);
2599 if ((pName) && (pName[0]) && (attrib_loc >= 0))
2601 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2602 GL_ENTRYPOINT(glBindAttribLocationARB)(replay_handle, attrib_loc, pName);
2604 GL_ENTRYPOINT(glBindAttribLocation)(replay_handle, attrib_loc, reinterpret_cast<const GLchar *>(pName));
2611 const json_node *pOutputs_object = doc_root.find_child_array("active_outputs");
2612 if (pOutputs_object)
2614 for (uint i = 0; i < pOutputs_object->size(); i++)
2616 const json_node *pOutput_node = pOutputs_object->get_child(i);
2620 dynamic_string name(pOutput_node->value_as_string("name"));
2621 if ((name.is_empty()) || (name.begins_with("gl_", true)))
2624 int location = pOutput_node->value_as_int("location");
2625 int location_index = pOutput_node->value_as_int("location_index");
2627 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_blend_func_extended") && GL_ENTRYPOINT(glBindFragDataLocationIndexed))
2629 GL_ENTRYPOINT(glBindFragDataLocationIndexed)(replay_handle, location, location_index, reinterpret_cast<const GLchar *>(name.get_ptr()));
2634 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);
2636 GL_ENTRYPOINT(glBindFragDataLocation)(replay_handle, location, reinterpret_cast<const GLchar *>(name.get_ptr()));
2643 GLenum transform_feedback_mode = vogl_get_json_value_as_enum(doc_root, "transform_feedback_mode");
2644 GLint num_varyings = doc_root.value_as_int("transform_feedback_num_varyings");
2647 const json_node *pTransform_feedback_varyings = doc_root.find_child_array("transform_feedback_varyings");
2648 if (pTransform_feedback_varyings)
2650 dynamic_string_array names;
2652 for (uint i = 0; i < pTransform_feedback_varyings->size(); i++)
2654 const json_node *pVarying_node = pTransform_feedback_varyings->get_child(i);
2658 GLint index = pVarying_node->value_as_int("index");
2662 dynamic_string name(pVarying_node->value_as_string("name"));
2664 //GLsizei size(pVarying_node->value_as_int("size"));
2665 //GLenum type(vogl_get_json_value_as_enum(*pVarying_node, "type"));
2667 names.ensure_element_is_valid(index);
2668 names[index] = name;
2671 vogl::vector<GLchar *> varyings(names.size());
2672 for (uint i = 0; i < names.size(); i++)
2673 varyings[i] = (GLchar *)(names[i].get_ptr());
2675 GL_ENTRYPOINT(glTransformFeedbackVaryings)(replay_handle, varyings.size(), varyings.get_ptr(), transform_feedback_mode);
2681 switch (entrypoint_id)
2683 case VOGL_ENTRYPOINT_glLinkProgram:
2685 GL_ENTRYPOINT(glLinkProgram)(replay_handle);
2688 case VOGL_ENTRYPOINT_glLinkProgramARB:
2690 GL_ENTRYPOINT(glLinkProgramARB)(replay_handle);
2693 case VOGL_ENTRYPOINT_glProgramBinary:
2695 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));
2707 GLint replay_link_status = 0;
2708 GLint replay_active_attributes = 0;
2709 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2711 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_LINK_STATUS_ARB, &replay_link_status);
2714 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &replay_active_attributes);
2719 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_LINK_STATUS, &replay_link_status);
2722 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ACTIVE_ATTRIBUTES, &replay_active_attributes);
2726 if ((replay_link_status) || (!get_shared_state()->m_shadow_state.m_linked_programs.find_snapshot(replay_handle)))
2729 if (entrypoint_id == VOGL_ENTRYPOINT_glProgramBinary)
2730 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));
2732 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);
2735 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);
2738 if ((pDoc) && (replay_link_status != trace_link_status))
2740 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);
2743 if (!replay_link_status)
2745 vogl::vector<GLchar> log;
2747 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2750 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
2757 GLint actual_length = 0;
2758 GL_ENTRYPOINT(glGetInfoLogARB)(replay_handle, log.size(), &actual_length, reinterpret_cast<GLcharARB *>(log.get_ptr()));
2765 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_INFO_LOG_LENGTH, &length);
2772 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, log.size(), &length, log.get_ptr());
2777 if ((log.size()) && (log[0]))
2779 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());
2783 if ((pDoc) && (replay_active_attributes != trace_active_attributes))
2785 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);
2788 const json_node *pUniforms_node = pDoc ? pDoc->get_root()->find_child_array("active_uniforms") : NULL;
2792 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
2793 if (it == get_shared_state()->m_glsl_program_hash_map.end())
2794 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
2795 glsl_program_state &prog_state = it->second;
2797 for (uint i = 0; i < pUniforms_node->size(); i++)
2799 const json_node *pUniform = pUniforms_node->get_child(i);
2806 const char *pName = pUniform->value_as_string_ptr("name");
2812 int trace_loc = pUniform->value_as_int("location");
2813 int trace_array_size = pUniform->value_as_int("size");
2814 //int trace_type = pUniform->value_as_int("type");
2816 VOGL_ASSERT(trace_array_size >= 1);
2818 if ((trace_loc < 0) || (trace_array_size <= 0))
2821 if (trace_array_size > 1)
2823 dynamic_string element_name;
2824 for (int i = 0; i < trace_array_size; i++)
2826 element_name = pName;
2827 int start_bracket_ofs = element_name.find_right('[');
2828 if (start_bracket_ofs >= 0)
2829 element_name.left(start_bracket_ofs);
2830 element_name.format_append("[%u]", i);
2832 GLint element_trace_loc = trace_loc + i;
2833 GLint element_replay_loc;
2834 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2835 element_replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(element_name.get_ptr()));
2837 element_replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(element_name.get_ptr()));
2840 if (element_replay_loc < 0)
2842 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);
2846 prog_state.m_uniform_locations.erase(element_trace_loc);
2847 prog_state.m_uniform_locations.insert(element_trace_loc, element_replay_loc);
2851 else if (trace_array_size == 1)
2854 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2855 replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(pName));
2857 replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(pName));
2862 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);
2866 prog_state.m_uniform_locations.erase(trace_loc);
2867 prog_state.m_uniform_locations.insert(trace_loc, replay_loc);
2874 //----------------------------------------------------------------------------------------------------------------------
2875 // vogl_gl_replayer::post_draw_call
2876 // Called after each draw call or blit.
2877 //----------------------------------------------------------------------------------------------------------------------
2878 vogl_gl_replayer::status_t vogl_gl_replayer::post_draw_call()
2882 if (m_pCur_context_state->m_inside_gl_begin)
2885 if (check_gl_error())
2886 return cStatusGLError;
2888 bool is_draw = vogl_is_draw_entrypoint(m_pCur_gl_packet->get_entrypoint_id());
2890 if ((m_flags & cGLReplayerDumpShadersOnDraw) && (is_draw))
2892 dump_current_shaders();
2895 if (m_flags & cGLReplayerDumpFramebufferOnDraws)
2897 bool should_dump = false;
2899 if (m_dump_framebuffer_on_draw_frame_index != -1)
2901 if (m_frame_index == m_dump_framebuffer_on_draw_frame_index)
2904 else if ((m_dump_framebuffer_on_draw_first_gl_call_index >= 0) && (m_dump_framebuffer_on_draw_last_gl_call_index >= 0))
2906 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);
2915 dump_current_framebuffer();
2919 m_frame_draw_counter += is_draw;
2924 //----------------------------------------------------------------------------------------------------------------------
2925 // vogl_gl_replayer::dump_framebuffer
2926 //----------------------------------------------------------------------------------------------------------------------
2927 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)
2931 uint trace_read_framebuffer = 0;
2932 if (read_framebuffer)
2934 gl_handle_hash_map::const_iterator it = get_context_state()->m_framebuffers.search_table_for_value(read_framebuffer);
2935 if (it != get_context_state()->m_framebuffers.end())
2936 trace_read_framebuffer = it->second;
2939 uint trace_texture = replay_texture;
2942 if (!get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_texture, trace_texture))
2943 vogl_warning_printf("%s: Failed finding GL handle %u in texture handle shadow!\n", VOGL_METHOD_NAME, replay_texture);
2949 if (!get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_rbo, trace_rbo))
2950 vogl_error_printf("%s: Failed finding GL handle %u in RBO handle shadow!\n", VOGL_METHOD_NAME, replay_rbo);
2953 m_screenshot_buffer.resize(width * height * 3);
2955 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);
2959 process_entrypoint_warning("%s: vogl_copy_buffer_to_image() failed!\n", VOGL_METHOD_NAME);
2963 size_t png_size = 0;
2964 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
2966 dynamic_string screenshot_filename(cVarArg, "%s_GLCTR%08llu_%s_FR%06u_DCTR%05llu_W%04i_H%04i_FBO%04u_%s",
2967 m_dump_framebuffer_on_draw_prefix.get_ptr(),
2968 (unsigned long long)m_pCur_gl_packet->get_call_counter(),
2969 g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
2971 (unsigned long long)m_frame_draw_counter,
2973 trace_read_framebuffer,
2974 g_gl_enums.find_gl_name(read_buffer));
2976 if (internal_format != GL_NONE)
2978 screenshot_filename += "_";
2979 screenshot_filename += g_gl_enums.find_gl_image_format_name(internal_format);
2982 if (orig_samples != 0)
2983 screenshot_filename += dynamic_string(cVarArg, "_MSAA%u", orig_samples);
2985 screenshot_filename += dynamic_string(cVarArg, "_TEX%04u", replay_texture);
2987 screenshot_filename += dynamic_string(cVarArg, "_RBO%04u", replay_rbo);
2989 screenshot_filename += ".png";
2991 file_utils::create_directories(file_utils::get_pathname(screenshot_filename.get_ptr()), false);
2993 if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
2995 process_entrypoint_error("%s: Failed writing framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
3000 vogl_printf("%s: Wrote framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
3008 //----------------------------------------------------------------------------------------------------------------------
3009 // vogl_gl_replayer::dump_current_framebuffer
3010 //----------------------------------------------------------------------------------------------------------------------
3011 void vogl_gl_replayer::dump_current_framebuffer()
3015 uint draw_framebuffer_binding = vogl_get_gl_integer(GL_DRAW_FRAMEBUFFER_BINDING);
3017 uint max_draw_buffers = vogl_get_gl_integer(GL_MAX_DRAW_BUFFERS);
3018 if (!max_draw_buffers)
3020 process_entrypoint_warning("%s: GL_MAX_DRAW_BUFFERS is 0\n", VOGL_METHOD_NAME);
3024 //GL_COLOR_ATTACHMENT0-GL_COLOR_ATTACHMENT15, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT
3026 vogl::vector<GLenum> draw_buffers(max_draw_buffers);
3027 for (uint i = 0; i < max_draw_buffers; i++)
3028 draw_buffers[i] = vogl_get_gl_integer(GL_DRAW_BUFFER0 + i);
3030 if (!draw_framebuffer_binding)
3032 for (uint i = 0; i < max_draw_buffers; i++)
3033 if (draw_buffers[i] != GL_NONE)
3034 dump_framebuffer(m_pWindow->get_width(), m_pWindow->get_height(), 0, draw_buffers[i], GL_NONE, 0, 0, 0);
3038 // TODO: We should probably keep around a persistent set of per-context (or sharelist) remappers
3039 vogl_framebuffer_state fbo_state;
3040 if (!fbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, draw_framebuffer_binding, GL_NONE))
3042 process_entrypoint_warning("%s: Unable to snapshot current FBO %u\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3046 for (uint i = 0; i < draw_buffers.size(); i++)
3048 if (draw_buffers[i] == GL_NONE)
3051 const vogl_framebuffer_attachment *pAttachment = fbo_state.get_attachments().find_value(draw_buffers[i]);
3054 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);
3058 if (pAttachment->get_type() == GL_FRAMEBUFFER_DEFAULT)
3060 else if (pAttachment->get_type() == GL_RENDERBUFFER)
3062 GLuint rbo_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3066 vogl_renderbuffer_state rbo_state;
3067 if (!rbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, rbo_handle, GL_NONE))
3069 process_entrypoint_warning("%s: Failed getting RBO %u's' state!\n", VOGL_METHOD_NAME, rbo_handle);
3073 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))
3076 uint width = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_WIDTH);
3077 uint height = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_HEIGHT);
3078 uint samples = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_SAMPLES);
3079 GLenum internal_format = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_INTERNAL_FORMAT);
3081 if ((!width) || (!height) || (!internal_format))
3083 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);
3089 vogl_scoped_binding_state orig_framebuffers(GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_RENDERBUFFER);
3091 GLuint temp_rbo = 0;
3092 GL_ENTRYPOINT(glGenRenderbuffers)(1, &temp_rbo);
3098 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, temp_rbo);
3101 GL_ENTRYPOINT(glRenderbufferStorage)(GL_RENDERBUFFER, internal_format, width, height);
3104 GLuint temp_fbo = 0;
3105 GL_ENTRYPOINT(glGenFramebuffers)(1, &temp_fbo);
3108 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, temp_fbo);
3111 GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, temp_rbo);
3114 GLenum draw_buf = GL_COLOR_ATTACHMENT0;
3115 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_buf);
3118 GL_ENTRYPOINT(glReadBuffer)(GL_NONE);
3121 GLenum cur_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
3124 if (cur_status == GL_FRAMEBUFFER_COMPLETE)
3126 GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, draw_framebuffer_binding);
3129 // Save the framebuffer's readbuffer (it's per-framebuffer state, not context state).
3130 vogl_scoped_state_saver state_saver(cGSTReadBuffer);
3132 GL_ENTRYPOINT(glReadBuffer)(draw_buffers[i]);
3135 GL_ENTRYPOINT(glBlitFramebuffer)(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3137 if (!check_gl_error())
3138 dump_framebuffer(width, height, temp_fbo, GL_COLOR_ATTACHMENT0, internal_format, samples, 0, rbo_handle);
3141 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);
3145 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, 0);
3148 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
3151 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &temp_fbo);
3154 GL_ENTRYPOINT(glDeleteRenderbuffers)(1, &temp_rbo);
3159 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, 0, rbo_handle);
3162 else if (pAttachment->get_type() == GL_TEXTURE)
3164 GLuint tex_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3167 process_entrypoint_warning("%s: Current FBO %u has a invalid object name\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3171 GLenum target = get_shared_state()->m_shadow_state.m_textures.get_target_inv(tex_handle);
3172 if (target == GL_NONE)
3174 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);
3178 if ((target == GL_TEXTURE_CUBE_MAP) || (target == GL_TEXTURE_CUBE_MAP_ARRAY))
3179 target = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE);
3181 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))
3183 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);
3187 uint level = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
3188 uint layer = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
3189 VOGL_NOTE_UNUSED(layer);
3191 GLint width = 0, height = 0, samples = 0;
3192 GLenum internal_format = GL_NONE;
3195 vogl_scoped_binding_state binding_saver;
3196 binding_saver.save_textures();
3198 GL_ENTRYPOINT(glBindTexture)(target, tex_handle);
3201 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_WIDTH, &width);
3204 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_HEIGHT, &height);
3207 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_format));
3210 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_texture_multisample"))
3212 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_SAMPLES, &samples);
3217 if ((!width) || (!height))
3219 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);
3225 process_entrypoint_warning("%s: Can't dump multisample texture FBO attachments yet\n", VOGL_METHOD_NAME);
3229 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, tex_handle, 0);
3234 //----------------------------------------------------------------------------------------------------------------------
3235 // vogl_gl_replayer::dump_current_shaders
3236 //----------------------------------------------------------------------------------------------------------------------
3237 void vogl_gl_replayer::dump_current_shaders()
3241 if (!m_pCur_context_state)
3246 const GLuint replay_program = m_pCur_context_state->m_cur_replay_program;
3248 // Get the current program.
3249 GLuint current_program = 0;
3250 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, (GLint *)(¤t_program));
3253 VOGL_ASSERT(replay_program == current_program);
3255 if (!current_program)
3258 // Get the attached shaders.
3259 GLsizei attached_shader_count = -1;
3260 GL_ENTRYPOINT(glGetProgramiv)(replay_program, GL_ATTACHED_SHADERS, &attached_shader_count);
3263 if (!attached_shader_count)
3266 vogl::vector<GLuint> shaders(attached_shader_count);
3267 GLsizei actual_shader_count = 0;
3268 GL_ENTRYPOINT(glGetAttachedShaders)(replay_program,
3269 attached_shader_count,
3270 &actual_shader_count,
3274 VOGL_ASSERT(attached_shader_count == actual_shader_count); // Sanity check.
3276 vogl_printf("Trace context 0x%" PRIx64 ", GL draw counter %" PRIu64 ", frame %u, replay program %u trace program %u has %d attached shaders:\n",
3277 cast_val_to_uint64(m_cur_trace_context), m_last_parsed_call_counter, m_frame_index,
3278 replay_program, m_pCur_context_state->m_cur_trace_program,
3279 attached_shader_count);
3281 // Get source from shaders.
3282 vogl::vector<GLchar> source; // Shared buffer for each iteration.
3283 for (GLsizei i = 0; i < attached_shader_count; ++i)
3285 const GLuint shader = shaders[i];
3286 GLint shader_type = 0;
3287 GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_TYPE, &shader_type);
3290 vogl_printf("\n%s: %u\n", g_gl_enums.find_gl_name(shader_type), shader);
3292 GLint source_length = -1; // Includes NUL terminator.
3293 GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
3296 VOGL_ASSERT(source_length > 0);
3298 source.resize(source_length);
3299 GLint actual_length = 0; // Excludes NUL terminator!
3300 GL_ENTRYPOINT(glGetShaderSource)(shader, source_length, &actual_length, source.get_ptr());
3303 VOGL_ASSERT(source_length == actual_length + 1); // Sanity check.
3304 vogl_printf("%.*s\n", source_length, source.get_const_ptr());
3306 vogl_printf("========\n");
3309 //----------------------------------------------------------------------------------------------------------------------
3310 // vogl_gl_replayer::handle_ShaderSource
3311 // Handle ShaderSource and ShaderSourceARB.
3312 //----------------------------------------------------------------------------------------------------------------------
3313 vogl_gl_replayer::status_t vogl_gl_replayer::handle_ShaderSource(GLhandleARB trace_object,
3315 const vogl_client_memory_array trace_strings_glchar_ptr_array,
3316 const GLint *pTrace_lengths)
3320 GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
3322 // m_pCur_gl_packet->get_param_client_memory_data_size(2) / sizeof(const GLchar *);
3323 const uint trace_strings_count = trace_strings_glchar_ptr_array.size();
3324 const uint trace_lengths_count = m_pCur_gl_packet->get_param_client_memory_data_size(3) / sizeof(const GLint);
3326 if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3327 (trace_strings_count != static_cast<uint>(count)))
3329 process_entrypoint_error("%s: Trace strings array has an invalid count (expected %u, got %u)\n",
3330 VOGL_METHOD_NAME, count, trace_strings_count);
3331 return cStatusHardFailure;
3334 if ((pTrace_lengths) && (trace_lengths_count != static_cast<uint>(count)))
3336 process_entrypoint_error("%s: Trace lengths array has an invalid count (expected %u, got %u)\n",
3337 VOGL_METHOD_NAME, count, trace_lengths_count);
3338 return cStatusHardFailure;
3341 vogl::vector<const GLcharARB *> strings(count);
3342 vogl::vector<GLint> lengths(count);
3344 const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
3346 vogl::vector<uint8_vec> blobs(count);
3348 for (GLsizei i = 0; i < count; i++)
3351 if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3352 (trace_strings_glchar_ptr_array.get_element<vogl_trace_ptr_value>(i) != 0))
3357 lengths[i] = pTrace_lengths ? pTrace_lengths[i] : 0;
3359 key_value_map::const_iterator it = map.find(i);
3360 if (it == map.end())
3364 process_entrypoint_error("%s: Failed finding blob for non-empty string %i in packet's key value map\n",
3365 VOGL_METHOD_NAME, i);
3366 return cStatusHardFailure;
3371 const uint8_vec *pBlob = it->second.get_blob();
3374 process_entrypoint_error("%s: Can't convert string %i to a blob\n", VOGL_METHOD_NAME, i);
3375 return cStatusHardFailure;
3379 uint8_vec &blob = blobs[i];
3381 if ((pTrace_lengths) && (pTrace_lengths[i] >= 0))
3383 if (static_cast<uint>(pTrace_lengths[i]) != blob.size())
3385 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());
3386 lengths[i] = blob.size();
3391 if ((blob.size()) && (blob.back() != '\0'))
3393 process_entrypoint_warning("%s: String %u doesn't end in 0 terminator - appending terminator\n", VOGL_METHOD_NAME, i);
3395 blob.push_back('\0');
3398 VOGL_ASSERT(blob.size() &&
3399 (blob.back() == '\0') &&
3400 (blob.size() == (1 + vogl_strlen(reinterpret_cast<const char *>(blob.get_ptr())))));
3403 strings[i] = reinterpret_cast<const GLcharARB *>(blob.get_ptr());
3406 if (m_pCur_gl_packet->get_entrypoint_id() == VOGL_ENTRYPOINT_glShaderSource)
3408 GL_ENTRYPOINT(glShaderSource)(replay_object,
3410 trace_strings_glchar_ptr_array.get_ptr() ? (GLchar * const *)strings.get_ptr() : NULL,
3411 pTrace_lengths ? lengths.get_ptr() : NULL);
3415 GL_ENTRYPOINT(glShaderSourceARB)(replay_object,
3417 trace_strings_glchar_ptr_array.get_ptr() ? strings.get_ptr() : NULL,
3418 pTrace_lengths ? lengths.get_ptr() : NULL);
3423 //----------------------------------------------------------------------------------------------------------------------
3424 // vogl_gl_replayer::display_list_bind_callback
3425 // handle is in the trace namespace
3426 //----------------------------------------------------------------------------------------------------------------------
3427 void vogl_gl_replayer::display_list_bind_callback(vogl_namespace_t handle_namespace, GLenum target, GLuint handle, void *pOpaque)
3431 vogl_gl_replayer *pReplayer = static_cast<vogl_gl_replayer *>(pOpaque);
3433 if (handle_namespace == VOGL_NAMESPACE_TEXTURES)
3435 if ((handle) && (target != GL_NONE))
3437 // A conditional update because we can't really test to see if the bind inside the display list really succeeded.
3438 pReplayer->get_shared_state()->m_shadow_state.m_textures.conditional_update(handle, GL_NONE, target);
3443 // TODO - right now the display list whitelist doens't let anything else get bound.
3444 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);
3448 //----------------------------------------------------------------------------------------------------------------------
3449 // Helper macros - slightly simplifies hand-generating entrypoints with EXT/ARB/etc. variants
3450 //----------------------------------------------------------------------------------------------------------------------
3451 #define SWITCH_GL_ENTRYPOINT2(e0, e1, ...) \
3452 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3453 result = GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3455 result = GL_ENTRYPOINT(e1)(__VA_ARGS__);
3457 #define SWITCH_GL_ENTRYPOINT3(e0, e1, e2, ...) \
3458 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3459 result = GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3460 else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3461 result = GL_ENTRYPOINT(e1)(__VA_ARGS__); \
3463 result = GL_ENTRYPOINT(e2)(__VA_ARGS__);
3465 #define SWITCH_GL_ENTRYPOINT2_VOID(e0, e1, ...) \
3466 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3467 GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3469 GL_ENTRYPOINT(e1)(__VA_ARGS__);
3471 #define SWITCH_GL_ENTRYPOINT3_VOID(e0, e1, e2, ...) \
3472 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3473 GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3474 else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3475 GL_ENTRYPOINT(e1)(__VA_ARGS__); \
3477 GL_ENTRYPOINT(e2)(__VA_ARGS__);
3479 //----------------------------------------------------------------------------------------------------------------------
3480 // vogl_replayer::process_gl_entrypoint_packet
3481 // This will be called during replaying, or when building display lists during state restoring.
3482 //----------------------------------------------------------------------------------------------------------------------
3483 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet(vogl_trace_packet& trace_packet)
3485 m_pCur_gl_packet = &trace_packet;
3487 status_t status = cStatusOK;
3489 if (m_pPending_snapshot)
3491 status = process_applying_pending_snapshot();
3492 if (status != cStatusOK)
3496 if (m_pending_make_current_packet.is_valid())
3498 status = process_pending_make_current();
3499 if (status != cStatusOK)
3503 const vogl_trace_gl_entrypoint_packet &entrypoint_packet = trace_packet.get_entrypoint_packet();
3505 m_last_parsed_call_counter = entrypoint_packet.m_call_counter;
3507 status = process_gl_entrypoint_packet_internal(trace_packet);
3509 if (status != cStatusResizeWindow)
3510 m_last_processed_call_counter = entrypoint_packet.m_call_counter;
3512 m_pCur_gl_packet = NULL;
3517 //----------------------------------------------------------------------------------------------------------------------
3518 // vogl_replayer::process_gl_entrypoint_packet_internal
3519 // This will be called during replaying, or when building display lists during state restoring.
3520 //----------------------------------------------------------------------------------------------------------------------
3521 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet_internal(vogl_trace_packet& trace_packet)
3525 m_at_frame_boundary = false;
3527 const vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = trace_packet.get_entrypoint_packet();
3528 const gl_entrypoint_id_t entrypoint_id = trace_packet.get_entrypoint_id();
3530 if (m_flags & cGLReplayerDebugMode)
3531 dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
3533 if (m_flags & cGLReplayerDebugMode)
3534 dump_packet_as_func_call(trace_packet);
3536 if (m_flags & cGLReplayerDumpAllPackets)
3537 print_detailed_context(cDebugConsoleMessage);
3539 if (entrypoint_id == VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
3540 return process_internal_trace_command(gl_entrypoint_packet);
3542 status_t status = cStatusOK;
3544 if (gl_entrypoint_packet.m_context_handle != m_cur_trace_context)
3546 status = switch_contexts(gl_entrypoint_packet.m_context_handle);
3547 if (status != cStatusOK)
3551 bool processed_glx_packet = true;
3552 switch (entrypoint_id)
3554 case VOGL_ENTRYPOINT_glXDestroyContext:
3556 const Display *dpy = m_pWindow->get_display();
3558 vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3559 GLXContext replay_context = remap_context(trace_context);
3561 if ((trace_context) && (!replay_context))
3563 process_entrypoint_error("%s: Failed remapping GL trace context 0x%" PRIx64 "\n", VOGL_METHOD_NAME, (uint64_t)trace_context);
3564 return cStatusHardFailure;
3567 if (trace_context == m_cur_trace_context)
3569 process_entrypoint_warning("%s: glXDestroyContext() called while trace context 0x%" PRIx64 " is still current, forcing it to not be current\n",
3570 VOGL_METHOD_NAME, (uint64_t)trace_context);
3572 m_cur_trace_context = 0;
3573 m_cur_replay_context = 0;
3574 m_pCur_context_state = NULL;
3577 GL_ENTRYPOINT(glXDestroyContext)(dpy, replay_context);
3579 destroy_context(trace_context);
3583 case VOGL_ENTRYPOINT_glXMakeCurrent:
3584 case VOGL_ENTRYPOINT_glXMakeContextCurrent:
3586 Bool trace_result = trace_packet.get_return_value<Bool>();
3588 vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
3590 // pContext_state can be NULL!
3591 context_state *pContext_state = get_trace_context_state(trace_context);
3592 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
3594 if ((trace_context) && (!replay_context))
3596 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
3597 return cStatusHardFailure;
3600 int viewport_x = trace_packet.get_key_value_map().get_int(string_hash("viewport_x"));
3601 VOGL_NOTE_UNUSED(viewport_x);
3602 int viewport_y = trace_packet.get_key_value_map().get_int(string_hash("viewport_y"));
3603 VOGL_NOTE_UNUSED(viewport_y);
3604 int viewport_width = trace_packet.get_key_value_map().get_int(string_hash("viewport_width"));
3605 VOGL_NOTE_UNUSED(viewport_width);
3606 int viewport_height = trace_packet.get_key_value_map().get_int(string_hash("viewport_height"));
3607 VOGL_NOTE_UNUSED(viewport_height);
3608 int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3609 int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3611 // 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.
3612 if ((trace_context) && (trace_result))
3614 if ((win_width) && (win_height))
3616 if (!(m_flags & cGLReplayerLockWindowDimensions))
3618 if ((m_pWindow->get_width() != win_width) || (m_pWindow->get_height() != win_height))
3620 m_pending_make_current_packet = *m_pCur_gl_packet;
3622 status = trigger_pending_window_resize(win_width, win_height);
3624 vogl_printf("%s: Deferring glXMakeCurrent() until window resizes to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3630 if (status != cStatusResizeWindow)
3632 const Display *dpy = m_pWindow->get_display();
3633 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
3635 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
3640 process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
3641 return cStatusHardFailure;
3645 process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
3650 m_cur_trace_context = trace_context;
3651 m_cur_replay_context = replay_context;
3652 m_pCur_context_state = pContext_state;
3656 process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
3660 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
3661 viewport_x, viewport_y,
3662 viewport_width, viewport_height,
3663 win_width, win_height);
3666 if (m_cur_replay_context)
3668 if (!handle_context_made_current())
3669 return cStatusHardFailure;
3676 case VOGL_ENTRYPOINT_glXQueryVersion:
3678 int major = 0, minor = 0;
3679 Bool status = GL_ENTRYPOINT(glXQueryVersion)(m_pWindow->get_display(), &major, &minor);
3680 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,
3681 *trace_packet.get_param_client_memory<int>(1),
3682 *trace_packet.get_param_client_memory<int>(2),
3683 trace_packet.get_return_value<Bool>());
3687 case VOGL_ENTRYPOINT_glXChooseFBConfig:
3692 case VOGL_ENTRYPOINT_glXGetFBConfigAttrib:
3697 case VOGL_ENTRYPOINT_glXGetVisualFromFBConfig:
3702 case VOGL_ENTRYPOINT_glXGetProcAddress:
3703 case VOGL_ENTRYPOINT_glXGetProcAddressARB:
3705 const GLubyte *procName = trace_packet.get_param_client_memory<GLubyte>(0);
3706 vogl_trace_ptr_value trace_func_ptr_value = trace_packet.get_return_ptr_value();
3708 void *pFunc = (void *)GL_ENTRYPOINT(glXGetProcAddress)(procName);
3710 if ((pFunc != NULL) != (trace_func_ptr_value != 0))
3712 process_entrypoint_warning("%s: glXGetProcAddress of function %s %s in the replay, but %s in the trace\n", VOGL_METHOD_NAME,
3713 (const char *)procName,
3714 (pFunc != NULL) ? "succeeded" : "failed",
3715 (trace_func_ptr_value != 0) ? "succeeded" : "failed");
3720 case VOGL_ENTRYPOINT_glXCreateNewContext:
3722 Display *dpy = m_pWindow->get_display();
3723 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3724 int render_type = trace_packet.get_param_value<GLint>(2);
3726 vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(3);
3727 GLXContext replay_share_context = remap_context(trace_share_context);
3729 if ((trace_share_context) && (!replay_share_context))
3731 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3734 Bool direct = trace_packet.get_param_value<Bool>(4);
3735 vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3737 if (m_flags & cGLReplayerForceDebugContexts)
3739 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);
3741 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3742 if (status != cStatusOK)
3747 GLXContext replay_context = GL_ENTRYPOINT(glXCreateNewContext)(dpy, fb_config, render_type, replay_share_context, direct);
3749 if (!replay_context)
3753 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3754 return cStatusHardFailure;
3758 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3766 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateNewContext, NULL, 0);
3767 VOGL_NOTE_UNUSED(pContext_state);
3771 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3778 case VOGL_ENTRYPOINT_glXCreateContext:
3780 Display *dpy = m_pWindow->get_display();
3782 vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3783 GLXContext replay_share_context = remap_context(trace_share_context);
3785 if ((trace_share_context) && (!replay_share_context))
3787 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3790 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3791 Bool direct = trace_packet.get_param_value<Bool>(3);
3792 vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3794 if (m_flags & cGLReplayerForceDebugContexts)
3796 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3797 if (status != cStatusOK)
3802 XVisualInfo *pVisual_info = GL_ENTRYPOINT(glXGetVisualFromFBConfig)(dpy, fb_config);
3804 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContext)(dpy, pVisual_info, replay_share_context, direct);
3806 if (!replay_context)
3810 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3811 return cStatusHardFailure;
3815 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3823 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContext, NULL, 0);
3824 VOGL_NOTE_UNUSED(pContext_state);
3828 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3835 case VOGL_ENTRYPOINT_glXCreateContextAttribsARB:
3837 Display *dpy = m_pWindow->get_display();
3838 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3840 vogl_trace_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3841 GLXContext replay_share_context = remap_context(trace_share_context);
3843 if ((trace_share_context) && (!replay_share_context))
3845 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3848 Bool direct = trace_packet.get_param_value<Bool>(3);
3849 const int *pTrace_attrib_list = static_cast<const int *>(trace_packet.get_param_client_memory_ptr(4));
3850 const uint trace_attrib_list_size = trace_packet.get_param_client_memory_data_size(4) / sizeof(int);
3852 vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3854 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, pTrace_attrib_list, trace_attrib_list_size, true);
3855 if (status != cStatusOK)
3860 case VOGL_ENTRYPOINT_glXSwapBuffers:
3862 check_program_binding_shadow();
3864 if (m_flags & cGLReplayerLowLevelDebugMode)
3866 if (!validate_program_and_shader_handle_tables())
3867 vogl_warning_printf("%s: Failed validating program/shaders against handle mapping tables\n", VOGL_METHOD_NAME);
3868 if (!validate_textures())
3869 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
3872 const Display *dpy = m_pWindow->get_display();
3873 GLXDrawable drawable = m_pWindow->get_xwindow();
3875 if ((m_flags & cGLReplayerHashBackbuffer) || (m_flags & cGLReplayerDumpScreenshots) || (m_flags & cGLReplayerDumpBackbufferHashes))
3877 snapshot_backbuffer();
3880 if (m_dump_frontbuffer_filename.has_content())
3882 dump_frontbuffer_to_file(m_dump_frontbuffer_filename);
3883 m_dump_frontbuffer_filename.clear();
3886 GL_ENTRYPOINT(glXSwapBuffers)(dpy, drawable);
3888 if (m_swap_sleep_time)
3889 vogl_sleep(m_swap_sleep_time);
3891 status = cStatusNextFrame;
3893 m_at_frame_boundary = true;
3895 if (m_flags & cGLReplayerDebugMode)
3897 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);
3903 m_frame_draw_counter = 0;
3905 int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3906 int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3907 if ((win_width) && (win_height))
3909 if (!(m_flags & cGLReplayerLockWindowDimensions))
3911 if ((win_width != m_pWindow->get_width()) || (win_height != m_pWindow->get_height()))
3913 // TODO: This resize might need to be deferred until the window system actually resizes the window.
3914 //m_pWindow->resize(win_width, win_height);
3915 trigger_pending_window_resize(win_width, win_height);
3917 vogl_printf("%s: Resizing window after swap to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3924 case VOGL_ENTRYPOINT_glXWaitX:
3926 VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitX;
3928 VOGL_REPLAY_CALL_GL_HELPER_glXWaitX;
3932 case VOGL_ENTRYPOINT_glXWaitGL:
3934 VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitGL;
3936 VOGL_REPLAY_CALL_GL_HELPER_glXWaitGL;
3940 case VOGL_ENTRYPOINT_glXIsDirect:
3942 const Display *dpy = m_pWindow->get_display();
3944 vogl_trace_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3945 GLXContext replay_context = remap_context(trace_context);
3947 Bool replay_is_direct = GL_ENTRYPOINT(glXIsDirect)(dpy, replay_context);
3948 Bool trace_is_direct = trace_packet.get_return_value<Bool>();
3950 if (replay_is_direct != trace_is_direct)
3952 process_entrypoint_warning("%s: glXIsDirect() returned different results while replaying (%u) vs tracing (%u)!\n", VOGL_METHOD_NAME, replay_is_direct, trace_is_direct);
3957 case VOGL_ENTRYPOINT_glXGetCurrentContext:
3959 GLXContext replay_context = GL_ENTRYPOINT(glXGetCurrentContext)();
3960 vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3962 if ((replay_context != 0) != (trace_context != 0))
3964 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);
3969 case VOGL_ENTRYPOINT_glXCreateWindow:
3970 case VOGL_ENTRYPOINT_glXDestroyWindow:
3971 case VOGL_ENTRYPOINT_glXChooseVisual:
3972 case VOGL_ENTRYPOINT_glXGetCurrentDisplay:
3973 case VOGL_ENTRYPOINT_glXQueryDrawable:
3974 case VOGL_ENTRYPOINT_glXQueryExtension:
3975 case VOGL_ENTRYPOINT_glXQueryExtensionsString:
3976 case VOGL_ENTRYPOINT_glXSwapIntervalEXT:
3977 case VOGL_ENTRYPOINT_glXSwapIntervalSGI:
3978 case VOGL_ENTRYPOINT_glXGetCurrentDrawable:
3979 case VOGL_ENTRYPOINT_glXGetCurrentReadDrawable:
3980 case VOGL_ENTRYPOINT_glXQueryContext:
3981 case VOGL_ENTRYPOINT_glXGetClientString:
3982 case VOGL_ENTRYPOINT_glXGetConfig:
3983 case VOGL_ENTRYPOINT_glXGetFBConfigs:
3990 processed_glx_packet = false;
3995 if (processed_glx_packet)
3997 // TODO: Check for GLX errors?
4001 if (!m_cur_replay_context)
4003 process_entrypoint_error("%s: Trace contains a GL call with no current context! Skipping call.\n", VOGL_METHOD_NAME);
4004 return cStatusSoftFailure;
4007 VOGL_ASSERT(m_pCur_context_state);
4008 m_pCur_context_state->m_last_call_counter = m_last_parsed_call_counter;
4010 #ifdef VOGL_BUILD_DEBUG
4011 VOGL_ASSERT(get_trace_context_state(m_cur_trace_context) == m_pCur_context_state);
4014 // Add call to current display list
4015 if ((get_context_state()->is_composing_display_list()) && (g_vogl_entrypoint_descs[entrypoint_id].m_is_listable))
4017 if (!vogl_display_list_state::is_call_listable(entrypoint_id, trace_packet))
4019 if (!g_vogl_entrypoint_descs[entrypoint_id].m_whitelisted_for_displaylists)
4020 process_entrypoint_error("%s: Failed serializing trace packet into display list shadow! Call is not whitelisted for display list usage by vogl.\n", VOGL_FUNCTION_NAME);
4022 process_entrypoint_warning("%s: Failed serializing trace packet into display list shadow! Call with these parameters is not listable.\n", VOGL_FUNCTION_NAME);
4026 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))
4028 process_entrypoint_warning("%s: Failed adding current packet to display list shadow!\n", VOGL_METHOD_NAME);
4033 switch (entrypoint_id)
4035 // ----- Create simple auto-generated replay funcs - voglgen creates this inc file from the funcs in gl_glx_simple_replay_funcs.txt
4036 // These simple GL entrypoints only take value params that don't require handle remapping, or simple pointers to client memory
4037 // (typically pointers to fixed size buffers, or params directly controlling the size of buffers).
4038 #define VOGL_SIMPLE_REPLAY_FUNC_BEGIN(name, num_params) \
4039 case VOGL_ENTRYPOINT_##name: \
4040 { 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 \
4041 GL_ENTRYPOINT(name)(
4042 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE(type, index) trace_packet.get_param_value<type>(index)
4043 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR ,
4044 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY(type, index) trace_packet.get_param_client_memory<type>(index)
4045 #define VOGL_SIMPLE_REPLAY_FUNC_END(name) ); \
4048 #include "gl_glx_simple_replay_funcs.inc"
4049 #undef VOGL_SIMPLE_REPLAY_FUNC_BEGIN
4050 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE
4051 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR
4052 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY
4053 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_END
4055 case VOGL_ENTRYPOINT_glXUseXFont:
4057 const key_value_map &key_value_map = trace_packet.get_key_value_map();
4059 const dynamic_string *pFont_name = key_value_map.get_string_ptr("font_name");
4060 if ((!pFont_name) || (pFont_name->is_empty()))
4062 process_entrypoint_warning("%s: Couldn't find font_name key, or key was empty - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME);
4066 XFontStruct *pFont = XLoadQueryFont(m_pWindow->get_display(), pFont_name->get_ptr());
4069 process_entrypoint_warning("%s: Couldn't load X font %s - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME, pFont_name->get_ptr());
4073 GLint first = trace_packet.get_param_value<int>(1);
4074 GLint count = trace_packet.get_param_value<int>(2);
4075 int trace_list_base = trace_packet.get_param_value<int>(3);
4076 GLuint replay_list_base = map_handle(get_shared_state()->m_lists, trace_list_base);
4078 GL_ENTRYPOINT(glXUseXFont)(pFont->fid, first, count, replay_list_base);
4080 XFreeFont(m_pWindow->get_display(), pFont);
4082 if (get_context_state()->is_composing_display_list())
4084 process_entrypoint_warning("%s: glXUseXFont() called while composing a display list!\n", VOGL_METHOD_NAME);
4088 if (!get_shared_state()->m_shadow_state.m_display_lists.glx_font(pFont_name->get_ptr(), first, count, trace_list_base))
4090 process_entrypoint_warning("%s: Failed updating display list shadow\n", VOGL_METHOD_NAME);
4098 case VOGL_ENTRYPOINT_glBlitFramebufferEXT:
4100 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebufferEXT;
4102 VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebufferEXT;
4104 if ((status = post_draw_call()) != cStatusOK)
4109 case VOGL_ENTRYPOINT_glBlitFramebuffer:
4111 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebuffer;
4113 VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebuffer;
4115 if ((status = post_draw_call()) != cStatusOK)
4120 case VOGL_ENTRYPOINT_glBegin:
4122 if (m_pCur_context_state->m_inside_gl_begin)
4124 process_entrypoint_warning("%s: Got a glBegin while already inside a glBegin\n", VOGL_METHOD_NAME);
4126 m_pCur_context_state->m_inside_gl_begin = true;
4128 g_vogl_actual_gl_entrypoints.m_glBegin(trace_packet.get_param_value<GLenum>(0));
4132 case VOGL_ENTRYPOINT_glEnd:
4134 if (!m_pCur_context_state->m_inside_gl_begin)
4136 process_entrypoint_warning("%s: Got glEnd without a matching glBegin\n", VOGL_METHOD_NAME);
4138 m_pCur_context_state->m_inside_gl_begin = false;
4140 g_vogl_actual_gl_entrypoints.m_glEnd();
4142 if ((status = post_draw_call()) != cStatusOK)
4147 case VOGL_ENTRYPOINT_glGetError:
4149 // TODO: Compare trace error vs. replay error
4153 case VOGL_ENTRYPOINT_glGetStringi:
4155 if (!benchmark_mode())
4157 const GLubyte *pStr = GL_ENTRYPOINT(glGetStringi)(
4158 trace_packet.get_param_value<GLenum>(0),
4159 trace_packet.get_param_value<GLuint>(1));
4160 VOGL_NOTE_UNUSED(pStr);
4162 // TODO: Compare vs. trace's?
4167 case VOGL_ENTRYPOINT_glGetString:
4169 if (!benchmark_mode())
4171 const GLubyte *pStr = GL_ENTRYPOINT(glGetString)(
4172 trace_packet.get_param_value<GLenum>(0));
4173 VOGL_NOTE_UNUSED(pStr);
4175 // TODO: Compare vs. trace's?
4180 case VOGL_ENTRYPOINT_glGenFramebuffers:
4181 case VOGL_ENTRYPOINT_glGenFramebuffersEXT:
4183 if (!gen_handles(get_context_state()->m_framebuffers,
4184 trace_packet.get_param_value<GLsizei>(0),
4185 static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)),
4186 (entrypoint_id == VOGL_ENTRYPOINT_glGenFramebuffers) ? GL_ENTRYPOINT(glGenFramebuffers) : GL_ENTRYPOINT(glGenFramebuffersEXT), NULL))
4187 return cStatusHardFailure;
4191 case VOGL_ENTRYPOINT_glBindFramebuffer:
4192 case VOGL_ENTRYPOINT_glBindFramebufferEXT:
4194 GLenum target = trace_packet.get_param_value<GLenum>(0);
4195 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
4197 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
4199 SWITCH_GL_ENTRYPOINT2_VOID(glBindFramebuffer, glBindFramebufferEXT, target, replay_handle);
4203 case VOGL_ENTRYPOINT_glGetRenderbufferParameterivEXT:
4204 case VOGL_ENTRYPOINT_glGetRenderbufferParameteriv:
4206 if (!benchmark_mode())
4208 GLenum target = trace_packet.get_param_value<GLenum>(0);
4209 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4210 GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(2);
4211 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
4212 uint trace_params_count = trace_params_size / sizeof(GLint);
4214 int n = g_gl_enums.get_pname_count(pname);
4217 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4218 return cStatusSoftFailure;
4220 else if (n < static_cast<int>(trace_params_count))
4222 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);
4223 return cStatusSoftFailure;
4227 vogl::growable_array<GLint, 16> params(n + 1);
4228 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4230 SWITCH_GL_ENTRYPOINT2_VOID(glGetRenderbufferParameteriv, glGetRenderbufferParameterivEXT, target, pname, params.get_ptr());
4232 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4234 if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
4236 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));
4243 case VOGL_ENTRYPOINT_glCheckFramebufferStatus:
4244 case VOGL_ENTRYPOINT_glCheckFramebufferStatusEXT:
4247 SWITCH_GL_ENTRYPOINT2(glCheckFramebufferStatus, glCheckFramebufferStatusEXT, trace_packet.get_param_value<GLenum>(0));
4249 GLenum trace_status = trace_packet.get_return_value<GLenum>();
4250 if (result != trace_status)
4252 process_entrypoint_warning("%s: glCheckFramebufferStatus returned status 0x%08X during trace, but status 0x%08X during replay\n", VOGL_METHOD_NAME, trace_status, result);
4256 case VOGL_ENTRYPOINT_glDeleteFramebuffers:
4258 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));
4261 case VOGL_ENTRYPOINT_glDeleteFramebuffersEXT:
4263 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));
4266 case VOGL_ENTRYPOINT_glFramebufferTexture:
4268 GLenum target = trace_packet.get_param_value<GLenum>(0);
4269 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4270 GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4271 GLuint replay_texture = trace_texture;
4272 GLint level = trace_packet.get_param_value<GLint>(3);
4274 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4277 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);
4280 GL_ENTRYPOINT(glFramebufferTexture)(target, attachment, replay_texture, level);
4284 case VOGL_ENTRYPOINT_glFramebufferTextureLayer:
4285 case VOGL_ENTRYPOINT_glFramebufferTextureLayerEXT:
4287 GLenum target = trace_packet.get_param_value<GLenum>(0);
4288 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4289 GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4290 GLuint replay_texture = trace_texture;
4291 GLint level = trace_packet.get_param_value<GLint>(3);
4292 GLint layer = trace_packet.get_param_value<GLint>(4);
4294 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4297 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);
4300 SWITCH_GL_ENTRYPOINT2_VOID(glFramebufferTextureLayer, glFramebufferTextureLayerEXT, target, attachment, replay_texture, level, layer);
4304 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4305 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4306 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4307 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4308 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4309 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4311 GLenum target = trace_packet.get_param_value<GLenum>(0);
4312 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4313 GLenum textarget = trace_packet.get_param_value<GLenum>(2);
4314 GLuint trace_texture = trace_packet.get_param_value<GLuint>(3);
4315 GLuint replay_texture = trace_texture;
4316 GLint level = trace_packet.get_param_value<GLint>(4);
4318 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4321 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);
4324 switch (entrypoint_id)
4326 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4327 GL_ENTRYPOINT(glFramebufferTexture1DEXT)(target, attachment, textarget, replay_texture, level);
4329 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4330 GL_ENTRYPOINT(glFramebufferTexture1D)(target, attachment, textarget, replay_texture, level);
4332 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4333 GL_ENTRYPOINT(glFramebufferTexture2DEXT)(target, attachment, textarget, replay_texture, level);
4335 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4336 GL_ENTRYPOINT(glFramebufferTexture2D)(target, attachment, textarget, replay_texture, level);
4338 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4339 GL_ENTRYPOINT(glFramebufferTexture3DEXT)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4341 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4342 GL_ENTRYPOINT(glFramebufferTexture3D)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4350 case VOGL_ENTRYPOINT_glGenTextures:
4352 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))
4353 return cStatusHardFailure;
4356 case VOGL_ENTRYPOINT_glGenTexturesEXT:
4358 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))
4359 return cStatusHardFailure;
4362 case VOGL_ENTRYPOINT_glDeleteTextures:
4364 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));
4367 case VOGL_ENTRYPOINT_glDeleteTexturesEXT:
4369 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));
4372 case VOGL_ENTRYPOINT_glBindMultiTextureEXT:
4374 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindMultiTextureEXT;
4376 GLuint trace_texture = texture;
4377 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4379 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4382 VOGL_REPLAY_CALL_GL_HELPER_glBindMultiTextureEXT;
4384 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4386 if (!check_gl_error())
4387 get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4392 case VOGL_ENTRYPOINT_glBindTexture:
4393 case VOGL_ENTRYPOINT_glBindTextureEXT:
4395 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindTexture;
4397 GLuint trace_texture = texture;
4398 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4400 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4403 SWITCH_GL_ENTRYPOINT2_VOID(glBindTexture, glBindTextureEXT, target, texture);
4405 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4407 if (!check_gl_error())
4408 get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4413 case VOGL_ENTRYPOINT_glBindSampler:
4415 GLuint replay_handle = map_handle(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLuint>(1));
4416 GL_ENTRYPOINT(glBindSampler)(trace_packet.get_param_value<GLuint>(0), replay_handle);
4419 case VOGL_ENTRYPOINT_glDeleteSamplers:
4421 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));
4424 case VOGL_ENTRYPOINT_glGenSamplers:
4426 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))
4427 return cStatusHardFailure;
4431 case VOGL_ENTRYPOINT_glSamplerParameterf:
4433 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterf;
4434 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4435 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterf;
4438 case VOGL_ENTRYPOINT_glSamplerParameteri:
4440 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteri;
4441 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4442 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteri;
4445 case VOGL_ENTRYPOINT_glSamplerParameterfv:
4447 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterfv;
4448 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4449 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterfv;
4452 case VOGL_ENTRYPOINT_glSamplerParameteriv:
4454 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteriv;
4455 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4456 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteriv;
4459 case VOGL_ENTRYPOINT_glSamplerParameterIiv:
4461 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIiv;
4462 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4463 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIiv;
4466 case VOGL_ENTRYPOINT_glSamplerParameterIuiv:
4468 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIuiv;
4469 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4470 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIuiv;
4473 case VOGL_ENTRYPOINT_glGenBuffers:
4474 case VOGL_ENTRYPOINT_glGenBuffersARB:
4476 uint n = trace_packet.get_param_value<GLsizei>(0);
4477 const GLuint *pTrace_handles = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4479 if (entrypoint_id == VOGL_ENTRYPOINT_glGenBuffers)
4481 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffers), NULL))
4482 return cStatusHardFailure;
4486 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffersARB), NULL))
4487 return cStatusHardFailure;
4492 for (uint i = 0; i < n; i++)
4494 if (pTrace_handles[i])
4495 get_shared_state()->m_buffer_targets.insert(pTrace_handles[i], GL_NONE);
4501 case VOGL_ENTRYPOINT_glDeleteBuffers:
4502 case VOGL_ENTRYPOINT_glDeleteBuffersARB:
4504 GLsizei trace_n = trace_packet.get_param_value<GLsizei>(0);
4505 const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4506 uint trace_ids_count = trace_packet.get_param_client_memory_data_size(1);
4508 if ((pTrace_ids) && (static_cast<GLsizei>(trace_ids_count) < trace_n))
4510 process_entrypoint_warning("%s: trace_ids trace array is too small\n", VOGL_METHOD_NAME);
4511 return cStatusHardFailure;
4514 for (GLsizei iter = 0; iter < trace_n; iter++)
4516 GLuint trace_id = pTrace_ids[iter];
4520 if (!get_shared_state()->m_buffer_targets.erase(trace_id))
4522 process_entrypoint_warning("%s: Couldn't find trace buffer id %u in buffer target map!\n", VOGL_METHOD_NAME, trace_id);
4525 gl_handle_hash_map::const_iterator it = get_shared_state()->m_buffers.find(trace_id);
4526 if (it == get_shared_state()->m_buffers.end())
4528 process_entrypoint_warning("%s: Couldn't map trace buffer id %u to GL buffer id\n", VOGL_METHOD_NAME, trace_id);
4532 GLuint replay_id = it->second;
4534 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
4536 for (uint i = 0; i < mapped_bufs.size(); i++)
4538 if (mapped_bufs[i].m_buffer == replay_id)
4540 process_entrypoint_warning("%s: glDeleteBuffers() called on mapped trace buffer %u GL buffer %u\n", VOGL_METHOD_NAME, trace_id, replay_id);
4542 mapped_bufs.erase_unordered(i);
4548 if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteBuffers)
4549 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffers));
4551 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffersARB));
4555 case VOGL_ENTRYPOINT_glGenProgramsARB:
4557 // arb program objects
4558 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGenProgramsARB;
4560 if (!gen_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glGenProgramsARB), NULL))
4561 return cStatusHardFailure;
4563 for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4564 if (pTrace_programs[i])
4565 get_shared_state()->m_arb_program_targets.insert(pTrace_programs[i], GL_NONE);
4569 case VOGL_ENTRYPOINT_glDeleteProgramsARB:
4571 // arb program objects
4572 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDeleteProgramsARB;
4574 for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4575 get_shared_state()->m_arb_program_targets.erase(pTrace_programs[i]);
4577 delete_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glDeleteProgramsARB));
4580 case VOGL_ENTRYPOINT_glBindProgramARB:
4582 // arb program objects
4583 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindProgramARB;
4585 GLuint trace_program = program;
4586 gl_handle_hash_map::const_iterator it;
4589 it = get_shared_state()->m_arb_programs.find(program);
4590 if (it != get_shared_state()->m_arb_programs.end())
4591 program = it->second;
4593 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);
4598 VOGL_REPLAY_CALL_GL_HELPER_glBindProgramARB;
4600 if (!check_gl_error() && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4604 if (it == get_shared_state()->m_arb_programs.end())
4605 get_shared_state()->m_arb_programs.insert(trace_program, program);
4607 get_shared_state()->m_arb_program_targets[trace_program] = target;
4612 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));
4613 return cStatusGLError;
4618 case VOGL_ENTRYPOINT_glIsProgramARB:
4620 if (!benchmark_mode())
4622 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIsProgramARB;
4624 GLuint trace_program = program;
4625 program = map_handle(get_shared_state()->m_arb_programs, program);
4627 GLboolean replay_result = VOGL_REPLAY_CALL_GL_HELPER_glIsProgramARB;
4628 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4630 if (trace_result != replay_result)
4631 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);
4636 case VOGL_ENTRYPOINT_glGenQueries:
4637 case VOGL_ENTRYPOINT_glGenQueriesARB:
4639 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4640 vogl::growable_array<GLuint, 16> replay_handles(n);
4642 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()))
4643 return cStatusHardFailure;
4645 for (GLsizei i = 0; i < n; i++)
4646 get_shared_state()->m_query_targets[replay_handles[i]] = GL_NONE;
4650 case VOGL_ENTRYPOINT_glDeleteQueries:
4651 case VOGL_ENTRYPOINT_glDeleteQueriesARB:
4653 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4654 const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4658 for (GLsizei i = 0; i < n; i++)
4660 GLuint trace_id = pTrace_ids[i];
4663 gl_handle_hash_map::const_iterator it(get_shared_state()->m_queries.find(trace_id));
4664 if (it != get_shared_state()->m_queries.end())
4665 get_shared_state()->m_query_targets.erase(it->second);
4669 if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteQueries)
4670 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));
4672 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));
4676 case VOGL_ENTRYPOINT_glGenRenderbuffersEXT:
4678 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))
4679 return cStatusHardFailure;
4682 case VOGL_ENTRYPOINT_glGenRenderbuffers:
4684 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))
4685 return cStatusHardFailure;
4688 case VOGL_ENTRYPOINT_glDeleteRenderbuffersEXT:
4690 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));
4693 case VOGL_ENTRYPOINT_glDeleteRenderbuffers:
4695 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));
4698 case VOGL_ENTRYPOINT_glIsRenderbuffer:
4700 if (!benchmark_mode())
4702 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbuffer)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4703 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4704 if (replay_result != trace_result)
4706 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);
4711 case VOGL_ENTRYPOINT_glIsRenderbufferEXT:
4713 if (!benchmark_mode())
4715 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbufferEXT)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4716 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4717 if (replay_result != trace_result)
4719 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);
4724 case VOGL_ENTRYPOINT_glBindRenderbufferEXT:
4726 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)));
4729 case VOGL_ENTRYPOINT_glBindRenderbuffer:
4731 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)));
4734 case VOGL_ENTRYPOINT_glFramebufferRenderbufferEXT:
4736 GL_ENTRYPOINT(glFramebufferRenderbufferEXT)(
4737 trace_packet.get_param_value<GLenum>(0),
4738 trace_packet.get_param_value<GLenum>(1),
4739 trace_packet.get_param_value<GLenum>(2),
4740 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4743 case VOGL_ENTRYPOINT_glFramebufferRenderbuffer:
4745 GL_ENTRYPOINT(glFramebufferRenderbuffer)(
4746 trace_packet.get_param_value<GLenum>(0),
4747 trace_packet.get_param_value<GLenum>(1),
4748 trace_packet.get_param_value<GLenum>(2),
4749 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4752 case VOGL_ENTRYPOINT_glUseProgramObjectARB:
4753 case VOGL_ENTRYPOINT_glUseProgram:
4755 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4756 handle_use_program(trace_handle, entrypoint_id);
4759 case VOGL_ENTRYPOINT_glProgramParameteri:
4760 case VOGL_ENTRYPOINT_glProgramParameteriARB:
4761 case VOGL_ENTRYPOINT_glProgramParameteriEXT:
4763 VOGL_REPLAY_LOAD_PARAMS_HELPER_glProgramParameteri;
4765 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4767 if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriARB)
4768 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriARB;
4769 else if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriEXT)
4770 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriEXT;
4772 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteri;
4776 case VOGL_ENTRYPOINT_glBindFragDataLocation:
4777 case VOGL_ENTRYPOINT_glBindFragDataLocationEXT:
4779 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocation;
4781 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4783 if (entrypoint_id == VOGL_ENTRYPOINT_glBindFragDataLocation)
4784 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocation;
4786 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationEXT;
4790 case VOGL_ENTRYPOINT_glBindFragDataLocationIndexed:
4792 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocationIndexed;
4794 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4796 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationIndexed;
4800 case VOGL_ENTRYPOINT_glValidateProgramARB:
4802 VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgramARB;
4804 programObj = map_handle(get_shared_state()->m_shadow_state.m_objs, programObj);
4806 VOGL_REPLAY_CALL_GL_HELPER_glValidateProgramARB;
4810 case VOGL_ENTRYPOINT_glValidateProgram:
4812 VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgram;
4814 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4816 VOGL_REPLAY_CALL_GL_HELPER_glValidateProgram;
4820 case VOGL_ENTRYPOINT_glCreateProgram:
4821 case VOGL_ENTRYPOINT_glCreateProgramObjectARB:
4823 GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4826 GLuint replay_handle;
4828 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateProgram)
4829 replay_handle = GL_ENTRYPOINT(glCreateProgram)();
4831 replay_handle = GL_ENTRYPOINT(glCreateProgramObjectARB)();
4833 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0));
4835 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_PROGRAM_OBJECT))
4836 return cStatusHardFailure;
4840 case VOGL_ENTRYPOINT_glDeleteProgram:
4842 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4843 handle_delete_program(trace_handle);
4847 case VOGL_ENTRYPOINT_glDeleteObjectARB:
4849 GLuint trace_handle = trace_packet.get_param_value<GLenum>(0);
4850 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle);
4852 if (target == VOGL_SHADER_OBJECT)
4853 handle_delete_shader(trace_handle);
4854 else if (target == VOGL_PROGRAM_OBJECT)
4855 handle_delete_program(trace_handle);
4858 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
4860 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);
4861 return cStatusSoftFailure;
4866 case VOGL_ENTRYPOINT_glDeleteShader:
4868 GLuint trace_shader = trace_packet.get_param_value<GLuint>(0);
4869 handle_delete_shader(trace_shader);
4873 case VOGL_ENTRYPOINT_glCreateShader:
4874 case VOGL_ENTRYPOINT_glCreateShaderObjectARB:
4876 GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4879 GLuint replay_handle;
4881 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateShader)
4882 replay_handle = GL_ENTRYPOINT(glCreateShader)(trace_packet.get_param_value<GLenum>(0));
4884 replay_handle = GL_ENTRYPOINT(glCreateShaderObjectARB)(trace_packet.get_param_value<GLenum>(0));
4886 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsShader)(replay_handle) != 0));
4888 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_SHADER_OBJECT))
4889 return cStatusHardFailure;
4893 case VOGL_ENTRYPOINT_glAttachShader:
4895 GL_ENTRYPOINT(glAttachShader)(
4896 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4897 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(1)));
4900 case VOGL_ENTRYPOINT_glAttachObjectARB:
4902 GL_ENTRYPOINT(glAttachObjectARB)(
4903 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4904 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(1)));
4907 case VOGL_ENTRYPOINT_glDetachShader:
4909 handle_detach_shader(entrypoint_id);
4913 case VOGL_ENTRYPOINT_glDetachObjectARB:
4915 GLhandleARB trace_object_handle = trace_packet.get_param_value<GLhandleARB>(1);
4917 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_object_handle);
4919 if (target == VOGL_SHADER_OBJECT)
4920 handle_detach_shader(entrypoint_id);
4923 GLuint replay_object_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object_handle);
4924 GL_ENTRYPOINT(glDetachObjectARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)), replay_object_handle);
4929 case VOGL_ENTRYPOINT_glBindAttribLocation:
4931 GL_ENTRYPOINT(glBindAttribLocation)(
4932 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4933 trace_packet.get_param_value<GLuint>(1),
4934 trace_packet.get_param_client_memory<GLchar>(2));
4937 case VOGL_ENTRYPOINT_glBindAttribLocationARB:
4939 GL_ENTRYPOINT(glBindAttribLocationARB)(
4940 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4941 trace_packet.get_param_value<GLuint>(1),
4942 trace_packet.get_param_client_memory<GLcharARB>(2));
4945 case VOGL_ENTRYPOINT_glGetObjectParameterivARB:
4947 if (!benchmark_mode())
4949 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4950 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
4952 int n = g_gl_enums.get_pname_count(pname);
4955 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4956 return cStatusSoftFailure;
4960 vogl::growable_array<GLint, 16> params(n + 1);
4961 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4963 GL_ENTRYPOINT(glGetObjectParameterivARB)(
4964 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4968 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4970 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
4972 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));
4978 case VOGL_ENTRYPOINT_glGetBufferParameteriv:
4980 if (!benchmark_mode())
4982 GLenum target = trace_packet.get_param_value<GLenum>(0);
4983 GLenum value = trace_packet.get_param_value<GLenum>(1);
4984 const GLint *pTrace_data = trace_packet.get_param_client_memory<GLint>(2);
4986 int n = g_gl_enums.get_pname_count(value);
4989 process_entrypoint_error("%s: Can't determine count of GL value 0x%08X\n", VOGL_METHOD_NAME, value);
4990 return cStatusSoftFailure;
4994 vogl::growable_array<GLint, 16> data(n + 1);
4995 data[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4997 GL_ENTRYPOINT(glGetBufferParameteriv)(target, value, data.get_ptr());
4999 VOGL_VERIFY(data[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5001 GLint trace_data = pTrace_data ? pTrace_data[0] : -1;
5002 if (data[0] != trace_data)
5004 process_entrypoint_warning("%s: Replay's returned GLint differed from trace's!\n", VOGL_METHOD_NAME);
5005 vogl_warning_printf("Trace data: %i, Replay data: %i\n", trace_data, data[0]);
5013 case VOGL_ENTRYPOINT_glGetBufferPointerv:
5015 if (!benchmark_mode())
5017 GLvoid *pReplay_ptr = NULL;
5018 GL_ENTRYPOINT(glGetBufferPointerv)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLenum>(1), &pReplay_ptr);
5020 vogl_client_memory_array trace_void_ptr_array = trace_packet.get_param_client_memory_array(2);
5021 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;
5023 if ((pReplay_ptr != NULL) != (first_trace_ptr != 0))
5025 process_entrypoint_warning("%s: First replay's returned GLvoid* differed from trace's!\n", VOGL_METHOD_NAME);
5026 vogl_warning_printf("Trace: 0x%" PRIx64 ", Replay: 0x%" PRIx64 "\n", first_trace_ptr, reinterpret_cast<uint64_t>(pReplay_ptr));
5032 case VOGL_ENTRYPOINT_glShaderSource:
5033 case VOGL_ENTRYPOINT_glShaderSourceARB:
5035 const status_t status = handle_ShaderSource(trace_packet.get_param_value<GLhandleARB>(0),
5036 trace_packet.get_param_value<GLsizei>(1),
5037 trace_packet.get_param_client_memory_array(2),
5038 trace_packet.get_param_client_memory<const GLint>(3));
5039 if (status != cStatusOK)
5043 case VOGL_ENTRYPOINT_glGetProgramInfoLog:
5045 GLuint trace_object = trace_packet.get_param_value<GLuint>(0);
5046 GLuint replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5049 GL_ENTRYPOINT(glGetProgramiv)(replay_object, GL_INFO_LOG_LENGTH, &length);
5052 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5053 return cStatusSoftFailure;
5057 vogl::vector<GLchar> log(length);
5059 GLsizei actual_length = 0;
5060 GL_ENTRYPOINT(glGetProgramInfoLog)(replay_object, length, &actual_length, log.get_ptr());
5064 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());
5070 case VOGL_ENTRYPOINT_glGetPointerv:
5072 if (!benchmark_mode())
5075 GL_ENTRYPOINT(glGetPointerv)(trace_packet.get_param_value<GLenum>(0), &ptr);
5077 // TODO: Differ vs. trace's in some way?
5082 case VOGL_ENTRYPOINT_glGetInfoLogARB:
5084 GLhandleARB trace_object = trace_packet.get_param_value<GLhandleARB>(0);
5085 GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5087 GLsizei length = -1;
5088 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
5091 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5092 return cStatusSoftFailure;
5096 vogl::vector<GLcharARB> log(length);
5098 GLsizei actual_length = 0;
5099 GL_ENTRYPOINT(glGetInfoLogARB)(replay_object, length, &actual_length, log.get_ptr());
5103 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());
5109 case VOGL_ENTRYPOINT_glGetUniformLocation:
5111 GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5112 GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5113 GLint trace_loc = trace_packet.get_return_value<GLint>();
5117 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5119 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, pName);
5123 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);
5128 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);
5131 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5132 if (it == get_shared_state()->m_glsl_program_hash_map.end())
5133 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5135 glsl_program_state &state = it->second;
5136 state.m_uniform_locations.erase(trace_loc);
5137 state.m_uniform_locations.insert(trace_loc, replay_loc);
5144 case VOGL_ENTRYPOINT_glGetUniformLocationARB:
5146 GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5147 GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5148 GLint trace_loc = trace_packet.get_return_value<GLint>();
5152 const GLcharARB *pName = trace_packet.get_param_client_memory<GLcharARB>(1);
5154 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, pName);
5158 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);
5163 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);
5166 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5167 if (it == get_shared_state()->m_glsl_program_hash_map.end())
5168 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5170 glsl_program_state &state = it->second;
5171 state.m_uniform_locations.erase(trace_loc);
5172 state.m_uniform_locations.insert(trace_loc, replay_loc);
5179 case VOGL_ENTRYPOINT_glGetActiveAttrib:
5180 case VOGL_ENTRYPOINT_glGetActiveUniform:
5182 if (!benchmark_mode())
5184 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5185 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5187 GLuint index = trace_packet.get_param_value<GLuint>(1);
5188 GLsizei bufSize = trace_packet.get_param_value<GLsizei>(2);
5190 GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(3);
5191 GLint *pTrace_size = trace_packet.get_param_client_memory<GLint>(4);
5192 GLenum *pTrace_type = trace_packet.get_param_client_memory<GLenum>(5);
5193 GLchar *pTrace_name = trace_packet.get_param_client_memory<GLchar>(6);
5195 vogl::growable_array<GLchar, 1024> name_buf(bufSize + 1); // + 1 guarantees non-empty and null terminated
5201 if (entrypoint_id == VOGL_ENTRYPOINT_glGetActiveAttrib)
5202 GL_ENTRYPOINT(glGetActiveAttrib)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5204 GL_ENTRYPOINT(glGetActiveUniform)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5206 bool mismatch = false;
5208 GLsizei trace_len = 0;
5211 trace_len = pTrace_length[0];
5212 if (trace_len != len)
5216 GLint trace_size = 0;
5219 trace_size = pTrace_size[0];
5220 if (trace_size != size)
5224 GLenum trace_type = 0;
5227 trace_type = pTrace_type[0];
5228 if (trace_type != type)
5232 if ((bufSize) && (pTrace_name))
5234 uint n = vogl_strlen((const char *)pTrace_name) + 1;
5235 if (bufSize < (GLsizei)n)
5237 else if (memcmp(name_buf.get_ptr(), pTrace_name, n) != 0)
5243 process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5244 vogl_warning_printf("Trace handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5245 (uint)trace_handle, (uint)index, (uint)bufSize, (uint)trace_len, (uint)trace_type, (pTrace_name != NULL) ? (const char *)pTrace_name : "");
5246 vogl_warning_printf("GL handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5247 (uint)replay_handle, (uint)index, (uint)bufSize, (uint)len, (uint)type, name_buf.get_ptr());
5253 case VOGL_ENTRYPOINT_glGetAttachedShaders:
5255 if (!benchmark_mode())
5257 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5258 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5260 GLsizei max_count = trace_packet.get_param_value<GLsizei>(1);
5262 vogl::growable_array<GLuint, 16> shaders(max_count);
5264 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, trace_packet.get_param_value<GLsizei>(1), &count, shaders.get_ptr());
5266 // TODO: Diff results
5271 case VOGL_ENTRYPOINT_glGetAttribLocation:
5273 if (!benchmark_mode())
5275 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5276 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5278 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5280 GLint replay_result = GL_ENTRYPOINT(glGetAttribLocation)(replay_handle, pName);
5281 GLint trace_result = trace_packet.get_return_value<GLint>();
5283 if (replay_result != trace_result)
5285 process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5286 vogl_warning_printf("Trace value: %i, replay: %i\n", trace_result, replay_result);
5292 case VOGL_ENTRYPOINT_glGetProgramivARB:
5294 if (!benchmark_mode())
5296 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5297 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5298 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5299 uint params_count = params_size / sizeof(GLint);
5301 int n = g_gl_enums.get_pname_count(pname);
5304 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5305 return cStatusSoftFailure;
5309 vogl::growable_array<GLint, 16> params(n + 1);
5310 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5312 GL_ENTRYPOINT(glGetProgramivARB)(
5313 trace_packet.get_param_value<GLenum>(0),
5317 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5319 if (params_count != static_cast<uint>(n))
5321 process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5323 else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5325 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));
5332 case VOGL_ENTRYPOINT_glGetProgramiv:
5334 if (!benchmark_mode())
5336 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5337 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5339 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5341 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5342 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5343 uint params_count = params_size / sizeof(GLint);
5345 int n = g_gl_enums.get_pname_count(pname);
5348 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5349 return cStatusSoftFailure;
5353 vogl::growable_array<GLint, 16> params(n + 1);
5354 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5356 GL_ENTRYPOINT(glGetProgramiv)(
5361 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5363 if (params_count != static_cast<uint>(n))
5365 process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5367 else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5369 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));
5376 case VOGL_ENTRYPOINT_glLinkProgram:
5377 case VOGL_ENTRYPOINT_glLinkProgramARB:
5378 case VOGL_ENTRYPOINT_glProgramBinary:
5380 handle_link_program(entrypoint_id);
5384 case VOGL_ENTRYPOINT_glCompileShader:
5386 GL_ENTRYPOINT(glCompileShader)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)));
5389 case VOGL_ENTRYPOINT_glCompileShaderARB:
5391 GL_ENTRYPOINT(glCompileShaderARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)));
5394 case VOGL_ENTRYPOINT_glGetShaderiv:
5396 if (!benchmark_mode())
5398 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5399 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5401 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5404 const GLint *pClient_params = trace_packet.get_param_client_memory<GLint>(2);
5406 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, pname, ¶ms);
5408 if ((pClient_params) && (*pClient_params != params))
5410 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
5411 vogl_warning_printf("Trace data: %i, Replay data: %i\n", pClient_params ? *pClient_params : 0, params);
5417 case VOGL_ENTRYPOINT_glGetShaderInfoLog:
5419 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5420 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5422 GLsizei trace_max_length = trace_packet.get_param_value<GLsizei>(1);
5423 const GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(2);
5424 VOGL_NOTE_UNUSED(pTrace_length);
5425 const GLchar *pTrace_info_log = trace_packet.get_param_client_memory<GLchar>(3);
5426 VOGL_NOTE_UNUSED(pTrace_info_log);
5428 vogl::growable_array<GLchar, 512> log(trace_max_length);
5430 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, trace_max_length, &length, log.get_ptr());
5434 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());
5439 case VOGL_ENTRYPOINT_glGetBooleanv:
5441 if (!benchmark_mode())
5443 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5444 const GLboolean *pParams = trace_packet.get_param_client_memory<GLboolean>(1);
5446 int n = g_gl_enums.get_pname_count(pname);
5449 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));
5450 return cStatusSoftFailure;
5454 vogl::growable_array<GLboolean, 16> params(n + 1);
5455 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC;
5457 GL_ENTRYPOINT(glGetBooleanv)(pname, params.get_ptr());
5459 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC);
5461 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLboolean)) != 0)
5463 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));
5470 case VOGL_ENTRYPOINT_glGetDoublev:
5472 if (!benchmark_mode())
5474 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5475 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(1);
5477 int n = g_gl_enums.get_pname_count(pname);
5480 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5481 return cStatusSoftFailure;
5485 vogl::growable_array<GLdouble, 17> params(n + 1);
5486 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5488 GL_ENTRYPOINT(glGetDoublev)(pname, params.get_ptr());
5490 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5492 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLdouble)) != 0)
5494 process_entrypoint_warning("%s: Replay's returned GLdouble data differed from trace's\n", VOGL_METHOD_NAME);
5501 case VOGL_ENTRYPOINT_glGetFloatv:
5503 if (!benchmark_mode())
5505 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5506 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<GLfloat>(1);
5507 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLfloat);
5509 int n = g_gl_enums.get_pname_count(pname);
5512 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5513 return cStatusSoftFailure;
5516 vogl::growable_array<GLfloat, 17> params(n + 1);
5517 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5519 GL_ENTRYPOINT(glGetFloatv)(pname, params.get_ptr());
5521 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5523 if (static_cast<int>(trace_params_count) < n)
5524 process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5525 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLfloat)) != 0)
5527 process_entrypoint_warning("%s: Replay's returned GLfloat data differed from trace's\n", VOGL_METHOD_NAME);
5533 case VOGL_ENTRYPOINT_glGetIntegerv:
5535 if (!benchmark_mode())
5537 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5538 const GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(1);
5539 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLint);
5541 int n = g_gl_enums.get_pname_count(pname);
5544 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5545 return cStatusSoftFailure;
5548 vogl::growable_array<GLint, 16> params(n + 1);
5549 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5551 GL_ENTRYPOINT(glGetIntegerv)(pname, params.get_ptr());
5553 VOGL_VERIFY(params[n] == (GLint)VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5555 bool is_binding = false;
5558 case GL_ARRAY_BUFFER_BINDING:
5559 case GL_COLOR_ARRAY_BUFFER_BINDING:
5560 case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
5561 case GL_DRAW_FRAMEBUFFER_BINDING:
5562 case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
5563 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5564 case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
5565 case GL_INDEX_ARRAY_BUFFER_BINDING:
5566 case GL_NORMAL_ARRAY_BUFFER_BINDING:
5567 case GL_PIXEL_PACK_BUFFER_BINDING:
5568 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5569 case GL_PROGRAM_PIPELINE_BINDING:
5570 case GL_READ_FRAMEBUFFER_BINDING:
5571 case GL_RENDERBUFFER_BINDING:
5572 case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
5573 case GL_SHADER_STORAGE_BUFFER_BINDING:
5574 case GL_TEXTURE_BINDING_1D:
5575 case GL_TEXTURE_BINDING_1D_ARRAY:
5576 case GL_TEXTURE_BINDING_2D:
5577 case GL_TEXTURE_BINDING_2D_ARRAY:
5578 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
5579 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
5580 case GL_TEXTURE_BINDING_3D:
5581 case GL_TEXTURE_BINDING_BUFFER:
5582 case GL_TEXTURE_BINDING_CUBE_MAP:
5583 case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
5584 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5585 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
5586 case GL_UNIFORM_BUFFER_BINDING:
5587 case GL_VERTEX_ARRAY_BINDING:
5588 case GL_VERTEX_ARRAY_BUFFER_BINDING:
5589 case GL_CURRENT_PROGRAM:
5598 // Don't bother diffing bindings, the trace's are in the trace domain while the glGet's results are in the replay domain.
5601 if (static_cast<int>(trace_params_count) < n)
5603 process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5605 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
5607 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));
5608 for (int i = 0; i < n; i++)
5609 vogl_printf("GLint %u: Trace: %i, Replay: %i\n", i, pTrace_params[i], params[i]);
5616 // glProgramUniform's
5617 case VOGL_ENTRYPOINT_glProgramUniform1f:
5619 set_program_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glProgramUniform1f));
5622 case VOGL_ENTRYPOINT_glProgramUniform1i:
5624 set_program_uniform_helper1<GLint>(GL_ENTRYPOINT(glProgramUniform1i));
5627 case VOGL_ENTRYPOINT_glProgramUniform1ui:
5629 set_program_uniform_helper1<GLuint>(GL_ENTRYPOINT(glProgramUniform1ui));
5632 case VOGL_ENTRYPOINT_glProgramUniform2f:
5634 set_program_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glProgramUniform2f));
5637 case VOGL_ENTRYPOINT_glProgramUniform2i:
5639 set_program_uniform_helper2<GLint>(GL_ENTRYPOINT(glProgramUniform2i));
5642 case VOGL_ENTRYPOINT_glProgramUniform2ui:
5644 set_program_uniform_helper2<GLuint>(GL_ENTRYPOINT(glProgramUniform2ui));
5647 case VOGL_ENTRYPOINT_glProgramUniform3f:
5649 set_program_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glProgramUniform3f));
5652 case VOGL_ENTRYPOINT_glProgramUniform3i:
5654 set_program_uniform_helper3<GLint>(GL_ENTRYPOINT(glProgramUniform3i));
5657 case VOGL_ENTRYPOINT_glProgramUniform3ui:
5659 set_program_uniform_helper3<GLuint>(GL_ENTRYPOINT(glProgramUniform3ui));
5662 case VOGL_ENTRYPOINT_glProgramUniform4f:
5664 set_program_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glProgramUniform4f));
5667 case VOGL_ENTRYPOINT_glProgramUniform4i:
5669 set_program_uniform_helper4<GLint>(GL_ENTRYPOINT(glProgramUniform4i));
5672 case VOGL_ENTRYPOINT_glProgramUniform4ui:
5674 set_program_uniform_helper4<GLuint>(GL_ENTRYPOINT(glProgramUniform4ui));
5677 case VOGL_ENTRYPOINT_glProgramUniform1fv:
5679 set_program_uniformv_helper<1, float>(GL_ENTRYPOINT(glProgramUniform1fv));
5682 case VOGL_ENTRYPOINT_glProgramUniform2fv:
5684 set_program_uniformv_helper<2, float>(GL_ENTRYPOINT(glProgramUniform2fv));
5687 case VOGL_ENTRYPOINT_glProgramUniform3fv:
5689 set_program_uniformv_helper<3, float>(GL_ENTRYPOINT(glProgramUniform3fv));
5692 case VOGL_ENTRYPOINT_glProgramUniform4fv:
5694 set_program_uniformv_helper<4, float>(GL_ENTRYPOINT(glProgramUniform4fv));
5697 case VOGL_ENTRYPOINT_glProgramUniform1iv:
5699 set_program_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glProgramUniform1iv));
5702 case VOGL_ENTRYPOINT_glProgramUniform2iv:
5704 set_program_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glProgramUniform2iv));
5707 case VOGL_ENTRYPOINT_glProgramUniform3iv:
5709 set_program_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glProgramUniform3iv));
5712 case VOGL_ENTRYPOINT_glProgramUniform4iv:
5714 set_program_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glProgramUniform4iv));
5717 case VOGL_ENTRYPOINT_glProgramUniform1uiv:
5719 set_program_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glProgramUniform1uiv));
5722 case VOGL_ENTRYPOINT_glProgramUniform2uiv:
5724 set_program_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glProgramUniform2uiv));
5727 case VOGL_ENTRYPOINT_glProgramUniform3uiv:
5729 set_program_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glProgramUniform3uiv));
5732 case VOGL_ENTRYPOINT_glProgramUniform4uiv:
5734 set_program_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glProgramUniform4uiv));
5737 case VOGL_ENTRYPOINT_glProgramUniformMatrix2fv:
5739 set_program_uniform_matrixv_helper<2, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix2fv));
5742 case VOGL_ENTRYPOINT_glProgramUniformMatrix3fv:
5744 set_program_uniform_matrixv_helper<3, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix3fv));
5747 case VOGL_ENTRYPOINT_glProgramUniformMatrix4fv:
5749 set_program_uniform_matrixv_helper<4, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix4fv));
5752 case VOGL_ENTRYPOINT_glProgramUniformMatrix2x3fv:
5754 set_program_uniform_matrixv_helper<2, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x3fv));
5757 case VOGL_ENTRYPOINT_glProgramUniformMatrix3x2fv:
5759 set_program_uniform_matrixv_helper<3, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x2fv));
5762 case VOGL_ENTRYPOINT_glProgramUniformMatrix2x4fv:
5764 set_program_uniform_matrixv_helper<2, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x4fv));
5767 case VOGL_ENTRYPOINT_glProgramUniformMatrix4x2fv:
5769 set_program_uniform_matrixv_helper<4, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x2fv));
5772 case VOGL_ENTRYPOINT_glProgramUniformMatrix3x4fv:
5774 set_program_uniform_matrixv_helper<3, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x4fv));
5777 case VOGL_ENTRYPOINT_glProgramUniformMatrix4x3fv:
5779 set_program_uniform_matrixv_helper<4, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x3fv));
5783 case VOGL_ENTRYPOINT_glUniform1f:
5785 set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1f));
5788 case VOGL_ENTRYPOINT_glUniform1fARB:
5790 set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1fARB));
5793 case VOGL_ENTRYPOINT_glUniform2f:
5795 set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2f));
5798 case VOGL_ENTRYPOINT_glUniform2fARB:
5800 set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2fARB));
5803 case VOGL_ENTRYPOINT_glUniform3f:
5805 set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3f));
5808 case VOGL_ENTRYPOINT_glUniform3fARB:
5810 set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3fARB));
5813 case VOGL_ENTRYPOINT_glUniform4f:
5815 set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4f));
5818 case VOGL_ENTRYPOINT_glUniform4fARB:
5820 set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4fARB));
5823 case VOGL_ENTRYPOINT_glUniform1i:
5825 set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1i));
5828 case VOGL_ENTRYPOINT_glUniform1iARB:
5830 set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1iARB));
5833 case VOGL_ENTRYPOINT_glUniform2i:
5835 set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2i));
5838 case VOGL_ENTRYPOINT_glUniform2iARB:
5840 set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2iARB));
5843 case VOGL_ENTRYPOINT_glUniform3i:
5845 set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3i));
5848 case VOGL_ENTRYPOINT_glUniform3iARB:
5850 set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3iARB));
5853 case VOGL_ENTRYPOINT_glUniform4i:
5855 set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4i));
5858 case VOGL_ENTRYPOINT_glUniform4iARB:
5860 set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4iARB));
5863 case VOGL_ENTRYPOINT_glUniform1ui:
5865 set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1ui));
5868 case VOGL_ENTRYPOINT_glUniform1uiEXT:
5870 set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1uiEXT));
5873 case VOGL_ENTRYPOINT_glUniform2ui:
5875 set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2ui));
5878 case VOGL_ENTRYPOINT_glUniform2uiEXT:
5880 set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2uiEXT));
5883 case VOGL_ENTRYPOINT_glUniform3ui:
5885 set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3ui));
5888 case VOGL_ENTRYPOINT_glUniform3uiEXT:
5890 set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3uiEXT));
5893 case VOGL_ENTRYPOINT_glUniform4ui:
5895 set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4ui));
5898 case VOGL_ENTRYPOINT_glUniform4uiEXT:
5900 set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4uiEXT));
5903 case VOGL_ENTRYPOINT_glUniform1uiv:
5905 set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uiv));
5908 case VOGL_ENTRYPOINT_glUniform1uivEXT:
5910 set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uivEXT));
5913 case VOGL_ENTRYPOINT_glUniform2uiv:
5915 set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uiv));
5918 case VOGL_ENTRYPOINT_glUniform2uivEXT:
5920 set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uivEXT));
5923 case VOGL_ENTRYPOINT_glUniform3uiv:
5925 set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uiv));
5928 case VOGL_ENTRYPOINT_glUniform3uivEXT:
5930 set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uivEXT));
5933 case VOGL_ENTRYPOINT_glUniform4uiv:
5935 set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uiv));
5938 case VOGL_ENTRYPOINT_glUniform4uivEXT:
5940 set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uivEXT));
5943 case VOGL_ENTRYPOINT_glUniform1iv:
5945 set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1iv));
5948 case VOGL_ENTRYPOINT_glUniform1ivARB:
5950 set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1ivARB));
5953 case VOGL_ENTRYPOINT_glUniform2iv:
5955 set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2iv));
5958 case VOGL_ENTRYPOINT_glUniform2ivARB:
5960 set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2ivARB));
5963 case VOGL_ENTRYPOINT_glUniform3iv:
5965 set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3iv));
5968 case VOGL_ENTRYPOINT_glUniform3ivARB:
5970 set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3ivARB));
5973 case VOGL_ENTRYPOINT_glUniform4iv:
5975 set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4iv));
5978 case VOGL_ENTRYPOINT_glUniform4ivARB:
5980 set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4ivARB));
5983 case VOGL_ENTRYPOINT_glUniform1fv:
5985 set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fv));
5988 case VOGL_ENTRYPOINT_glUniform1fvARB:
5990 set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fvARB));
5993 case VOGL_ENTRYPOINT_glUniform2fv:
5995 set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fv));
5998 case VOGL_ENTRYPOINT_glUniform2fvARB:
6000 set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fvARB));
6003 case VOGL_ENTRYPOINT_glUniform3fv:
6005 set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fv));
6008 case VOGL_ENTRYPOINT_glUniform3fvARB:
6010 set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fvARB));
6013 case VOGL_ENTRYPOINT_glUniform4fv:
6015 set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fv));
6018 case VOGL_ENTRYPOINT_glUniform4fvARB:
6020 set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fvARB));
6023 case VOGL_ENTRYPOINT_glUniformMatrix2fvARB:
6025 set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fvARB));
6028 case VOGL_ENTRYPOINT_glUniformMatrix2fv:
6030 set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fv));
6033 case VOGL_ENTRYPOINT_glUniformMatrix3fvARB:
6035 set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fvARB));
6038 case VOGL_ENTRYPOINT_glUniformMatrix3fv:
6040 set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fv));
6043 case VOGL_ENTRYPOINT_glUniformMatrix4fvARB:
6045 set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fvARB));
6048 case VOGL_ENTRYPOINT_glUniformMatrix4fv:
6050 set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fv));
6053 case VOGL_ENTRYPOINT_glUniformMatrix2x3fv:
6055 set_uniform_matrixv_helper<2, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x3fv));
6058 case VOGL_ENTRYPOINT_glUniformMatrix3x2fv:
6060 set_uniform_matrixv_helper<3, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x2fv));
6063 case VOGL_ENTRYPOINT_glUniformMatrix2x4fv:
6065 set_uniform_matrixv_helper<2, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x4fv));
6068 case VOGL_ENTRYPOINT_glUniformMatrix4x2fv:
6070 set_uniform_matrixv_helper<4, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x2fv));
6073 case VOGL_ENTRYPOINT_glUniformMatrix3x4fv:
6075 set_uniform_matrixv_helper<3, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x4fv));
6078 case VOGL_ENTRYPOINT_glUniformMatrix4x3fv:
6080 set_uniform_matrixv_helper<4, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x3fv));
6083 case VOGL_ENTRYPOINT_glBeginQuery:
6084 case VOGL_ENTRYPOINT_glBeginQueryARB:
6086 GLenum target = trace_packet.get_param_value<GLenum>(0);
6087 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6088 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6090 if (!m_pCur_context_state->m_inside_gl_begin)
6093 if (entrypoint_id == VOGL_ENTRYPOINT_glBeginQuery)
6094 GL_ENTRYPOINT(glBeginQuery)(target, replay_handle);
6096 GL_ENTRYPOINT(glBeginQueryARB)(target, replay_handle);
6098 if ((replay_handle) && (!m_pCur_context_state->m_inside_gl_begin) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6100 if (check_gl_error())
6101 return cStatusGLError;
6103 get_shared_state()->m_query_targets[replay_handle] = target;
6108 case VOGL_ENTRYPOINT_glEndQuery:
6110 GL_ENTRYPOINT(glEndQuery)(trace_packet.get_param_value<GLenum>(0));
6113 case VOGL_ENTRYPOINT_glEndQueryARB:
6115 GL_ENTRYPOINT(glEndQueryARB)(trace_packet.get_param_value<GLenum>(0));
6118 case VOGL_ENTRYPOINT_glGetQueryObjectiv:
6120 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6121 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6123 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6125 int n = g_gl_enums.get_pname_count(pname);
6128 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6129 return cStatusSoftFailure;
6133 vogl::growable_array<GLint, 16> params(n + 1);
6134 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6136 GL_ENTRYPOINT(glGetQueryObjectiv)(replay_handle, pname, params.get_ptr());
6138 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6143 case VOGL_ENTRYPOINT_glGetQueryObjectivARB:
6145 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6146 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6148 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6150 int n = g_gl_enums.get_pname_count(pname);
6153 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6154 return cStatusSoftFailure;
6158 vogl::growable_array<GLint, 16> params(n + 1);
6159 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6161 GL_ENTRYPOINT(glGetQueryObjectivARB)(replay_handle, pname, params.get_ptr());
6163 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6168 case VOGL_ENTRYPOINT_glGetQueryObjectuiv:
6170 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6171 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6173 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6175 int n = g_gl_enums.get_pname_count(pname);
6178 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6179 return cStatusSoftFailure;
6183 vogl::growable_array<GLuint, 16> params(n + 1);
6184 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6186 GL_ENTRYPOINT(glGetQueryObjectuiv)(replay_handle, pname, params.get_ptr());
6188 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6193 case VOGL_ENTRYPOINT_glGetQueryObjectuivARB:
6195 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6196 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6198 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6200 int n = g_gl_enums.get_pname_count(pname);
6203 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6204 return cStatusSoftFailure;
6208 vogl::growable_array<GLuint, 16> params(n + 1);
6209 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6211 GL_ENTRYPOINT(glGetQueryObjectuivARB)(replay_handle, pname, params.get_ptr());
6213 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6218 case VOGL_ENTRYPOINT_glQueryCounter:
6220 VOGL_REPLAY_LOAD_PARAMS_HELPER_glQueryCounter;
6222 id = map_handle(get_shared_state()->m_queries, id);
6224 VOGL_REPLAY_CALL_GL_HELPER_glQueryCounter;
6228 case VOGL_ENTRYPOINT_glGetQueryObjecti64v:
6230 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjecti64v;
6231 VOGL_NOTE_UNUSED(pTrace_params);
6233 id = map_handle(get_shared_state()->m_queries, id);
6235 int n = g_gl_enums.get_pname_count(pname);
6238 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6239 return cStatusSoftFailure;
6242 vogl::growable_array<GLint64, 16> temp_params(n + 1);
6243 temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6245 GLint64 *pReplay_params = temp_params.get_ptr();
6247 VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjecti64v;
6249 VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6253 case VOGL_ENTRYPOINT_glGetQueryObjectui64v:
6255 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjectui64v;
6256 VOGL_NOTE_UNUSED(pTrace_params);
6258 id = map_handle(get_shared_state()->m_queries, id);
6260 int n = g_gl_enums.get_pname_count(pname);
6263 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6264 return cStatusSoftFailure;
6267 vogl::growable_array<GLuint64, 16> temp_params(n + 1);
6268 temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6270 GLuint64 *pReplay_params = temp_params.get_ptr();
6272 VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjectui64v;
6274 VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6278 case VOGL_ENTRYPOINT_glBindBuffer:
6279 case VOGL_ENTRYPOINT_glBindBufferARB:
6281 GLenum target = trace_packet.get_param_value<GLenum>(0);
6282 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6283 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
6287 SWITCH_GL_ENTRYPOINT2_VOID(glBindBuffer, glBindBufferARB, target, replay_handle);
6289 if (check_gl_error())
6290 return cStatusGLError;
6292 if ((trace_handle) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6294 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_handle);
6296 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_handle);
6297 else if (*pBinding == GL_NONE)
6303 case VOGL_ENTRYPOINT_glBindBufferBase:
6304 case VOGL_ENTRYPOINT_glBindBufferBaseEXT:
6305 case VOGL_ENTRYPOINT_glBindBufferBaseNV:
6307 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferBase;
6309 GLuint trace_buffer = buffer;
6310 buffer = map_handle(get_shared_state()->m_buffers, buffer);
6314 if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseNV)
6315 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseNV;
6316 else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseEXT)
6317 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseEXT;
6319 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBase;
6321 if (check_gl_error())
6322 return cStatusGLError;
6324 if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6326 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6328 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6329 else if (*pBinding == GL_NONE)
6335 case VOGL_ENTRYPOINT_glBindBufferRange:
6336 case VOGL_ENTRYPOINT_glBindBufferRangeEXT:
6337 case VOGL_ENTRYPOINT_glBindBufferRangeNV:
6339 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferRange;
6341 GLuint trace_buffer = buffer;
6342 buffer = map_handle(get_shared_state()->m_buffers, buffer);
6346 if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeNV)
6347 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeNV;
6348 else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeEXT)
6349 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeEXT;
6351 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRange;
6353 if (check_gl_error())
6354 return cStatusGLError;
6356 if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6358 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6360 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6361 else if (*pBinding == GL_NONE)
6367 case VOGL_ENTRYPOINT_glFenceSync:
6369 vogl_sync_ptr_value trace_handle = trace_packet.get_return_ptr_value();
6372 GLsync replay_handle = GL_ENTRYPOINT(glFenceSync)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLbitfield>(1));
6375 process_entrypoint_error("%s: glFenceSync on trace handle 0x%" PRIX64 " succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME, trace_handle);
6376 return cStatusHardFailure;
6380 get_shared_state()->m_syncs.insert(trace_handle, replay_handle);
6386 case VOGL_ENTRYPOINT_glWaitSync:
6387 case VOGL_ENTRYPOINT_glClientWaitSync:
6389 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6390 GLsync replay_sync = NULL;
6392 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6393 if (it == get_shared_state()->m_syncs.end())
6397 process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6398 return cStatusHardFailure;
6403 replay_sync = it->second;
6406 if (entrypoint_id == VOGL_ENTRYPOINT_glWaitSync)
6407 GL_ENTRYPOINT(glWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6409 GL_ENTRYPOINT(glClientWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6413 case VOGL_ENTRYPOINT_glDeleteSync:
6415 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6416 GLsync replay_sync = NULL;
6418 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6419 if (it == get_shared_state()->m_syncs.end())
6423 process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6424 return cStatusHardFailure;
6429 replay_sync = it->second;
6432 GL_ENTRYPOINT(glDeleteSync)(replay_sync);
6436 get_shared_state()->m_syncs.erase(trace_sync);
6441 case VOGL_ENTRYPOINT_glVertexPointer:
6443 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),
6444 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6447 case VOGL_ENTRYPOINT_glVertexPointerEXT:
6449 VOGL_REPLAY_LOAD_PARAMS_HELPER_glVertexPointerEXT;
6450 VOGL_NOTE_UNUSED(pTrace_pointer);
6452 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]);
6455 case VOGL_ENTRYPOINT_glColorPointer:
6457 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),
6458 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6461 case VOGL_ENTRYPOINT_glColorPointerEXT:
6463 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorPointerEXT;
6464 VOGL_NOTE_UNUSED(pTrace_pointer);
6466 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]);
6469 case VOGL_ENTRYPOINT_glSecondaryColorPointer:
6471 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),
6472 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointer), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6475 case VOGL_ENTRYPOINT_glSecondaryColorPointerEXT:
6477 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),
6478 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointerEXT), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6481 case VOGL_ENTRYPOINT_glTexCoordPointer:
6483 GLint cur_client_active_texture = 0;
6484 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6486 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6487 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6489 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);
6490 return cStatusSoftFailure;
6493 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),
6494 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6497 case VOGL_ENTRYPOINT_glTexCoordPointerEXT:
6499 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexCoordPointerEXT;
6500 VOGL_NOTE_UNUSED(pTrace_pointer);
6502 GLint cur_client_active_texture = 0;
6503 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6505 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6506 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6508 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);
6509 return cStatusSoftFailure;
6512 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]);
6515 case VOGL_ENTRYPOINT_glFogCoordPointer:
6517 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),
6518 vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointer));
6521 case VOGL_ENTRYPOINT_glFogCoordPointerEXT:
6523 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),
6524 vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointerEXT));
6527 case VOGL_ENTRYPOINT_glIndexPointer:
6529 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),
6530 vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointer));
6533 case VOGL_ENTRYPOINT_glIndexPointerEXT:
6535 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIndexPointerEXT;
6536 VOGL_NOTE_UNUSED(pTrace_pointer);
6538 vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointerEXT));
6541 case VOGL_ENTRYPOINT_glNormalPointer:
6543 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),
6544 vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6547 case VOGL_ENTRYPOINT_glNormalPointerEXT:
6549 VOGL_REPLAY_LOAD_PARAMS_HELPER_glNormalPointerEXT;
6550 VOGL_NOTE_UNUSED(pTrace_pointer);
6552 vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointerEXT));
6555 case VOGL_ENTRYPOINT_glEdgeFlagPointer:
6557 vertex_array_helper_no_type_no_size(trace_packet.get_param_value<GLsizei>(0), trace_packet.get_param_ptr_value(1),
6558 vogl_edge_flag_pointer_array_id, GL_ENTRYPOINT(glEdgeFlagPointer));
6561 case VOGL_ENTRYPOINT_glEdgeFlagPointerEXT:
6563 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEdgeFlagPointerEXT;
6564 VOGL_NOTE_UNUSED(pTrace_pointer);
6566 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));
6569 case VOGL_ENTRYPOINT_glInterleavedArrays:
6571 // TODO: Test this more!
6572 GLenum format = trace_packet.get_param_value<GLenum>(0);
6573 GLsizei stride = trace_packet.get_param_value<GLsizei>(1);
6574 const vogl_trace_ptr_value trace_pointer_value = trace_packet.get_param_ptr_value(2);
6577 for (fmt_index = 0; fmt_index < VOGL_INTERLEAVED_ARRAY_SIZE; fmt_index++)
6578 if (format == vogl_g_interleaved_array_descs[fmt_index].fmt)
6580 if (fmt_index == VOGL_INTERLEAVED_ARRAY_SIZE)
6582 process_entrypoint_error("%s: Invalid interleaved vertex format: 0x%X \n", VOGL_METHOD_NAME, format);
6583 return cStatusSoftFailure;
6588 process_entrypoint_error("%s: Invalid interleaved vertex stride: %i\n", VOGL_METHOD_NAME, static_cast<int>(stride));
6589 return cStatusSoftFailure;
6592 const interleaved_array_desc_entry_t &fmt = vogl_g_interleaved_array_descs[fmt_index];
6597 VOGL_ASSERT(stride > 0);
6600 GL_ENTRYPOINT(glDisableClientState)(GL_EDGE_FLAG_ARRAY);
6601 GL_ENTRYPOINT(glDisableClientState)(GL_INDEX_ARRAY);
6602 GL_ENTRYPOINT(glDisableClientState)(GL_SECONDARY_COLOR_ARRAY);
6603 GL_ENTRYPOINT(glDisableClientState)(GL_FOG_COORD_ARRAY);
6609 GLint cur_client_active_texture = 0;
6610 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6612 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6613 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6615 process_entrypoint_error("%s: glInterleavedArrays called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6616 return cStatusSoftFailure;
6619 GL_ENTRYPOINT(glEnableClientState)(GL_TEXTURE_COORD_ARRAY);
6620 vertex_array_helper(fmt.st, GL_FLOAT, stride, trace_pointer_value,
6621 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6625 GL_ENTRYPOINT(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
6632 GL_ENTRYPOINT(glEnableClientState)(GL_COLOR_ARRAY);
6633 vertex_array_helper(fmt.sc, fmt.tc, stride, trace_pointer_value + fmt.pc,
6634 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6638 GL_ENTRYPOINT(glDisableClientState)(GL_COLOR_ARRAY);
6645 GL_ENTRYPOINT(glEnableClientState)(GL_NORMAL_ARRAY);
6646 vertex_array_helper_no_size(GL_FLOAT, stride, trace_pointer_value + fmt.pn,
6647 vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6651 GL_ENTRYPOINT(glDisableClientState)(GL_NORMAL_ARRAY);
6656 GL_ENTRYPOINT(glEnableClientState)(GL_VERTEX_ARRAY);
6657 vertex_array_helper(fmt.sv, GL_FLOAT, stride, trace_pointer_value + fmt.pv,
6658 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6662 case VOGL_ENTRYPOINT_glVertexAttribIPointer:
6663 case VOGL_ENTRYPOINT_glVertexAttribIPointerEXT:
6665 GLuint index = trace_packet.get_param_value<GLuint>(0);
6666 GLint size = trace_packet.get_param_value<GLint>(1);
6667 GLenum type = trace_packet.get_param_value<GLenum>(2);
6668 GLsizei stride = trace_packet.get_param_value<GLsizei>(3);
6669 vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(4);
6671 if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6673 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6674 return cStatusSoftFailure;
6677 GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6678 void *pPtr = reinterpret_cast<void *>(trace_pointer);
6679 if ((!buffer) && (trace_pointer))
6681 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6682 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6683 if (!m_client_side_vertex_attrib_data[index].size())
6685 m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6687 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6690 if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribIPointer)
6691 GL_ENTRYPOINT(glVertexAttribIPointer)(index, size, type, stride, pPtr);
6693 GL_ENTRYPOINT(glVertexAttribIPointerEXT)(index, size, type, stride, pPtr);
6697 case VOGL_ENTRYPOINT_glVertexAttribPointerARB:
6698 case VOGL_ENTRYPOINT_glVertexAttribPointer:
6700 GLuint index = trace_packet.get_param_value<GLuint>(0);
6701 GLint size = trace_packet.get_param_value<GLint>(1);
6702 GLenum type = trace_packet.get_param_value<GLenum>(2);
6703 GLboolean normalized = trace_packet.get_param_value<GLboolean>(3);
6704 GLsizei stride = trace_packet.get_param_value<GLsizei>(4);
6705 vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(5);
6707 if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6709 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6710 return cStatusSoftFailure;
6713 GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6714 void *pPtr = reinterpret_cast<void *>(trace_pointer);
6715 if ((!buffer) && (trace_pointer))
6717 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6718 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6719 if (!m_client_side_vertex_attrib_data[index].size())
6721 m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6723 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6726 if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribPointer)
6727 GL_ENTRYPOINT(glVertexAttribPointer)(index, size, type, normalized, stride, pPtr);
6729 GL_ENTRYPOINT(glVertexAttribPointerARB)(index, size, type, normalized, stride, pPtr);
6733 case VOGL_ENTRYPOINT_glDrawRangeElements:
6734 case VOGL_ENTRYPOINT_glDrawRangeElementsEXT:
6736 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6737 GLuint start = trace_packet.get_param_value<GLuint>(1);
6738 GLuint end = trace_packet.get_param_value<GLuint>(2);
6739 GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6740 GLenum type = trace_packet.get_param_value<GLenum>(4);
6741 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6743 const GLvoid *pIndices;
6744 if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, 0, true, true))
6745 return cStatusSoftFailure;
6747 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6749 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawRangeElements)
6750 GL_ENTRYPOINT(glDrawRangeElements)(mode, start, end, count, type, pIndices);
6752 GL_ENTRYPOINT(glDrawRangeElementsEXT)(mode, start, end, count, type, pIndices);
6757 case VOGL_ENTRYPOINT_glDrawRangeElementsBaseVertex:
6759 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6760 GLuint start = trace_packet.get_param_value<GLuint>(1);
6761 GLuint end = trace_packet.get_param_value<GLuint>(2);
6762 GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6763 GLenum type = trace_packet.get_param_value<GLenum>(4);
6764 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6765 GLint basevertex = trace_packet.get_param_value<GLint>(6);
6767 const GLvoid *pIndices;
6768 if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, basevertex, true, true))
6769 return cStatusSoftFailure;
6771 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6773 GL_ENTRYPOINT(glDrawRangeElementsBaseVertex)(mode, start, end, count, type, pIndices, basevertex);
6778 case VOGL_ENTRYPOINT_glDrawElements:
6780 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6781 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6782 GLenum type = trace_packet.get_param_value<GLenum>(2);
6783 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6785 const GLvoid *pIndices;
6786 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6787 return cStatusSoftFailure;
6789 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6791 GL_ENTRYPOINT(glDrawElements)(mode, count, type, pIndices);
6796 case VOGL_ENTRYPOINT_glDrawArraysInstanced:
6797 case VOGL_ENTRYPOINT_glDrawArraysInstancedEXT:
6799 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawArraysInstanced;
6801 const GLvoid *pIndices = NULL;
6802 if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6803 return cStatusSoftFailure;
6805 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysInstancedEXT)
6807 GLsizei start = first, primcount = instancecount;
6808 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstancedEXT;
6811 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstanced;
6815 case VOGL_ENTRYPOINT_glDrawArrays:
6816 case VOGL_ENTRYPOINT_glDrawArraysEXT:
6818 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6819 GLint first = trace_packet.get_param_value<GLint>(1);
6820 GLsizei count = trace_packet.get_param_value<GLsizei>(2);
6822 const GLvoid *pIndices = NULL;
6823 if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6824 return cStatusSoftFailure;
6826 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6828 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysEXT)
6829 GL_ENTRYPOINT(glDrawArraysEXT)(mode, first, count);
6831 GL_ENTRYPOINT(glDrawArrays)(mode, first, count);
6836 case VOGL_ENTRYPOINT_glDrawElementsInstanced:
6837 case VOGL_ENTRYPOINT_glDrawElementsInstancedARB:
6838 case VOGL_ENTRYPOINT_glDrawElementsInstancedEXT:
6840 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6841 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6842 GLenum type = trace_packet.get_param_value<GLenum>(2);
6843 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6844 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6846 const GLvoid *pIndices;
6847 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6848 return cStatusSoftFailure;
6850 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6852 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstanced)
6853 GL_ENTRYPOINT(glDrawElementsInstanced)(mode, count, type, pIndices, primcount);
6854 else if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstancedEXT)
6855 GL_ENTRYPOINT(glDrawElementsInstancedEXT)(mode, count, type, pIndices, primcount);
6857 GL_ENTRYPOINT(glDrawElementsInstancedARB)(mode, count, type, pIndices, primcount);
6862 case VOGL_ENTRYPOINT_glDrawElementsInstancedBaseVertex:
6864 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6865 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6866 GLenum type = trace_packet.get_param_value<GLenum>(2);
6867 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6868 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6869 GLint basevertex = trace_packet.get_param_value<GLint>(5);
6871 const GLvoid *pIndices;
6872 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, basevertex, false, true))
6873 return cStatusSoftFailure;
6875 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6877 GL_ENTRYPOINT(glDrawElementsInstancedBaseVertex)(mode, count, type, pIndices, primcount, basevertex);
6882 case VOGL_ENTRYPOINT_glMultiDrawArrays:
6883 case VOGL_ENTRYPOINT_glMultiDrawArraysEXT:
6885 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6887 const GLint *pFirst = trace_packet.get_param_client_memory<const GLint>(1);
6888 uint first_size = trace_packet.get_param_client_memory_data_size(1);
6890 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(2);
6891 uint count_size = trace_packet.get_param_client_memory_data_size(2);
6893 GLsizei primcount = trace_packet.get_param_value<GLsizei>(3);
6895 if ((first_size != primcount * sizeof(GLint)) || (count_size != primcount * sizeof(GLsizei)))
6897 process_entrypoint_error("%s: first and/or count params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6898 return cStatusSoftFailure;
6901 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6903 // Multi-draws with client side arrays are not supported for replay.
6904 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6905 GL_ENTRYPOINT(glMultiDrawArrays)(mode, pFirst, pCount, primcount);
6907 GL_ENTRYPOINT(glMultiDrawArraysEXT)(mode, pFirst, pCount, primcount);
6912 case VOGL_ENTRYPOINT_glMultiDrawElements:
6913 case VOGL_ENTRYPOINT_glMultiDrawElementsEXT:
6915 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6917 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6918 uint count_size = trace_packet.get_param_client_memory_data_size(1);
6920 GLenum type = trace_packet.get_param_value<GLenum>(2);
6922 const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6924 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6926 if ((count_size != static_cast<uint>(primcount * sizeof(GLsizei))) || (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)))
6928 process_entrypoint_error("%s: count and/or indices params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6929 return cStatusSoftFailure;
6932 vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6933 for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6934 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6936 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6938 // Multi-draws with client side arrays are not supported for replay.
6939 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6940 GL_ENTRYPOINT(glMultiDrawElements)(mode, pCount, type, replay_indices.get_ptr(), primcount);
6942 GL_ENTRYPOINT(glMultiDrawElementsEXT)(mode, pCount, type, (const GLvoid **)replay_indices.get_ptr(), primcount);
6947 case VOGL_ENTRYPOINT_glMultiDrawElementsBaseVertex:
6949 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6951 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6952 uint count_size = trace_packet.get_param_client_memory_data_size(1);
6954 GLenum type = trace_packet.get_param_value<GLenum>(2);
6956 const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6957 //GLvoid * const *ppIndices = trace_packet.get_param_client_memory<GLvoid *>(3);
6958 //uint index_size = trace_packet.get_param_client_memory_data_size(3);
6960 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6962 const GLint *pBase_vertex = trace_packet.get_param_client_memory<const GLint>(5);
6963 uint base_vertex_size = trace_packet.get_param_client_memory_data_size(5);
6965 if ((count_size != primcount * sizeof(GLsizei)) ||
6966 (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)) ||
6967 (base_vertex_size != primcount * sizeof(GLint)))
6969 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);
6970 return cStatusSoftFailure;
6973 vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6974 for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6975 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6977 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6979 // Multi-draws with client side arrays are not supported for replay.
6980 GL_ENTRYPOINT(glMultiDrawElementsBaseVertex)(mode, pCount, type, replay_indices.get_ptr(), primcount, pBase_vertex);
6985 case VOGL_ENTRYPOINT_glDrawElementsBaseVertex:
6987 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6988 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6989 GLenum type = trace_packet.get_param_value<GLenum>(2);
6990 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6991 GLint base_vertex = trace_packet.get_param_value<GLint>(4);
6993 const GLvoid *pIndices;
6994 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, base_vertex, false, true))
6995 return cStatusSoftFailure;
6997 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6999 GL_ENTRYPOINT(glDrawElementsBaseVertex)(mode, count, type, pIndices, base_vertex);
7004 case VOGL_ENTRYPOINT_glGetBufferSubData:
7006 if (!benchmark_mode())
7008 GLenum target = trace_packet.get_param_value<GLenum>(0);
7009 vogl_trace_ptr_value offset = trace_packet.get_param_ptr_value(1);
7010 vogl_trace_ptr_value size = trace_packet.get_param_ptr_value(2);
7011 GLvoid *pTrace_ptr = trace_packet.get_param_client_memory<GLvoid>(3);
7013 if (offset != static_cast<uintptr_t>(offset))
7015 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)offset);
7016 return cStatusHardFailure;
7019 if ((size > cUINT32_MAX) || (size != static_cast<uintptr_t>(size)))
7021 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)size);
7022 return cStatusHardFailure;
7025 vogl::growable_array<uint8, 1024> buf(pTrace_ptr ? static_cast<uint>(size) : 0);
7027 GL_ENTRYPOINT(glGetBufferSubData)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), pTrace_ptr ? buf.get_ptr() : NULL);
7029 if ((buf.size()) && (pTrace_ptr))
7031 if (memcmp(buf.get_ptr(), pTrace_ptr, static_cast<size_t>(size)) != 0)
7033 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7040 case VOGL_ENTRYPOINT_glGetClipPlane:
7042 if (!benchmark_mode())
7044 GLenum plane = trace_packet.get_param_value<GLenum>(0);
7045 const GLdouble *pTrace_equation = trace_packet.get_param_client_memory<GLdouble>(1);
7047 GLdouble equation[4];
7048 GL_ENTRYPOINT(glGetClipPlane)(plane, pTrace_equation ? equation : NULL);
7050 if (pTrace_equation)
7052 if (memcmp(equation, pTrace_equation, sizeof(GLdouble) * 4) != 0)
7054 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7061 case VOGL_ENTRYPOINT_glBufferData:
7062 case VOGL_ENTRYPOINT_glBufferDataARB:
7064 GLenum target = trace_packet.get_param_value<GLenum>(0);
7065 vogl_trace_ptr_value size = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLsizeiptrARB
7066 const GLvoid *data = trace_packet.get_param_client_memory_ptr(2);
7067 uint data_size = trace_packet.get_param_client_memory_data_size(2);
7068 GLenum usage = trace_packet.get_param_value<GLenum>(3);
7070 if ((data) && (static_cast<vogl_trace_ptr_value>(data_size) < size))
7072 process_entrypoint_error("%s: trace's data array is too small\n", VOGL_METHOD_NAME);
7073 return cStatusHardFailure;
7076 if (size != static_cast<uintptr_t>(size))
7078 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(size));
7079 return cStatusHardFailure;
7082 if (entrypoint_id == VOGL_ENTRYPOINT_glBufferData)
7083 g_vogl_actual_gl_entrypoints.m_glBufferData(target, static_cast<GLsizeiptr>(size), data, usage);
7085 g_vogl_actual_gl_entrypoints.m_glBufferDataARB(target, static_cast<GLsizeiptrARB>(size), data, usage);
7087 GLuint buffer = vogl_get_bound_gl_buffer(target);
7090 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7093 for (i = 0; i < mapped_bufs.size(); i++)
7095 if (mapped_bufs[i].m_buffer == buffer)
7097 process_entrypoint_warning("%s: glBufferData() called on already mapped GL buffer %u, assuming GL will be unmapping it\n", VOGL_METHOD_NAME, buffer);
7099 mapped_bufs.erase_unordered(i);
7107 case VOGL_ENTRYPOINT_glMapBufferARB:
7108 case VOGL_ENTRYPOINT_glMapBuffer:
7110 GLenum target = trace_packet.get_param_value<GLenum>(0);
7111 GLenum access = trace_packet.get_param_value<GLenum>(1);
7112 vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7114 // FIXME - must call GL even if !pTrace_result
7115 if (trace_result_ptr_value)
7118 if (entrypoint_id == VOGL_ENTRYPOINT_glMapBuffer)
7119 pMap = GL_ENTRYPOINT(glMapBuffer)(target, access);
7121 pMap = GL_ENTRYPOINT(glMapBufferARB)(target, access);
7125 process_entrypoint_error("%s: glMapBuffer succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7126 return cStatusHardFailure;
7129 GLuint buffer = vogl_get_bound_gl_buffer(target);
7131 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7134 for (i = 0; i < mapped_bufs.size(); i++)
7136 if (mapped_bufs[i].m_buffer == buffer)
7138 process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7139 return cStatusHardFailure;
7143 if (i == mapped_bufs.size())
7146 GL_ENTRYPOINT(glGetBufferParameteriv)(target, GL_BUFFER_SIZE, &length);
7148 vogl_mapped_buffer_desc m;
7149 m.m_buffer = buffer;
7150 m.m_target = target;
7152 m.m_length = length;
7153 m.m_access = access;
7156 mapped_bufs.push_back(m);
7162 case VOGL_ENTRYPOINT_glMapBufferRange:
7164 GLenum target = trace_packet.get_param_value<GLenum>(0);
7165 vogl_trace_ptr_value offset = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLintptr
7166 vogl_trace_ptr_value length = trace_packet.get_param_value<vogl_trace_ptr_value>(2); // GLsizeiptr
7167 GLbitfield access = trace_packet.get_param_value<GLbitfield>(3);
7168 vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7170 if (offset != static_cast<uintptr_t>(offset))
7172 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(offset));
7173 return cStatusHardFailure;
7175 if (length != static_cast<uintptr_t>(length))
7177 process_entrypoint_error("%s: length parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(length));
7178 return cStatusHardFailure;
7181 // FIXME - must call GL even if !pTrace_result
7182 if (trace_result_ptr_value)
7184 void *pMap = GL_ENTRYPOINT(glMapBufferRange)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(length), access);
7187 process_entrypoint_error("%s: glMapBufferRange succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7188 return cStatusHardFailure;
7191 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7193 GLuint buffer = vogl_get_bound_gl_buffer(target);
7195 for (i = 0; i < mapped_bufs.size(); i++)
7197 if (mapped_bufs[i].m_buffer == buffer)
7199 process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7200 return cStatusHardFailure;
7204 if (i == mapped_bufs.size())
7206 vogl_mapped_buffer_desc m;
7207 m.m_buffer = buffer;
7208 m.m_target = target;
7209 m.m_offset = offset;
7210 m.m_length = length;
7211 m.m_access = access;
7214 mapped_bufs.push_back(m);
7220 case VOGL_ENTRYPOINT_glFlushMappedBufferRange:
7222 // vogltrace queues up the flushes, will process them while handling the glUnmapBuffer() call
7225 case VOGL_ENTRYPOINT_glUnmapBufferARB:
7226 case VOGL_ENTRYPOINT_glUnmapBuffer:
7228 GLenum target = trace_packet.get_param_value<GLenum>(0);
7229 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7231 GLuint buffer = vogl_get_bound_gl_buffer(target);
7233 // FIXME - must call GL even if !buffer
7236 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7238 uint mapped_buffers_index;
7239 for (mapped_buffers_index = 0; mapped_buffers_index < mapped_bufs.size(); mapped_buffers_index++)
7240 if (mapped_bufs[mapped_buffers_index].m_buffer == buffer)
7242 if (mapped_buffers_index == mapped_bufs.size())
7244 process_entrypoint_error("%s: Unable to find mapped buffer during unmap\n", VOGL_METHOD_NAME);
7245 return cStatusHardFailure;
7248 vogl_mapped_buffer_desc &map_desc = mapped_bufs[mapped_buffers_index];
7250 bool writable_map = false;
7251 bool explicit_bit = false;
7252 if (map_desc.m_range)
7254 writable_map = ((map_desc.m_access & GL_MAP_WRITE_BIT) != 0);
7255 explicit_bit = (map_desc.m_access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0;
7259 writable_map = (map_desc.m_access != GL_READ_ONLY);
7264 const key_value_map &unmap_data = trace_packet.get_key_value_map();
7268 int num_flushed_ranges = unmap_data.get_int(string_hash("flushed_ranges"));
7270 for (int i = 0; i < num_flushed_ranges; i++)
7272 int64_t ofs = unmap_data.get_int64(i * 4 + 0);
7273 int64_t size = unmap_data.get_int64(i * 4 + 1);
7274 VOGL_NOTE_UNUSED(size);
7275 const uint8_vec *pData = unmap_data.get_blob(i * 4 + 2);
7278 process_entrypoint_error("%s: Failed finding flushed range data in key value map\n", VOGL_METHOD_NAME);
7279 return cStatusHardFailure;
7282 if (ofs != static_cast<GLintptr>(ofs))
7284 process_entrypoint_error("%s: Flush offset is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(ofs));
7285 return cStatusHardFailure;
7288 VOGL_ASSERT(size == pData->size());
7290 memcpy(static_cast<uint8 *>(map_desc.m_pPtr) + ofs, pData->get_ptr(), pData->size());
7292 GL_ENTRYPOINT(glFlushMappedBufferRange)(target, static_cast<GLintptr>(ofs), pData->size());
7297 int64_t ofs = unmap_data.get_int64(0);
7298 VOGL_NOTE_UNUSED(ofs);
7299 int64_t size = unmap_data.get_int64(1);
7300 VOGL_NOTE_UNUSED(size);
7301 const uint8_vec *pData = unmap_data.get_blob(2);
7304 process_entrypoint_error("%s: Failed finding mapped data in key value map\n", VOGL_METHOD_NAME);
7305 return cStatusHardFailure;
7309 memcpy(map_desc.m_pPtr, pData->get_ptr(), pData->size());
7314 get_shared_state()->m_shadow_state.m_mapped_buffers.erase_unordered(mapped_buffers_index);
7317 GLboolean replay_result;
7318 if (entrypoint_id == VOGL_ENTRYPOINT_glUnmapBuffer)
7319 replay_result = GL_ENTRYPOINT(glUnmapBuffer)(target);
7321 replay_result = GL_ENTRYPOINT(glUnmapBufferARB)(target);
7323 if (trace_result != replay_result)
7324 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);
7328 case VOGL_ENTRYPOINT_glGenVertexArrays:
7330 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))
7331 return cStatusHardFailure;
7334 case VOGL_ENTRYPOINT_glBindVertexArray:
7336 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7337 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7339 GL_ENTRYPOINT(glBindVertexArray)(replay_handle);
7342 case VOGL_ENTRYPOINT_glDeleteVertexArrays:
7344 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));
7347 case VOGL_ENTRYPOINT_glIsFramebuffer:
7348 case VOGL_ENTRYPOINT_glIsFramebufferEXT:
7350 if (!benchmark_mode())
7352 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7353 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
7354 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7356 GLboolean replay_result;
7357 if (entrypoint_id == VOGL_ENTRYPOINT_glIsFramebuffer)
7358 replay_result = GL_ENTRYPOINT(glIsFramebuffer)(replay_handle);
7360 replay_result = GL_ENTRYPOINT(glIsFramebufferEXT)(replay_handle);
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));
7368 case VOGL_ENTRYPOINT_glIsBuffer:
7370 if (!benchmark_mode())
7372 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7373 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
7374 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7376 GLboolean replay_result = GL_ENTRYPOINT(glIsBuffer)(replay_handle);
7377 if (trace_result != replay_result)
7378 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));
7382 case VOGL_ENTRYPOINT_glIsEnabledi:
7384 if (!benchmark_mode())
7386 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7387 GLuint index = trace_packet.get_param_value<GLuint>(1);
7388 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7390 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabledi)(cap, index);
7391 if (trace_result != replay_result)
7392 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));
7396 case VOGL_ENTRYPOINT_glIsEnabled:
7398 if (!benchmark_mode())
7400 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7401 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7403 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabled)(cap);
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_glIsProgram:
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(glIsProgram)(replay_handle);
7419 if (trace_result != replay_result)
7420 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));
7424 case VOGL_ENTRYPOINT_glIsQuery:
7426 if (!benchmark_mode())
7428 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7429 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
7430 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7432 GLboolean replay_result = GL_ENTRYPOINT(glIsQuery)(replay_handle);
7433 if (trace_result != replay_result)
7434 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));
7438 case VOGL_ENTRYPOINT_glIsShader:
7440 if (!benchmark_mode())
7442 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7443 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7444 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7446 GLboolean replay_result = GL_ENTRYPOINT(glIsShader)(replay_handle);
7447 if (trace_result != replay_result)
7448 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));
7452 case VOGL_ENTRYPOINT_glIsTexture:
7453 case VOGL_ENTRYPOINT_glIsTextureEXT:
7455 if (!benchmark_mode())
7457 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7458 GLuint replay_handle = trace_handle;
7459 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7461 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_handle, replay_handle);
7463 GLboolean replay_result;
7464 if (entrypoint_id == VOGL_ENTRYPOINT_glIsTexture)
7465 replay_result = GL_ENTRYPOINT(glIsTexture)(replay_handle);
7467 replay_result = GL_ENTRYPOINT(glIsTextureEXT)(replay_handle);
7469 if (trace_result != replay_result)
7470 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));
7475 case VOGL_ENTRYPOINT_glIsVertexArray:
7477 if (!benchmark_mode())
7479 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7480 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7481 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7483 GLboolean replay_result = GL_ENTRYPOINT(glIsVertexArray)(replay_handle);
7484 if (trace_result != replay_result)
7485 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));
7490 case VOGL_ENTRYPOINT_glReadPixels:
7492 // TODO: This is causing huge stalls when replaying metro, not sure why. Also, the # of traced bytes is zero in metro.
7494 if (!benchmark_mode())
7496 GLint x = trace_packet.get_param_value<GLint>(0);
7497 GLint y = trace_packet.get_param_value<GLint>(1);
7498 GLsizei width = trace_packet.get_param_value<GLsizei>(2);
7499 GLsizei height = trace_packet.get_param_value<GLsizei>(3);
7500 GLenum format = trace_packet.get_param_value<GLenum>(4);
7501 GLenum type = trace_packet.get_param_value<GLenum>(5);
7502 const GLvoid *trace_data = trace_packet.get_param_client_memory<const GLvoid>(6);
7503 uint trace_data_size = trace_packet.get_param_client_memory_data_size(6);
7505 size_t replay_data_size = vogl_get_image_size(format, type, width, height, 1);
7506 if (replay_data_size != trace_data_size)
7508 process_entrypoint_warning("%s: Unexpected trace data size, got %u expected %" PRIu64 "\n", VOGL_METHOD_NAME, trace_data_size, (uint64_t)replay_data_size);
7510 else if (!trace_data)
7512 process_entrypoint_warning("%s: Trace data is missing from packet\n", VOGL_METHOD_NAME);
7515 if (replay_data_size > cUINT32_MAX)
7517 process_entrypoint_error("%s: Replay data size is too large (%" PRIu64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_data_size);
7518 return cStatusHardFailure;
7521 vogl::vector<uint8> data(static_cast<uint>(replay_data_size));
7522 GL_ENTRYPOINT(glReadPixels)(x, y, width, height, format, type, data.get_ptr());
7524 if ((trace_data_size == replay_data_size) && (trace_data_size) && (trace_data))
7526 if (memcmp(data.get_ptr(), trace_data, trace_data_size) != 0)
7528 process_entrypoint_error("%s: Replay's returned pixel data differed from trace's!\n", VOGL_METHOD_NAME);
7535 case VOGL_ENTRYPOINT_glGetTexLevelParameterfv:
7537 if (!benchmark_mode())
7539 GLenum target = trace_packet.get_param_value<GLenum>(0);
7540 GLint level = trace_packet.get_param_value<GLint>(1);
7541 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7542 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(3);
7543 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7545 int n = g_gl_enums.get_pname_count(pname);
7548 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7549 return cStatusSoftFailure;
7552 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7553 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7555 GL_ENTRYPOINT(glGetTexLevelParameterfv)(target, level, pname, replay_params.get_ptr());
7557 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7560 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7561 else if (trace_params_size != sizeof(GLfloat) * n)
7562 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7563 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7564 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7569 case VOGL_ENTRYPOINT_glGetTexLevelParameteriv:
7571 if (!benchmark_mode())
7573 GLenum target = trace_packet.get_param_value<GLenum>(0);
7574 GLint level = trace_packet.get_param_value<GLint>(1);
7575 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7576 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(3);
7577 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7579 int n = g_gl_enums.get_pname_count(pname);
7582 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7583 return cStatusSoftFailure;
7586 vogl::growable_array<GLint, 16> replay_params(n + 1);
7587 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7589 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, pname, replay_params.get_ptr());
7591 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7594 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7595 else if (trace_params_size != sizeof(GLint) * n)
7596 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7597 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7598 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7603 case VOGL_ENTRYPOINT_glGetTexParameterIiv:
7604 case VOGL_ENTRYPOINT_glGetTexParameteriv:
7606 if (!benchmark_mode())
7608 GLenum target = trace_packet.get_param_value<GLenum>(0);
7609 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7610 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(2);
7611 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7613 int n = g_gl_enums.get_pname_count(pname);
7616 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7617 return cStatusSoftFailure;
7620 vogl::growable_array<GLint, 16> replay_params(n + 1);
7621 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7623 if (entrypoint_id == VOGL_ENTRYPOINT_glGetTexParameterIiv)
7624 GL_ENTRYPOINT(glGetTexParameterIiv)(target, pname, replay_params.get_ptr());
7626 GL_ENTRYPOINT(glGetTexParameteriv)(target, pname, replay_params.get_ptr());
7628 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7631 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7632 else if (trace_params_size != sizeof(GLint) * n)
7633 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7634 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7635 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7640 case VOGL_ENTRYPOINT_glGetTexParameterIuiv:
7642 if (!benchmark_mode())
7644 GLenum target = trace_packet.get_param_value<GLenum>(0);
7645 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7646 const GLuint *pTrace_params = trace_packet.get_param_client_memory<const GLuint>(2);
7647 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7649 int n = g_gl_enums.get_pname_count(pname);
7652 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7653 return cStatusSoftFailure;
7656 vogl::growable_array<GLuint, 16> replay_params(n + 1);
7657 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7659 GL_ENTRYPOINT(glGetTexParameterIuiv)(target, pname, replay_params.get_ptr());
7661 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7664 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7665 else if (trace_params_size != sizeof(GLuint) * n)
7666 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7667 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLuint) * n) != 0)
7668 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7673 case VOGL_ENTRYPOINT_glGetTexParameterfv:
7675 if (!benchmark_mode())
7677 GLenum target = trace_packet.get_param_value<GLenum>(0);
7678 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7679 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(2);
7680 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7682 int n = g_gl_enums.get_pname_count(pname);
7685 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7686 return cStatusSoftFailure;
7689 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7690 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7692 GL_ENTRYPOINT(glGetTexParameterfv)(target, pname, replay_params.get_ptr());
7694 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7697 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7698 else if (trace_params_size != sizeof(GLfloat) * n)
7699 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7700 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7701 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7707 case VOGL_ENTRYPOINT_glGetVertexAttribdv:
7709 status = get_vertex_attrib_helper<GLdouble>(GL_ENTRYPOINT(glGetVertexAttribdv));
7710 if (status != cStatusOK)
7714 case VOGL_ENTRYPOINT_glGetVertexAttribfv:
7716 status = get_vertex_attrib_helper<GLfloat>(GL_ENTRYPOINT(glGetVertexAttribfv));
7717 if (status != cStatusOK)
7721 case VOGL_ENTRYPOINT_glGetVertexAttribiv:
7723 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribiv));
7724 if (status != cStatusOK)
7728 case VOGL_ENTRYPOINT_glGetVertexAttribIiv:
7730 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIiv));
7731 if (status != cStatusOK)
7735 case VOGL_ENTRYPOINT_glGetVertexAttribIivEXT:
7737 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIivEXT));
7738 if (status != cStatusOK)
7742 case VOGL_ENTRYPOINT_glGetVertexAttribIuiv:
7744 status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuiv));
7745 if (status != cStatusOK)
7749 case VOGL_ENTRYPOINT_glGetVertexAttribIuivEXT:
7751 status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuivEXT));
7752 if (status != cStatusOK)
7756 case VOGL_ENTRYPOINT_glGenLists:
7758 GLsizei range = trace_packet.get_param_value<GLsizei>(0);
7759 GLuint trace_base_handle = trace_packet.get_return_value<GLuint>();
7761 if (trace_base_handle)
7765 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7767 if ((check_gl_error()) || (!replay_base_handle))
7769 process_entrypoint_error("%s: glGenLists() succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME);
7770 return cStatusHardFailure;
7773 for (GLsizei i = 0; i < range; i++)
7775 GLuint trace_handle = trace_base_handle + i;
7776 GLuint replay_handle = replay_base_handle + i;
7778 if (!gen_handle(get_shared_state()->m_lists, trace_handle, replay_handle))
7779 return cStatusHardFailure;
7781 if (!get_shared_state()->m_shadow_state.m_display_lists.gen_lists(trace_handle, 1, &replay_handle))
7783 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);
7789 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7790 if (replay_base_handle)
7792 process_entrypoint_warning("%s: glGenLists() failed in the trace, but succeeded during replay!\n", VOGL_METHOD_NAME);
7794 GL_ENTRYPOINT(glDeleteLists)(replay_base_handle, range);
7800 case VOGL_ENTRYPOINT_glCallList:
7802 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7803 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7805 GL_ENTRYPOINT(glCallList)(replay_handle);
7807 if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7809 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7812 if ((status = post_draw_call()) != cStatusOK)
7817 case VOGL_ENTRYPOINT_glCallLists:
7819 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
7820 GLenum type = trace_packet.get_param_value<GLenum>(1);
7821 const GLvoid *pTrace_lists = trace_packet.get_param_client_memory<const GLvoid>(2);
7822 uint trace_lists_size = trace_packet.get_param_client_memory_data_size(2);
7824 uint type_size = vogl_get_gl_type_size(type);
7827 process_entrypoint_error("%s: Unable to execute glCallLists, type is invalid\n", VOGL_METHOD_NAME);
7828 return cStatusSoftFailure;
7831 if ((n) && (!pTrace_lists))
7833 process_entrypoint_error("%s: Unable to execute glCallLists, lists param is NULL\n", VOGL_METHOD_NAME);
7834 return cStatusSoftFailure;
7837 if (trace_lists_size < (type_size * n))
7839 process_entrypoint_error("%s: Unable to execute glCallLists, lists param data size is too small in trace\n", VOGL_METHOD_NAME);
7840 return cStatusSoftFailure;
7843 GLuint list_base = 0;
7844 GL_ENTRYPOINT(glGetIntegerv)(GL_LIST_BASE, reinterpret_cast<GLint *>(&list_base));
7846 const uint8 *pTrace_lists_ptr = static_cast<const uint8 *>(pTrace_lists);
7847 for (GLsizei i = 0; i < n; i++)
7849 GLint trace_handle = list_base;
7854 trace_handle += *reinterpret_cast<const signed char *>(pTrace_lists_ptr);
7858 case GL_UNSIGNED_BYTE:
7860 trace_handle += *pTrace_lists_ptr;
7866 trace_handle += *reinterpret_cast<const int16 *>(pTrace_lists_ptr);
7867 pTrace_lists_ptr += sizeof(int16);
7870 case GL_UNSIGNED_SHORT:
7872 trace_handle += *reinterpret_cast<const uint16 *>(pTrace_lists_ptr);
7873 pTrace_lists_ptr += sizeof(uint16);
7878 trace_handle += *reinterpret_cast<const int32 *>(pTrace_lists_ptr);
7879 pTrace_lists_ptr += sizeof(int32);
7882 case GL_UNSIGNED_INT:
7884 trace_handle += *reinterpret_cast<const uint32 *>(pTrace_lists_ptr);
7885 pTrace_lists_ptr += sizeof(uint32);
7890 trace_handle += static_cast<GLint>(*reinterpret_cast<const float *>(pTrace_lists_ptr));
7891 pTrace_lists_ptr += sizeof(float);
7896 trace_handle += ((pTrace_lists_ptr[0] << 8U) + pTrace_lists_ptr[1]);
7897 pTrace_lists_ptr += 2;
7902 trace_handle += ((pTrace_lists_ptr[0] << 16U) + (pTrace_lists_ptr[1] << 8U) + pTrace_lists_ptr[2]);
7903 pTrace_lists_ptr += 3;
7908 trace_handle += ((pTrace_lists_ptr[0] << 24U) + (pTrace_lists_ptr[1] << 16U) + (pTrace_lists_ptr[2] << 8U) + pTrace_lists_ptr[3]);
7909 pTrace_lists_ptr += 4;
7914 process_entrypoint_error("%s: Invalid type parameter (0x%08X)\n", VOGL_METHOD_NAME, type);
7915 return cStatusSoftFailure;
7919 if (trace_handle <= 0)
7921 process_entrypoint_error("%s: Trace handle after adding list base is negative (%i), skipping this list index\n", VOGL_METHOD_NAME, trace_handle);
7925 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7926 GL_ENTRYPOINT(glCallList)(replay_handle);
7928 if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7930 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7935 if ((status = post_draw_call()) != cStatusOK)
7940 case VOGL_ENTRYPOINT_glDeleteLists:
7942 GLuint trace_list = trace_packet.get_param_value<GLuint>(0);
7943 GLsizei range = trace_packet.get_param_value<GLsizei>(1);
7945 for (GLsizei i = 0; i < range; i++)
7947 GLuint trace_handle = trace_list + i;
7948 delete_handles(get_shared_state()->m_lists, 1, &trace_handle, delete_list_helper);
7950 if (!get_shared_state()->m_shadow_state.m_display_lists.del_lists(trace_handle, 1))
7952 process_entrypoint_warning("%s: Unable to delete list in display list shadow, trace handle %u\n", VOGL_METHOD_NAME, trace_handle);
7958 case VOGL_ENTRYPOINT_glIsList:
7960 if (!benchmark_mode())
7962 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7963 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7964 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7966 GLboolean replay_result = GL_ENTRYPOINT(glIsList)(replay_handle);
7967 if (trace_result != replay_result)
7968 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));
7973 case VOGL_ENTRYPOINT_glNewList:
7975 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7976 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7977 GLenum mode = trace_packet.get_param_value<GLenum>(1);
7981 GL_ENTRYPOINT(glNewList)(replay_handle, mode);
7983 if (!check_gl_error())
7985 get_shared_state()->m_shadow_state.m_display_lists.new_list(trace_handle, replay_handle);
7987 get_context_state()->m_current_display_list_mode = mode;
7988 get_context_state()->m_current_display_list_handle = trace_handle;
7991 // TODO: Check if glNewList() failed vs the replay.
7992 // This is important, because if the new failed during tracing but succeeded during replay then we've seriously diverged.
7993 // 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.
7996 case VOGL_ENTRYPOINT_glListBase:
7998 GLuint base = trace_packet.get_param_value<GLuint>(0);
7999 GL_ENTRYPOINT(glListBase)(base);
8002 case VOGL_ENTRYPOINT_glEndList:
8004 GL_ENTRYPOINT(glEndList)();
8006 if (!get_context_state()->is_composing_display_list())
8008 process_entrypoint_warning("%s: glEndList() called without calling glNewList()!\n", VOGL_METHOD_NAME);
8012 if (!get_shared_state()->m_shadow_state.m_display_lists.end_list(get_context_state()->m_current_display_list_handle))
8013 process_entrypoint_warning("%s: Failed ending display list, trace handle %u\n", VOGL_METHOD_NAME, get_context_state()->m_current_display_list_handle);
8015 get_context_state()->m_current_display_list_mode = GL_NONE;
8016 get_context_state()->m_current_display_list_handle = -1;
8021 case VOGL_ENTRYPOINT_glFeedbackBuffer:
8023 GLsizei size = trace_packet.get_param_value<GLsizei>(0);
8024 GLenum type = trace_packet.get_param_value<GLenum>(1);
8026 if (static_cast<GLsizei>(m_pCur_context_state->m_feedback_buffer.size()) < size)
8027 m_pCur_context_state->m_feedback_buffer.resize(size);
8029 GL_ENTRYPOINT(glFeedbackBuffer)(size, type, m_pCur_context_state->m_feedback_buffer.get_ptr());
8033 case VOGL_ENTRYPOINT_glSeparableFilter2D:
8035 GLenum target = trace_packet.get_param_value<GLenum>(0);
8036 GLenum internalformat = trace_packet.get_param_value<GLenum>(1);
8037 GLsizei width = trace_packet.get_param_value<GLsizei>(2);
8038 GLsizei height = trace_packet.get_param_value<GLsizei>(3);
8039 GLenum format = trace_packet.get_param_value<GLenum>(4);
8040 GLenum type = trace_packet.get_param_value<GLenum>(5);
8042 const GLvoid *row = trace_packet.get_param_client_memory<const GLvoid>(6);
8043 uint row_size = trace_packet.get_param_client_memory_data_size(6);
8044 if (row_size < vogl_get_image_size(format, type, width, 1, 1))
8046 process_entrypoint_error("%s: row trace array is too small\n", VOGL_METHOD_NAME);
8047 return cStatusSoftFailure;
8050 const GLvoid *column = trace_packet.get_param_client_memory<const GLvoid>(7);
8051 uint col_size = trace_packet.get_param_client_memory_data_size(7);
8052 if (col_size < vogl_get_image_size(format, type, width, 1, 1))
8054 process_entrypoint_error("%s: column trace array is too small\n", VOGL_METHOD_NAME);
8055 return cStatusSoftFailure;
8058 GL_ENTRYPOINT(glSeparableFilter2D)(target, internalformat, width, height, format, type, row, column);
8062 case VOGL_ENTRYPOINT_glNamedProgramLocalParameters4fvEXT:
8064 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8065 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8067 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));
8071 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4iEXT:
8073 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8074 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8076 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));
8079 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4ivEXT:
8081 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8082 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8084 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));
8088 case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4ivEXT:
8090 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8091 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8093 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));
8096 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uiEXT:
8098 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8099 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8101 GL_ENTRYPOINT(glNamedProgramLocalParameterI4uiEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2),
8102 trace_packet.get_param_value<GLuint>(3), trace_packet.get_param_value<GLuint>(4),
8103 trace_packet.get_param_value<GLuint>(5), trace_packet.get_param_value<GLuint>(6));
8106 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uivEXT:
8108 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8109 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8111 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));
8114 case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4uivEXT:
8116 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8117 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8119 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));
8122 case VOGL_ENTRYPOINT_glNamedProgramLocalParameter4fvEXT:
8124 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8125 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8127 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));
8130 case VOGL_ENTRYPOINT_glGetTexEnvfv:
8132 if (!benchmark_mode())
8134 GLenum target = trace_packet.get_param_value<GLenum>(0);
8135 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8136 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8138 GLfloat vals[4] = { 0, 0, 0, 0 };
8140 int n = g_gl_enums.get_pname_count(pname);
8141 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8143 GL_ENTRYPOINT(glGetTexEnvfv)(target, pname, vals);
8147 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8149 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8151 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8157 case VOGL_ENTRYPOINT_glGetTexEnviv:
8159 if (!benchmark_mode())
8161 GLenum target = trace_packet.get_param_value<GLenum>(0);
8162 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8163 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8165 GLint vals[4] = { 0, 0, 0, 0 };
8167 int n = g_gl_enums.get_pname_count(pname);
8168 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8170 GL_ENTRYPOINT(glGetTexEnviv)(target, pname, vals);
8174 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8176 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8178 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8184 case VOGL_ENTRYPOINT_glGetTexGendv:
8186 if (!benchmark_mode())
8188 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8189 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8190 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(2);
8192 GLdouble vals[4] = { 0, 0, 0, 0 };
8194 int n = g_gl_enums.get_pname_count(pname);
8195 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8197 GL_ENTRYPOINT(glGetTexGendv)(coord, pname, vals);
8201 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8203 else if (memcmp(pParams, vals, n * sizeof(GLdouble)) != 0)
8205 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8211 case VOGL_ENTRYPOINT_glGetTexGenfv:
8213 if (!benchmark_mode())
8215 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8216 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8217 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8219 GLfloat vals[4] = { 0, 0, 0, 0 };
8221 int n = g_gl_enums.get_pname_count(pname);
8222 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8224 GL_ENTRYPOINT(glGetTexGenfv)(coord, pname, vals);
8228 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8230 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8232 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8238 case VOGL_ENTRYPOINT_glGetTexGeniv:
8240 if (!benchmark_mode())
8242 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8243 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8244 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8246 GLint vals[4] = { 0, 0, 0, 0 };
8248 int n = g_gl_enums.get_pname_count(pname);
8249 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8251 GL_ENTRYPOINT(glGetTexGeniv)(coord, pname, vals);
8255 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8257 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8259 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8265 case VOGL_ENTRYPOINT_glGetLightfv:
8267 if (!benchmark_mode())
8269 GLenum light = trace_packet.get_param_value<GLenum>(0);
8270 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8271 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8273 GLfloat vals[4] = { 0, 0, 0, 0 };
8275 int n = g_gl_enums.get_pname_count(pname);
8276 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8278 GL_ENTRYPOINT(glGetLightfv)(light, pname, vals);
8282 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8284 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8286 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8292 case VOGL_ENTRYPOINT_glGetLightiv:
8294 if (!benchmark_mode())
8296 GLenum light = trace_packet.get_param_value<GLenum>(0);
8297 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8298 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8300 GLint vals[4] = { 0, 0, 0, 0 };
8302 int n = g_gl_enums.get_pname_count(pname);
8303 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8305 GL_ENTRYPOINT(glGetLightiv)(light, pname, vals);
8309 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8311 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8313 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8319 case VOGL_ENTRYPOINT_glSelectBuffer:
8321 GLsizei size = trace_packet.get_param_value<GLsizei>(0);
8323 if (m_pCur_context_state->m_select_buffer.try_resize(size))
8325 GL_ENTRYPOINT(glSelectBuffer)(size, m_pCur_context_state->m_select_buffer.get_ptr());
8329 process_entrypoint_error("%s: Failed resizing context's select buffer\n", VOGL_METHOD_NAME);
8334 case VOGL_ENTRYPOINT_glClearBufferfv:
8336 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferfv;
8338 // TODO: Check params
8340 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferfv;
8344 case VOGL_ENTRYPOINT_glClearBufferiv:
8346 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferiv;
8348 // TODO: Check params
8350 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferiv;
8354 case VOGL_ENTRYPOINT_glClearBufferuiv:
8356 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferuiv;
8358 // TODO: Check params
8360 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferuiv;
8364 case VOGL_ENTRYPOINT_glTexBuffer:
8365 case VOGL_ENTRYPOINT_glTexBufferARB:
8366 case VOGL_ENTRYPOINT_glTexBufferEXT:
8368 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexBuffer;
8370 buffer = map_handle(get_shared_state()->m_buffers, buffer);
8372 SWITCH_GL_ENTRYPOINT3_VOID(glTexBuffer, glTexBufferARB, glTexBufferEXT, target, internalformat, buffer);
8375 case VOGL_ENTRYPOINT_glBeginConditionalRender:
8377 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginConditionalRender;
8379 id = map_handle(get_shared_state()->m_queries, id);
8381 VOGL_REPLAY_CALL_GL_HELPER_glBeginConditionalRender;
8384 case VOGL_ENTRYPOINT_glEndConditionalRender:
8386 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndConditionalRender;
8388 VOGL_REPLAY_CALL_GL_HELPER_glEndConditionalRender;
8391 case VOGL_ENTRYPOINT_glBeginTransformFeedback:
8393 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginTransformFeedback;
8395 VOGL_REPLAY_CALL_GL_HELPER_glBeginTransformFeedback;
8398 case VOGL_ENTRYPOINT_glEndTransformFeedback:
8400 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndTransformFeedback;
8402 VOGL_REPLAY_CALL_GL_HELPER_glEndTransformFeedback;
8406 case VOGL_ENTRYPOINT_glTransformFeedbackVaryings:
8408 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTransformFeedbackVaryings;
8409 VOGL_NOTE_UNUSED(pTrace_varyings);
8411 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8413 dynamic_string_array replay_varyings(count);
8415 const key_value_map &key_value_map = trace_packet.get_key_value_map();
8416 const value_to_value_hash_map &hash_map = key_value_map.get_map();
8418 for (value_to_value_hash_map::const_iterator it = hash_map.begin(); it != hash_map.end(); ++it)
8420 int key_index = it->first.get_int();
8422 if ((key_index >= 0) && (key_index < count))
8424 const dynamic_string *pName = it->second.get_string_ptr();
8427 replay_varyings[key_index] = pName ? *pName : "";
8435 vogl::vector<const GLchar *> str_ptrs(count);
8436 for (int i = 0; i < count; i++)
8437 str_ptrs[i] = reinterpret_cast<const GLchar *>(replay_varyings[i].get_ptr());
8439 GLchar *const *pReplay_varyings = (GLchar *const *)(str_ptrs.get_ptr());
8441 VOGL_REPLAY_CALL_GL_HELPER_glTransformFeedbackVaryings;
8445 case VOGL_ENTRYPOINT_glUniformBufferEXT:
8447 VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBufferEXT;
8449 GLuint trace_program = program;
8451 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8452 location = determine_uniform_replay_location(trace_program, location);
8453 buffer = map_handle(get_shared_state()->m_buffers, buffer);
8455 VOGL_REPLAY_CALL_GL_HELPER_glUniformBufferEXT;
8458 case VOGL_ENTRYPOINT_glUniformBlockBinding:
8460 // TODO: Does any of this other stuff need to be remapped?
8461 VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBlockBinding;
8463 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8465 VOGL_REPLAY_CALL_GL_HELPER_glUniformBlockBinding;
8468 case VOGL_ENTRYPOINT_glFrameTerminatorGREMEDY:
8470 // TODO - we need to hook up this extension to the tracer
8473 case VOGL_ENTRYPOINT_glStringMarkerGREMEDY:
8475 // TODO - we need to hook up this extension to the tracer
8478 case VOGL_ENTRYPOINT_glBitmap:
8480 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBitmap;
8482 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8484 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8485 pTrace_bitmap = (const GLubyte *)ptr_val;
8488 VOGL_REPLAY_CALL_GL_HELPER_glBitmap;
8492 case VOGL_ENTRYPOINT_glColorSubTable:
8494 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTable;
8496 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8498 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8499 pTrace_data = (const GLvoid *)ptr_val;
8502 VOGL_REPLAY_CALL_GL_HELPER_glColorSubTable;
8506 case VOGL_ENTRYPOINT_glColorSubTableEXT:
8508 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTableEXT;
8510 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8512 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8513 pTrace_data = (const GLvoid *)ptr_val;
8516 VOGL_REPLAY_CALL_GL_HELPER_glColorSubTableEXT;
8520 case VOGL_ENTRYPOINT_glColorTable:
8522 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTable;
8524 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8526 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8527 pTrace_table = (const GLvoid *)ptr_val;
8530 VOGL_REPLAY_CALL_GL_HELPER_glColorTable;
8534 case VOGL_ENTRYPOINT_glColorTableEXT:
8536 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTableEXT;
8538 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8540 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8541 pTrace_table = (const GLvoid *)ptr_val;
8544 VOGL_REPLAY_CALL_GL_HELPER_glColorTableEXT;
8548 case VOGL_ENTRYPOINT_glConvolutionFilter1D:
8550 VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter1D;
8552 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8554 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8555 pTrace_image = (const GLvoid *)ptr_val;
8558 VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter1D;
8562 case VOGL_ENTRYPOINT_glConvolutionFilter2D:
8564 VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter2D;
8566 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8568 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8569 pTrace_image = (const GLvoid *)ptr_val;
8572 VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter2D;
8576 case VOGL_ENTRYPOINT_glDrawPixels:
8578 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawPixels;
8580 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8582 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(4);
8583 pTrace_pixels = (const GLvoid *)ptr_val;
8586 VOGL_REPLAY_CALL_GL_HELPER_glDrawPixels;
8590 case VOGL_ENTRYPOINT_glPolygonStipple:
8592 VOGL_REPLAY_LOAD_PARAMS_HELPER_glPolygonStipple;
8594 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8596 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(0);
8597 pTrace_mask = (const GLubyte *)ptr_val;
8600 VOGL_REPLAY_CALL_GL_HELPER_glPolygonStipple;
8604 case VOGL_ENTRYPOINT_glTexImage1D:
8606 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage1D;
8608 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8610 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(7);
8611 pTrace_pixels = (const GLvoid *)ptr_val;
8614 VOGL_REPLAY_CALL_GL_HELPER_glTexImage1D;
8618 case VOGL_ENTRYPOINT_glTexImage2D:
8620 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage2D;
8622 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8624 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8625 pTrace_pixels = (const GLvoid *)ptr_val;
8628 VOGL_REPLAY_CALL_GL_HELPER_glTexImage2D;
8632 case VOGL_ENTRYPOINT_glTexImage3D:
8634 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3D;
8636 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8638 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8639 pTrace_pixels = (const GLvoid *)ptr_val;
8642 VOGL_REPLAY_CALL_GL_HELPER_glTexImage3D;
8646 case VOGL_ENTRYPOINT_glTexImage3DEXT:
8648 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3DEXT;
8650 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8652 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8653 pTrace_pixels = (const GLvoid *)ptr_val;
8656 VOGL_REPLAY_CALL_GL_HELPER_glTexImage3DEXT;
8660 case VOGL_ENTRYPOINT_glTexSubImage1D:
8662 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1D;
8664 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8666 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8667 pTrace_pixels = (const GLvoid *)ptr_val;
8670 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1D;
8674 case VOGL_ENTRYPOINT_glTexSubImage1DEXT:
8676 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1DEXT;
8678 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8680 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8681 pTrace_pixels = (const GLvoid *)ptr_val;
8684 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1DEXT;
8688 case VOGL_ENTRYPOINT_glTexSubImage2D:
8690 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2D;
8692 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8694 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8695 pTrace_pixels = (const GLvoid *)ptr_val;
8698 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2D;
8702 case VOGL_ENTRYPOINT_glTexSubImage2DEXT:
8704 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2DEXT;
8706 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8708 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8709 pTrace_pixels = (const GLvoid *)ptr_val;
8712 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2DEXT;
8716 case VOGL_ENTRYPOINT_glTexSubImage3D:
8718 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3D;
8720 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8722 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8723 pTrace_pixels = (const GLvoid *)ptr_val;
8726 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3D;
8730 case VOGL_ENTRYPOINT_glTexSubImage3DEXT:
8732 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3DEXT;
8734 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8736 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8737 pTrace_pixels = (const GLvoid *)ptr_val;
8740 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3DEXT;
8744 case VOGL_ENTRYPOINT_glDebugMessageInsert:
8746 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDebugMessageInsert;
8748 VOGL_REPLAY_CALL_GL_HELPER_glDebugMessageInsert;
8751 case VOGL_ENTRYPOINT_glDebugMessageInsertARB:
8753 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDebugMessageInsertARB;
8755 VOGL_REPLAY_CALL_GL_HELPER_glDebugMessageInsertARB;
8758 case VOGL_ENTRYPOINT_glDebugMessageCallbackARB:
8760 GL_ENTRYPOINT(glDebugMessageCallbackARB)(debug_callback_arb, (GLvoid *)m_pCur_context_state);
8764 case VOGL_ENTRYPOINT_glDebugMessageCallback:
8766 GL_ENTRYPOINT(glDebugMessageCallback)(debug_callback, (GLvoid *)m_pCur_context_state);
8770 case VOGL_ENTRYPOINT_glObjectLabel:
8772 VOGL_REPLAY_LOAD_PARAMS_HELPER_glObjectLabel;
8778 name = map_handle(get_shared_state()->m_buffers, name);
8784 name = map_handle(get_shared_state()->m_shadow_state.m_objs, name);
8787 case GL_VERTEX_ARRAY:
8789 name = map_handle(get_shared_state()->m_vertex_array_objects, name);
8794 name = map_handle(get_shared_state()->m_queries, name);
8799 name = map_handle(get_shared_state()->m_sampler_objects, name);
8804 name = map_handle(get_shared_state()->m_shadow_state.m_textures, name);
8807 case GL_RENDERBUFFER:
8809 name = map_handle(get_shared_state()->m_shadow_state.m_rbos, name);
8812 case GL_FRAMEBUFFER:
8814 name = map_handle(get_shared_state()->m_framebuffers, name);
8817 case GL_DISPLAY_LIST:
8819 name = map_handle(get_shared_state()->m_lists, name);
8822 case GL_TRANSFORM_FEEDBACK: // TODO: Investigate this more
8823 case GL_PROGRAM_PIPELINE: // TODO: We don't support program pipelines yet
8826 process_entrypoint_error("%s: Unsupported object identifier 0x%X\n", VOGL_METHOD_NAME, identifier);
8827 return cStatusSoftFailure;
8831 VOGL_REPLAY_CALL_GL_HELPER_glObjectLabel;
8835 case VOGL_ENTRYPOINT_glObjectPtrLabel:
8837 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
8838 GLsizei length = trace_packet.get_param_value<GLsizei>(1);
8839 const GLchar *pTrace_label = reinterpret_cast<const GLchar *>(trace_packet.get_param_client_memory_ptr(2));
8840 GLsync replay_sync = NULL;
8844 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
8845 if (it == get_shared_state()->m_syncs.end())
8847 process_entrypoint_error("%s: Failed remapping trace sync value 0x%" PRIx64 "\n", VOGL_METHOD_NAME, static_cast<uint64_t>(trace_sync));
8848 return cStatusSoftFailure;
8852 replay_sync = it->second;
8856 GL_ENTRYPOINT(glObjectPtrLabel)(replay_sync, length, pTrace_label);
8860 case VOGL_ENTRYPOINT_glGetDebugMessageLogARB:
8861 case VOGL_ENTRYPOINT_glGetObjectLabel:
8862 case VOGL_ENTRYPOINT_glGetObjectPtrLabel:
8863 case VOGL_ENTRYPOINT_glGetDebugMessageLog:
8864 case VOGL_ENTRYPOINT_glAreTexturesResident:
8865 case VOGL_ENTRYPOINT_glAreTexturesResidentEXT:
8866 case VOGL_ENTRYPOINT_glGetActiveAtomicCounterBufferiv:
8867 case VOGL_ENTRYPOINT_glGetActiveAttribARB:
8868 case VOGL_ENTRYPOINT_glGetActiveSubroutineName:
8869 case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformName:
8870 case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformiv:
8871 case VOGL_ENTRYPOINT_glGetActiveUniformARB:
8872 case VOGL_ENTRYPOINT_glGetActiveUniformBlockName:
8873 case VOGL_ENTRYPOINT_glGetActiveUniformBlockiv:
8874 case VOGL_ENTRYPOINT_glGetActiveUniformName:
8875 case VOGL_ENTRYPOINT_glGetActiveUniformsiv:
8876 case VOGL_ENTRYPOINT_glGetActiveVaryingNV:
8877 case VOGL_ENTRYPOINT_glGetArrayObjectfvATI:
8878 case VOGL_ENTRYPOINT_glGetArrayObjectivATI:
8879 case VOGL_ENTRYPOINT_glGetAttachedObjectsARB:
8880 case VOGL_ENTRYPOINT_glGetAttribLocationARB:
8881 case VOGL_ENTRYPOINT_glGetBooleanIndexedvEXT:
8882 case VOGL_ENTRYPOINT_glGetBooleani_v:
8883 case VOGL_ENTRYPOINT_glGetBufferParameteri64v:
8884 case VOGL_ENTRYPOINT_glGetBufferParameterivARB:
8885 case VOGL_ENTRYPOINT_glGetBufferParameterui64vNV:
8886 case VOGL_ENTRYPOINT_glGetBufferPointervARB:
8887 case VOGL_ENTRYPOINT_glGetBufferSubDataARB:
8888 case VOGL_ENTRYPOINT_glGetClipPlanefOES:
8889 case VOGL_ENTRYPOINT_glGetClipPlanexOES:
8890 case VOGL_ENTRYPOINT_glGetColorTable:
8891 case VOGL_ENTRYPOINT_glGetColorTableEXT:
8892 case VOGL_ENTRYPOINT_glGetColorTableParameterfv:
8893 case VOGL_ENTRYPOINT_glGetColorTableParameterfvEXT:
8894 case VOGL_ENTRYPOINT_glGetColorTableParameterfvSGI:
8895 case VOGL_ENTRYPOINT_glGetColorTableParameteriv:
8896 case VOGL_ENTRYPOINT_glGetColorTableParameterivEXT:
8897 case VOGL_ENTRYPOINT_glGetColorTableParameterivSGI:
8898 case VOGL_ENTRYPOINT_glGetColorTableSGI:
8899 case VOGL_ENTRYPOINT_glGetCombinerInputParameterfvNV:
8900 case VOGL_ENTRYPOINT_glGetCombinerInputParameterivNV:
8901 case VOGL_ENTRYPOINT_glGetCombinerOutputParameterfvNV:
8902 case VOGL_ENTRYPOINT_glGetCombinerOutputParameterivNV:
8903 case VOGL_ENTRYPOINT_glGetCombinerStageParameterfvNV:
8904 case VOGL_ENTRYPOINT_glGetCompressedMultiTexImageEXT:
8905 case VOGL_ENTRYPOINT_glGetCompressedTexImage:
8906 case VOGL_ENTRYPOINT_glGetCompressedTexImageARB:
8907 case VOGL_ENTRYPOINT_glGetCompressedTextureImageEXT:
8908 case VOGL_ENTRYPOINT_glGetConvolutionFilter:
8909 case VOGL_ENTRYPOINT_glGetConvolutionFilterEXT:
8910 case VOGL_ENTRYPOINT_glGetConvolutionParameterfv:
8911 case VOGL_ENTRYPOINT_glGetConvolutionParameterfvEXT:
8912 case VOGL_ENTRYPOINT_glGetConvolutionParameteriv:
8913 case VOGL_ENTRYPOINT_glGetConvolutionParameterivEXT:
8914 case VOGL_ENTRYPOINT_glGetConvolutionParameterxvOES:
8916 case VOGL_ENTRYPOINT_glGetDebugMessageLogAMD:
8917 case VOGL_ENTRYPOINT_glGetDetailTexFuncSGIS:
8918 case VOGL_ENTRYPOINT_glGetDoubleIndexedvEXT:
8919 case VOGL_ENTRYPOINT_glGetDoublei_v:
8920 case VOGL_ENTRYPOINT_glGetFenceivNV:
8921 case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterfvNV:
8922 case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterivNV:
8923 case VOGL_ENTRYPOINT_glGetFixedvOES:
8924 case VOGL_ENTRYPOINT_glGetFloatIndexedvEXT:
8925 case VOGL_ENTRYPOINT_glGetFloati_v:
8926 case VOGL_ENTRYPOINT_glGetFogFuncSGIS:
8927 case VOGL_ENTRYPOINT_glGetFragDataIndex:
8928 case VOGL_ENTRYPOINT_glGetFragDataLocation:
8929 case VOGL_ENTRYPOINT_glGetFragDataLocationEXT:
8930 case VOGL_ENTRYPOINT_glGetFragmentLightfvSGIX:
8931 case VOGL_ENTRYPOINT_glGetFragmentLightivSGIX:
8932 case VOGL_ENTRYPOINT_glGetFragmentMaterialfvSGIX:
8933 case VOGL_ENTRYPOINT_glGetFragmentMaterialivSGIX:
8934 case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameteriv:
8935 case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameterivEXT:
8936 case VOGL_ENTRYPOINT_glGetFramebufferParameteriv:
8937 case VOGL_ENTRYPOINT_glGetFramebufferParameterivEXT:
8938 case VOGL_ENTRYPOINT_glGetGraphicsResetStatusARB:
8939 case VOGL_ENTRYPOINT_glGetHandleARB:
8940 case VOGL_ENTRYPOINT_glGetHistogram:
8941 case VOGL_ENTRYPOINT_glGetHistogramEXT:
8942 case VOGL_ENTRYPOINT_glGetHistogramParameterfv:
8943 case VOGL_ENTRYPOINT_glGetHistogramParameterfvEXT:
8944 case VOGL_ENTRYPOINT_glGetHistogramParameteriv:
8945 case VOGL_ENTRYPOINT_glGetHistogramParameterivEXT:
8946 case VOGL_ENTRYPOINT_glGetHistogramParameterxvOES:
8947 case VOGL_ENTRYPOINT_glGetImageHandleNV:
8948 case VOGL_ENTRYPOINT_glGetImageTransformParameterfvHP:
8949 case VOGL_ENTRYPOINT_glGetImageTransformParameterivHP:
8950 case VOGL_ENTRYPOINT_glGetInstrumentsSGIX:
8951 case VOGL_ENTRYPOINT_glGetInteger64i_v:
8952 case VOGL_ENTRYPOINT_glGetInteger64v:
8953 case VOGL_ENTRYPOINT_glGetIntegerIndexedvEXT:
8954 case VOGL_ENTRYPOINT_glGetIntegeri_v:
8955 case VOGL_ENTRYPOINT_glGetIntegerui64i_vNV:
8956 case VOGL_ENTRYPOINT_glGetIntegerui64vNV:
8957 case VOGL_ENTRYPOINT_glGetInternalformati64v:
8958 case VOGL_ENTRYPOINT_glGetInternalformativ:
8959 case VOGL_ENTRYPOINT_glGetInvariantBooleanvEXT:
8960 case VOGL_ENTRYPOINT_glGetInvariantFloatvEXT:
8961 case VOGL_ENTRYPOINT_glGetInvariantIntegervEXT:
8962 case VOGL_ENTRYPOINT_glGetLightxOES:
8963 case VOGL_ENTRYPOINT_glGetListParameterfvSGIX:
8964 case VOGL_ENTRYPOINT_glGetListParameterivSGIX:
8965 case VOGL_ENTRYPOINT_glGetLocalConstantBooleanvEXT:
8966 case VOGL_ENTRYPOINT_glGetLocalConstantFloatvEXT:
8967 case VOGL_ENTRYPOINT_glGetLocalConstantIntegervEXT:
8968 case VOGL_ENTRYPOINT_glGetMapAttribParameterfvNV:
8969 case VOGL_ENTRYPOINT_glGetMapAttribParameterivNV:
8970 case VOGL_ENTRYPOINT_glGetMapControlPointsNV:
8971 case VOGL_ENTRYPOINT_glGetMapParameterfvNV:
8972 case VOGL_ENTRYPOINT_glGetMapParameterivNV:
8973 case VOGL_ENTRYPOINT_glGetMapdv:
8974 case VOGL_ENTRYPOINT_glGetMapfv:
8975 case VOGL_ENTRYPOINT_glGetMapiv:
8976 case VOGL_ENTRYPOINT_glGetMapxvOES:
8977 case VOGL_ENTRYPOINT_glGetMaterialfv:
8978 case VOGL_ENTRYPOINT_glGetMaterialiv:
8979 case VOGL_ENTRYPOINT_glGetMaterialxOES:
8980 case VOGL_ENTRYPOINT_glGetMinmax:
8981 case VOGL_ENTRYPOINT_glGetMinmaxEXT:
8982 case VOGL_ENTRYPOINT_glGetMinmaxParameterfv:
8983 case VOGL_ENTRYPOINT_glGetMinmaxParameterfvEXT:
8984 case VOGL_ENTRYPOINT_glGetMinmaxParameteriv:
8985 case VOGL_ENTRYPOINT_glGetMinmaxParameterivEXT:
8986 case VOGL_ENTRYPOINT_glGetMultiTexEnvfvEXT:
8987 case VOGL_ENTRYPOINT_glGetMultiTexEnvivEXT:
8988 case VOGL_ENTRYPOINT_glGetMultiTexGendvEXT:
8989 case VOGL_ENTRYPOINT_glGetMultiTexGenfvEXT:
8990 case VOGL_ENTRYPOINT_glGetMultiTexGenivEXT:
8991 case VOGL_ENTRYPOINT_glGetMultiTexImageEXT:
8992 case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterfvEXT:
8993 case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterivEXT:
8994 case VOGL_ENTRYPOINT_glGetMultiTexParameterIivEXT:
8995 case VOGL_ENTRYPOINT_glGetMultiTexParameterIuivEXT:
8996 case VOGL_ENTRYPOINT_glGetMultiTexParameterfvEXT:
8997 case VOGL_ENTRYPOINT_glGetMultiTexParameterivEXT:
8998 case VOGL_ENTRYPOINT_glGetMultisamplefv:
8999 case VOGL_ENTRYPOINT_glGetMultisamplefvNV:
9000 case VOGL_ENTRYPOINT_glGetNamedBufferParameterivEXT:
9001 case VOGL_ENTRYPOINT_glGetNamedBufferParameterui64vNV:
9002 case VOGL_ENTRYPOINT_glGetNamedBufferPointervEXT:
9003 case VOGL_ENTRYPOINT_glGetNamedBufferSubDataEXT:
9004 case VOGL_ENTRYPOINT_glGetNamedFramebufferAttachmentParameterivEXT:
9005 case VOGL_ENTRYPOINT_glGetNamedFramebufferParameterivEXT:
9006 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIivEXT:
9007 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIuivEXT:
9008 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterdvEXT:
9009 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterfvEXT:
9010 case VOGL_ENTRYPOINT_glGetNamedProgramStringEXT:
9011 case VOGL_ENTRYPOINT_glGetNamedProgramivEXT:
9012 case VOGL_ENTRYPOINT_glGetNamedRenderbufferParameterivEXT:
9013 case VOGL_ENTRYPOINT_glGetNamedStringARB:
9014 case VOGL_ENTRYPOINT_glGetNamedStringivARB:
9015 case VOGL_ENTRYPOINT_glGetObjectBufferfvATI:
9016 case VOGL_ENTRYPOINT_glGetObjectBufferivATI:
9017 case VOGL_ENTRYPOINT_glGetObjectParameterfvARB:
9018 case VOGL_ENTRYPOINT_glGetObjectParameterivAPPLE:
9019 case VOGL_ENTRYPOINT_glGetOcclusionQueryivNV:
9020 case VOGL_ENTRYPOINT_glGetOcclusionQueryuivNV:
9021 case VOGL_ENTRYPOINT_glGetPathColorGenfvNV:
9022 case VOGL_ENTRYPOINT_glGetPathColorGenivNV:
9023 case VOGL_ENTRYPOINT_glGetPathCommandsNV:
9024 case VOGL_ENTRYPOINT_glGetPathCoordsNV:
9025 case VOGL_ENTRYPOINT_glGetPathDashArrayNV:
9026 case VOGL_ENTRYPOINT_glGetPathLengthNV:
9027 case VOGL_ENTRYPOINT_glGetPathMetricRangeNV:
9028 case VOGL_ENTRYPOINT_glGetPathMetricsNV:
9029 case VOGL_ENTRYPOINT_glGetPathParameterfvNV:
9030 case VOGL_ENTRYPOINT_glGetPathParameterivNV:
9031 case VOGL_ENTRYPOINT_glGetPathSpacingNV:
9032 case VOGL_ENTRYPOINT_glGetPathTexGenfvNV:
9033 case VOGL_ENTRYPOINT_glGetPathTexGenivNV:
9034 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterDataAMD:
9035 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterInfoAMD:
9036 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterStringAMD:
9037 case VOGL_ENTRYPOINT_glGetPerfMonitorCountersAMD:
9038 case VOGL_ENTRYPOINT_glGetPerfMonitorGroupStringAMD:
9039 case VOGL_ENTRYPOINT_glGetPerfMonitorGroupsAMD:
9040 case VOGL_ENTRYPOINT_glGetPixelMapfv:
9041 case VOGL_ENTRYPOINT_glGetPixelMapuiv:
9042 case VOGL_ENTRYPOINT_glGetPixelMapusv:
9043 case VOGL_ENTRYPOINT_glGetPixelMapxv:
9044 case VOGL_ENTRYPOINT_glGetPixelTexGenParameterfvSGIS:
9045 case VOGL_ENTRYPOINT_glGetPixelTexGenParameterivSGIS:
9046 case VOGL_ENTRYPOINT_glGetPixelTransformParameterfvEXT:
9047 case VOGL_ENTRYPOINT_glGetPixelTransformParameterivEXT:
9048 case VOGL_ENTRYPOINT_glGetPointerIndexedvEXT:
9049 case VOGL_ENTRYPOINT_glGetPointervEXT:
9050 case VOGL_ENTRYPOINT_glGetPolygonStipple:
9051 case VOGL_ENTRYPOINT_glGetProgramBinary:
9052 case VOGL_ENTRYPOINT_glGetProgramEnvParameterIivNV:
9053 case VOGL_ENTRYPOINT_glGetProgramEnvParameterIuivNV:
9054 case VOGL_ENTRYPOINT_glGetProgramEnvParameterdvARB:
9055 case VOGL_ENTRYPOINT_glGetProgramEnvParameterfvARB:
9056 case VOGL_ENTRYPOINT_glGetProgramInterfaceiv:
9057 case VOGL_ENTRYPOINT_glGetProgramLocalParameterIivNV:
9058 case VOGL_ENTRYPOINT_glGetProgramLocalParameterIuivNV:
9059 case VOGL_ENTRYPOINT_glGetProgramLocalParameterdvARB:
9060 case VOGL_ENTRYPOINT_glGetProgramLocalParameterfvARB:
9061 case VOGL_ENTRYPOINT_glGetProgramNamedParameterdvNV:
9062 case VOGL_ENTRYPOINT_glGetProgramNamedParameterfvNV:
9063 case VOGL_ENTRYPOINT_glGetProgramParameterdvNV:
9064 case VOGL_ENTRYPOINT_glGetProgramParameterfvNV:
9065 case VOGL_ENTRYPOINT_glGetProgramPipelineInfoLog:
9066 case VOGL_ENTRYPOINT_glGetProgramPipelineiv:
9067 case VOGL_ENTRYPOINT_glGetProgramResourceIndex:
9068 case VOGL_ENTRYPOINT_glGetProgramResourceLocation:
9069 case VOGL_ENTRYPOINT_glGetProgramResourceLocationIndex:
9070 case VOGL_ENTRYPOINT_glGetProgramResourceName:
9071 case VOGL_ENTRYPOINT_glGetProgramResourceiv:
9072 case VOGL_ENTRYPOINT_glGetProgramStageiv:
9073 case VOGL_ENTRYPOINT_glGetProgramStringARB:
9074 case VOGL_ENTRYPOINT_glGetProgramStringNV:
9075 case VOGL_ENTRYPOINT_glGetProgramSubroutineParameteruivNV:
9076 case VOGL_ENTRYPOINT_glGetProgramivNV:
9077 case VOGL_ENTRYPOINT_glGetQueryIndexediv:
9078 case VOGL_ENTRYPOINT_glGetQueryObjecti64vEXT:
9079 case VOGL_ENTRYPOINT_glGetQueryObjectui64vEXT:
9080 case VOGL_ENTRYPOINT_glGetQueryiv:
9081 case VOGL_ENTRYPOINT_glGetQueryivARB:
9082 case VOGL_ENTRYPOINT_glGetSamplerParameterIiv:
9083 case VOGL_ENTRYPOINT_glGetSamplerParameterIuiv:
9084 case VOGL_ENTRYPOINT_glGetSamplerParameterfv:
9085 case VOGL_ENTRYPOINT_glGetSamplerParameteriv:
9086 case VOGL_ENTRYPOINT_glGetSeparableFilter:
9087 case VOGL_ENTRYPOINT_glGetSeparableFilterEXT:
9088 case VOGL_ENTRYPOINT_glGetShaderPrecisionFormat:
9089 case VOGL_ENTRYPOINT_glGetShaderSource:
9090 case VOGL_ENTRYPOINT_glGetShaderSourceARB:
9091 case VOGL_ENTRYPOINT_glGetSharpenTexFuncSGIS:
9092 case VOGL_ENTRYPOINT_glGetSubroutineIndex:
9093 case VOGL_ENTRYPOINT_glGetSubroutineUniformLocation:
9094 case VOGL_ENTRYPOINT_glGetSynciv:
9095 case VOGL_ENTRYPOINT_glGetTexBumpParameterfvATI:
9096 case VOGL_ENTRYPOINT_glGetTexBumpParameterivATI:
9097 case VOGL_ENTRYPOINT_glGetTexEnvxvOES:
9098 case VOGL_ENTRYPOINT_glGetTexFilterFuncSGIS:
9099 case VOGL_ENTRYPOINT_glGetTexGenxvOES:
9100 case VOGL_ENTRYPOINT_glGetTexImage:
9101 case VOGL_ENTRYPOINT_glGetTexLevelParameterxvOES:
9102 case VOGL_ENTRYPOINT_glGetTexParameterIivEXT:
9103 case VOGL_ENTRYPOINT_glGetTexParameterIuivEXT:
9104 case VOGL_ENTRYPOINT_glGetTexParameterPointervAPPLE:
9105 case VOGL_ENTRYPOINT_glGetTexParameterxvOES:
9106 case VOGL_ENTRYPOINT_glGetTextureHandleNV:
9107 case VOGL_ENTRYPOINT_glGetTextureImageEXT:
9108 case VOGL_ENTRYPOINT_glGetTextureLevelParameterfvEXT:
9109 case VOGL_ENTRYPOINT_glGetTextureLevelParameterivEXT:
9110 case VOGL_ENTRYPOINT_glGetTextureParameterIivEXT:
9111 case VOGL_ENTRYPOINT_glGetTextureParameterIuivEXT:
9112 case VOGL_ENTRYPOINT_glGetTextureParameterfvEXT:
9113 case VOGL_ENTRYPOINT_glGetTextureParameterivEXT:
9114 case VOGL_ENTRYPOINT_glGetTextureSamplerHandleNV:
9115 case VOGL_ENTRYPOINT_glGetTrackMatrixivNV:
9116 case VOGL_ENTRYPOINT_glGetTransformFeedbackVarying:
9117 case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingEXT:
9118 case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingNV:
9119 case VOGL_ENTRYPOINT_glGetUniformBlockIndex:
9120 case VOGL_ENTRYPOINT_glGetUniformBufferSizeEXT:
9121 case VOGL_ENTRYPOINT_glGetUniformIndices:
9122 case VOGL_ENTRYPOINT_glGetUniformOffsetEXT:
9123 case VOGL_ENTRYPOINT_glGetUniformSubroutineuiv:
9124 case VOGL_ENTRYPOINT_glGetUniformdv:
9125 case VOGL_ENTRYPOINT_glGetUniformfv:
9126 case VOGL_ENTRYPOINT_glGetUniformfvARB:
9127 case VOGL_ENTRYPOINT_glGetUniformi64vNV:
9128 case VOGL_ENTRYPOINT_glGetUniformiv:
9129 case VOGL_ENTRYPOINT_glGetUniformivARB:
9130 case VOGL_ENTRYPOINT_glGetUniformui64vNV:
9131 case VOGL_ENTRYPOINT_glGetUniformuiv:
9132 case VOGL_ENTRYPOINT_glGetUniformuivEXT:
9133 case VOGL_ENTRYPOINT_glGetVariantArrayObjectfvATI:
9134 case VOGL_ENTRYPOINT_glGetVariantArrayObjectivATI:
9135 case VOGL_ENTRYPOINT_glGetVariantBooleanvEXT:
9136 case VOGL_ENTRYPOINT_glGetVariantFloatvEXT:
9137 case VOGL_ENTRYPOINT_glGetVariantIntegervEXT:
9138 case VOGL_ENTRYPOINT_glGetVariantPointervEXT:
9139 case VOGL_ENTRYPOINT_glGetVaryingLocationNV:
9140 case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectfvATI:
9141 case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectivATI:
9142 case VOGL_ENTRYPOINT_glGetVertexAttribLdv:
9143 case VOGL_ENTRYPOINT_glGetVertexAttribLdvEXT:
9144 case VOGL_ENTRYPOINT_glGetVertexAttribLi64vNV:
9145 case VOGL_ENTRYPOINT_glGetVertexAttribLui64vNV:
9146 case VOGL_ENTRYPOINT_glGetVertexAttribPointerv:
9147 case VOGL_ENTRYPOINT_glGetVertexAttribPointervARB:
9148 case VOGL_ENTRYPOINT_glGetVertexAttribPointervNV:
9149 case VOGL_ENTRYPOINT_glGetVertexAttribdvARB:
9150 case VOGL_ENTRYPOINT_glGetVertexAttribdvNV:
9151 case VOGL_ENTRYPOINT_glGetVertexAttribfvARB:
9152 case VOGL_ENTRYPOINT_glGetVertexAttribfvNV:
9153 case VOGL_ENTRYPOINT_glGetVertexAttribivARB:
9154 case VOGL_ENTRYPOINT_glGetVertexAttribivNV:
9155 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamdvNV:
9156 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamfvNV:
9157 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamivNV:
9158 case VOGL_ENTRYPOINT_glGetVideoCaptureivNV:
9159 case VOGL_ENTRYPOINT_glGetVideoi64vNV:
9160 case VOGL_ENTRYPOINT_glGetVideoivNV:
9161 case VOGL_ENTRYPOINT_glGetVideoui64vNV:
9162 case VOGL_ENTRYPOINT_glGetVideouivNV:
9163 case VOGL_ENTRYPOINT_glGetnColorTableARB:
9164 case VOGL_ENTRYPOINT_glGetnCompressedTexImageARB:
9165 case VOGL_ENTRYPOINT_glGetnConvolutionFilterARB:
9166 case VOGL_ENTRYPOINT_glGetnHistogramARB:
9167 case VOGL_ENTRYPOINT_glGetnMapdvARB:
9168 case VOGL_ENTRYPOINT_glGetnMapfvARB:
9169 case VOGL_ENTRYPOINT_glGetnMapivARB:
9170 case VOGL_ENTRYPOINT_glGetnMinmaxARB:
9171 case VOGL_ENTRYPOINT_glGetnPixelMapfvARB:
9172 case VOGL_ENTRYPOINT_glGetnPixelMapuivARB:
9173 case VOGL_ENTRYPOINT_glGetnPixelMapusvARB:
9174 case VOGL_ENTRYPOINT_glGetnPolygonStippleARB:
9175 case VOGL_ENTRYPOINT_glGetnSeparableFilterARB:
9176 case VOGL_ENTRYPOINT_glGetnTexImageARB:
9177 case VOGL_ENTRYPOINT_glGetnUniformdvARB:
9178 case VOGL_ENTRYPOINT_glGetnUniformfvARB:
9179 case VOGL_ENTRYPOINT_glGetnUniformivARB:
9180 case VOGL_ENTRYPOINT_glGetnUniformuivARB:
9181 case VOGL_ENTRYPOINT_glIsBufferARB:
9182 case VOGL_ENTRYPOINT_glIsEnabledIndexedEXT:
9183 case VOGL_ENTRYPOINT_glIsQueryARB:
9184 case VOGL_ENTRYPOINT_glIsSync:
9185 case VOGL_ENTRYPOINT_glPrioritizeTextures:
9186 case VOGL_ENTRYPOINT_glPrioritizeTexturesEXT:
9188 if (!(g_vogl_entrypoint_descs[entrypoint_id].m_flags & cGLEFPrintedUnimplementedWarning))
9190 process_entrypoint_warning("%s: TODO: Implement glGet() function %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[entrypoint_id].m_pName);
9192 g_vogl_entrypoint_descs[entrypoint_id].m_flags |= cGLEFPrintedUnimplementedWarning;
9198 if (g_vogl_entrypoint_descs[entrypoint_id].m_is_whitelisted)
9199 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);
9201 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);
9202 return cStatusSoftFailure;
9206 m_last_processed_call_counter = trace_packet.get_call_counter();
9208 if (!m_pCur_context_state->m_inside_gl_begin)
9210 if (check_gl_error())
9211 return cStatusGLError;
9214 if (vogl_is_draw_entrypoint(entrypoint_id) || vogl_is_clear_entrypoint(entrypoint_id) || (entrypoint_id == VOGL_ENTRYPOINT_glBitmap))
9216 if ((status = post_draw_call()) != cStatusOK)
9223 //----------------------------------------------------------------------------------------------------------------------
9224 // vogl_gl_replayer::snapshot_backbuffer
9225 //----------------------------------------------------------------------------------------------------------------------
9226 void vogl_gl_replayer::snapshot_backbuffer()
9230 if (!m_pCur_context_state)
9232 vogl_warning_printf("%s: Can't take snapshot without an active context\n", VOGL_METHOD_NAME);
9236 uint recorded_width = m_pWindow->get_width();
9237 uint recorded_height = m_pWindow->get_height();
9239 uint width = 0, height = 0;
9240 m_pWindow->get_actual_dimensions(width, height);
9242 VOGL_ASSERT((recorded_width == width) && (recorded_height == height));
9243 VOGL_NOTE_UNUSED(recorded_width);
9244 VOGL_NOTE_UNUSED(recorded_height);
9246 m_screenshot_buffer.resize(width * height * 3);
9248 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);
9251 process_entrypoint_error("%s: Failed calling glReadPixels() to take screenshot\n", VOGL_METHOD_NAME);
9254 if (m_flags & cGLReplayerDumpScreenshots)
9256 size_t png_size = 0;
9257 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
9259 dynamic_string screenshot_filename(cVarArg, "%s_%07u.png", m_screenshot_prefix.get_ptr(), m_total_swaps);
9260 if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
9262 process_entrypoint_error("Failed writing PNG screenshot to file %s\n", screenshot_filename.get_ptr());
9266 vogl_message_printf("Wrote screenshot to file %s\n", screenshot_filename.get_ptr());
9272 if ((m_flags & cGLReplayerDumpBackbufferHashes) || (m_flags & cGLReplayerHashBackbuffer))
9274 uint64_t backbuffer_crc64;
9276 if (m_flags & cGLReplayerSumHashing)
9278 backbuffer_crc64 = calc_sum64(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9282 backbuffer_crc64 = calc_crc64(CRC64_INIT, m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9285 vogl_printf("Frame %u hash: 0x%016" PRIX64 "\n", m_frame_index, backbuffer_crc64);
9287 if (m_backbuffer_hash_filename.has_content())
9289 FILE *pFile = vogl_fopen(m_backbuffer_hash_filename.get_ptr(), "a");
9291 vogl_error_printf("Failed writing to backbuffer hash file %s\n", m_backbuffer_hash_filename.get_ptr());
9294 vogl_fprintf(pFile, "0x%016" PRIX64 "\n", cast_val_to_uint64(backbuffer_crc64));
9301 //----------------------------------------------------------------------------------------------------------------------
9302 // vogl_gl_replayer::is_valid_handle
9303 //----------------------------------------------------------------------------------------------------------------------
9304 bool vogl_gl_replayer::replay_to_trace_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9311 uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9313 switch (handle_namespace)
9315 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9317 VOGL_ASSERT(replay_handle32 == replay_handle);
9318 return (m_replayer.get_context_state()->m_vertex_array_objects.search_table_for_value_get_count(replay_handle32) != 0);
9320 case VOGL_NAMESPACE_FRAMEBUFFERS:
9322 VOGL_ASSERT(replay_handle32 == replay_handle);
9323 return (m_replayer.get_context_state()->m_framebuffers.search_table_for_value_get_count(replay_handle32) != 0);
9325 case VOGL_NAMESPACE_TEXTURES:
9327 VOGL_ASSERT(replay_handle32 == replay_handle);
9328 return (m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle32) != 0);
9330 case VOGL_NAMESPACE_RENDER_BUFFERS:
9332 VOGL_ASSERT(replay_handle32 == replay_handle);
9333 return (m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains_inv(replay_handle32) != 0);
9335 case VOGL_NAMESPACE_QUERIES:
9337 VOGL_ASSERT(replay_handle32 == replay_handle);
9338 return (m_replayer.get_shared_state()->m_queries.search_table_for_value_get_count(replay_handle32) != 0);
9340 case VOGL_NAMESPACE_SAMPLERS:
9342 VOGL_ASSERT(replay_handle32 == replay_handle);
9343 return (m_replayer.get_shared_state()->m_sampler_objects.search_table_for_value_get_count(replay_handle32) != 0);
9345 case VOGL_NAMESPACE_PROGRAMS:
9347 VOGL_ASSERT(replay_handle32 == replay_handle);
9348 return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT;
9350 case VOGL_NAMESPACE_SHADERS:
9352 VOGL_ASSERT(replay_handle32 == replay_handle);
9353 return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT;
9355 case VOGL_NAMESPACE_BUFFERS:
9357 VOGL_ASSERT(replay_handle32 == replay_handle);
9358 return m_replayer.get_shared_state()->m_buffers.search_table_for_value_get_count(replay_handle32);
9360 case VOGL_NAMESPACE_SYNCS:
9362 GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9363 return m_replayer.get_shared_state()->m_syncs.search_table_for_value_get_count(replay_sync) != 0;
9365 case VOGL_NAMESPACE_PROGRAM_ARB:
9367 VOGL_ASSERT(replay_handle32 == replay_handle);
9368 return m_replayer.get_shared_state()->m_arb_programs.search_table_for_value_get_count(replay_handle32) != 0;
9379 //----------------------------------------------------------------------------------------------------------------------
9380 // vogl_gl_replayer::remap_handle
9381 //----------------------------------------------------------------------------------------------------------------------
9382 uint64_t vogl_gl_replayer::replay_to_trace_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9389 uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9391 switch (handle_namespace)
9393 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9395 VOGL_ASSERT(replay_handle32 == replay_handle);
9396 if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_vertex_array_objects, replay_handle32))
9397 return replay_handle32;
9400 case VOGL_NAMESPACE_FRAMEBUFFERS:
9402 VOGL_ASSERT(replay_handle32 == replay_handle);
9403 if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_framebuffers, replay_handle32))
9404 return replay_handle32;
9407 case VOGL_NAMESPACE_TEXTURES:
9409 VOGL_ASSERT(replay_handle32 == replay_handle);
9411 uint32 trace_handle = replay_handle32;
9412 if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle32, trace_handle))
9413 return trace_handle;
9417 case VOGL_NAMESPACE_RENDER_BUFFERS:
9419 VOGL_ASSERT(replay_handle32 == replay_handle);
9420 GLuint trace_handle = replay_handle32;
9421 if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_handle32, trace_handle))
9422 return trace_handle;
9426 case VOGL_NAMESPACE_QUERIES:
9428 VOGL_ASSERT(replay_handle32 == replay_handle);
9429 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_queries, replay_handle32))
9430 return replay_handle32;
9433 case VOGL_NAMESPACE_SAMPLERS:
9435 VOGL_ASSERT(replay_handle32 == replay_handle);
9436 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_sampler_objects, replay_handle32))
9437 return replay_handle32;
9440 case VOGL_NAMESPACE_PROGRAMS:
9442 VOGL_ASSERT(replay_handle32 == replay_handle);
9443 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT);
9444 GLuint trace_handle = replay_handle32;
9445 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9446 return trace_handle;
9449 case VOGL_NAMESPACE_SHADERS:
9451 VOGL_ASSERT(replay_handle32 == replay_handle);
9452 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT);
9453 GLuint trace_handle = replay_handle32;
9454 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9455 return trace_handle;
9458 case VOGL_NAMESPACE_BUFFERS:
9460 VOGL_ASSERT(replay_handle32 == replay_handle);
9461 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_buffers, replay_handle32))
9462 return replay_handle32;
9465 case VOGL_NAMESPACE_SYNCS:
9467 GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9469 gl_sync_hash_map::const_iterator it(m_replayer.get_shared_state()->m_syncs.search_table_for_value(replay_sync));
9470 if (it != m_replayer.get_shared_state()->m_syncs.end())
9472 VOGL_ASSERT(it->second == replay_sync);
9478 case VOGL_NAMESPACE_PROGRAM_ARB:
9480 VOGL_ASSERT(replay_handle32 == replay_handle);
9481 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_arb_programs, replay_handle32))
9482 return replay_handle32;
9492 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));
9496 return replay_handle;
9499 //----------------------------------------------------------------------------------------------------------------------
9500 // vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location
9501 //----------------------------------------------------------------------------------------------------------------------
9502 int32 vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location(uint32 replay_program, int32 replay_location)
9506 if ((!replay_program) || (replay_location < 0))
9507 return replay_location;
9509 GLuint trace_program = static_cast<GLuint>(remap_handle(VOGL_NAMESPACE_PROGRAMS, replay_program));
9511 glsl_program_hash_map::const_iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.find(trace_program));
9512 if (it != m_replayer.get_shared_state()->m_glsl_program_hash_map.end())
9514 const glsl_program_state &state = it->second;
9516 uniform_location_hash_map::const_iterator loc_it(state.m_uniform_locations.search_table_for_value(replay_location));
9517 if (loc_it != state.m_uniform_locations.end())
9518 return loc_it->first;
9521 vogl_warning_printf("%s: Failed remapping location %i of program %u\n", VOGL_METHOD_NAME, replay_location, replay_program);
9523 return replay_location;
9526 //----------------------------------------------------------------------------------------------------------------------
9527 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target
9528 //----------------------------------------------------------------------------------------------------------------------
9529 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
9535 uint32 handle32 = static_cast<uint32>(replay_handle);
9537 switch (handle_namespace)
9539 case VOGL_NAMESPACE_TEXTURES:
9541 VOGL_ASSERT(handle32 == replay_handle);
9542 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
9545 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
9556 //----------------------------------------------------------------------------------------------------------------------
9557 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target
9558 //----------------------------------------------------------------------------------------------------------------------
9559 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
9565 uint32 handle32 = static_cast<uint32>(trace_handle);
9567 switch (handle_namespace)
9569 case VOGL_NAMESPACE_TEXTURES:
9571 VOGL_ASSERT(handle32 == trace_handle);
9572 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
9575 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
9586 //----------------------------------------------------------------------------------------------------------------------
9587 // vogl_replayer::determine_used_program_handles
9588 //----------------------------------------------------------------------------------------------------------------------
9589 bool vogl_gl_replayer::determine_used_program_handles(const vogl_trace_packet_array &trim_packets, vogl_handle_hash_set &replay_program_handles)
9593 trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
9596 GLint cur_program_handle = 0;
9597 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &cur_program_handle);
9600 if (cur_program_handle)
9601 replay_program_handles.insert(cur_program_handle);
9604 // Scan for bound programs on all contexts in this sharegroup
9605 context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
9606 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
9608 context_state *pContext = it->second;
9609 if (pContext->m_pShared_state == pContext_shareroot)
9611 if (pContext->m_cur_replay_program)
9612 replay_program_handles.insert(pContext->m_cur_replay_program);
9616 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
9618 if (trim_packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
9621 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
9623 // 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.
9624 if (!m_temp2_gl_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
9627 GLuint trace_handle = 0;
9628 bool refers_to_program = vogl_does_packet_refer_to_program(m_temp2_gl_packet, trace_handle);
9629 if (!refers_to_program)
9634 // 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
9635 // 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).
9636 if (!trace_to_replay_remapper.is_valid_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle))
9639 uint64_t replay_handle = trace_to_replay_remapper.remap_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle);
9643 VOGL_ASSERT(utils::is_32bit(replay_handle));
9645 replay_program_handles.insert(static_cast<uint32>(replay_handle));
9648 vogl_message_printf("%s: Found %u actually referenced program handles\n", VOGL_METHOD_NAME, replay_program_handles.size());
9653 //----------------------------------------------------------------------------------------------------------------------
9654 // vogl_replayer::fill_replay_handle_hash_set
9655 //----------------------------------------------------------------------------------------------------------------------
9656 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)
9660 replay_handle_hash.reset();
9661 replay_handle_hash.reserve(trace_to_replay_hash.size());
9662 for (gl_handle_hash_map::const_iterator it = trace_to_replay_hash.begin(); it != trace_to_replay_hash.end(); ++it)
9664 // Insert replay handles into destination hash table
9665 bool success = replay_handle_hash.insert(it->second).second;
9666 VOGL_ASSERT(success);
9667 VOGL_NOTE_UNUSED(success);
9671 //----------------------------------------------------------------------------------------------------------------------
9672 // vogl_replayer::snapshot_state
9673 //----------------------------------------------------------------------------------------------------------------------
9674 vogl_gl_state_snapshot *vogl_gl_replayer::snapshot_state(const vogl_trace_packet_array *pTrim_packets, bool optimize_snapshot)
9678 timed_scope ts(VOGL_METHOD_NAME);
9680 vogl_gl_state_snapshot *pSnapshot = vogl_new(vogl_gl_state_snapshot);
9682 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,
9683 m_pWindow->get_width(), m_pWindow->get_height(), m_cur_trace_context, m_frame_index, m_last_parsed_call_counter, m_at_frame_boundary);
9685 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))
9687 vogl_error_printf("%s: Failed beginning capture\n", VOGL_METHOD_NAME);
9689 vogl_delete(pSnapshot);
9695 vogl_client_side_array_desc_vec client_side_vertex_attrib_ptrs;
9696 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_vertex_attrib_data); i++)
9697 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()));
9699 vogl_client_side_array_desc_vec client_side_array_ptrs;
9700 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_array_data); i++)
9701 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()));
9703 vogl_client_side_array_desc_vec client_side_texcoord_ptrs;
9704 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_texcoord_data); i++)
9705 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()));
9707 pSnapshot->add_client_side_array_ptrs(client_side_vertex_attrib_ptrs, client_side_array_ptrs, client_side_texcoord_ptrs);
9709 vogl_printf("%s: Capturing %u context(s)\n", VOGL_METHOD_NAME, m_contexts.size());
9711 context_hash_map::iterator it;
9712 for (it = m_contexts.begin(); it != m_contexts.end(); ++it)
9714 context_state *pContext_state = it->second;
9716 if (pContext_state->m_deleted)
9718 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));
9722 vogl_capture_context_params temp_shadow_state;
9723 vogl_capture_context_params *pShadow_state = &temp_shadow_state;
9725 if (pContext_state->m_has_been_made_current)
9727 status_t status = switch_contexts(it->first);
9728 if (status != cStatusOK)
9730 vogl_error_printf("%s: Failed switching to trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first));
9734 VOGL_ASSERT(m_pCur_context_state == pContext_state);
9736 if (m_pCur_context_state->m_inside_gl_begin)
9738 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));
9739 pSnapshot->set_is_restorable(false);
9743 // Init the shadow state needed by the snapshot code.
9744 if (!m_pCur_context_state->is_root_context())
9746 // Only fill in non-shared state.
9747 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9748 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9752 pShadow_state = &m_pCur_context_state->m_shadow_state;
9754 pShadow_state->m_query_targets = get_shared_state()->m_query_targets;
9756 fill_replay_handle_hash_set(pShadow_state->m_samplers, get_shared_state()->m_sampler_objects);
9757 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9758 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9761 pShadow_state->m_buffer_targets.reset();
9762 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)
9764 GLuint trace_handle = buf_it->first;
9765 GLuint replay_handle = buf_it->second;
9767 gl_handle_hash_map::const_iterator target_it = get_shared_state()->m_buffer_targets.find(trace_handle);
9768 if (target_it == get_shared_state()->m_buffer_targets.end())
9770 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);
9773 GLenum target = target_it->second;
9775 pShadow_state->m_buffer_targets.insert(replay_handle, target);
9779 pShadow_state->m_syncs.reset();
9780 pShadow_state->m_syncs.reserve(get_shared_state()->m_syncs.size());
9781 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)
9783 bool success = pShadow_state->m_syncs.insert(vogl_sync_to_handle(sync_it->second)).second;
9784 VOGL_ASSERT(success);
9785 VOGL_NOTE_UNUSED(success);
9788 // Program handles filter
9789 pShadow_state->m_filter_program_handles = false;
9790 pShadow_state->m_program_handles_filter.reset();
9793 // 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).
9794 // This is an optimization issue, and we're concentrating on correctness right now so let's figure this out later.
9795 if ((pTrim_packets) && (optimize_snapshot))
9797 if (!determine_used_program_handles(*pTrim_packets, pShadow_state->m_program_handles_filter))
9799 vogl_warning_printf("%s: Failed determining used program handles\n", VOGL_METHOD_NAME);
9800 pShadow_state->m_program_handles_filter.clear();
9804 pShadow_state->m_filter_program_handles = true;
9808 VOGL_NOTE_UNUSED(optimize_snapshot);
9809 VOGL_NOTE_UNUSED(pTrim_packets);
9812 // ARB program targets
9813 pShadow_state->m_arb_program_targets.reset();
9814 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)
9816 GLuint trace_handle = arb_prog_it->first;
9817 GLuint replay_handle = get_shared_state()->m_arb_programs.value(trace_handle);
9818 if ((!trace_handle) || (!replay_handle))
9824 GLenum target = arb_prog_it->second;
9825 pShadow_state->m_arb_program_targets.insert(replay_handle, target);
9828 // Deal with any currently mapped buffers.
9829 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9831 pShadow_state->m_mapped_buffers = mapped_bufs;
9833 if (mapped_bufs.size())
9835 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());
9837 for (uint i = 0; i < mapped_bufs.size(); i++)
9839 vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9841 GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9843 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9844 VOGL_CHECK_GL_ERROR;
9846 GL_ENTRYPOINT(glUnmapBuffer)(desc.m_target);
9847 VOGL_CHECK_GL_ERROR;
9851 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9852 VOGL_CHECK_GL_ERROR;
9856 } // if (!m_pCur_context_state->is_root_context())
9858 } // if (pContext_state->m_has_been_made_current)
9860 if (!pSnapshot->capture_context(pContext_state->m_context_desc, pContext_state->m_context_info, m_replay_to_trace_remapper, *pShadow_state))
9862 vogl_error_printf("%s: Failed capturing trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, static_cast<uint64_t>(it->first));
9866 if ((pContext_state->m_has_been_made_current) && (m_pCur_context_state->is_root_context()))
9868 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9870 // Now remap any mapped buffers
9871 for (uint i = 0; i < mapped_bufs.size(); i++)
9873 vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9875 GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9877 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9878 VOGL_CHECK_GL_ERROR;
9882 desc.m_pPtr = GL_ENTRYPOINT(glMapBufferRange)(desc.m_target, static_cast<GLintptr>(desc.m_offset), static_cast<GLsizeiptr>(desc.m_length), desc.m_access);
9883 VOGL_CHECK_GL_ERROR;
9887 desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(desc.m_target, desc.m_access);
9888 VOGL_CHECK_GL_ERROR;
9891 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9892 VOGL_CHECK_GL_ERROR;
9898 if ((it == m_contexts.end()) && (pSnapshot->end_capture()))
9900 vogl_printf("%s: Capture succeeded\n", VOGL_METHOD_NAME);
9904 vogl_printf("%s: Capture failed\n", VOGL_METHOD_NAME);
9906 vogl_delete(pSnapshot);
9913 //----------------------------------------------------------------------------------------------------------------------
9914 // vogl_replayer::reset_state
9915 //----------------------------------------------------------------------------------------------------------------------
9916 void vogl_gl_replayer::reset_state()
9920 // Purposely does NOT destroy the cached snapshots
9922 destroy_pending_snapshot();
9925 m_pending_make_current_packet.clear();
9926 m_pending_window_resize_width = 0;
9927 m_pending_window_resize_height = 0;
9928 m_pending_window_resize_attempt_counter = 0;
9931 m_last_parsed_call_counter = -1;
9932 m_last_processed_call_counter = -1;
9933 m_at_frame_boundary = true;
9935 m_cur_trace_context = 0;
9936 m_cur_replay_context = 0;
9937 m_pCur_context_state = NULL;
9940 //if (m_pWindow->is_opened())
9941 // m_pWindow->clear_window();
9944 //----------------------------------------------------------------------------------------------------------------------
9945 // trace_to_replay_handle_remapper::is_valid_handle
9946 //----------------------------------------------------------------------------------------------------------------------
9947 bool vogl_gl_replayer::trace_to_replay_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9954 uint32 from_handle32 = static_cast<uint32>(from_handle);
9956 switch (handle_namespace)
9958 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9960 VOGL_ASSERT(from_handle32 == from_handle);
9961 return m_replayer.get_context_state()->m_vertex_array_objects.contains(from_handle32);
9963 case VOGL_NAMESPACE_TEXTURES:
9965 VOGL_ASSERT(from_handle32 == from_handle);
9966 return m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(from_handle32);
9968 case VOGL_NAMESPACE_SAMPLERS:
9970 VOGL_ASSERT(from_handle32 == from_handle);
9971 return m_replayer.get_shared_state()->m_sampler_objects.contains(from_handle32);
9973 case VOGL_NAMESPACE_BUFFERS:
9975 VOGL_ASSERT(from_handle32 == from_handle);
9976 return m_replayer.get_shared_state()->m_buffers.contains(from_handle32);
9978 case VOGL_NAMESPACE_SHADERS:
9979 case VOGL_NAMESPACE_PROGRAMS:
9981 VOGL_ASSERT(from_handle32 == from_handle);
9982 return m_replayer.get_shared_state()->m_shadow_state.m_objs.contains(from_handle32);
9984 case VOGL_NAMESPACE_FRAMEBUFFERS:
9986 VOGL_ASSERT(from_handle32 == from_handle);
9987 return m_replayer.get_context_state()->m_framebuffers.contains(from_handle32);
9989 case VOGL_NAMESPACE_RENDER_BUFFERS:
9991 VOGL_ASSERT(from_handle32 == from_handle);
9992 return m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains(from_handle32);
9994 case VOGL_NAMESPACE_QUERIES:
9996 VOGL_ASSERT(from_handle32 == from_handle);
9997 return m_replayer.get_shared_state()->m_queries.contains(from_handle32);
9999 case VOGL_NAMESPACE_SYNCS:
10001 return m_replayer.get_shared_state()->m_syncs.contains(from_handle);
10003 case VOGL_NAMESPACE_PROGRAM_ARB:
10005 return m_replayer.get_shared_state()->m_arb_programs.contains(from_handle32);
10016 //----------------------------------------------------------------------------------------------------------------------
10017 // trace_to_replay_handle_remapper::remap_handle
10018 //----------------------------------------------------------------------------------------------------------------------
10019 uint64_t vogl_gl_replayer::trace_to_replay_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
10024 return from_handle;
10026 uint32 from_handle32 = static_cast<uint32>(from_handle);
10028 switch (handle_namespace)
10030 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10032 VOGL_ASSERT(from_handle32 == from_handle);
10033 return m_replayer.get_context_state()->m_vertex_array_objects.value(from_handle32, from_handle32);
10035 case VOGL_NAMESPACE_TEXTURES:
10037 VOGL_ASSERT(from_handle32 == from_handle);
10039 uint32 replay_handle = from_handle32;
10040 if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(from_handle32, replay_handle))
10041 return replay_handle;
10044 case VOGL_NAMESPACE_SAMPLERS:
10046 VOGL_ASSERT(from_handle32 == from_handle);
10047 return m_replayer.get_shared_state()->m_sampler_objects.value(from_handle32, from_handle32);
10049 case VOGL_NAMESPACE_BUFFERS:
10051 VOGL_ASSERT(from_handle32 == from_handle);
10052 return m_replayer.get_shared_state()->m_buffers.value(from_handle32, from_handle32);
10054 case VOGL_NAMESPACE_SHADERS:
10055 case VOGL_NAMESPACE_PROGRAMS:
10057 VOGL_ASSERT(from_handle32 == from_handle);
10059 GLuint replay_handle = from_handle32;
10060 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_handle32, replay_handle))
10061 return replay_handle;
10064 case VOGL_NAMESPACE_FRAMEBUFFERS:
10066 VOGL_ASSERT(from_handle32 == from_handle);
10067 return m_replayer.get_context_state()->m_framebuffers.value(from_handle32, from_handle32);
10069 case VOGL_NAMESPACE_RENDER_BUFFERS:
10071 VOGL_ASSERT(from_handle32 == from_handle);
10073 GLuint replay_handle = from_handle32;
10074 if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_handle_to_inv_handle(from_handle32, replay_handle))
10075 return replay_handle;
10079 case VOGL_NAMESPACE_QUERIES:
10081 VOGL_ASSERT(from_handle32 == from_handle);
10082 return m_replayer.get_shared_state()->m_queries.value(from_handle32, from_handle32);
10084 case VOGL_NAMESPACE_SYNCS:
10086 return vogl_sync_to_handle(m_replayer.get_shared_state()->m_syncs.value(from_handle, vogl_handle_to_sync(from_handle)));
10088 case VOGL_NAMESPACE_PROGRAM_ARB:
10090 return m_replayer.get_shared_state()->m_arb_programs.value(from_handle32, from_handle32);
10098 VOGL_ASSERT_ALWAYS;
10100 vogl_error_printf("%s: Failed remapping handle %" PRIu64 " in namespace %s.\n", VOGL_METHOD_NAME, from_handle, vogl_get_namespace_name(handle_namespace));
10102 return from_handle;
10105 //----------------------------------------------------------------------------------------------------------------------
10106 // trace_to_replay_handle_remapper::remap_location
10107 //----------------------------------------------------------------------------------------------------------------------
10108 int32 vogl_gl_replayer::trace_to_replay_handle_remapper::remap_location(uint32 trace_program, int32 from_location)
10112 VOGL_NOTE_UNUSED(trace_program);
10114 // restoring declares, but doesn't need to remap
10115 VOGL_ASSERT_ALWAYS;
10117 return from_location;
10120 //----------------------------------------------------------------------------------------------------------------------
10121 // trace_to_replay_handle_remapper::remap_vertex_attrib_ptr
10122 //----------------------------------------------------------------------------------------------------------------------
10123 vogl_trace_ptr_value vogl_gl_replayer::trace_to_replay_handle_remapper::remap_vertex_attrib_ptr(uint index, vogl_trace_ptr_value ptr_val)
10130 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_vertex_attrib_data));
10131 if (!m_replayer.m_client_side_vertex_attrib_data[index].size())
10133 m_replayer.m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10136 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_vertex_attrib_data[index].get_ptr());
10139 //----------------------------------------------------------------------------------------------------------------------
10140 // trace_to_replay_handle_remapper::remap_vertex_array_ptr
10141 //----------------------------------------------------------------------------------------------------------------------
10142 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)
10146 VOGL_ASSERT(id < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS);
10151 if (id == vogl_texcoord_pointer_array_id)
10153 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_texcoord_data));
10155 if (!m_replayer.m_client_side_texcoord_data[index].size())
10157 m_replayer.m_client_side_texcoord_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10160 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_texcoord_data[index].get_ptr());
10164 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_array_data));
10166 if (!m_replayer.m_client_side_array_data[id].size())
10168 m_replayer.m_client_side_array_data[id].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10171 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_array_data[id].get_ptr());
10175 //----------------------------------------------------------------------------------------------------------------------
10176 // trace_to_replay_handle_remapper::declare_handle
10177 //----------------------------------------------------------------------------------------------------------------------
10178 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)
10182 if ((!from_handle) || (!to_handle))
10184 VOGL_ASSERT_ALWAYS;
10188 uint32 from_handle32 = static_cast<uint32>(from_handle);
10189 uint32 to_handle32 = static_cast<uint32>(to_handle);
10191 switch (handle_namespace)
10193 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10195 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10196 m_replayer.get_context_state()->m_vertex_array_objects.insert(from_handle32, to_handle32);
10199 case VOGL_NAMESPACE_TEXTURES:
10201 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10202 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.update(from_handle32, to_handle32, target))
10203 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);
10206 case VOGL_NAMESPACE_SAMPLERS:
10208 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10209 m_replayer.get_shared_state()->m_sampler_objects.insert(from_handle32, to_handle32);
10212 case VOGL_NAMESPACE_BUFFERS:
10214 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10215 m_replayer.get_shared_state()->m_buffers.insert(from_handle32, to_handle32);
10216 m_replayer.get_shared_state()->m_buffer_targets.insert(from_handle32, target);
10219 case VOGL_NAMESPACE_SHADERS:
10221 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10222 if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_SHADER_OBJECT))
10223 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);
10226 case VOGL_NAMESPACE_PROGRAMS:
10228 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10229 if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_PROGRAM_OBJECT))
10230 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);
10233 case VOGL_NAMESPACE_FRAMEBUFFERS:
10235 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10236 m_replayer.get_context_state()->m_framebuffers.insert(from_handle32, to_handle32);
10239 case VOGL_NAMESPACE_RENDER_BUFFERS:
10241 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10242 if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.insert(from_handle32, to_handle32, GL_NONE))
10243 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);
10246 case VOGL_NAMESPACE_QUERIES:
10248 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10249 m_replayer.get_shared_state()->m_queries.insert(from_handle32, to_handle32);
10250 m_replayer.get_shared_state()->m_query_targets[to_handle32] = target;
10253 case VOGL_NAMESPACE_SYNCS:
10255 m_replayer.get_shared_state()->m_syncs.insert(from_handle, vogl_handle_to_sync(to_handle));
10258 case VOGL_NAMESPACE_PROGRAM_ARB:
10260 m_replayer.get_shared_state()->m_arb_programs.insert(from_handle32, to_handle32);
10261 m_replayer.get_shared_state()->m_arb_program_targets.insert(from_handle32, target);
10272 //----------------------------------------------------------------------------------------------------------------------
10273 // trace_to_replay_handle_remapper::delete_handle_and_object
10274 //----------------------------------------------------------------------------------------------------------------------
10275 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)
10279 if ((!from_handle) || (!to_handle))
10281 VOGL_ASSERT_ALWAYS;
10285 uint32 from_handle32 = static_cast<uint32>(from_handle);
10286 uint32 to_handle32 = static_cast<uint32>(to_handle);
10287 VOGL_NOTE_UNUSED(to_handle32);
10289 switch (handle_namespace)
10291 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10293 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10294 m_replayer.get_context_state()->m_vertex_array_objects.erase(from_handle32);
10295 vogl_destroy_gl_object(handle_namespace, to_handle);
10298 case VOGL_NAMESPACE_TEXTURES:
10300 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10301 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.erase(from_handle32))
10302 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);
10304 vogl_destroy_gl_object(handle_namespace, to_handle);
10307 case VOGL_NAMESPACE_SAMPLERS:
10309 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10310 m_replayer.get_shared_state()->m_sampler_objects.erase(from_handle32);
10311 vogl_destroy_gl_object(handle_namespace, to_handle);
10314 case VOGL_NAMESPACE_BUFFERS:
10316 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10317 m_replayer.get_shared_state()->m_buffers.erase(from_handle32);
10318 m_replayer.get_shared_state()->m_buffer_targets.erase(from_handle32);
10319 vogl_destroy_gl_object(handle_namespace, to_handle);
10322 case VOGL_NAMESPACE_SHADERS:
10324 m_replayer.handle_delete_shader(from_handle32);
10327 case VOGL_NAMESPACE_PROGRAMS:
10329 m_replayer.handle_delete_program(from_handle32);
10332 case VOGL_NAMESPACE_FRAMEBUFFERS:
10334 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10335 m_replayer.get_context_state()->m_framebuffers.erase(from_handle32);
10336 vogl_destroy_gl_object(handle_namespace, to_handle);
10339 case VOGL_NAMESPACE_RENDER_BUFFERS:
10341 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10343 if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.erase(from_handle32))
10344 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);
10346 vogl_destroy_gl_object(handle_namespace, to_handle);
10349 case VOGL_NAMESPACE_QUERIES:
10351 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10352 m_replayer.get_shared_state()->m_queries.erase(from_handle32);
10353 vogl_destroy_gl_object(handle_namespace, to_handle);
10356 case VOGL_NAMESPACE_SYNCS:
10358 m_replayer.get_shared_state()->m_syncs.erase(from_handle);
10359 vogl_destroy_gl_object(handle_namespace, to_handle);
10362 case VOGL_NAMESPACE_PROGRAM_ARB:
10364 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10365 m_replayer.get_shared_state()->m_arb_programs.erase(from_handle32);
10366 m_replayer.get_shared_state()->m_arb_program_targets.erase(from_handle32);
10367 vogl_destroy_gl_object(handle_namespace, to_handle);
10378 //----------------------------------------------------------------------------------------------------------------------
10379 // vogl_replayer::trace_to_replay_handle_remapper::declare_location
10380 //----------------------------------------------------------------------------------------------------------------------
10381 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)
10385 GLuint check_replay_handle = 0;
10386 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_program_handle, check_replay_handle));
10387 VOGL_ASSERT(check_replay_handle == to_program_handle);
10388 VOGL_NOTE_UNUSED(check_replay_handle);
10390 VOGL_NOTE_UNUSED(to_program_handle);
10392 glsl_program_hash_map::iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.insert(from_program_handle).first);
10394 glsl_program_state &prog_state = it->second;
10396 VOGL_ASSERT(!prog_state.m_uniform_locations.contains(from_location));
10398 prog_state.m_uniform_locations.insert(from_location, to_location);
10401 //----------------------------------------------------------------------------------------------------------------------
10402 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target
10403 //----------------------------------------------------------------------------------------------------------------------
10404 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
10410 uint32 handle32 = static_cast<uint32>(trace_handle);
10412 switch (handle_namespace)
10414 case VOGL_NAMESPACE_TEXTURES:
10416 VOGL_ASSERT(handle32 == trace_handle);
10417 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
10420 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
10431 //----------------------------------------------------------------------------------------------------------------------
10432 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target
10433 //----------------------------------------------------------------------------------------------------------------------
10434 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
10440 uint32 handle32 = static_cast<uint32>(replay_handle);
10442 switch (handle_namespace)
10444 case VOGL_NAMESPACE_TEXTURES:
10446 VOGL_ASSERT(handle32 == replay_handle);
10447 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
10450 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
10461 //----------------------------------------------------------------------------------------------------------------------
10462 // vogl_replayer::restore_objects
10463 //----------------------------------------------------------------------------------------------------------------------
10464 vogl_gl_replayer::status_t vogl_gl_replayer::restore_objects(
10465 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,
10466 vogl_const_gl_object_state_ptr_vec &objects_to_delete)
10470 VOGL_NOTE_UNUSED(snapshot);
10472 if (m_flags & cGLReplayerVerboseMode)
10473 vogl_printf("%s: Restoring %s objects\n", VOGL_METHOD_NAME, get_gl_object_state_type_str(state_type));
10476 if (m_flags & cGLReplayerVerboseMode)
10479 const vogl_gl_object_state_ptr_vec &object_ptrs = context_state.get_objects();
10483 for (uint i = 0; i < object_ptrs.size(); i++)
10485 const vogl_gl_object_state *pState_obj = object_ptrs[i];
10487 if (pState_obj->get_type() != state_type)
10490 GLuint64 restore_handle = 0;
10491 if (!pState_obj->restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, restore_handle))
10493 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);
10494 return cStatusHardFailure;
10498 if (pState_obj->get_marked_for_deletion())
10500 objects_to_delete.push_back(pState_obj);
10503 VOGL_ASSERT(trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle()) == restore_handle);
10505 switch (pState_obj->get_type())
10509 const vogl_query_state *pQuery = static_cast<const vogl_query_state *>(pState_obj);
10511 VOGL_ASSERT(restore_handle <= cUINT32_MAX);
10512 get_shared_state()->m_query_targets[static_cast<GLuint>(restore_handle)] = pQuery->get_target();
10518 const vogl_program_state *pProg = static_cast<const vogl_program_state *>(pState_obj);
10520 if (pProg->has_link_time_snapshot())
10522 vogl_program_state link_snapshot(*pProg->get_link_time_snapshot());
10523 if (!link_snapshot.remap_handles(trace_to_replay_remapper))
10525 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);
10529 get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(static_cast<uint32>(restore_handle), link_snapshot);
10533 if (m_flags & cGLReplayerVerboseMode)
10535 if ((n & 255) == 255)
10536 vogl_printf("%s: Restored %u programs\n", VOGL_METHOD_NAME, n);
10543 const vogl_buffer_state *pBuf = static_cast<const vogl_buffer_state *>(pState_obj);
10545 // Check if the buffer was mapped during the snapshot, if so remap it and record the ptr in the replayer's context shadow.
10546 if (pBuf->get_is_mapped())
10548 vogl_mapped_buffer_desc map_desc;
10549 map_desc.m_buffer = static_cast<GLuint>(restore_handle);
10550 map_desc.m_target = pBuf->get_target();
10551 map_desc.m_offset = pBuf->get_map_ofs();
10552 map_desc.m_length = pBuf->get_map_size();
10553 map_desc.m_access = pBuf->get_map_access();
10554 map_desc.m_range = pBuf->get_is_map_range();
10556 GLuint prev_handle = vogl_get_bound_gl_buffer(map_desc.m_target);
10558 GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, map_desc.m_buffer);
10559 VOGL_CHECK_GL_ERROR;
10561 if (map_desc.m_range)
10563 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);
10564 VOGL_CHECK_GL_ERROR;
10568 map_desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(map_desc.m_target, map_desc.m_access);
10569 VOGL_CHECK_GL_ERROR;
10572 GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, prev_handle);
10573 VOGL_CHECK_GL_ERROR;
10575 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
10576 mapped_bufs.push_back(map_desc);
10586 if (m_flags & cGLReplayerVerboseMode)
10589 vogl_printf("%s: Restore took %f secs\n", VOGL_METHOD_NAME, tm.get_elapsed_secs());
10591 vogl_printf("%s: Finished restoring %u %s objects\n", VOGL_METHOD_NAME, n, get_gl_object_state_type_str(state_type));
10597 //----------------------------------------------------------------------------------------------------------------------
10598 // vogl_xfont_cache
10599 //----------------------------------------------------------------------------------------------------------------------
10600 class vogl_xfont_cache
10602 VOGL_NO_COPY_OR_ASSIGNMENT_OP(vogl_xfont_cache);
10605 vogl_xfont_cache(Display *dpy)
10611 ~vogl_xfont_cache()
10622 for (xfont_map::iterator it = m_xfonts.begin(); it != m_xfonts.end(); ++it)
10623 XFreeFont(m_dpy, it->second);
10627 XFontStruct *get_or_create(const char *pName)
10631 XFontStruct **ppXFont = m_xfonts.find_value(pName);
10635 XFontStruct *pXFont = XLoadQueryFont(m_dpy, pName);
10637 m_xfonts.insert(pName, pXFont);
10645 typedef vogl::map<dynamic_string, XFontStruct *> xfont_map;
10646 xfont_map m_xfonts;
10649 //----------------------------------------------------------------------------------------------------------------------
10650 // vogl_replayer::restore_display_lists
10651 //----------------------------------------------------------------------------------------------------------------------
10652 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)
10656 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10657 VOGL_NOTE_UNUSED(snapshot);
10659 VOGL_ASSERT(m_cur_trace_context);
10663 const vogl_display_list_state &disp_lists = context_snapshot.get_display_list_state();
10665 if (!disp_lists.size())
10668 vogl_message_printf("%s: Recreating %u display lists\n", VOGL_METHOD_NAME, disp_lists.get_display_list_map().size());
10670 vogl_xfont_cache xfont_cache(m_pWindow->get_display());
10672 const vogl_display_list_map &disp_list_map = disp_lists.get_display_list_map();
10674 for (vogl_display_list_map::const_iterator it = disp_list_map.begin(); it != disp_list_map.end(); ++it)
10676 GLuint trace_handle = it->first;
10677 const vogl_display_list &disp_list = it->second;
10681 VOGL_ASSERT_ALWAYS;
10685 GLuint replay_handle = GL_ENTRYPOINT(glGenLists)(1);
10686 if (check_gl_error() || !replay_handle)
10687 goto handle_failure;
10689 if (disp_list.is_valid())
10691 if (disp_list.is_xfont())
10693 XFontStruct *pXFont = xfont_cache.get_or_create(disp_list.get_xfont_name().get_ptr());
10696 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);
10700 GL_ENTRYPOINT(glXUseXFont)(pXFont->fid, disp_list.get_xfont_glyph(), 1, replay_handle);
10705 GL_ENTRYPOINT(glNewList)(replay_handle, GL_COMPILE);
10707 if (check_gl_error() || !replay_handle)
10709 GL_ENTRYPOINT(glDeleteLists)(replay_handle, 1);
10712 goto handle_failure;
10715 const vogl_trace_packet_array &packets = disp_list.get_packets();
10717 for (uint packet_index = 0; packet_index < packets.size(); packet_index++)
10719 if (packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
10721 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);
10725 const uint8_vec &packet_buf = packets.get_packet_buf(packet_index);
10727 if (!m_temp2_gl_packet.deserialize(packet_buf, true))
10729 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);
10733 vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = m_temp2_gl_packet.get_entrypoint_packet();
10735 gl_entrypoint_packet.m_context_handle = m_cur_trace_context;
10737 if (m_flags & cGLReplayerDebugMode)
10738 dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
10740 int64_t prev_parsed_call_counter = m_last_parsed_call_counter;
10741 int64_t prev_processed_call_counter = m_last_processed_call_counter;
10742 m_last_parsed_call_counter = gl_entrypoint_packet.m_call_counter;
10743 m_last_processed_call_counter = gl_entrypoint_packet.m_call_counter;
10744 bool prev_at_frame_boundary = m_at_frame_boundary;
10746 const vogl_trace_packet *pPrev_gl_packet = m_pCur_gl_packet;
10748 m_pCur_gl_packet = &m_temp2_gl_packet;
10750 vogl_gl_replayer::status_t status = process_gl_entrypoint_packet_internal(m_temp2_gl_packet);
10752 m_pCur_gl_packet = pPrev_gl_packet;
10754 m_last_parsed_call_counter = prev_parsed_call_counter;
10755 m_last_processed_call_counter = prev_processed_call_counter;
10756 m_at_frame_boundary = prev_at_frame_boundary;
10758 if (status != cStatusOK)
10760 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);
10765 // TODO: Set context state because we're currently generating a display list!
10766 if (disp_list.is_generating())
10768 VOGL_ASSERT_ALWAYS;
10771 GL_ENTRYPOINT(glEndList)();
10776 get_shared_state()->m_lists.insert(trace_handle, replay_handle);
10778 if (!get_shared_state()->m_shadow_state.m_display_lists.define_list(trace_handle, replay_handle, disp_list))
10780 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);
10786 vogl_message_printf("%s: Done recreating display lists\n", VOGL_METHOD_NAME);
10791 return cStatusHardFailure;
10794 //----------------------------------------------------------------------------------------------------------------------
10795 // vogl_replayer::restore_general_state
10796 //----------------------------------------------------------------------------------------------------------------------
10797 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)
10801 VOGL_NOTE_UNUSED(snapshot);
10803 vogl_general_context_state::vogl_persistent_restore_state persistent_restore_state;
10804 persistent_restore_state.m_pSelect_buffer = &m_pCur_context_state->m_select_buffer;
10806 if (!context_snapshot.get_general_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, persistent_restore_state))
10807 return cStatusHardFailure;
10809 if (!m_pCur_context_state->m_context_info.is_core_profile())
10811 if (context_snapshot.get_texenv_state().is_valid())
10813 if (!context_snapshot.get_texenv_state().restore(m_pCur_context_state->m_context_info))
10814 return cStatusHardFailure;
10817 if (context_snapshot.get_material_state().is_valid())
10819 if (!context_snapshot.get_material_state().restore(m_pCur_context_state->m_context_info))
10820 return cStatusHardFailure;
10823 if (context_snapshot.get_light_state().is_valid())
10825 if (!context_snapshot.get_light_state().restore(m_pCur_context_state->m_context_info))
10826 return cStatusHardFailure;
10829 if (context_snapshot.get_matrix_state().is_valid())
10831 if (!context_snapshot.get_matrix_state().restore(m_pCur_context_state->m_context_info))
10832 return cStatusHardFailure;
10835 if (context_snapshot.get_polygon_stipple_state().is_valid())
10837 if (!context_snapshot.get_polygon_stipple_state().restore(m_pCur_context_state->m_context_info))
10838 return cStatusHardFailure;
10841 if (context_snapshot.get_arb_program_environment_state().is_valid())
10843 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_vertex_program"))
10845 if (!context_snapshot.get_arb_program_environment_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper))
10846 return cStatusHardFailure;
10850 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);
10855 if (context_snapshot.get_current_vertex_attrib_state().is_valid())
10857 if (!context_snapshot.get_current_vertex_attrib_state().restore(m_pCur_context_state->m_context_info))
10858 return cStatusHardFailure;
10864 //----------------------------------------------------------------------------------------------------------------------
10865 // vogl_replayer::validate_program_and_shader_handle_tables
10866 //----------------------------------------------------------------------------------------------------------------------
10867 bool vogl_gl_replayer::validate_program_and_shader_handle_tables()
10871 if (!m_pCur_context_state)
10874 if (!get_shared_state()->m_shadow_state.m_objs.check())
10875 vogl_error_printf("%s: Object handle tracker failed validation!\n", VOGL_METHOD_NAME);
10877 uint_vec replay_handles;
10878 get_shared_state()->m_shadow_state.m_objs.get_inv_handles(replay_handles);
10880 for (uint i = 0; i < replay_handles.size(); i++)
10882 GLuint replay_handle = replay_handles[i];
10883 GLuint trace_handle = replay_handle;
10884 bool map_succeeded = get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle, trace_handle);
10885 VOGL_ASSERT(map_succeeded);
10886 VOGL_NOTE_UNUSED(map_succeeded);
10888 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle);
10889 VOGL_ASSERT(target == get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle));
10891 if (target == VOGL_PROGRAM_OBJECT)
10893 if (!GL_ENTRYPOINT(glIsProgram)(replay_handle))
10895 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);
10898 if (!get_shared_state()->m_glsl_program_hash_map.contains(trace_handle))
10900 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);
10903 else if (target == VOGL_SHADER_OBJECT)
10905 if (!GL_ENTRYPOINT(glIsShader)(replay_handle))
10907 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);
10912 VOGL_ASSERT_ALWAYS;
10919 //----------------------------------------------------------------------------------------------------------------------
10920 // vogl_replayer::validate_textures
10921 //----------------------------------------------------------------------------------------------------------------------
10922 bool vogl_gl_replayer::validate_textures()
10926 if (!m_pCur_context_state)
10929 if (!get_shared_state()->m_shadow_state.m_textures.check())
10930 vogl_error_printf("%s: Texture handle tracker failed validation!\n", VOGL_METHOD_NAME);
10932 for (uint replay_handle = 1; replay_handle <= 0xFFFFU; replay_handle++)
10934 bool is_tex = GL_ENTRYPOINT(glIsTexture)(replay_handle) != 0;
10936 bool found_in_shadow = get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle);
10940 if (found_in_shadow)
10942 GLuint trace_handle = 0;
10943 get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle, trace_handle);
10944 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);
10949 if (!found_in_shadow)
10951 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);
10959 //----------------------------------------------------------------------------------------------------------------------
10960 // vogl_replayer::update_context_shadows
10961 //----------------------------------------------------------------------------------------------------------------------
10962 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)
10966 VOGL_NOTE_UNUSED(snapshot);
10967 VOGL_NOTE_UNUSED(context_snapshot);
10968 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10972 // Make sure shadow is good
10973 GLint actual_current_replay_program = 0;
10974 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
10977 m_pCur_context_state->m_cur_replay_program = actual_current_replay_program;
10978 if (!actual_current_replay_program)
10979 m_pCur_context_state->m_cur_trace_program = 0;
10982 GLuint trace_handle = actual_current_replay_program;
10983 if (!get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(actual_current_replay_program, trace_handle))
10985 process_entrypoint_error("%s: Failed finding restored GL shader %u in program/shader object handle hashmap\n", VOGL_METHOD_NAME, actual_current_replay_program);
10987 m_pCur_context_state->m_cur_replay_program = 0;
10988 m_pCur_context_state->m_cur_trace_program = 0;
10992 m_pCur_context_state->m_cur_trace_program = trace_handle;
10996 check_program_binding_shadow();
11001 //----------------------------------------------------------------------------------------------------------------------
11002 // vogl_replayer::handle_marked_for_deleted_objects
11003 //----------------------------------------------------------------------------------------------------------------------
11004 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)
11008 if (m_flags & cGLReplayerVerboseMode)
11010 vogl_debug_printf("%s: %u program/shader objects where marked as deleted\n", VOGL_METHOD_NAME, objects_to_delete.size());
11013 for (uint i = 0; i < objects_to_delete.size(); i++)
11015 const vogl_gl_object_state *pState_obj = objects_to_delete[i];
11017 GLuint64 trace_handle = pState_obj->get_snapshot_handle();
11018 GLuint64 restore_handle = trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle());
11020 if (m_flags & cGLReplayerVerboseMode)
11022 // This should be a rare/exception case so let's try to be a little paranoid.
11023 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,
11024 get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
11027 GLboolean object_is_still_a_name = true;
11029 switch (pState_obj->get_type())
11033 handle_delete_program(static_cast<GLuint>(trace_handle));
11035 object_is_still_a_name = GL_ENTRYPOINT(glIsProgram)(static_cast<GLuint>(restore_handle));
11041 handle_delete_shader(static_cast<GLuint>(trace_handle));
11043 object_is_still_a_name = GL_ENTRYPOINT(glIsShader)(static_cast<GLuint>(restore_handle));
11049 VOGL_ASSERT_ALWAYS;
11054 // "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."
11055 // Same for shaders.
11056 if (!object_is_still_a_name)
11058 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,
11059 get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
11064 //----------------------------------------------------------------------------------------------------------------------
11065 // vogl_replayer::begin_applying_snapshot
11066 // Takes ownership (even on errors) when delete_snapshot_after_applying is true.
11067 //----------------------------------------------------------------------------------------------------------------------
11068 vogl_gl_replayer::status_t vogl_gl_replayer::begin_applying_snapshot(const vogl_gl_state_snapshot *pSnapshot, bool delete_snapshot_after_applying)
11072 if (!pSnapshot->is_valid())
11074 if (delete_snapshot_after_applying)
11075 vogl_delete(const_cast<vogl_gl_state_snapshot *>(pSnapshot));
11077 return cStatusHardFailure;
11082 m_pPending_snapshot = pSnapshot;
11083 m_delete_pending_snapshot_after_applying = delete_snapshot_after_applying;
11085 m_frame_index = pSnapshot->get_frame_index();
11086 m_last_parsed_call_counter = pSnapshot->get_gl_call_counter();
11087 m_last_processed_call_counter = pSnapshot->get_gl_call_counter();
11088 m_at_frame_boundary = false;
11090 if (!(m_flags & cGLReplayerLockWindowDimensions))
11092 return trigger_pending_window_resize(pSnapshot->get_window_width(), pSnapshot->get_window_height());
11095 return process_applying_pending_snapshot();
11098 //----------------------------------------------------------------------------------------------------------------------
11099 // vogl_replayer::restore_context
11100 //----------------------------------------------------------------------------------------------------------------------
11101 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)
11105 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
11106 VOGL_NOTE_UNUSED(snapshot);
11108 // TODO: This always creates with attribs, also need to support plain glXCreateContext()
11110 Display *dpy = m_pWindow->get_display();
11111 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
11113 vogl_trace_context_ptr_value trace_share_context = context_snapshot.get_context_desc().get_trace_share_context();
11115 GLXContext replay_share_context = remap_context(trace_share_context);
11116 if ((trace_share_context) && (!replay_share_context))
11118 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));
11119 return cStatusHardFailure;
11122 GLboolean direct = context_snapshot.get_context_desc().get_direct();
11124 vogl_trace_context_ptr_value trace_context = context_snapshot.get_context_desc().get_trace_context();
11126 status_t status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct,
11127 context_snapshot.get_context_desc().get_attribs().get_vec().get_ptr(),
11128 context_snapshot.get_context_desc().get_attribs().get_vec().size(), true);
11129 if (status != cStatusOK)
11131 vogl_error_printf("%s: Failed creating new context\n", VOGL_METHOD_NAME);
11135 // Has this context ever been made current?
11136 if (context_snapshot.get_context_info().is_valid())
11138 context_state *pContext_state = get_trace_context_state(trace_context);
11139 if (!pContext_state)
11141 vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11142 return cStatusHardFailure;
11145 GLXContext replay_context = pContext_state->m_replay_context;
11146 if (!replay_context)
11148 vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11149 return cStatusHardFailure;
11152 GLXDrawable drawable = m_pWindow->get_xwindow();
11154 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
11157 vogl_error_printf("%s: Failed making context current\n", VOGL_METHOD_NAME);
11158 return cStatusHardFailure;
11161 m_cur_trace_context = trace_context;
11162 m_cur_replay_context = replay_context;
11163 m_pCur_context_state = pContext_state;
11165 if (!handle_context_made_current())
11166 return cStatusHardFailure;
11172 //----------------------------------------------------------------------------------------------------------------------
11173 // vogl_replayer::process_applying_pending_snapshot
11174 //----------------------------------------------------------------------------------------------------------------------
11175 vogl_gl_replayer::status_t vogl_gl_replayer::process_applying_pending_snapshot()
11179 if (!m_pPending_snapshot)
11182 timed_scope ts(VOGL_METHOD_NAME);
11184 const vogl_gl_state_snapshot &snapshot = *m_pPending_snapshot;
11186 trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
11188 m_frame_index = snapshot.get_frame_index();
11189 m_last_parsed_call_counter = snapshot.get_gl_call_counter();
11190 m_last_processed_call_counter = snapshot.get_gl_call_counter();
11191 m_at_frame_boundary = snapshot.get_at_frame_boundary();
11193 // Ensure the client side array bufs are large enough (we don't care about the actual ptr values).
11194 for (uint i = 0; i < snapshot.get_client_side_vertex_attrib_ptrs().size(); i++)
11195 m_client_side_vertex_attrib_data[i].resize(snapshot.get_client_side_vertex_attrib_ptrs()[i].m_size);
11197 for (uint i = 0; i < snapshot.get_client_side_array_ptrs().size(); i++)
11198 m_client_side_array_data[i].resize(snapshot.get_client_side_array_ptrs()[i].m_size);
11200 for (uint i = 0; i < snapshot.get_client_side_texcoord_ptrs().size(); i++)
11201 m_client_side_texcoord_data[i].resize(snapshot.get_client_side_texcoord_ptrs()[i].m_size);
11203 const vogl_context_snapshot_ptr_vec &context_ptrs = snapshot.get_contexts();
11205 vogl_context_snapshot_ptr_vec restore_context_ptrs(snapshot.get_contexts());
11206 vogl::vector<vogl_const_gl_object_state_ptr_vec> objects_to_delete_vec(context_ptrs.size());
11208 status_t status = cStatusOK;
11209 uint total_contexts_restored = 0;
11210 bool restored_default_framebuffer = false;
11214 uint num_contexts_restored_in_this_pass = 0;
11216 for (uint context_index = 0; context_index < restore_context_ptrs.size(); context_index++)
11218 if (!restore_context_ptrs[context_index])
11221 const vogl_context_snapshot &context_state = *restore_context_ptrs[context_index];
11223 if (context_state.get_context_desc().get_trace_share_context())
11225 // Don't restore this context if its sharelist context hasn't been restored yet
11226 if (!remap_context(context_state.get_context_desc().get_trace_share_context()))
11230 status = restore_context(trace_to_replay_remapper, snapshot, context_state);
11231 if (status != cStatusOK)
11234 // Has this context ever been made current?
11235 if (context_state.get_context_info().is_valid())
11237 // 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!)
11238 const vogl_gl_object_state_type s_object_type_restore_order[] = { cGLSTBuffer, cGLSTSampler, cGLSTQuery, cGLSTRenderbuffer, cGLSTTexture, cGLSTFramebuffer, cGLSTVertexArray, cGLSTShader, cGLSTProgram, cGLSTSync, cGLSTARBProgram };
11239 VOGL_ASSUME(VOGL_ARRAY_SIZE(s_object_type_restore_order) == (cGLSTTotalTypes - 1));
11241 if (m_flags & cGLReplayerLowLevelDebugMode)
11243 if (!validate_textures())
11244 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11247 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11249 for (uint i = 0; i < VOGL_ARRAY_SIZE(s_object_type_restore_order); i++)
11251 status = restore_objects(trace_to_replay_remapper, snapshot, context_state, s_object_type_restore_order[i], objects_to_delete);
11252 if (status != cStatusOK)
11255 if (m_flags & cGLReplayerLowLevelDebugMode)
11257 if (!validate_program_and_shader_handle_tables())
11258 vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11260 if (!validate_textures())
11261 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11265 if (m_flags & cGLReplayerLowLevelDebugMode)
11267 if (!validate_textures())
11268 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11271 status = restore_display_lists(trace_to_replay_remapper, snapshot, context_state);
11272 if (status != cStatusOK)
11275 // Restore default framebuffer
11276 if ((!restored_default_framebuffer) && (snapshot.get_default_framebuffer().is_valid()))
11278 restored_default_framebuffer = true;
11280 if (!snapshot.get_default_framebuffer().restore(m_pCur_context_state->m_context_info))
11282 vogl_warning_printf("%s: Failed restoring default framebuffer!\n", VOGL_METHOD_NAME);
11286 // Beware: restore_general_state() will bind a bunch of stuff from the trace!
11287 status = restore_general_state(trace_to_replay_remapper, snapshot, context_state);
11288 if (status != cStatusOK)
11291 status = update_context_shadows(trace_to_replay_remapper, snapshot, context_state);
11292 if (status != cStatusOK)
11295 if (m_flags & cGLReplayerLowLevelDebugMode)
11297 if (!validate_program_and_shader_handle_tables())
11298 vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11300 if (!validate_textures())
11301 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11305 num_contexts_restored_in_this_pass++;
11307 total_contexts_restored++;
11309 restore_context_ptrs[context_index] = NULL;
11312 if (!num_contexts_restored_in_this_pass)
11316 if (total_contexts_restored != snapshot.get_contexts().size())
11318 vogl_error_printf("%s: Failed satisfying sharelist dependency during context restoration\n", VOGL_METHOD_NAME);
11322 for (uint context_index = 0; context_index < context_ptrs.size(); context_index++)
11324 const vogl_context_snapshot &context_state = *context_ptrs[context_index];
11326 if (!context_state.get_context_info().is_valid())
11329 status_t status = switch_contexts(context_state.get_context_desc().get_trace_context());
11330 if (status != cStatusOK)
11332 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()));
11336 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11338 handle_marked_for_deleted_objects(objects_to_delete, trace_to_replay_remapper);
11341 destroy_pending_snapshot();
11352 //----------------------------------------------------------------------------------------------------------------------
11353 // vogl_gl_replayer::write_trim_file_internal
11354 //----------------------------------------------------------------------------------------------------------------------
11355 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)
11357 // Open the output trace
11358 // 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.
11359 const vogl_ctypes &trace_gl_ctypes = get_trace_gl_ctypes();
11361 vogl_trace_packet trace_packet(&trace_gl_ctypes);
11363 // TODO: This seems like WAY too much work! Move the snapshot to the beginning of the trace, in the header!
11364 bool found_state_snapshot = false;
11365 dynamic_string binary_snapshot_id, text_snapshot_id;
11367 bool is_at_start_of_trace = false;
11368 VOGL_NOTE_UNUSED(is_at_start_of_trace);
11370 int demarcation_packet_index = -1;
11371 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11373 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11374 if (packet_type != cTSPTGLEntrypoint)
11377 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11379 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11380 if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11383 if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11385 console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11389 GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11390 if (cmd == cITCRDemarcation)
11392 is_at_start_of_trace = true;
11393 demarcation_packet_index = packet_index;
11395 else if (cmd == cITCRKeyValueMap)
11397 key_value_map &kvm = trace_packet.get_key_value_map();
11399 dynamic_string cmd_type(kvm.get_string("command_type"));
11401 if (cmd_type == "state_snapshot")
11403 found_state_snapshot = true;
11405 text_snapshot_id = kvm.get_string("id");
11406 binary_snapshot_id = kvm.get_string("binary_id");
11411 vogl_trace_file_writer trace_writer(&trace_gl_ctypes);
11412 if (!trace_writer.open(trim_filename.get_ptr(), NULL, true, false, m_trace_pointer_size_in_bytes))
11414 console::error("%s: Failed creating trimmed trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11418 if (found_state_snapshot)
11420 // Copy over the source trace's archive (it contains the snapshot, along with any files it refers to).
11421 if (trace_reader.get_archive_blob_manager().is_initialized())
11423 dynamic_string_array blob_files(trace_reader.get_archive_blob_manager().enumerate());
11424 for (uint i = 0; i < blob_files.size(); i++)
11426 if ((blob_files[i].is_empty()) || (blob_files[i] == VOGL_TRACE_ARCHIVE_FRAME_FILE_OFFSETS_FILENAME))
11429 vogl_message_printf("Adding blob file %s to output trace archive\n", blob_files[i].get_ptr());
11431 if (!trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), blob_files[i], blob_files[i]).has_content())
11433 vogl_error_printf("%s: Failed copying blob data for file \"%s\" to output trace archive!\n", VOGL_FUNCTION_NAME, blob_files[i].get_ptr());
11441 // Copy over the source trace's backtrace map, machine info, etc. files.
11442 if (trace_reader.get_archive_blob_manager().is_initialized())
11444 // compiler_info.json
11445 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);
11446 // machine_info.json
11447 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);
11448 // backtrace_map_syms.json
11449 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);
11450 // backtrace_map_addrs.json
11451 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);
11454 vogl_unique_ptr<vogl_gl_state_snapshot> pTrim_snapshot(snapshot_state(&trim_packets, optimize_snapshot));
11456 if (!pTrim_snapshot.get())
11458 console::error("%s: Failed creating replayer GL snapshot!\n", VOGL_FUNCTION_NAME);
11462 pTrim_snapshot->set_frame_index(0);
11465 if (!pTrim_snapshot->serialize(*doc.get_root(), *trace_writer.get_trace_archive(), &trace_gl_ctypes))
11467 console::error("%s: Failed serializing GL state snapshot!\n", VOGL_FUNCTION_NAME);
11468 trace_writer.close();
11469 file_utils::delete_file(trim_filename.get_ptr());
11473 vogl::vector<char> snapshot_data;
11474 doc.serialize(snapshot_data, true, 0, false);
11476 uint8_vec binary_snapshot_data;
11477 doc.binary_serialize(binary_snapshot_data);
11479 pTrim_snapshot.reset();
11481 // Write the state_snapshot file to the trace archive
11482 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));
11483 if (snapshot_id.is_empty())
11485 console::error("%s: Failed adding GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11486 trace_writer.close();
11487 file_utils::delete_file(trim_filename.get_ptr());
11492 *pSnapshot_id = snapshot_id;
11494 snapshot_data.clear();
11496 // Write the binary_state_snapshot file to the trace archive
11497 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));
11498 if (binary_snapshot_id.is_empty())
11500 console::error("%s: Failed adding binary GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11501 trace_writer.close();
11502 file_utils::delete_file(trim_filename.get_ptr());
11506 binary_snapshot_data.clear();
11508 key_value_map snapshot_key_value_map;
11509 snapshot_key_value_map.insert("command_type", "state_snapshot");
11510 snapshot_key_value_map.insert("id", snapshot_id);
11511 snapshot_key_value_map.insert("binary_id", binary_snapshot_id);
11513 dynamic_stream snapshot_stream(0);
11514 if (!vogl_write_glInternalTraceCommandRAD(snapshot_stream, &trace_gl_ctypes, cITCRKeyValueMap, sizeof(snapshot_key_value_map), reinterpret_cast<const GLubyte *>(&snapshot_key_value_map)))
11516 console::error("%s: Failed serializing snapshot packet!\n", VOGL_FUNCTION_NAME);
11517 trace_writer.close();
11518 file_utils::delete_file(trim_filename.get_ptr());
11522 if (demarcation_packet_index >= 0)
11524 trim_packets.insert(demarcation_packet_index, snapshot_stream.get_buf());
11525 demarcation_packet_index++;
11529 dynamic_stream demarcation_stream(0);
11530 vogl_write_glInternalTraceCommandRAD(demarcation_stream, &trace_gl_ctypes, cITCRDemarcation, 0, NULL);
11532 // Screw the ctypes packet, it's only used for debugging right now anyway.
11533 trim_packets.insert(0, snapshot_stream.get_buf());
11534 trim_packets.insert(1, demarcation_stream.get_buf());
11538 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11540 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11542 const bool is_swap = trim_packets.is_swap_buffers_packet(packet_index);
11544 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11545 if (packet_type == cTSPTEOF)
11547 else if (packet_type != cTSPTGLEntrypoint)
11549 VOGL_ASSERT_ALWAYS;
11552 if (!trace_writer.write_packet(packet_buf.get_ptr(), packet_buf.size(), is_swap))
11554 console::error("%s: Failed writing trace packet to output trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11555 trace_writer.close();
11556 file_utils::delete_file(trim_filename.get_ptr());
11561 bool success = trace_writer.close();
11563 console::error("%s: Failed closing wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11565 console::message("%s: Successfully wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11570 //----------------------------------------------------------------------------------------------------------------------
11571 // vogl_gl_replayer::write_trim_file
11572 //----------------------------------------------------------------------------------------------------------------------
11573 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)
11579 console::error("%s: Trace is not open\n", VOGL_METHOD_NAME);
11583 bool from_start_of_frame = (flags & cWriteTrimFileFromStartOfFrame) != 0;
11585 if ((!from_start_of_frame) || (!trim_len))
11586 flags &= ~cWriteTrimFileOptimizeSnapshot;
11588 const uint trim_frame = static_cast<uint>(get_frame_index());
11589 const int64_t trim_call_counter = get_last_parsed_call_counter();
11591 // Read the desired packets from the source trace file
11592 vogl_trace_packet_array trim_packets;
11594 if ((trim_len) || (!trim_frame))
11596 console::message("%s: Reading trim packets from source trace file\n", VOGL_FUNCTION_NAME);
11598 uint frames_to_read = trim_len;
11599 if ((from_start_of_frame) && (!trim_frame) && (!trim_len))
11600 frames_to_read = 1;
11602 uint actual_trim_len = 0;
11603 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);
11604 if (read_packets_status == vogl_trace_file_reader::cFailed)
11606 console::error("%s: Failed reading source trace file packets beginning at frame %u!\n", VOGL_FUNCTION_NAME, trim_frame);
11610 if (actual_trim_len != frames_to_read)
11612 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);
11615 if (from_start_of_frame)
11617 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);
11619 if ((!trim_frame) && (!trim_len))
11621 // 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.
11622 // TODO: Most of this will go away once we move the state snapshot into the trace archive.
11624 vogl_trace_packet_array new_trim_packets;
11626 vogl_trace_packet trace_packet(&get_trace_gl_ctypes());
11628 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11630 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11631 if (packet_type != cTSPTGLEntrypoint)
11634 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11636 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11637 if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11640 if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11642 console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11646 GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11648 new_trim_packets.push_back(packet_buf);
11650 if (cmd == cITCRDemarcation)
11654 trim_packets.swap(new_trim_packets);
11657 else if (trim_call_counter >= 0)
11659 uint orig_num_packets = trim_packets.size();
11660 uint total_erased_packets = 0;
11662 // Remove any calls before the current one.
11663 for (int64_t packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11665 if (trim_packets.get_packet_type(static_cast<uint>(packet_index)) != cTSPTGLEntrypoint)
11668 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(static_cast<uint>(packet_index));
11670 if (static_cast<int64_t>(pGL_packet->m_call_counter) <= trim_call_counter)
11672 trim_packets.erase(static_cast<uint>(packet_index));
11675 total_erased_packets++;
11679 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());
11683 if (!write_trim_file_internal(trim_packets, trim_filename, trace_reader, (flags & cWriteTrimFileOptimizeSnapshot) != 0, pSnapshot_id))
11685 console::warning("%s: Trim file write failed, deleting invalid trim trace file %s\n", VOGL_METHOD_NAME, trim_filename.get_ptr());
11687 file_utils::delete_file(trim_filename.get_ptr());